Solidity – Using an Array of Addresses in Contract Development with Remix

contract-designcontract-developmentremixsolidity

I have an array of addresses and a function which returns how many times an address is in the array. For example, if the array has ['0x00', '0x01', '0x00'] the function will return 2 for 0x00 and 1 for 0x01

I would like to know if my approach is efficient enough to work with a large number of addresses

address[] public users;
function userCounter(address user) public view returns(uint){
        uint counter;
        for(uint i; i<users.length; i++){
            if(users[i] == user){
                counter++;
            }
        }
        return counter;
    } 

Any idea how I could improve it? Currently it takes a while to iterate over 300 elements so I imagine how bad it's going to be for a larger number.

Best Answer

You might be interested in using two storage structures for your scenario.

A mapping which can hold the key + value of address + count, and an array which holds the unique list of addresses which can be iterated on.

You mention a payable function which creates the original list of users through a payment. Here is an example of how that could be written to support these types:

pragma solidity ^0.4.24;

contract example {
    address[] public users;
    mapping (address => uint) public count;

    function donate() public payable{
        require(msg.value == .002 ether);
        if (count[msg.sender] == 0) {
            users.push(msg.sender);
        }

        count[msg.sender] += 1;

    }
}

In this case, whenever a brand new user donates .002 ETH, they get added to the users array. Otherwise, we simply increment on the mapping which tracks the count of donations per user.

Then your userCounter function simply becomes a read on the count mapping:

function userCounter(address user) public view returns(uint) {
    return count[user];
}
Related Topic