Solidity Storage Mapping – Access Through Assembler

assemblysoliditysolidity-0.5.x

referencing the question How to get access to the storage array through the solidity assembler? I have been trying to figure out how to access the mapping (or variable y from the question). The documentation has an example, but of course it has to be overly complicated and access a 2d mapping. However it does say that to get the value of a key (k) of a mapping you hash k . p and load this slot. Does this mean to get the mapping from the similarly asked question you would do:

contract Foo {
  uint internal x; // Storage slot #0
  mapping (uint => address) internal y; // Storage slot #1
  uint [] internal z; // Storage slot #2

  function zElement (uint key) public view returns (uint r) {
    assembly {
      sload(keccak256(add(key, y_slot), 32))
    }
  }
}

EDIT: fixed the link to go to the correctly mentioned question.
EDIT2: should compile now i think.

Best Answer

Solution

function getStorageValue(uint num, uint slot) public view returns (address result) {
    assembly {
        // Store num in memory scratch space (note: lookup "free memory pointer" if you need to allocate space)
        mstore(0, num)
        // Store slot number in scratch space after num
        mstore(32, slot)
        // Create hash from previously stored num and slot
        let hash := keccak256(0, 64)
        // Load mapping value using the just calculated hash
        result := sload(hash)
    } 
}

Explanation

To obtain the address stored behind a uint to address mapping, you have to obtain the storage key and subsequently load the data stored in that position by using sload. To do so you have to hash 64 bytes using keccak256. Those 64 bytes are composed of 32 bytes of the uint you want to use as a key concatenated to 32 bytes of the storage slot. The low-level keccak256 call takes a memory address and a number of bytes as arguments, therefore those values have to be stored cohesive in memory before by using mstore. The storage slot is determined by the position in which the storage variable is declared in comparison to other storage variables, starting from 0.