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?


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.

  • 1
    You can make an iterable map, but with the approach I suggested, you don't need to: a dividend requires only updating a single counter, with the cost of the updates to each user amortised out when they make transactions. – Nick Johnson Dec 22 '16 at 10:40
  • 1
    Why do you need to track dividends not yet withdrawn? – Nick Johnson Dec 23 '16 at 16:15
  • 1
    The system I described will work just as well for someone with only one token that they rarely interact with as it will for a large and active tokenholder; you don't need to do any per-user updates when you pay out dividends. – Nick Johnson Dec 29 '16 at 20:07
  • 1
    Why would they have to iterate? Over what? – Nick Johnson Jan 6 '17 at 12:45
  • 1
    I don't understand - why would their dividends lose value? – Nick Johnson Jan 7 '17 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.