In a contract (only a demo) I have:
struct Bank {
string name;
mapping(address => uint) balances;
}
mapping(address => uint) userIsAtBank;
Bank[] banks;
Now I would like to have a function that copies the mapping userIsAtBank/ the array banks without going through it (like all values in one return) and sets a new mapping with the same values. In my example: userIsAtBankNew = userIsAtBank – and: banksNew = banks. Is that possible?
If it's not possible, what's the best way to go through a length of 25.000 (if for example the latest bank is banks[25000]) without the transaction getting rejected or is too expensive?
Best Answer
You're on the right track as you turn your thinking to increasing cost.
You may be able to move the limit slightly with efficiencies, but the only way to solve the problem is to reconsider the approach so each transaction completes in O(1) ... one operation.
The suggested approach is not very blockchain. Suppose client, Alice, fetches the list of 25,000 banks. Why would she fetch it again? If she is listening to event logs, then she will know about bank number 25,001 when it is added. Why would she need to ask?
You can use a two-pronged approach.
Have a look at Mapped Struct with Index over here: Are there well-solved and simple storage patterns for Solidity?
The data structure starts out exactly per your pattern. What follow are functions to deal with single instances at a time. Explained with the rationale and more complete example over here: https://medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a
Hope it helps.
p.s. I should mention it's not possible to enumerate or count the keys in a
mapping
or pass mappings around in one gulp. You can do so with dynamic arrays but it is not completely supported and it doesn't work between contracts. One-row-at-a-time avoids the limitations and scaling issues.