- Send the data of appropriate dividend payment to the chain, based on the state at the payout date, saying how much each account should get. But instead of sending all that data to the chain and putting it in storage, which will cost you gas, arrange the data in a merkle tree or a similar hashed data structure, and just send the root hash to the chain. People claiming will have to send the hashes leading up to the root, which will allow the contract to confirm that their payment is in the tree, and send them the money.
- Calculate the amounts that need to be paid, but instead of sending anything to the chain, just sign a load of data. For each recipient, sign a message with an Ethereum key saying something like, "Account 0xdeadbeef gets 1234 coins"
"Account 0xdeadbeef gets 1234 coins"
. This signature will consist of 3 pieces of data, called v
, r
and s
, plus the hash of the signed message. Send the chain the address that you're doing the signing with. Each user can send those pieces of the data to the chaincontract, at which point it will check the signature with ecrecover
and claimcredit them with the money it saysthat the message said they should receive in the message.
If you don't have a trusted actor, and the contract needs to be able to confirm who should get paid itself, then it's a bit harder. Your contract needs to be able to keepYou have a historycouple of each account as it goes, so that it can tell how much money it had at each date or block. Again, this is costlyways to do in storage, but you can make it somewhat cheaper with a hashed data structure: Each account starts with a hash of zero, then when they make a transaction, a record is created for the change, and hashed, together with the previous hash, and the resulting change is saved back over the last one. The user can then send data to replay this chain, and prove how much money they had at the dividend payment date. See this code for an example; It's not exactly a dividend payment, but it's a similar process.:
Your contract keeps a history of each account as it goes, so that it can tell how much money it had at each date or block. Again, this is costly to do in storage, but you can make it somewhat cheaper with a hashed data structure: Each account starts with a hash of zero, then when they make a transaction, a record is created for the change, and hashed, together with the previous hash, and the resulting change is saved back over the last one. The user can then send data to replay this chain, and prove how much money they had at the dividend payment date. This allows you to apply dividends whenever you like, including based on dividend dates in the past. But you have to design it carefully to avoid situations where money becomes unclaimable because of gas costs. See this code for an example; It's not exactly a dividend payment, but it's a similar process.
Your contract knows the dividend date in advance, so it applies the dividend when you subsequently move funds, and records the fact that it has done it so that it won't do so again. So the contract knows that there is a dividend payable from future date X, and that it should be say 1% of holdings. As of the dividend date X, consider accounts are marked something like Dividend X paid: "0xdeadbeef => false"
. Then when the 0xdeadbeef
account next tries to withdraw funds, their balance will be credited with the dividend, and it marked true
. You also need to do something when receiving funds - for example, apply the dividend on the previous balance of the receiver, then mark the receiver record paid as well. The disadvantage with this is that it applies a gas cost on normal sends and receives, even once the dividend has been paid, and that cost grows if you have more dividends. You might want to put a deadline on how soon you have to collect the dividend before the contract considers it unclaimed and stops crediting it.