All answers are helpful but can be improved upon in context of space:
In both Ismael and Alex's answers, each address is stored three times - in the mapping containing the indices, in the balances mapping and in the array containing all addresses. A better way is:
Since the contract already has a mapping of balances (presumably for an ERC20), modify it to store a mapping of a struct:
Struct account {
uint balance;
bool doesItExistInArray
}
mapping (address => account) public balances
And then in your transfer
or transferFrom
function or anywhere you update balance presumably an internal function called _transfer
:
function _transfer(address _from, address _to, uint value) internal {
//do some error checking and balance checking.
....
//updating balance:
balances[_from].balance -= value;
balances[_to].balance += value;
if(!balances[_from].doesItExistInArray) {
allAccounts.push(_from);
balances[_from].doesItExistInArray = true;
}
//same for _to address
}
Haven't tested the code so may not be syntactically correct, but you get the logic. Here each address is only stored twice!