Get Keys of Solidity mapping

Viewed 9088

I was trying to get keys of a mapping to star name and address of particular contract (not exactly) in solidity contract

mapping(string=>address) nameOfAccounts;

What i am expecting is a method like the Object.keys(nameOfAccounts) in Javascript. Is there any similar method ?. or should i use an additional array. The additional Array may cause extra gas cost(This is not an option that i prefer). Please share some insights

I wanted to know if there is another method that i can do if getting keys is not an option?

3 Answers

Short answer: If the contract doesn't provide the list of map's object keys, you can't get it.

Long answer:

But since the blockchain is a public thing , you can get anything. To get all keys of the map, you would need to do this:

  • Setup archival node and enable tracing (you will need 9 terabytes disk, with SSD caching)
  • Get the traces of all the calls to your contract and search for SSTORE opcode (instruction)
  • The SSTORE instruction pops 2 parameters from the stack, Loc (location) and Val (Value) . The location is the key you are looking for.

If you don't have a budget for archival node, you can try Etherscan's API

There are answers on SO on how to read storage of a contract, might be useful.

There is another option, decompile the contract, and check its input, the input will have the key, then scan all transactions for that contract, and extract the keys by processing the input (the input is the tx.Data() field). This option is easier if you have the some knowledge about the contract, or if you have the sources, that's will be the easiest thing (process the Input)

There is also a function in StateDB object type called ForEachStorage(). It doesn't have a front-end from the RPC api, but with a little bit of effort you could implement your own RPC function to access it and put it on a Full node. This function accepts the address of the contract and a closure function , and it will iterate through the storage of the entire contract. Source: https://github.com/ethereum/go-ethereum/blob/0a3993c558616868e35f9730e92c704ac16ee437/core/state/statedb.go#L634 The only thing you would have to know is how the keys are built, and this can be only known from contract source.

The best way to iterate over the keys is that when a key is added you also emit a Solidity event.

You get keys from the event logs. This can be done client-side (JavaScript, Python) but not within Solidity itself, as EVM does not have access to event data.

Solidity/EVM does not store iterable keys due to efficiency reasons in execution constrained environment.

More information here.

Well, the easiest way to get the keys for your mapping variable, you can use the tool SmartMuv. This tool provides the list of mapping keys with their values and you can use it anyway.

Related