Source code for mythril.laser.ethereum.state.global_state

"""This module contains a representation of the global execution state."""
from typing import Dict, Union, List, Iterable, TYPE_CHECKING

from copy import copy, deepcopy
from z3 import BitVec

from mythril.laser.smt import symbol_factory
from mythril.laser.ethereum.cfg import Node
from mythril.laser.ethereum.state.environment import Environment
from mythril.laser.ethereum.state.machine_state import MachineState
from mythril.laser.ethereum.state.annotation import StateAnnotation

if TYPE_CHECKING:
    from mythril.laser.ethereum.state.world_state import WorldState
    from mythril.laser.ethereum.transaction.transaction_models import (
        MessageCallTransaction,
        ContractCreationTransaction,
    )


[docs]class GlobalState: """GlobalState represents the current globalstate.""" def __init__( self, world_state: "WorldState", environment: Environment, node: Node, machine_state=None, transaction_stack=None, last_return_data=None, annotations=None, ) -> None: """Constructor for GlobalState. :param world_state: :param environment: :param node: :param machine_state: :param transaction_stack: :param last_return_data: :param annotations: """ self.node = node self.world_state = world_state self.environment = environment self.mstate = ( machine_state if machine_state else MachineState(gas_limit=1000000000) ) self.transaction_stack = transaction_stack if transaction_stack else [] self.op_code = "" self.last_return_data = last_return_data self._annotations = annotations or []
[docs] def add_annotations(self, annotations: List[StateAnnotation]): """ Function used to add annotations to global state :param annotations: :return: """ self._annotations += annotations
def __copy__(self) -> "GlobalState": """ :return: """ world_state = copy(self.world_state) environment = copy(self.environment) mstate = deepcopy(self.mstate) transaction_stack = copy(self.transaction_stack) environment.active_account = world_state[environment.active_account.address] return GlobalState( world_state, environment, self.node, mstate, transaction_stack=transaction_stack, last_return_data=self.last_return_data, annotations=[copy(a) for a in self._annotations], ) def __deepcopy__(self, _) -> "GlobalState": """ Deepcopy is much slower than copy, since it deepcopies constraints. :return: """ world_state = deepcopy(self.world_state) environment = copy(self.environment) mstate = deepcopy(self.mstate) transaction_stack = copy(self.transaction_stack) environment.active_account = world_state[environment.active_account.address] return GlobalState( world_state, environment, self.node, mstate, transaction_stack=transaction_stack, last_return_data=self.last_return_data, annotations=[copy(a) for a in self._annotations], ) @property def accounts(self) -> Dict: """ :return: """ return self.world_state._accounts # TODO: remove this, as two instructions are confusing
[docs] def get_current_instruction(self) -> Dict: """Gets the current instruction for this GlobalState. :return: """ instructions = self.environment.code.instruction_list try: return instructions[self.mstate.pc] except IndexError: return {"address": self.mstate.pc, "opcode": "STOP"}
@property def current_transaction( self, ) -> Union["MessageCallTransaction", "ContractCreationTransaction", None]: """ :return: """ # TODO: Remove circular to transaction package to import Transaction classes try: return self.transaction_stack[-1][0] except IndexError: return None @property def instruction(self) -> Dict: """ :return: """ return self.get_current_instruction()
[docs] def new_bitvec(self, name: str, size=256, annotations=None) -> BitVec: """ :param name: :param size: :return: """ transaction_id = self.current_transaction.id return symbol_factory.BitVecSym( "{}_{}".format(transaction_id, name), size, annotations=annotations )
[docs] def annotate(self, annotation: StateAnnotation) -> None: """ :param annotation: """ self._annotations.append(annotation) if annotation.persist_to_world_state: self.world_state.annotate(annotation)
@property def annotations(self) -> List[StateAnnotation]: """ :return: """ return self._annotations
[docs] def get_annotations(self, annotation_type: type) -> Iterable[StateAnnotation]: """Filters annotations for the queried annotation type. Designed particularly for modules with annotations: globalstate.get_annotations(MySpecificModuleAnnotation) :param annotation_type: The type to filter annotations for :return: filter of matching annotations """ return filter(lambda x: isinstance(x, annotation_type), self.annotations)