My contract currently serves an array of addresses to a front-end:
address[] public addresses;
function getAddresses() public view returns (address[]) {
return addresses;
}
I'm concerned about scalability. Is there any limit to the length of an array of addresses that can be returned? Would it be better to store all addresses in a mapping, with a counter?
mapping public (uint => address) addressMap;
uint public addressCounter;
This seems like it would be more scalable, but would require the front-end to make many more calls to the contract, which then uses each address to make yet another call.
Best Answer
There are trade-offs between the different types of indexed storage and many of us find that we need to use a combination of the options to accomplish all a given contract's goals.
There is a scalability problem with passing the whole list in one move. There's no need to do that when the client possibly already has most of the list. In any case, you'll find scale is achieved when all operations are arranged as fixed-cost functions.
Even though your example is simple, I'll show you how to accomplish the most common long-term storage needs (long-term, because one doesn't normally get to amend the contract later).
Iterable list, like your example, but return them individually:
You might (very likely) find it handy to know (without iteration) if an address is somewhere in
addresses[]
to avoid issues like appending the same address twice. You want the contract to catch an errant client request, so it needs a way to do that at scale (no iteration). Mappings can help. In addition to the array:That accomodates something like:
You can get a little fancier with a pattern that will accomodate additional properties about the addresses (as many properties as you need):
You can make the contract state completely discoverable:
You can (should) emit events as changes happen:
By emitting the event, you give clients that are already synced a way to simply take note of new addresses as they arrive. It also means it is theoretically possible to reconstruct the entire state history of the contract when done properly.
The idea of using both mapping and array increases the insertion gas cost but it addresses the tradeoffs of using one or the other exclusively. Various structures and tradeoffs are described over here: Are there well-solved and simple storage patterns for Solidity?
Hope it helps.