⚠   EIP DRAFT STATUS — Community feedback welcome. Submit issues or PRs on GitHub.   ⚠
⟦ DRAFT ⟧◈ STANDARDS TRACKERC — TOKEN STANDARDBUILDS ON: EIP-20, EIP-712EPOCH I · 2025

ERC-OTTER: Progressive Community Token Standard

A formal on-chain standard for community-owned tokens — extending ERC-20 with immutable community protection mechanics, time-based loyalty tiers, an on-chain meme economy, and a transparent Protocol Guardian governance model.

━━━━━━━━━━ א · HOLD TOGETHER · BUILD TOGETHER · ERC-OTTER ב ━━━━━━━━━━
AUTHOR
OTTER Core Team
STATUS
Draft
TYPE
Standards Track
CATEGORY
ERC
CREATED
2025-05-18
REQUIRES
EIP-20, EIP-712
NETWORK
Ethereum / Sepolia
CHAIN ID
1 (mainnet)

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:

I
Immutable Transfer Tax Distribution
5% auto-split on every transfer — permanent, no admin override possible
II
Time-Based Holder Tier Progression
Hold duration unlocks MEMBER and OG tiers with multiplied governance weight
III
On-Chain Meme Economy
Submit, vote, and earn from a community-run content layer with epoch settlement
IV
Protocol 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:

StandardWhat It DefinesWhat ERC-OTTER Takes From ItWhat It Lacks
EIP-20 (ERC-20)Fungible token: transfer, approve, allowanceBase interface — all OTTER tokens ARE ERC-20No community mechanics, no tax, no governance
EIP-712Typed structured data hashing for signaturesOff-chain meme submission signatures (gas-efficient)No token or community layer
EIP-1363Callback after transfer/transferFromConceptual basis for auto-distribution on transferNo standard distribution logic
EIP-4626Tokenized vault yield accountingReward pool share accounting modelNot designed for community governance
EIP-5725Vesting contract — time-based token releaseTime-based hold duration → tier progression conceptNo loyalty incentive, no meme layer
EIP-173Contract ownership — owner() transferGuardian 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.

TierHold DurationReward MultiplierGovernance WeightMeme Submission
NEWCOMER0–30 days1.0× (10000 bps)1× balanceView only
MEMBER30–90 days1.5× (15000 bps)1.5× balanceSubmit + Vote
OG90+ days2.0× (20000 bps)2× balanceSubmit + 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
10%
Burn Rate
of every tax
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.solCore ERC-20 + tax distribution + tier tracking
OTTERGuardian.solGuardian role with explicit constraint enforcement
OTTEREpoch.solMeme submission, voting, and epoch settlement
OTTERGovernance.solProposal creation, voting, and execution
OTTERReferral.solReferral recording with signature verification
OTTERLiquidity.solAudited 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.

← BACK TO PROTOCOL