From 531b75572f9b9943bc574f2fbe9a540c91c403d2 Mon Sep 17 00:00:00 2001 From: bohendo Date: Mon, 26 Sep 2022 15:58:46 -0400 Subject: [PATCH 1/5] add block arg to slither-read-storage --- slither/tools/read_storage/README.md | 1 + slither/tools/read_storage/__main__.py | 12 ++++++++++++ slither/tools/read_storage/read_storage.py | 4 ++-- slither/tools/read_storage/utils/utils.py | 5 +++-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/slither/tools/read_storage/README.md b/slither/tools/read_storage/README.md index 91491a364..f8d4cc466 100644 --- a/slither/tools/read_storage/README.md +++ b/slither/tools/read_storage/README.md @@ -21,6 +21,7 @@ optional arguments: --layout Toggle used to write a JSON file with the entire storage layout. --value Toggle used to include values in output. --max-depth MAX_DEPTH Max depth to search in data structure. + --block BLOCK_NUMBER Block number to retrieve storage from (requires archive rpc node) ``` ### Examples diff --git a/slither/tools/read_storage/__main__.py b/slither/tools/read_storage/__main__.py index f3cc90efc..b10a74a1e 100644 --- a/slither/tools/read_storage/__main__.py +++ b/slither/tools/read_storage/__main__.py @@ -98,6 +98,12 @@ def parse_args() -> argparse.Namespace: parser.add_argument("--max-depth", help="Max depth to search in data structure.", default=20) + parser.add_argument( + "--block", + help="The block number to read storage from. Requires an archive node to be provided as the RPC url.", + default="latest", + ) + cryticparser.init(parser) return parser.parse_args() @@ -122,6 +128,12 @@ def main() -> None: srs = SlitherReadStorage(contracts, args.max_depth) + if args.block: + try: + srs.block = int(args.block) + except ValueError: + srs.block = str(args.block) + if args.rpc_url: # Remove target prefix e.g. rinkeby:0x0 -> 0x0. address = target[target.find(":") + 1 :] diff --git a/slither/tools/read_storage/read_storage.py b/slither/tools/read_storage/read_storage.py index c9523f733..e7ace41fb 100644 --- a/slither/tools/read_storage/read_storage.py +++ b/slither/tools/read_storage/read_storage.py @@ -231,7 +231,7 @@ class SlitherReadStorage: :param slot_info: """ hex_bytes = get_storage_data( - self.web3, self.checksum_address, int.to_bytes(slot_info.slot, 32, byteorder="big") + self.web3, self.checksum_address, int.to_bytes(slot_info.slot, 32, byteorder="big"), self.block ) slot_info.value = self.convert_value_to_type( hex_bytes, slot_info.size, slot_info.offset, slot_info.type_string @@ -609,7 +609,7 @@ class SlitherReadStorage: # Convert from hexadecimal to decimal. val = int( get_storage_data( - self.web3, self.checksum_address, int.to_bytes(slot, 32, byteorder="big") + self.web3, self.checksum_address, int.to_bytes(slot, 32, byteorder="big"), self.block ).hex(), 16, ) diff --git a/slither/tools/read_storage/utils/utils.py b/slither/tools/read_storage/utils/utils.py index db2052286..bb354eea4 100644 --- a/slither/tools/read_storage/utils/utils.py +++ b/slither/tools/read_storage/utils/utils.py @@ -55,16 +55,17 @@ def coerce_type( return value.hex() -def get_storage_data(web3, checksum_address: ChecksumAddress, slot: bytes) -> bytes: +def get_storage_data(web3, checksum_address: ChecksumAddress, slot: bytes, block: Union[int, str]) -> bytes: """ Retrieves the storage data from the blockchain at target address and slot. Args: web3: Web3 instance provider. checksum_address (ChecksumAddress): The address to query. slot (bytes): The slot to retrieve data from. + block (optional int|str): The block number to retrieve data from Returns: (HexBytes): The slot's storage data. """ - return bytes(web3.eth.get_storage_at(checksum_address, slot)).rjust( + return bytes(web3.eth.get_storage_at(checksum_address, slot, block)).rjust( 32, bytes(1) ) # pad to 32 bytes From d7396ec62e22d3d501e8d81aeab64d13668d9343 Mon Sep 17 00:00:00 2001 From: bohendo Date: Mon, 26 Sep 2022 17:39:59 -0400 Subject: [PATCH 2/5] run black code reformatter --- slither/tools/read_storage/read_storage.py | 10 ++++++++-- slither/tools/read_storage/utils/utils.py | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/slither/tools/read_storage/read_storage.py b/slither/tools/read_storage/read_storage.py index e7ace41fb..f71719c9c 100644 --- a/slither/tools/read_storage/read_storage.py +++ b/slither/tools/read_storage/read_storage.py @@ -231,7 +231,10 @@ class SlitherReadStorage: :param slot_info: """ hex_bytes = get_storage_data( - self.web3, self.checksum_address, int.to_bytes(slot_info.slot, 32, byteorder="big"), self.block + self.web3, + self.checksum_address, + int.to_bytes(slot_info.slot, 32, byteorder="big"), + self.block, ) slot_info.value = self.convert_value_to_type( hex_bytes, slot_info.size, slot_info.offset, slot_info.type_string @@ -609,7 +612,10 @@ class SlitherReadStorage: # Convert from hexadecimal to decimal. val = int( get_storage_data( - self.web3, self.checksum_address, int.to_bytes(slot, 32, byteorder="big"), self.block + self.web3, + self.checksum_address, + int.to_bytes(slot, 32, byteorder="big"), + self.block, ).hex(), 16, ) diff --git a/slither/tools/read_storage/utils/utils.py b/slither/tools/read_storage/utils/utils.py index bb354eea4..3e51e2181 100644 --- a/slither/tools/read_storage/utils/utils.py +++ b/slither/tools/read_storage/utils/utils.py @@ -55,7 +55,9 @@ def coerce_type( return value.hex() -def get_storage_data(web3, checksum_address: ChecksumAddress, slot: bytes, block: Union[int, str]) -> bytes: +def get_storage_data( + web3, checksum_address: ChecksumAddress, slot: bytes, block: Union[int, str] +) -> bytes: """ Retrieves the storage data from the blockchain at target address and slot. Args: From f0c87149f710ed80674e2b5136bb7f6657264054 Mon Sep 17 00:00:00 2001 From: bohendo Date: Mon, 26 Sep 2022 17:51:50 -0400 Subject: [PATCH 3/5] fix test --- .gitignore | 1 + tests/test_read_storage.py | 1 + 2 files changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index fe1019a11..2234f5618 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ coverage.xml *.cover .hypothesis/ .vscode/ +storage_layout.json # Translations *.mo *.pot diff --git a/tests/test_read_storage.py b/tests/test_read_storage.py index 67a89dae8..61ebc0653 100644 --- a/tests/test_read_storage.py +++ b/tests/test_read_storage.py @@ -112,6 +112,7 @@ def test_read_storage(web3, ganache) -> None: srs = SlitherReadStorage(contracts, 100) srs.rpc = ganache.provider + srs.block = "latest" srs.storage_address = address srs.get_all_storage_variables() srs.get_storage_layout() From b5e6ebbc36c3c5e62168211ec2e96f1c709eeab1 Mon Sep 17 00:00:00 2001 From: bohendo Date: Mon, 3 Oct 2022 12:24:39 -0400 Subject: [PATCH 4/5] add block member to srs class --- slither/tools/read_storage/read_storage.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/slither/tools/read_storage/read_storage.py b/slither/tools/read_storage/read_storage.py index f71719c9c..fd881c05e 100644 --- a/slither/tools/read_storage/read_storage.py +++ b/slither/tools/read_storage/read_storage.py @@ -53,15 +53,16 @@ class SlitherReadStorageException(Exception): # pylint: disable=too-many-instance-attributes class SlitherReadStorage: def __init__(self, contracts: List[Contract], max_depth: int) -> None: + self._checksum_address: Optional[ChecksumAddress] = None self._contracts: List[Contract] = contracts - self._max_depth: int = max_depth self._log: str = "" + self._max_depth: int = max_depth self._slot_info: Dict[str, SlotInfo] = {} self._target_variables: List[Tuple[Contract, StateVariable]] = [] self._web3: Optional[Web3] = None - self._checksum_address: Optional[ChecksumAddress] = None - self.storage_address: Optional[str] = None + self.block: Union[str, int] = "latest" self.rpc: Optional[str] = None + self.storage_address: Optional[str] = None self.table: Optional[MyPrettyTable] = None @property From 2b9f192b39a8327ec7d3131ee56f48e6547c26bf Mon Sep 17 00:00:00 2001 From: bohendo Date: Mon, 3 Oct 2022 12:33:42 -0400 Subject: [PATCH 5/5] fix lint warnings --- slither/tools/read_storage/__main__.py | 9 ++++----- tests/test_read_storage.py | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/slither/tools/read_storage/__main__.py b/slither/tools/read_storage/__main__.py index 88c381ac7..1a8901321 100644 --- a/slither/tools/read_storage/__main__.py +++ b/slither/tools/read_storage/__main__.py @@ -128,11 +128,10 @@ def main() -> None: srs = SlitherReadStorage(contracts, args.max_depth) - if args.block: - try: - srs.block = int(args.block) - except ValueError: - srs.block = str(args.block) + try: + srs.block = int(args.block) + except ValueError: + srs.block = str(args.block or "latest") if args.rpc_url: # Remove target prefix e.g. rinkeby:0x0 -> 0x0. diff --git a/tests/test_read_storage.py b/tests/test_read_storage.py index 61ebc0653..67a89dae8 100644 --- a/tests/test_read_storage.py +++ b/tests/test_read_storage.py @@ -112,7 +112,6 @@ def test_read_storage(web3, ganache) -> None: srs = SlitherReadStorage(contracts, 100) srs.rpc = ganache.provider - srs.block = "latest" srs.storage_address = address srs.get_all_storage_variables() srs.get_storage_layout()