|
|
|
@ -18,13 +18,11 @@ from mythril.laser.smt import ( |
|
|
|
|
ULT, |
|
|
|
|
UGT, |
|
|
|
|
BitVec, |
|
|
|
|
is_true, |
|
|
|
|
is_false, |
|
|
|
|
URem, |
|
|
|
|
SRem, |
|
|
|
|
If, |
|
|
|
|
Bool, |
|
|
|
|
Or, |
|
|
|
|
Not, |
|
|
|
|
LShR, |
|
|
|
|
) |
|
|
|
@ -41,7 +39,6 @@ from mythril.laser.ethereum.evm_exceptions import ( |
|
|
|
|
OutOfGasException, |
|
|
|
|
) |
|
|
|
|
from mythril.laser.ethereum.gas import OPCODE_GAS |
|
|
|
|
from mythril.laser.ethereum.keccak import KeccakFunctionManager |
|
|
|
|
from mythril.laser.ethereum.state.global_state import GlobalState |
|
|
|
|
from mythril.laser.ethereum.transaction import ( |
|
|
|
|
MessageCallTransaction, |
|
|
|
@ -56,8 +53,6 @@ log = logging.getLogger(__name__) |
|
|
|
|
TT256 = 2 ** 256 |
|
|
|
|
TT256M1 = 2 ** 256 - 1 |
|
|
|
|
|
|
|
|
|
keccak_function_manager = KeccakFunctionManager() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class StateTransition(object): |
|
|
|
|
"""Decorator that handles global state copy and original return. |
|
|
|
@ -193,7 +188,6 @@ class Instruction: |
|
|
|
|
if not post |
|
|
|
|
else getattr(self, op + "_" + "post", None) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
if instruction_mutator is None: |
|
|
|
|
raise NotImplementedError |
|
|
|
|
|
|
|
|
@ -417,6 +411,7 @@ class Instruction: |
|
|
|
|
* helper.pop_bitvec(global_state.mstate) |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
return [global_state] |
|
|
|
|
|
|
|
|
|
@StateTransition() |
|
|
|
@ -893,7 +888,6 @@ class Instruction: |
|
|
|
|
:param global_state: |
|
|
|
|
:return: |
|
|
|
|
""" |
|
|
|
|
global keccak_function_manager |
|
|
|
|
|
|
|
|
|
state = global_state.mstate |
|
|
|
|
op0, op1 = state.stack.pop(), state.stack.pop() |
|
|
|
@ -948,7 +942,6 @@ class Instruction: |
|
|
|
|
) |
|
|
|
|
log.debug("Created BitVecFunc hash.") |
|
|
|
|
|
|
|
|
|
keccak_function_manager.add_keccak(result, state.memory[index]) |
|
|
|
|
else: |
|
|
|
|
keccak = utils.sha3(data.value.to_bytes(length, byteorder="big")) |
|
|
|
|
result = symbol_factory.BitVecFuncVal( |
|
|
|
@ -1400,86 +1393,13 @@ class Instruction: |
|
|
|
|
:param global_state: |
|
|
|
|
:return: |
|
|
|
|
""" |
|
|
|
|
global keccak_function_manager |
|
|
|
|
|
|
|
|
|
state = global_state.mstate |
|
|
|
|
index = state.stack.pop() |
|
|
|
|
log.debug("Storage access at index " + str(index)) |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
index = util.get_concrete_int(index) |
|
|
|
|
return self._sload_helper(global_state, index) |
|
|
|
|
|
|
|
|
|
except TypeError: |
|
|
|
|
if not keccak_function_manager.is_keccak(index): |
|
|
|
|
return self._sload_helper(global_state, str(index)) |
|
|
|
|
|
|
|
|
|
storage_keys = global_state.environment.active_account.storage.keys() |
|
|
|
|
keccak_keys = list(filter(keccak_function_manager.is_keccak, storage_keys)) |
|
|
|
|
|
|
|
|
|
results = [] # type: List[GlobalState] |
|
|
|
|
constraints = [] |
|
|
|
|
|
|
|
|
|
for keccak_key in keccak_keys: |
|
|
|
|
key_argument = keccak_function_manager.get_argument(keccak_key) |
|
|
|
|
index_argument = keccak_function_manager.get_argument(index) |
|
|
|
|
constraints.append((keccak_key, key_argument == index_argument)) |
|
|
|
|
|
|
|
|
|
for (keccak_key, constraint) in constraints: |
|
|
|
|
if constraint in state.constraints: |
|
|
|
|
results += self._sload_helper( |
|
|
|
|
global_state, keccak_key, [constraint] |
|
|
|
|
) |
|
|
|
|
if len(results) > 0: |
|
|
|
|
return results |
|
|
|
|
|
|
|
|
|
for (keccak_key, constraint) in constraints: |
|
|
|
|
results += self._sload_helper( |
|
|
|
|
copy(global_state), keccak_key, [constraint] |
|
|
|
|
) |
|
|
|
|
if len(results) > 0: |
|
|
|
|
return results |
|
|
|
|
|
|
|
|
|
return self._sload_helper(global_state, str(index)) |
|
|
|
|
|
|
|
|
|
@staticmethod |
|
|
|
|
def _sload_helper( |
|
|
|
|
global_state: GlobalState, index: Union[str, int], constraints=None |
|
|
|
|
): |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
:param global_state: |
|
|
|
|
:param index: |
|
|
|
|
:param constraints: |
|
|
|
|
:return: |
|
|
|
|
""" |
|
|
|
|
try: |
|
|
|
|
data = global_state.environment.active_account.storage[index] |
|
|
|
|
except KeyError: |
|
|
|
|
data = global_state.new_bitvec("storage_" + str(index), 256) |
|
|
|
|
global_state.environment.active_account.storage[index] = data |
|
|
|
|
|
|
|
|
|
if constraints is not None: |
|
|
|
|
global_state.mstate.constraints += constraints |
|
|
|
|
|
|
|
|
|
global_state.mstate.stack.append(data) |
|
|
|
|
state.stack.append(global_state.environment.active_account.storage[index]) |
|
|
|
|
return [global_state] |
|
|
|
|
|
|
|
|
|
@staticmethod |
|
|
|
|
def _get_constraints(keccak_keys, this_key, argument): |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
:param keccak_keys: |
|
|
|
|
:param this_key: |
|
|
|
|
:param argument: |
|
|
|
|
""" |
|
|
|
|
global keccak_function_manager |
|
|
|
|
for keccak_key in keccak_keys: |
|
|
|
|
if keccak_key == this_key: |
|
|
|
|
continue |
|
|
|
|
keccak_argument = keccak_function_manager.get_argument(keccak_key) |
|
|
|
|
yield keccak_argument != argument |
|
|
|
|
|
|
|
|
|
@StateTransition() |
|
|
|
|
def sstore_(self, global_state: GlobalState) -> List[GlobalState]: |
|
|
|
|
""" |
|
|
|
@ -1487,90 +1407,10 @@ class Instruction: |
|
|
|
|
:param global_state: |
|
|
|
|
:return: |
|
|
|
|
""" |
|
|
|
|
global keccak_function_manager |
|
|
|
|
state = global_state.mstate |
|
|
|
|
index, value = state.stack.pop(), state.stack.pop() |
|
|
|
|
log.debug("Write to storage[" + str(index) + "]") |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
index = util.get_concrete_int(index) |
|
|
|
|
return self._sstore_helper(global_state, index, value) |
|
|
|
|
except TypeError: |
|
|
|
|
is_keccak = keccak_function_manager.is_keccak(index) |
|
|
|
|
if not is_keccak: |
|
|
|
|
return self._sstore_helper(global_state, str(index), value) |
|
|
|
|
|
|
|
|
|
storage_keys = global_state.environment.active_account.storage.keys() |
|
|
|
|
keccak_keys = filter(keccak_function_manager.is_keccak, storage_keys) |
|
|
|
|
|
|
|
|
|
results = [] # type: List[GlobalState] |
|
|
|
|
new = symbol_factory.Bool(False) |
|
|
|
|
|
|
|
|
|
for keccak_key in keccak_keys: |
|
|
|
|
key_argument = keccak_function_manager.get_argument( |
|
|
|
|
keccak_key |
|
|
|
|
) # type: Expression |
|
|
|
|
index_argument = keccak_function_manager.get_argument( |
|
|
|
|
index |
|
|
|
|
) # type: Expression |
|
|
|
|
condition = key_argument == index_argument |
|
|
|
|
condition = ( |
|
|
|
|
condition |
|
|
|
|
if type(condition) == bool |
|
|
|
|
else is_true(simplify(cast(Bool, condition))) |
|
|
|
|
) |
|
|
|
|
if condition: |
|
|
|
|
return self._sstore_helper( |
|
|
|
|
copy(global_state), |
|
|
|
|
keccak_key, |
|
|
|
|
value, |
|
|
|
|
key_argument == index_argument, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
results += self._sstore_helper( |
|
|
|
|
copy(global_state), |
|
|
|
|
keccak_key, |
|
|
|
|
value, |
|
|
|
|
key_argument == index_argument, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
new = Or(new, cast(Bool, key_argument != index_argument)) |
|
|
|
|
|
|
|
|
|
if len(results) > 0: |
|
|
|
|
results += self._sstore_helper( |
|
|
|
|
copy(global_state), str(index), value, new |
|
|
|
|
) |
|
|
|
|
return results |
|
|
|
|
|
|
|
|
|
return self._sstore_helper(global_state, str(index), value) |
|
|
|
|
|
|
|
|
|
@staticmethod |
|
|
|
|
def _sstore_helper(global_state, index, value, constraint=None): |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
:param global_state: |
|
|
|
|
:param index: |
|
|
|
|
:param value: |
|
|
|
|
:param constraint: |
|
|
|
|
:return: |
|
|
|
|
""" |
|
|
|
|
try: |
|
|
|
|
global_state.environment.active_account = deepcopy( |
|
|
|
|
global_state.environment.active_account |
|
|
|
|
) |
|
|
|
|
global_state.accounts[ |
|
|
|
|
global_state.environment.active_account.address.value |
|
|
|
|
] = global_state.environment.active_account |
|
|
|
|
|
|
|
|
|
global_state.environment.active_account.storage[index] = ( |
|
|
|
|
value if not isinstance(value, Expression) else simplify(value) |
|
|
|
|
) |
|
|
|
|
except KeyError: |
|
|
|
|
log.debug("Error writing to storage: Invalid index") |
|
|
|
|
|
|
|
|
|
if constraint is not None: |
|
|
|
|
global_state.mstate.constraints.append(constraint) |
|
|
|
|
|
|
|
|
|
global_state.environment.active_account.storage[index] = value |
|
|
|
|
return [global_state] |
|
|
|
|
|
|
|
|
|
@StateTransition(increment_pc=False, enable_gas=False) |
|
|
|
|