ERC-20 – Effective Ways to Store Dividends in Tokens

erc-20solidity

  1. I want to create a token that will allow an effective way to iterate through and update dividend values per token holder address. With my current idea, I'd have to manage 2 structures to keep ERC20 standard and be able to iterate through and calculate/store dividends (calculation will be divided into n steps due to gas limits). Is there any better way to implement dividends in current ERC20 standard?

ERC20 Token balances

mapping (address => uint256) public balances;

Array to store tokens and dividends

struct TokenDividend
{
    address addr;
    uint divident; 
}
Token[] public tokenDividends;

Users will be able to withdraw their rewards with withdraw() function, the problem here is that each user would have to iterate over tokenDividends array, this would cause out of gas errors at some point:

function withdraw() returns (bool) {}
  1. What are current plans about token standard?

  2. Is it possible to use iterable mapping as a token standard structure?
    https://github.com/chriseth/solidity-examples/blob/master/iterable_mapping.sol

  3. Are there any new structures planned to be added to Solidity?

  4. Should I combine standard mapping and iterable mapping to manage dividends and keep ERC20 token standard?

  5. Update:
    I have a requirement to add dividends weekly, all of the token holders have to be treated equally, users with small amounts of tokens will earn small dividends, those dividends will need to be accumulated over time so users won't spend more than they earn when withdrawing their rewards. Token will be tradable.

Similar question:
ERC20 Tokens with Rewards?

Best Answer

The token standard doesn't require you to store balances in any particular structure - a public mapping is not part of the standard - so you can simply do this:

struct Account {
    uint balance;
    uint dividends;
}

mapping(address=>Account) accounts;

Assuming you give out dividends proportional to a user's token balances, though, updating the dividends is still going to be a lot of work. Fortunately, there's a better way:

uint totalSupply;
uint totalDividends;

struct Account {
    uint balance;
    uint lastTotalDividends;
}
mapping(address=>Account) accounts;

Now, when you want to give out dividends, increase totalDividends by the amount of the dividend. When a user wants to withdraw their portion of any dividends, they calculate (accounts[user].balance * (totalDividends - accounts[user].lastTotalDividends)) / totalSupply - that is, take the amount of dividend disbursed since they last checked, and calculate the fraction of it they should receive based on the percentage of the tokens they own. Then, update lastTotalDividends to the current value of totalDividends.

Note that if you're doing this, you need to prevent users from sending or receiving tokens until they've withdrawn their dividends, or else users could 'double dip' by transferring tokens between accounts. You could avoid this by adding another field to Account that tracks the dividends they're entitled to but haven't yet withdrawn, and updating that before a transfer out of or into an account.

Related Topic