|
|
@ -24,16 +24,19 @@ class Storage: |
|
|
|
:param concrete: bool indicating whether to interpret uninitialized storage as concrete versus symbolic |
|
|
|
:param concrete: bool indicating whether to interpret uninitialized storage as concrete versus symbolic |
|
|
|
""" |
|
|
|
""" |
|
|
|
if concrete and args.unconstrained_storage is False: |
|
|
|
if concrete and args.unconstrained_storage is False: |
|
|
|
self._standard_storage = K(256, 256, 0) # type: BaseArray |
|
|
|
self._standard_storage: BaseArray = K(256, 256, 0) |
|
|
|
else: |
|
|
|
else: |
|
|
|
self._standard_storage = Array(f"Storage{address}", 256, 256) |
|
|
|
self._standard_storage = Array(f"Storage{address}", 256, 256) |
|
|
|
|
|
|
|
|
|
|
|
self.printable_storage = {} # type: Dict[BitVec, BitVec] |
|
|
|
self.printable_storage: Dict[BitVec, BitVec] = {} |
|
|
|
|
|
|
|
|
|
|
|
self.dynld = dynamic_loader |
|
|
|
self.dynld = dynamic_loader |
|
|
|
self.storage_keys_loaded = set() # type: Set[int] |
|
|
|
self.storage_keys_loaded: Set[int] = set() |
|
|
|
self.address = address |
|
|
|
self.address = address |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Stores all keys set in the storage |
|
|
|
|
|
|
|
self.keys_set: Set[BitVec] = set() |
|
|
|
|
|
|
|
|
|
|
|
def __getitem__(self, item: BitVec) -> BitVec: |
|
|
|
def __getitem__(self, item: BitVec) -> BitVec: |
|
|
|
storage = self._standard_storage |
|
|
|
storage = self._standard_storage |
|
|
|
if ( |
|
|
|
if ( |
|
|
@ -45,7 +48,7 @@ class Storage: |
|
|
|
and args.unconstrained_storage is False |
|
|
|
and args.unconstrained_storage is False |
|
|
|
): |
|
|
|
): |
|
|
|
try: |
|
|
|
try: |
|
|
|
storage[item] = symbol_factory.BitVecVal( |
|
|
|
value = symbol_factory.BitVecVal( |
|
|
|
int( |
|
|
|
int( |
|
|
|
self.dynld.read_storage( |
|
|
|
self.dynld.read_storage( |
|
|
|
contract_address="0x{:040X}".format(self.address.value), |
|
|
|
contract_address="0x{:040X}".format(self.address.value), |
|
|
@ -55,10 +58,16 @@ class Storage: |
|
|
|
), |
|
|
|
), |
|
|
|
256, |
|
|
|
256, |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for key in self.keys_set: |
|
|
|
|
|
|
|
value = If(key == item, storage[item], value) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
storage[item] = value |
|
|
|
self.storage_keys_loaded.add(int(item.value)) |
|
|
|
self.storage_keys_loaded.add(int(item.value)) |
|
|
|
self.printable_storage[item] = storage[item] |
|
|
|
self.printable_storage[item] = storage[item] |
|
|
|
except ValueError as e: |
|
|
|
except ValueError as e: |
|
|
|
log.debug("Couldn't read storage at %s: %s", item, e) |
|
|
|
log.debug("Couldn't read storage at %s: %s", item, e) |
|
|
|
|
|
|
|
|
|
|
|
return simplify(storage[item]) |
|
|
|
return simplify(storage[item]) |
|
|
|
|
|
|
|
|
|
|
|
def __setitem__(self, key, value: Any) -> None: |
|
|
|
def __setitem__(self, key, value: Any) -> None: |
|
|
@ -67,6 +76,9 @@ class Storage: |
|
|
|
|
|
|
|
|
|
|
|
self.printable_storage[key] = value |
|
|
|
self.printable_storage[key] = value |
|
|
|
self._standard_storage[key] = value |
|
|
|
self._standard_storage[key] = value |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.keys_set.add(key) |
|
|
|
|
|
|
|
|
|
|
|
if key.symbolic is False: |
|
|
|
if key.symbolic is False: |
|
|
|
self.storage_keys_loaded.add(int(key.value)) |
|
|
|
self.storage_keys_loaded.add(int(key.value)) |
|
|
|
|
|
|
|
|
|
|
@ -78,6 +90,7 @@ class Storage: |
|
|
|
storage._standard_storage = deepcopy(self._standard_storage) |
|
|
|
storage._standard_storage = deepcopy(self._standard_storage) |
|
|
|
storage.printable_storage = copy(self.printable_storage) |
|
|
|
storage.printable_storage = copy(self.printable_storage) |
|
|
|
storage.storage_keys_loaded = copy(self.storage_keys_loaded) |
|
|
|
storage.storage_keys_loaded = copy(self.storage_keys_loaded) |
|
|
|
|
|
|
|
storage.keys_set = copy(self.keys_set) |
|
|
|
return storage |
|
|
|
return storage |
|
|
|
|
|
|
|
|
|
|
|
def __str__(self) -> str: |
|
|
|
def __str__(self) -> str: |
|
|
|