This document presents an initial proposal of extra metadata that solc should emit for tools to be able to track all the mapping keys accessed by a transaction/call.

This document assumes basic knowledge about how mapping keys work in Solidity.

Metadata description

The minimal amount of information needed is a way to identify which of the sha3 instructions in the different bytecodes are used for computing mapping keys. For example, this could take the form of a list of program counters.

In order to future-proof this, giving Solidity more flexibility to change these values in the future, the compiler could also emit:

How to use it

This metadata can be used to track all the mapping keys that have been accessed in a single contract execution, without any historic information. Having the trace of the contract call, access to the storage and memory during each of its steps, and the compiler's output is enough.

To track the mapping keys of a contract execution, tools should analyze its trace, and identify which sha3 instructions have been tagged as part of mapping keys computation. Once identified, the preimage of the hash should be split into slot and key. The slot can be used to identify which mapping it belongs to, and with that information, get the type of the key and decode it.

In order to help identify the mapping of the slot solidity already provides a contract's storage layout. The slot can either:

  1. Be part of the base storage layout of the contract as a mapping, which can be easily identified by traversing it**.**
  2. Be a member of a struct in the base storage layout of the contract, which can be easily identified by traversing it accounting for the offset of the member.
  3. Be a member of an array in the base storage layout of the contract, which can be easily identified by traversing it checking if the slot is part of the range, for both dynamic and fixed-size arrays.
  4. Be a result of a previous mapping slot + key (for nested mappings) which can be tracked since in order to access the slot, some key computation must have been done before, which can be tracked by the debugging symbols.
  5. Be some recursive combination of the previous options. An extensive list of all possible mapping slots and their types can be done by simply traversing the storage layout making sure to recursively traverse if the containing type is a complex structure (like an array of structs, structs with mappings, mapping of structs, etc).