Fix get_slot_values + minor improvements

pull/1311/head
Josselin Feist 2 years ago
parent e917a8fd90
commit c57acfdde7
  1. 56
      slither/tools/read_storage/read_storage.py

@ -4,12 +4,6 @@ from math import floor
from os import environ from os import environ
from typing import Callable, Optional, Tuple, Union, List, Dict from typing import Callable, Optional, Tuple, Union, List, Dict
try:
from typing import TypedDict
except ImportError:
# < Python 3.8
from typing_extensions import TypedDict
try: try:
from web3 import Web3 from web3 import Web3
from eth_typing.evm import ChecksumAddress from eth_typing.evm import ChecksumAddress
@ -130,6 +124,8 @@ class SlitherReadStorage:
self._slot_info = tmp self._slot_info = tmp
# TODO: remove this pylint exception (montyly)
# pylint: disable=too-many-locals
def get_storage_slot( def get_storage_slot(
self, self,
target_variable: StateVariable, target_variable: StateVariable,
@ -226,24 +222,18 @@ class SlitherReadStorage:
var, contract, **kwargs var, contract, **kwargs
) )
def get_slot_values(self) -> Dict[str, SlotInfo]: def get_slot_values(self) -> None:
""" """
Fetches the slot values and inserts them in slot info dictionary. Fetches the slot values
Returns:
(`SlotInfo`): The dictionary of slot info.
""" """
stack = list(self.slot_info.items()) for slot_info in self.slot_info.values():
while stack: hex_bytes = get_storage_data(
_, v = stack.pop() self.web3, self.checksum_address, int.to_bytes(slot_info.slot, 32, byteorder="big")
if isinstance(v, dict): )
stack.extend(v.items()) slot_info.value = self.convert_value_to_type(
if "slot" in v: hex_bytes, slot_info.size, slot_info.offset, slot_info.type_string
hex_bytes = get_storage_data(self.web3, self.checksum_address, v["slot"]) )
v["value"] = self.convert_value_to_type( logger.info(f"\nValue: {slot_info.value}\n")
hex_bytes, v["size"], v["offset"], v["type_string"]
)
logger.info(f"\nValue: {v['value']}\n")
return self.slot_info
def get_all_storage_variables(self, func: Callable = None) -> None: def get_all_storage_variables(self, func: Callable = None) -> None:
"""Fetches all storage variables from a list of contracts. """Fetches all storage variables from a list of contracts.
@ -359,16 +349,13 @@ class SlitherReadStorage:
type_string = item.type_string type_string = item.type_string
struct_var = item.struct_var struct_var = item.struct_var
# doesn't handle deep keys currently
var_name_struct_or_array_var = f"{var} -> {struct_var}"
tabulate_data.append( tabulate_data.append(
[ [
slot, slot,
offset, offset,
size, size,
type_string, type_string,
var_name_struct_or_array_var, f"{var} -> {struct_var}", # doesn't handle deep keys currently
self.convert_value_to_type( self.convert_value_to_type(
get_storage_data( get_storage_data(
self.web3, self.web3,
@ -392,9 +379,6 @@ class SlitherReadStorage:
type_string = item.type_string type_string = item.type_string
struct_var = item.struct_var struct_var = item.struct_var
# doesn't handle deep keys currently
var_name_struct_or_array_var = f"{var}[{item_key}] -> {struct_var}"
hex_bytes = get_storage_data( hex_bytes = 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")
) )
@ -404,7 +388,7 @@ class SlitherReadStorage:
offset, offset,
size, size,
type_string, type_string,
var_name_struct_or_array_var, f"{var}[{item_key}] -> {struct_var}", # doesn't handle deep keys currently
self.convert_value_to_type(hex_bytes, size, offset, type_string), self.convert_value_to_type(hex_bytes, size, offset, type_string),
] ]
) )
@ -588,8 +572,8 @@ class SlitherReadStorage:
key = coerce_type(key_type, key) key = coerce_type(key_type, key)
slot = keccak(encode_abi([key_type, "uint256"], [key, decode_single("uint256", slot)])) slot = keccak(encode_abi([key_type, "uint256"], [key, decode_single("uint256", slot)]))
if isinstance(target_variable.type.type_to, UserDefinedType) and is_struct( if isinstance(target_variable.type.type_to, UserDefinedType) and isinstance(
target_variable.type.type_to.type target_variable.type.type_to.type, Structure
): # mapping(elem => struct) ): # mapping(elem => struct)
assert struct_var assert struct_var
elems = target_variable.type.type_to.type.elems_ordered elems = target_variable.type.type_to.type.elems_ordered
@ -615,8 +599,8 @@ class SlitherReadStorage:
size = byte_size * 8 # bits size = byte_size * 8 # bits
offset = 0 offset = 0
if isinstance(target_variable.type.type_to.type_to, UserDefinedType) and is_struct( if isinstance(target_variable.type.type_to.type_to, UserDefinedType) and isinstance(
target_variable.type.type_to.type_to.type target_variable.type.type_to.type_to.type, Structure
): # mapping(elem => mapping(elem => struct)) ): # mapping(elem => mapping(elem => struct))
assert struct_var assert struct_var
elems = target_variable.type.type_to.type_to.type.elems_ordered elems = target_variable.type.type_to.type_to.type.elems_ordered
@ -696,7 +680,7 @@ class SlitherReadStorage:
for i in range(min(array_length, self.max_depth)): for i in range(min(array_length, self.max_depth)):
# TODO: figure out why _all_struct_slots returns a Dict[str, SlotInfo] # TODO: figure out why _all_struct_slots returns a Dict[str, SlotInfo]
# but this expect a SlotInfo (montyly) # but this expect a SlotInfo (montyly)
elems[i] = self._all_struct_slots(var, st, key=str(i)) elems[i] = self._all_struct_slots(var, st, contract, key=str(i))
continue continue
else: else:
@ -710,7 +694,7 @@ class SlitherReadStorage:
elems[i] = info elems[i] = info
if isinstance(type_.type, ArrayType): # multidimensional array if isinstance(type_.type, ArrayType): # multidimensional array
array_length = self._get_array_length(type_.type, info["slot"]) array_length = self._get_array_length(type_.type, info.slot)
elems[i].elems = {} elems[i].elems = {}
for j in range(min(array_length, self.max_depth)): for j in range(min(array_length, self.max_depth)):

Loading…
Cancel
Save