[Ethereum] How to send some ether to all token holders

contract-developmentcontract-invocationsolidity

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?

Best Answer

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.

Related Topic