Revenue Sharing System for Token Holders Development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Revenue Sharing System for Token Holders Development
Medium
~3-5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Token Holder Revenue Sharing System Development

Revenue sharing is mechanism for distributing protocol income between token holders. Sounds simple, but implementation contains several non-trivial tasks: how to fairly calculate each holder's share, how to efficiently distribute among thousands of addresses, what to do with unclaimed income and how to avoid flash loan attacks.

Distribution Models

Continuous streaming (Superfluid/Sablier)

Income "flows" to holders continuously proportional to balance. Theoretically ideal — practically complex: every token transfer requires recalculating flows. On Ethereum this is expensive with large number of holders.

Snapshot + Merkle Distribution

Most common model. Once per period (week/month), take snapshot of balances, calculate each share, build Merkle tree. Holders claim their share themselves via Merkle proof.

contract RevenueDistributor {
    IERC20 public immutable rewardToken;
    bytes32 public merkleRoot;
    uint256 public distributionId;
    mapping(uint256 => mapping(address => bool)) public claimed;

    function setDistribution(bytes32 _root) external onlyOwner {
        distributionId++;
        merkleRoot = _root;
        emit DistributionSet(distributionId, _root);
    }

    function claim(
        uint256 amount,
        bytes32[] calldata proof
    ) external {
        require(!claimed[distributionId][msg.sender], "Already claimed");
        bytes32 leaf = keccak256(abi.encodePacked(msg.sender, amount));
        require(MerkleProof.verify(proof, merkleRoot, leaf), "Invalid proof");
        claimed[distributionId][msg.sender] = true;
        rewardToken.transfer(msg.sender, amount);
        emit Claimed(distributionId, msg.sender, amount);
    }
}

Plus: scales to any number of holders, user pays gas. Minus: requires off-chain infrastructure for snapshot and Merkle tree generation.

Dividend-bearing token (redistribution via index)

MasterChef / Synthetix Rewards model: contract stores rewardPerTokenStored. With each new income, index updates. Upon claim user gets difference between current and last claim index.

uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;

function rewardPerToken() public view returns (uint256) {
    if (totalStaked == 0) return rewardPerTokenStored;
    return rewardPerTokenStored + (
        (rewardRate * (block.timestamp - lastUpdateTime) * 1e18) / totalStaked
    );
}

function earned(address account) public view returns (uint256) {
    return (
        (balanceOf(account) * (rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18
    ) + rewards[account];
}

This is O(1) per user operation — no need to snapshot all holders. Ideal for staking contracts. Not suitable if tokens aren't staked — need to account for non-staked balances.

Protection Against Flash Loan Attacks

The most critical issue: attacker takes flash loan for huge token amount, snapshot happens in same block, they claim disproportionately large share.

Solution 1: Time-weighted balance. Snapshot counts not current balance but time-weighted average over period. Even if attacker has large balance at snapshot moment — helps nothing if balance was zero before.

Solution 2: Minimum holding period. Only addresses holding tokens longer than N days get revenue sharing rights. Implemented via timestamp of last transfer.

Solution 3: Snapshot via Chainlink or commit-reveal. Snapshot moment unknown in advance, determined randomly or with delay. Attacker can't prepare.

// Record timestamps of last incoming transfers
mapping(address => uint256) public lastReceived;

function _afterTokenTransfer(address, address to, uint256) internal override {
    lastReceived[to] = block.timestamp;
}

// On snapshot: include only addresses with lastReceived > N days ago
function isEligible(address holder) public view returns (bool) {
    return lastReceived[holder] <= block.timestamp - MIN_HOLD_DURATION;
}

Multi-token Distribution

Protocol often generates income in different tokens: ETH from trading fees, USDC from stabilization mechanism, native token from emission. System should aggregate all this.

Option 1: everything converts to single reward token (e.g., USDC) before distribution. Simple for users, requires on-chain swap via DEX.

Option 2: multi-reward contract with separate index for each token. User claims multiple tokens in one transaction.

// Multi-reward: separate rewardPerToken for each reward token
mapping(address => uint256) public rewardPerTokenStored; // rewardToken => value
mapping(address => mapping(address => uint256)) public userRewardPerTokenPaid;

Off-chain Infrastructure for Merkle Distribution

Merkle tree generation is off-chain process. Need pipeline:

  1. Snapshot: query archival node (Alchemy/Infura with archive access) for balances at specific block number
  2. Calculation: calculate each address's share proportional to balance
  3. Tree building: @openzeppelin/merkle-tree library
  4. Publishing: Merkle root posted on-chain, full tree in IPFS or public API
  5. Proof service: API to get proof by address

Entire pipeline must be reproducible and verifiable: any participant can independently recalculate root and verify correctness.

Practical Selection Parameters

If holders < 1000 and income distributed often — Synthetix-style staking rewards. If holders > 10,000 and distribution periodic — Merkle distribution. If flexibility needed (different tokens, different rules) — hybrid scheme with off-chain snapshot and on-chain verification.

Development timeline: 3-5 weeks for basic system, 6-9 weeks with multi-reward, anti-flash-loan protection and frontend dashboard.