Abstract
ERC-OTTER defines a formal Solidity interface for community-owned tokens on Ethereum. It builds directly on EIP-20 (ERC-20) as the base layer, incorporating principles from EIP-4626 (vault accounting for reward pools) and EIP-712 (typed structured data for off-chain signatures), and introducing four novel protocol primitives not found in any existing standard:
IImmutable Transfer Tax Distribution
5% auto-split on every transfer — permanent, no admin override possible
IITime-Based Holder Tier Progression
Hold duration unlocks MEMBER and OG tiers with multiplied governance weight
IIIOn-Chain Meme Economy
Submit, vote, and earn from a community-run content layer with epoch settlement
IVProtocol Guardian Model
Transparent founder controls with hard-coded constraints — not omnipotent Ownable
Any token contract implementing this standard MUST enforce these mechanics without owner override capability. Community protections cannot be disabled after deployment. This is the foundational design invariant.
Motivation
Meme tokens represent a genuinely new type of digital community — one where cultural contribution, loyalty, and shared identity carry real economic value. Yet the current ERC-20 standard provides no mechanisms to encode these community dynamics on-chain. The result is a structural misalignment between developer incentives and community interests.
Three Unsolved Problems
גCRITICALRug Pull Vulnerability
ERC-20 imposes no restrictions on liquidity removal. Developers can drain the liquidity pool at any time. Community trust is built on social promises with zero cryptographic enforcement.
דSTRUCTURALNo Contribution Incentive
Holders who create content, grow the community, or promote the project receive no on-chain compensation. Wealth accumulation is the only on-chain signal — rewarding speculation, not contribution.
הSYSTEMICPure Speculation Trap
Without standardized utility mechanics, meme tokens cannot evolve beyond zero-sum price speculation. There is no existing ERC framework for sustainable meme community economics.
ERC-OTTER addresses all three problems with a single coherent standard, making community protection a cryptographic guarantee rather than a social promise.
Prior Art
ERC-OTTER does not start from scratch. It builds on a body of existing Ethereum standards and draws specific principles from each:
| Standard | What It Defines | What ERC-OTTER Takes From It | What It Lacks |
|---|
| EIP-20 (ERC-20) | Fungible token: transfer, approve, allowance | Base interface — all OTTER tokens ARE ERC-20 | No community mechanics, no tax, no governance |
| EIP-712 | Typed structured data hashing for signatures | Off-chain meme submission signatures (gas-efficient) | No token or community layer |
| EIP-1363 | Callback after transfer/transferFrom | Conceptual basis for auto-distribution on transfer | No standard distribution logic |
| EIP-4626 | Tokenized vault yield accounting | Reward pool share accounting model | Not designed for community governance |
| EIP-5725 | Vesting contract — time-based token release | Time-based hold duration → tier progression concept | No loyalty incentive, no meme layer |
| EIP-173 | Contract ownership — owner() transfer | Guardian role architecture (but with explicit constraints) | Omnipotent owner — no power constraints |
◈ IMPORTANT
What makes ERC-OTTER unique: No existing standard combines immutable tax distribution, time-based loyalty tiers, on-chain cultural rewards, and a constrained guardian model into a single coherent interface. ERC-OTTER is not a replacement for ERC-20 — it is a community protection layer built on top of it.
Specification
The key words MUST, MUST NOT, REQUIRED, SHALL, SHOULD, and MAY in this document are interpreted as described in RFC 2119.
Full Interface
◈IERC_OTTER.sol
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.24;
/// @title IERC-OTTER: Progressive Community Token Standard
/// @notice Interface for community-owned tokens with immutable protection mechanics
/// @dev Extends ERC-20. All tax constants are immutable — no admin override possible.
interface IERC_OTTER {
// ─── ENUMS ─────────────────────────────────────────────────────────────
enum Tier { NEWCOMER, MEMBER, OG }
enum ProposalStatus { PENDING, ACTIVE, PASSED, FAILED, EXECUTED, VETOED }
// ─── EVENTS ────────────────────────────────────────────────────────────
event TierUpgraded(address indexed holder, Tier oldTier, Tier newTier);
event TaxDistributed(uint256 toTreasury, uint256 toRewards,
uint256 toLiquidity, uint256 burned);
event MemeSubmitted(address indexed creator, bytes32 indexed contentHash,
uint256 indexed memeId);
event MemeVoted(uint256 indexed memeId, address indexed voter,
bool upvote, uint256 weight);
event EpochSettled(uint256 indexed epoch, uint256 distributed,
uint256 winnerCount);
event RewardsClaimed(address indexed holder, uint256 amount);
event ReferralRecorded(address indexed referrer, address indexed referee);
event ProposalCreated(uint256 indexed id, address indexed proposer,
bytes32 descriptionHash);
event ProposalPassed(uint256 indexed id, uint256 forVotes,
uint256 againstVotes);
event GuardianAction(address indexed guardian, bytes4 selector, bytes32 reason);
// ─── ERRORS ────────────────────────────────────────────────────────────
error AlreadyVoted();
error NothingToClaim();
error InsufficientTier(Tier required, Tier actual);
error GuardianOnly();
error TimelockActive(uint256 unlocksAt);
error ExceedsParameterBounds(uint256 value, uint256 min, uint256 max);
// ─── HOLDER STATE (READ) ────────────────────────────────────────────────
function holderTier(address account) external view returns (Tier);
function holdDuration(address account) external view returns (uint256);
function pendingRewards(address account) external view returns (uint256);
function rewardMultiplier(address account)external view returns (uint256 bps);
function governanceWeight(address account)external view returns (uint256);
function referralCount(address referrer) external view returns (uint256);
// ─── TAX CONSTANTS (IMMUTABLE — CANNOT BE CHANGED AFTER DEPLOY) ────────
function TAX_RATE() external view returns (uint16); // 500 = 5%
function TREASURY_SHARE() external view returns (uint16); // 4000 = 40%
function REWARDS_SHARE() external view returns (uint16); // 3000 = 30%
function LIQUIDITY_SHARE() external view returns (uint16); // 2000 = 20%
function BURN_SHARE() external view returns (uint16); // 1000 = 10%
// ─── COMMUNITY ACTIONS ─────────────────────────────────────────────────
function submitMeme(bytes32 contentHash) external returns (uint256 memeId);
function voteOnMeme(uint256 memeId, bool upvote) external;
function claimRewards() external returns (uint256 claimed);
function recordReferral(address referee, bytes32 proof) external;
// ─── GOVERNANCE ────────────────────────────────────────────────────────
function createProposal(bytes32 descriptionHash, bytes calldata payload)
external returns (uint256 proposalId);
function castVote(uint256 proposalId, bool support) external;
function executeProposal(uint256 proposalId) external;
function treasury() external view returns (address);
// ─── PROTOCOL GUARDIAN ─────────────────────────────────────────────────
// Guardian CAN: pause (max 24h), queue upgrades (72h timelock), veto proposals
// Guardian CANNOT: change tax constants, access treasury, disable community mechanics
function guardian() external view returns (address);
function emergencyPause(uint256 duration) external; // MAX: 86400 seconds
function queueUpgrade(address implementation) external; // 72h timelock
function vetoProposal(uint256 proposalId, bytes32 reason) external;
function setEpochDuration(uint256 days_) external; // bounds: 3–30 days
}
Holder Tiers
An ERC-OTTER contract MUST maintain three holder tiers based on uninterrupted hold duration. The timer MUST reset to zero whenever an address transfers any tokens out.
| Tier | Hold Duration | Reward Multiplier | Governance Weight | Meme Submission |
|---|
| NEWCOMER | 0–30 days | 1.0× (10000 bps) | 1× balance | View only |
| MEMBER | 30–90 days | 1.5× (15000 bps) | 1.5× balance | Submit + Vote |
| OG | 90+ days | 2.0× (20000 bps) | 2× balance | Submit + Vote + Propose |
◈OTTERTier.sol (excerpt)
// Tier thresholds
uint256 constant MEMBER_THRESHOLD = 30 days; // 2,592,000 seconds
uint256 constant OG_THRESHOLD = 90 days; // 7,776,000 seconds
// Reward multipliers in basis points
uint256 constant NEWCOMER_BPS = 10000; // 1.0x
uint256 constant MEMBER_BPS = 15000; // 1.5x
uint256 constant OG_BPS = 20000; // 2.0x
mapping(address => uint256) private _holdSince;
function holderTier(address account) public view returns (Tier) {
uint256 held = holdDuration(account);
if (held >= OG_THRESHOLD) return Tier.OG;
if (held >= MEMBER_THRESHOLD) return Tier.MEMBER;
return Tier.NEWCOMER;
}
function holdDuration(address account) public view returns (uint256) {
uint256 since = _holdSince[account];
if (since == 0 || balanceOf(account) == 0) return 0;
return block.timestamp - since;
}
/// @dev Resets hold timer on ANY outbound transfer — prevents gaming
function _afterTokenTransfer(address from, address to, uint256 amount)
internal override
{
if (from != address(0) && amount > 0) {
// Seller loses all accumulated hold time
_holdSince[from] = 0;
}
if (to != address(0) && _holdSince[to] == 0) {
_holdSince[to] = block.timestamp;
}
_updateTierIfChanged(from);
_updateTierIfChanged(to);
}
Transfer Tax — Immutable Distribution
An ERC-OTTER contract MUST apply exactly TAX_RATE (500 bps = 5%) on all transfers, excluding mints, burns, and internal contract-to-contract transfers. All four distribution shares MUST be declared as constant — no setter function for these values is permissible.
Community TreasuryTREASURY_SHARE
DAO-governed spending — community votes on use of funds
40%Creator Rewards PoolREWARDS_SHARE
Epoch-distributed to top meme creators by community vote
30%Liquidity LockLIQUIDITY_SHARE
Auto-compounded into locked liquidity — no withdrawal
20%Token BurnBURN_SHARE
Permanently burned — deflationary pressure on supply
10%On-Chain Meme Economy — Epoch System
An ERC-OTTER contract MUST provide on-chain meme submission and voting. Meme rewards are distributed in epochs (default 7 days). Only MEMBER and OG tier holders may submit memes. Any address with positive token balance MAY vote.
◈OTTEREpoch.sol (excerpt)
// ─── Epoch-Based Meme Reward Settlement ─────────────────────
uint256 public epochDuration; // settable by Guardian: 3–30 days
uint256 public currentEpoch;
uint256 public epochStartTime;
struct Meme {
address creator;
bytes32 contentHash;
uint256 epoch;
int256 netVotes; // upvotes minus downvotes (weighted)
uint256 rewardShare; // set at settlement
bool settled;
}
/// @notice Settle current epoch: calculate shares, enable claiming.
/// @dev Called by any address after epochDuration passes.
function settleEpoch() external {
require(block.timestamp >= epochStartTime + epochDuration,
"Epoch not over");
uint256 poolBalance = rewardsPool.balance();
uint256[] memory winners = _topMemes(currentEpoch, 10);
uint256 totalWeight;
for (uint i; i < winners.length; i++) {
totalWeight += uint256(memes[winners[i]].netVotes);
}
for (uint i; i < winners.length; i++) {
uint256 share = (poolBalance * uint256(
memes[winners[i]].netVotes)) / totalWeight;
memes[winners[i]].rewardShare = share;
memes[winners[i]].settled = true;
}
emit EpochSettled(currentEpoch, poolBalance, winners.length);
currentEpoch++;
epochStartTime = block.timestamp;
}
Referral Engine
An ERC-OTTER contract SHOULD implement on-chain referral tracking. When a new holder records a referral via recordReferral(referee, proof), the referrer's count increments on-chain. Referral count MAY contribute to tier eligibility and governance weight calculations at the implementer's discretion.
ℹ NOTE
The proof parameter is a keccak256 hash of a signed message linking referrer and referee. Implementations SHOULD verify this signature to prevent false referral claims.
Community Governance
ERC-OTTER defines a dual-layer governance model: community-controlled treasury and direction, with a Protocol Guardian layer providing emergency protection. This model is designed to give the community genuine ownership power while ensuring the protocol cannot be broken or exploited.
Community Powers
Any holder with OG tier status MAY create governance proposals. All token holders MAY vote, with weight proportional to governanceWeight() (balance × tier multiplier).
🏛️Treasury Spending
Propose and vote on how the 40% community treasury is used — grants, development, events, marketing
⚒️Feature Proposals
OG holders can propose new protocol mechanics, which are implemented if passed
🤝Partner Integrations
Vote on which protocols and platforms ERC-OTTER integrates with
⏱️Epoch Parameters
Community may propose changes to epoch duration within the 3–30 day bounds
🔑Guardian Transfer
Community vote (>50% governance weight) required to transfer the Guardian role
Protocol Guardian — Explicit Power Framework
The Protocol Guardian is a named address (initially the core team) with strictly limited on-chain powers. Unlike a standard Ownablepattern where the owner is omnipotent, the Guardian's capabilities are hard-coded constraints — not configurable permissions.
◈OTTERGuardian.sol
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.24;
/// @notice Protocol Guardian role — explicit power constraints on-chain
abstract contract OTTERGuardian {
address public guardian;
uint256 public upgradeTimelockExpiry;
address public pendingImplementation;
uint256 constant MAX_PAUSE_DURATION = 86400; // 24 hours
uint256 constant UPGRADE_TIMELOCK = 259200; // 72 hours
uint256 constant MIN_EPOCH_DAYS = 3;
uint256 constant MAX_EPOCH_DAYS = 30;
modifier onlyGuardian() {
require(msg.sender == guardian, "Guardian only");
_;
}
/// @notice Pause all transfers for emergency. MAX 24 hours.
function emergencyPause(uint256 duration) external onlyGuardian {
require(duration <= MAX_PAUSE_DURATION,
"Exceeds max pause duration");
_pause(duration);
emit GuardianAction(guardian, msg.sig, bytes32(duration));
}
/// @notice Queue an upgrade. 72-hour community observation window.
function queueUpgrade(address implementation) external onlyGuardian {
pendingImplementation = implementation;
upgradeTimelockExpiry = block.timestamp + UPGRADE_TIMELOCK;
emit GuardianAction(guardian, msg.sig, bytes32(uint256(
uint160(implementation))));
}
/// @notice Execute queued upgrade only after timelock.
function executeUpgrade() external onlyGuardian {
require(block.timestamp >= upgradeTimelockExpiry,
"Timelock not expired");
_upgradeTo(pendingImplementation);
}
/// @notice Veto a governance proposal with on-chain reason.
function vetoProposal(uint256 proposalId, bytes32 reason)
external onlyGuardian
{
_vetoProposal(proposalId, reason);
emit GuardianAction(guardian, msg.sig, reason);
}
/// @dev NOTE: TAX_RATE and distribution shares are declared as
/// 'constant' — no setter exists. Guardian CANNOT modify them.
function _pause(uint256) internal virtual;
function _upgradeTo(address) internal virtual;
function _vetoProposal(uint256, bytes32) internal virtual;
}
✓ GUARDIAN CAN
●Emergency pause (max 24 hours)
●Queue contract upgrade (72h timelock)
●Veto harmful governance proposals
●Adjust epoch duration (3–30 day bounds)
●Add approved meme content categories
✗ GUARDIAN CANNOT
●Modify TAX_RATE (declared constant)
●Change any distribution share (constant)
●Access treasury without DAO vote
●Disable tier mechanics or meme voting
●Transfer Guardian role without community vote
🦦 COMMUNITY
Path to Full Decentralization: The Guardian role is designed to be progressively transferred to a community multisig as the protocol matures. Stage 1: core team Guardian. Stage 2: 2-of-3 multisig with community members. Stage 3: on-chain DAO with no individual Guardian. This roadmap will be published and community-voted at each stage.
Token Economics
Supply Parameters
100,000,000,000
Total Supply
100 Billion OTTER
5%
Transfer Tax
immutable constant
30%
Creator Rewards
of every tax
40%
Treasury Share
DAO governed
20%
Liquidity
auto-compounding
No Pre-mine. No Team Allocation.
🦦 COMMUNITY
ERC-OTTER's reference token has no team allocation, no VC round, and no pre-mine. The only token distribution mechanism is through the community: 100% of supply enters circulation through the open market. Community treasury accumulates through the transfer tax — not through a founding team holding tokens. Every holder contributes equally to community growth.
Deflationary Mechanics
Every transfer reduces supply by BURN_SHARE (1% of transfer, 10% of the 5% tax). With 100 billion initial supply and sustained trading volume, the supply is programmatically deflationary. Burn events are emitted as Transfer events to the zero address, visible on all block explorers.
Reference Implementation
A minimal reference implementation is available on the companion GitHub repository. The abbreviated interface is shown above. The full implementation includes:
◈OTTERToken.sol— Core ERC-20 + tax distribution + tier tracking
◈OTTERGuardian.sol— Guardian role with explicit constraint enforcement
◈OTTEREpoch.sol— Meme submission, voting, and epoch settlement
◈OTTERGovernance.sol— Proposal creation, voting, and execution
◈OTTERReferral.sol— Referral recording with signature verification
◈OTTERLiquidity.sol— Audited liquidity lock with auto-compounding
Implementations SHOULD use OpenZeppelin's audited ERC-20 base. The complete reference implementation is available in the companion repository. A Sepolia testnet deployment exists for community testing.
Rationale
Why enforce tax at the standard level?
Community protection that can be disabled by the owner offers false security. By declaring the tax rate and all distribution shares as Solidity constant variables — not storage variables — ERC-OTTER ensures no setter function can exist. There is no setTaxRate(). There is no setTreasuryShare(). This is the fundamental difference from all existing tax-enabled tokens.
Why time-based tiers over balance-based?
Balance-based tiers create plutocracy: large holders gain disproportionate power, incentivizing whale accumulation over community commitment. Time-based tiers reward conviction and loyalty. A small holder who has held for 90 days has proven genuine community alignment — and deserves equivalent governance weight to a larger short-term holder. ERC-OTTER chooses alignment over wealth.
Why on-chain meme voting?
Meme culture is the primary driver of meme token growth. Moving this on-chain creates a transparent, tamper-proof record of cultural contribution and enables automatic reward distribution without trusted intermediaries. This is a first — no existing ERC standard addresses community cultural value creation.
Why the Protocol Guardian instead of standard Ownable?
Standard Ownable (EIP-173) gives the owner unrestricted power — they can change any storage variable and call any privileged function. This creates the same rug-pull risk ERC-OTTER is designed to prevent. The Guardian model explicitly enumerates what is and is not permitted, publishes this on-chain, and makes the constraints unmodifiable. Transparency of power is as important as limitation of power.
Why 5% transfer tax?
Historical analysis of fee-on-transfer tokens shows that rates above 10% cause liquidity fragmentation and dex router failures. Rates below 3% generate insufficient treasury funding for meaningful community initiatives. 5% is the established optimum. Implementations MAY lower to a minimum of 100 bps (1%) but MUST NOT exceed 1000 bps (10%).
Backwards Compatibility
ERC-OTTER is fully backwards compatible with EIP-20. An ERC-OTTER token IS an ERC-20 token. All standard functions — transfer, transferFrom, approve, allowance, balanceOf, totalSupply — behave exactly as specified in EIP-20, with one addition: transfer and transferFrom apply the tax deduction transparently.
The Transfer event MUST emit the post-tax amount received by the recipient. A separate TaxDistributed event provides the full breakdown. Wallets and block explorers will correctly show the net amount received.
ℹ NOTE
DEX integrations MUST account for the 5% fee-on-transfer when calculating minimum output amounts. Standard Uniswap V2/V3 swaps work correctly with ERC-OTTER tokens using the supportingFeeOnTransfer variants of swap functions.
Security Considerations
זHIGHRe-entrancy in claimRewards()
MUST follow checks-effects-interactions. Zero the pending rewards BEFORE the token transfer. Consider using OpenZeppelin ReentrancyGuard as an additional safeguard.
חMEDIUMTier manipulation via flash loans
Hold duration uses block.timestamp from first acquisition. Flash loan positions do not accumulate hold time as the timer resets on any outbound transfer. SHOULD verify using timestamps, not block numbers.
טMEDIUMMeme voting Sybil attacks
Mitigated by MEMBER tier requirement (30+ day hold) to submit. Voting weight is proportional to governance weight, not address count. SHOULD consider snapshot voting for large reward pools.
יHIGHLiquidity lock integrity
The locked liquidity mechanism MUST be independently audited. STRONGLY RECOMMENDED to use established audited lock protocols (Unicrypt, Team Finance) rather than custom implementations.
כLOWGuardian timelock bypass
The 72-hour upgrade timelock is enforced in contract code. However, the community SHOULD monitor the queueUpgrade() event and be prepared to coordinate opposition via governance if needed.
לLOWEpoch settlement manipulation
settleEpoch() is callable by anyone after epoch end. Last-minute large votes may influence settlement. SHOULD consider snapshot-based voting weight (balance at epoch start) to prevent last-block manipulation.
Copyright
Copyright and related rights waived via CC0 1.0 Universal. The ERC-OTTER interface is free for any project to implement.
🦦 COMMUNITY
ERC-OTTER is open source and community-driven. If you're building a token using this standard, we want to hear from you. Submit your project for inclusion in the official ERC-OTTER registry. Compliant implementations receive the ◈ OTTER CERTIFIED badge.