Last active
March 22, 2022 07:03
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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