3

Is it possible to get a list of token holders for a given ERC20 token from within another solidity contract?

Since "balances" are stored in a mapping in most ERC20 contracts, I do not think it is possible, since you can't get a list of keys for a mapping in solidity.

Is there anything I missed? Or is this just impossible?

Thanks!

Shane Fontaine
  • 2,431
  • 3
  • 13
  • 23
user1558646
  • 145
  • 4
  • 9

2 Answers2

7

It is not possible to get a list of ERC20 token holders directly from a contract.

You are correct in that you cannot do this because you cannot get a list of keys for a mapping in Solidity, therefore it is impossible without external intervention.

With that said, there are many people who need this functionality and perform tasks to achieve this. The biggest example I can think of is airdropping tokens to various accounts based on their holdings of another token. The way that most people do this is to read all of the token holders from the blockchain and store it in a local database. From there, they will implement a gas-efficient function that takes in the addresses as a parameter and performs actions on them that way.

It is not possible to accomplish what you desire using only the blockchain, but using a combination of on-chain/off-chain logic can achieve your goals.

Shane Fontaine
  • 2,431
  • 3
  • 13
  • 23
  • Thanks Shane! Unfortunately an off chain solution wont work because I need to do this trustlessly. Oh well! – user1558646 Oct 03 '18 at 03:09
  • What if the token is one of those like Safemoon that taxates sell transactions and distributes an amount to token holders - if the Safemoon contract can traverse the list of accounts, perhaps one can also do it from another contract? (Asking as a complete beginner) – Hervian Jun 16 '21 at 13:15
0

It maybe possible. If you make a function that can pick sender and receiver when transfer function is called, it's possible.

mapping(address => bool) _holderList;

function transferFrom(address from, address to, uint256 amount) {
    checkHolderList(from);
    checkHolderList(to);
    _transfer(from, to, amount);
}

function checkHolderList(address _address) {
    require(balanceOf(_address) > 0, "this address can't be holder");
    require(_holderList[address] != true, "this address is already in holder list");
    _holderList[_address] = true;
}
LEON
  • 1
  • 1