8

I created contract A which generates and sends my tokens. I would like to send some ether to each token holder from another contract B. So how to find all token holders from contract B?

  • Could you post the code of your contract? – Nicolas Massart Jun 7 '16 at 15:29
6

There's some trickiness when sending ether to lots of recipients.

If you use address.send(), the send can fail if the recipient is a contract that consumes some gas, because send() only forwards a fixed amount of gas. So (a) you don't want to throw if send returns false, because it would block everybody, and (b) that recipient will never get the ether, no matter how much gas he includes.

The other way is to use address.call.value, which does forward all gas. But you don't want to use that in this situation because a contract that consumes all the gas will halt everything even if you don't throw upon failure. So if you insist on looping the sends, you have to use address.send() and ignore failures.

To make sure everyone can get their ether, have each recipient call a withdraw() method in your contract. Within that method, do whatever update you need to record the withdrawal, then say "if (!address.call.value(x)()) throw;". If the recipient doesn't include enough gas, everything gets rolled back and he can try again.

If you do this, you no longer have to worry about finding all token holders. This also prevents the problem of having so many people in the loop that you exceed the gas limit of the entire block.

But if you really want to loop and address.send, then you're going to need a data structure like this:

mapping(address => uint) public holders; //people's balances
mapping(uint => address) public indexes;
uint public topindex;

Every time you add a token holder, you increment topindex, put the new index and holder address in indexes, and the address and balance in holders. This is necessary because there's no native way to iterate through a mapping, which is because of the way the mapping is stored in the blockchain.

Anything marked "public" is accessible from other contracts.

2

Contract A would also have to call Contract B informing it every time a transfer has taken place.

having said that - you have a bigger problem which is, how does Contract B handle the ether that it receives, and when should it pay out. What happens to those people who did not originally have tokens, but acquired them later? Would they also receive Ether retrospectively?

  • 2
    Also don't forget, contracts require gas. If you have a lot of token holders, you will not be able to send a transaction to all of them in one go because it will not fit into a block. This could potentially lock your contract up! – Péter Szilágyi Jun 7 '16 at 15:09
0

Getting all token holders of ERC-20 token contract is not currently feasible in EVM / smart contract due to heaviness this operation of all but trivial amount of token holders.

Here is a tool I have created to build a local database of token holders, for any block number. The particular use case I have is to pay dividends / interest.

  • Build a list of token holders offchain

  • Upload this list to your token distribution smart contract or use any of other standard token distribution tools

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.