Skip to content

Instantly share code, notes, and snippets.

@riordant
Last active March 22, 2022 07:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save riordant/361412888ebc7c888c50c294425d1aea to your computer and use it in GitHub Desktop.
Save riordant/361412888ebc7c888c50c294425d1aea to your computer and use it in GitHub Desktop.
Retrieve the storage slot value of a (mapping => Struct) -> (mapping => uint) in Solidity.
/*
architecture is like so:
Struct struct {
...
mapping(address => uint) map;
...
}
contract X {
...
mapping(address => struct) structs;
...
}
ie. base_slot corresponds to storage position in contract X, inner_slot corresponds to storage position in Struct struct.
Rationale: this is useful to get slots where there is no getters available for this kind of (complex) setup.
*/
export async function getInnerStructMapping(contract: string, address: string, base_slot: number, inner_slot: number): Promise<BigNumber> {
// first get the start slot of the struct for the address parameter
const struct_slot = ethers.utils.keccak256( ethers.utils.defaultAbiCoder.encode(['address', 'uint'],[address, base_slot]))
// then, get the start slot of the 'map' mapping
const struct_base_slot = ethers.BigNumber.from(struct_slot).add(inner_slot).toHexString()
// Finally, get the slot of the address => uint mapping
const maps_slot = ethers.utils.keccak256( ethers.utils.defaultAbiCoder.encode(['address', 'uint'],[address, struct_base_slot]))
// get the storage slot value and parse as a BigNumber
const result = ethers.BigNumber.from(await ethers.provider.getStorageAt(contract, maps_slot));
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment