I have a function that needs to send tokens to a lot of accounts. I know that a write operation into a store is very costly. I have read when doing computing on storage it's better to do it on a memory variable and then set this memory variable into the storage and by that save the write operation on storage.
so what I was thinking to do is something like this
mapping (address => uint256) private _balances;
function addToBalance(address[] memory accounts,uint[] memory amounts) public{
mapping (address => uint256) memory balances = _balances;
for(uint i=0;i<accounts.length;i++){
balances[accounts[i]]+=amounts[i];
}
_balances = balances;
}
the _balances mapping can become pretty big. so is it really a better way to reduce the costs?
Not with a mapping.
Mapping (and dynamic-size array) values are all "scattered" in different storage slots. The slot positions are determinable, but because they are calculated based on a hash, the value for key 1
can be in storage slot 123456789
and the value for key 2
can be in storage slot 5
. (The numbers are made up just to show an easy example.)
Which means, when you're saving N
values into a mapping (under N
keys), you always need to write into (the same amount) N
storage slots. Writing into one (256bit) slot costs 5,000 gas, and it can add up quickly.
So apart from moving the values into a fixed-size array (which doesn't make much sense in this use case when you're storing balances of an unknown amount of addresses), I'd consider shifting the transaction costs to your users (have a list of eligible users and another list of already used airdrops and let them claim it themselves).