@ -3,9 +3,8 @@ import logging
from copy import copy , deepcopy
from copy import copy , deepcopy
from ethereum import utils
from ethereum import utils
from z3 import BitVec , Extract , UDiv , simplify , Concat , ULT , UGT , BitVecNumRef , Not , \
from z3 import Extract , UDiv , simplify , Concat , ULT , UGT , BitVecNumRef , Not , \
is_false , is_expr , ExprRef , URem , SRem
is_false , is_expr , ExprRef , URem , SRem , BitVec , Solver , is_true , BitVecVal , If , BoolRef , Or
from z3 import BitVecVal , If , BoolRef
import mythril . laser . ethereum . util as helper
import mythril . laser . ethereum . util as helper
from mythril . laser . ethereum import util
from mythril . laser . ethereum import util
@ -15,10 +14,13 @@ import mythril.laser.ethereum.natives as natives
from mythril . laser . ethereum . transaction import MessageCallTransaction , TransactionStartSignal , \
from mythril . laser . ethereum . transaction import MessageCallTransaction , TransactionStartSignal , \
ContractCreationTransaction
ContractCreationTransaction
from mythril . laser . ethereum . exceptions import VmException , StackUnderflowException
from mythril . laser . ethereum . exceptions import VmException , StackUnderflowException
from mythril . laser . ethereum . keccak import KeccakFunctionManager
TT256 = 2 * * 256
TT256 = 2 * * 256
TT256M1 = 2 * * 256 - 1
TT256M1 = 2 * * 256 - 1
keccak_function_manager = KeccakFunctionManager ( )
def instruction ( func ) :
def instruction ( func ) :
""" Wrapper that handles copy and original return """
""" Wrapper that handles copy and original return """
@ -166,7 +168,7 @@ class Instruction:
result = 0
result = 0
except AttributeError :
except AttributeError :
logging . debug ( " BYTE: Unsupported symbolic byte offset " )
logging . debug ( " BYTE: Unsupported symbolic byte offset " )
result = BitV ec( str ( simplify ( op1 ) ) + " [ " + str ( simplify ( op0 ) ) + " ] " , 256 )
result = global_state . new_bitv ec( str ( simplify ( op1 ) ) + " [ " + str ( simplify ( op0 ) ) + " ] " , 256 )
mstate . stack . append ( result )
mstate . stack . append ( result )
return [ global_state ]
return [ global_state ]
@ -240,7 +242,7 @@ class Instruction:
base , exponent = util . pop_bitvec ( state ) , util . pop_bitvec ( state )
base , exponent = util . pop_bitvec ( state ) , util . pop_bitvec ( state )
if ( type ( base ) != BitVecNumRef ) or ( type ( exponent ) != BitVecNumRef ) :
if ( type ( base ) != BitVecNumRef ) or ( type ( exponent ) != BitVecNumRef ) :
state . stack . append ( BitV ec( " ( " + str ( simplify ( base ) ) + " )**( " + str ( simplify ( exponent ) ) + " ) " , 256 ) )
state . stack . append ( global_state . new_bitv ec( " ( " + str ( simplify ( base ) ) + " )**( " + str ( simplify ( exponent ) ) + " ) " , 256 ) )
else :
else :
state . stack . append ( pow ( base . as_long ( ) , exponent . as_long ( ) , 2 * * 256 ) )
state . stack . append ( pow ( base . as_long ( ) , exponent . as_long ( ) , 2 * * 256 ) )
@ -347,12 +349,12 @@ class Instruction:
b = environment . calldata [ offset ]
b = environment . calldata [ offset ]
except AttributeError :
except AttributeError :
logging . debug ( " CALLDATALOAD: Unsupported symbolic index " )
logging . debug ( " CALLDATALOAD: Unsupported symbolic index " )
state . stack . append ( BitV ec(
state . stack . append ( global_state . new_bitv ec(
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( simplify ( op0 ) ) + " ] " , 256 ) )
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( simplify ( op0 ) ) + " ] " , 256 ) )
return [ global_state ]
return [ global_state ]
except IndexError :
except IndexError :
logging . debug ( " Calldata not set, using symbolic variable instead " )
logging . debug ( " Calldata not set, using symbolic variable instead " )
state . stack . append ( BitV ec(
state . stack . append ( global_state . new_bitv ec(
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( simplify ( op0 ) ) + " ] " , 256 ) )
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( simplify ( op0 ) ) + " ] " , 256 ) )
return [ global_state ]
return [ global_state ]
@ -367,11 +369,11 @@ class Instruction:
state . stack . append ( BitVecVal ( int . from_bytes ( val , byteorder = ' big ' ) , 256 ) )
state . stack . append ( BitVecVal ( int . from_bytes ( val , byteorder = ' big ' ) , 256 ) )
# FIXME: broad exception catch
# FIXME: broad exception catch
except :
except :
state . stack . append ( BitV ec(
state . stack . append ( global_state . new_bitv ec(
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( simplify ( op0 ) ) + " ] " , 256 ) )
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( simplify ( op0 ) ) + " ] " , 256 ) )
else :
else :
# symbolic variable
# symbolic variable
state . stack . append ( BitV ec(
state . stack . append ( global_state . new_bitv ec(
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( simplify ( op0 ) ) + " ] " , 256 ) )
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( simplify ( op0 ) ) + " ] " , 256 ) )
return [ global_state ]
return [ global_state ]
@ -381,7 +383,7 @@ class Instruction:
state = global_state . mstate
state = global_state . mstate
environment = global_state . environment
environment = global_state . environment
if environment . calldata_type == CalldataType . SYMBOLIC :
if environment . calldata_type == CalldataType . SYMBOLIC :
state . stack . append ( BitV ec( " calldatasize_ " + environment . active_account . contract_name , 256 ) )
state . stack . append ( global_state . new_bitv ec( " calldatasize_ " + environment . active_account . contract_name , 256 ) )
else :
else :
state . stack . append ( BitVecVal ( len ( environment . calldata ) , 256 ) )
state . stack . append ( BitVecVal ( len ( environment . calldata ) , 256 ) )
return [ global_state ]
return [ global_state ]
@ -419,7 +421,7 @@ class Instruction:
if dstart_sym or size_sym :
if dstart_sym or size_sym :
state . mem_extend ( mstart , 1 )
state . mem_extend ( mstart , 1 )
state . memory [ mstart ] = BitV ec(
state . memory [ mstart ] = global_state . new_bitv ec(
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( dstart ) + " : + " + str (
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( dstart ) + " : + " + str (
size ) + " ] " , 256 )
size ) + " ] " , 256 )
return [ global_state ]
return [ global_state ]
@ -431,7 +433,7 @@ class Instruction:
except :
except :
logging . debug ( " Memory allocation error: mstart = " + str ( mstart ) + " , size = " + str ( size ) )
logging . debug ( " Memory allocation error: mstart = " + str ( mstart ) + " , size = " + str ( size ) )
state . mem_extend ( mstart , 1 )
state . mem_extend ( mstart , 1 )
state . memory [ mstart ] = BitV ec(
state . memory [ mstart ] = global_state . new_bitv ec(
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( dstart ) + " : + " + str (
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( dstart ) + " : + " + str (
size ) + " ] " , 256 )
size ) + " ] " , 256 )
return [ global_state ]
return [ global_state ]
@ -445,7 +447,7 @@ class Instruction:
except :
except :
logging . debug ( " Exception copying calldata to memory " )
logging . debug ( " Exception copying calldata to memory " )
state . memory [ mstart ] = BitV ec(
state . memory [ mstart ] = global_state . new_bitv ec(
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( dstart ) + " : + " + str (
" calldata_ " + str ( environment . active_account . contract_name ) + " [ " + str ( dstart ) + " : + " + str (
size ) + " ] " , 256 )
size ) + " ] " , 256 )
return [ global_state ]
return [ global_state ]
@ -462,7 +464,7 @@ class Instruction:
def balance_ ( self , global_state ) :
def balance_ ( self , global_state ) :
state = global_state . mstate
state = global_state . mstate
address = state . stack . pop ( )
address = state . stack . pop ( )
state . stack . append ( BitV ec( " balance_at_ " + str ( address ) , 256 ) )
state . stack . append ( global_state . new_bitv ec( " balance_at_ " + str ( address ) , 256 ) )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
@ -489,6 +491,8 @@ class Instruction:
@instruction
@instruction
def sha3_ ( self , global_state ) :
def sha3_ ( self , global_state ) :
global keccak_function_manager
state = global_state . mstate
state = global_state . mstate
environment = global_state . environment
environment = global_state . environment
op0 , op1 = state . stack . pop ( ) , state . stack . pop ( )
op0 , op1 = state . stack . pop ( ) , state . stack . pop ( )
@ -509,23 +513,22 @@ class Instruction:
for i in state . memory [ index : index + length ] ] )
for i in state . memory [ index : index + length ] ] )
except AttributeError :
except AttributeError :
argument = str ( state . memory [ index ] ) . replace ( " " , " _ " )
svar = str ( state . memory [ index ] )
result = BitVec ( " KECCAC[ {} ] " . format ( argument ) , 256 )
keccak_function_manager . add_keccak ( result , state . memory [ index ] )
svar = svar . replace ( " " , " _ " )
state . stack . append ( result )
state . stack . append ( BitVec ( " keccac_ " + svar , 256 ) )
return [ global_state ]
return [ global_state ]
keccac = utils . sha3 ( utils . bytearray_to_bytestr ( data ) )
keccak = utils . sha3 ( utils . bytearray_to_bytestr ( data ) )
logging . debug ( " Computed SHA3 Hash: " + str ( binascii . hexlify ( keccac ) ) )
logging . debug ( " Computed SHA3 Hash: " + str ( binascii . hexlify ( keccak ) ) )
state . stack . append ( BitVecVal ( util . concrete_int_from_bytes ( keccac , 0 ) , 256 ) )
state . stack . append ( BitVecVal ( util . concrete_int_from_bytes ( keccak , 0 ) , 256 ) )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
def gasprice_ ( self , global_state ) :
def gasprice_ ( self , global_state ) :
global_state . mstate . stack . append ( BitV ec( " gasprice " , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " gasprice " , 256 ) )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
@ -545,7 +548,7 @@ class Instruction:
# except both attribute error and Exception
# except both attribute error and Exception
global_state . mstate . mem_extend ( concrete_memory_offset , 1 )
global_state . mstate . mem_extend ( concrete_memory_offset , 1 )
global_state . mstate . memory [ concrete_memory_offset ] = \
global_state . mstate . memory [ concrete_memory_offset ] = \
BitV ec( " code( {} ) " . format ( global_state . environment . active_account . contract_name ) , 256 )
global_state . new_bitv ec( " code( {} ) " . format ( global_state . environment . active_account . contract_name ) , 256 )
return [ global_state ]
return [ global_state ]
try :
try :
@ -555,7 +558,7 @@ class Instruction:
global_state . mstate . mem_extend ( concrete_memory_offset , concrete_size )
global_state . mstate . mem_extend ( concrete_memory_offset , concrete_size )
for i in range ( concrete_size ) :
for i in range ( concrete_size ) :
global_state . mstate . memory [ concrete_memory_offset + i ] = \
global_state . mstate . memory [ concrete_memory_offset + i ] = \
BitV ec( " code( {} ) " . format ( global_state . environment . active_account . contract_name ) , 256 )
global_state . new_bitv ec( " code( {} ) " . format ( global_state . environment . active_account . contract_name ) , 256 )
return [ global_state ]
return [ global_state ]
bytecode = global_state . environment . code . bytecode
bytecode = global_state . environment . code . bytecode
@ -564,7 +567,7 @@ class Instruction:
if concrete_code_offset > = len ( global_state . environment . code . bytecode ) / / 2 :
if concrete_code_offset > = len ( global_state . environment . code . bytecode ) / / 2 :
global_state . mstate . mem_extend ( concrete_memory_offset , 1 )
global_state . mstate . mem_extend ( concrete_memory_offset , 1 )
global_state . mstate . memory [ concrete_memory_offset ] = \
global_state . mstate . memory [ concrete_memory_offset ] = \
BitV ec( " code( {} ) " . format ( global_state . environment . active_account . contract_name ) , 256 )
global_state . new_bitv ec( " code( {} ) " . format ( global_state . environment . active_account . contract_name ) , 256 )
return [ global_state ]
return [ global_state ]
for i in range ( concrete_size ) :
for i in range ( concrete_size ) :
@ -573,7 +576,7 @@ class Instruction:
int ( bytecode [ 2 * ( concrete_code_offset + i ) : 2 * ( concrete_code_offset + i + 1 ) ] , 16 )
int ( bytecode [ 2 * ( concrete_code_offset + i ) : 2 * ( concrete_code_offset + i + 1 ) ] , 16 )
else :
else :
global_state . mstate . memory [ concrete_memory_offset + i ] = \
global_state . mstate . memory [ concrete_memory_offset + i ] = \
BitV ec( " code( {} ) " . format ( global_state . environment . active_account . contract_name ) , 256 )
global_state . new_bitv ec( " code( {} ) " . format ( global_state . environment . active_account . contract_name ) , 256 )
return [ global_state ]
return [ global_state ]
@ -586,14 +589,14 @@ class Instruction:
addr = hex ( helper . get_concrete_int ( addr ) )
addr = hex ( helper . get_concrete_int ( addr ) )
except AttributeError :
except AttributeError :
logging . info ( " unsupported symbolic address for EXTCODESIZE " )
logging . info ( " unsupported symbolic address for EXTCODESIZE " )
state . stack . append ( BitV ec( " extcodesize_ " + str ( addr ) , 256 ) )
state . stack . append ( global_state . new_bitv ec( " extcodesize_ " + str ( addr ) , 256 ) )
return [ global_state ]
return [ global_state ]
try :
try :
code = self . dynamic_loader . dynld ( environment . active_account . address , addr )
code = self . dynamic_loader . dynld ( environment . active_account . address , addr )
except Exception as e :
except Exception as e :
logging . info ( " error accessing contract storage due to: " + str ( e ) )
logging . info ( " error accessing contract storage due to: " + str ( e ) )
state . stack . append ( BitV ec( " extcodesize_ " + str ( addr ) , 256 ) )
state . stack . append ( global_state . new_bitv ec( " extcodesize_ " + str ( addr ) , 256 ) )
return [ global_state ]
return [ global_state ]
if code is None :
if code is None :
@ -613,39 +616,39 @@ class Instruction:
@instruction
@instruction
def returndatasize_ ( self , global_state ) :
def returndatasize_ ( self , global_state ) :
global_state . mstate . stack . append ( BitV ec( " returndatasize " , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " returndatasize " , 256 ) )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
def blockhash_ ( self , global_state ) :
def blockhash_ ( self , global_state ) :
state = global_state . mstate
state = global_state . mstate
blocknumber = state . stack . pop ( )
blocknumber = state . stack . pop ( )
state . stack . append ( BitV ec( " blockhash_block_ " + str ( blocknumber ) , 256 ) )
state . stack . append ( global_state . new_bitv ec( " blockhash_block_ " + str ( blocknumber ) , 256 ) )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
def coinbase_ ( self , global_state ) :
def coinbase_ ( self , global_state ) :
global_state . mstate . stack . append ( BitV ec( " coinbase " , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " coinbase " , 256 ) )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
def timestamp_ ( self , global_state ) :
def timestamp_ ( self , global_state ) :
global_state . mstate . stack . append ( BitV ec( " timestamp " , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " timestamp " , 256 ) )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
def number_ ( self , global_state ) :
def number_ ( self , global_state ) :
global_state . mstate . stack . append ( BitV ec( " block_number " , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " block_number " , 256 ) )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
def difficulty_ ( self , global_state ) :
def difficulty_ ( self , global_state ) :
global_state . mstate . stack . append ( BitV ec( " block_difficulty " , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " block_difficulty " , 256 ) )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
def gaslimit_ ( self , global_state ) :
def gaslimit_ ( self , global_state ) :
global_state . mstate . stack . append ( BitV ec( " block_gaslimit " , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " block_gaslimit " , 256 ) )
return [ global_state ]
return [ global_state ]
# Memory operations
# Memory operations
@ -660,14 +663,14 @@ class Instruction:
offset = util . get_concrete_int ( op0 )
offset = util . get_concrete_int ( op0 )
except AttributeError :
except AttributeError :
logging . debug ( " Can ' t MLOAD from symbolic index " )
logging . debug ( " Can ' t MLOAD from symbolic index " )
data = BitV ec( " mem[ " + str ( simplify ( op0 ) ) + " ] " , 256 )
data = global_state . new_bitv ec( " mem[ " + str ( simplify ( op0 ) ) + " ] " , 256 )
state . stack . append ( data )
state . stack . append ( data )
return [ global_state ]
return [ global_state ]
try :
try :
data = util . concrete_int_from_bytes ( state . memory , offset )
data = util . concrete_int_from_bytes ( state . memory , offset )
except IndexError : # Memory slot not allocated
except IndexError : # Memory slot not allocated
data = BitV ec( " mem[ " + str ( offset ) + " ] " , 256 )
data = global_state . new_bitv ec( " mem[ " + str ( offset ) + " ] " , 256 )
except TypeError : # Symbolic memory
except TypeError : # Symbolic memory
data = state . memory [ offset ]
data = state . memory [ offset ]
@ -732,26 +735,68 @@ class Instruction:
@instruction
@instruction
def sload_ ( self , global_state ) :
def sload_ ( self , global_state ) :
global keccak_function_manager
state = global_state . mstate
state = global_state . mstate
index = state . stack . pop ( )
index = state . stack . pop ( )
logging . debug ( " Storage access at index " + str ( index ) )
logging . debug ( " Storage access at index " + str ( index ) )
try :
try :
index = util . get_concrete_int ( index )
index = util . get_concrete_int ( index )
return self . _sload_helper ( global_state , index )
except AttributeError :
except AttributeError :
index = str ( index )
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 = [ ]
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 ) )
def _sload_helper ( self , global_state , index , constraints = None ) :
try :
try :
data = global_state . environment . active_account . storage [ index ]
data = global_state . environment . active_account . storage [ index ]
except KeyError :
except KeyError :
data = BitVec ( " storage_ " + str ( index ) , 256 )
data = global_state . new_bitv ec( " storage_ " + str ( index ) , 256 )
global_state . environment . active_account . storage [ index ] = data
global_state . environment . active_account . storage [ index ] = data
state . stack . append ( data )
if constraints is not None :
global_state . mstate . constraints + = constraints
global_state . mstate . stack . append ( data )
return [ global_state ]
return [ global_state ]
def _get_constraints ( self , keccak_keys , this_key , 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
@instruction
@instruction
def sstore_ ( self , global_state ) :
def sstore_ ( self , global_state ) :
global keccak_function_manager
state = global_state . mstate
state = global_state . mstate
index , value = state . stack . pop ( ) , state . stack . pop ( )
index , value = state . stack . pop ( ) , state . stack . pop ( )
@ -759,17 +804,52 @@ class Instruction:
try :
try :
index = util . get_concrete_int ( index )
index = util . get_concrete_int ( index )
return self . _sstore_helper ( global_state , index , value )
except AttributeError :
except AttributeError :
index = str ( index )
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 )
solver = Solver ( )
solver . set ( timeout = 1000 )
results = [ ]
new = False
for keccak_key in keccak_keys :
key_argument = keccak_function_manager . get_argument ( keccak_key )
index_argument = keccak_function_manager . get_argument ( index )
if is_true ( key_argument == index_argument ) :
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 , 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 )
def _sstore_helper ( self , global_state , index , value , constraint = None ) :
try :
try :
global_state . environment . active_account = deepcopy ( global_state . environment . active_account )
global_state . environment . active_account = deepcopy ( global_state . environment . active_account )
global_state . accounts [
global_state . accounts [
global_state . environment . active_account . address ] = global_state . environment . active_account
global_state . environment . active_account . address ] = global_state . environment . active_account
global_state . environment . active_account . storage [ index ] = value
global_state . environment . active_account . storage [ index ] = \
value if not isinstance ( value , ExprRef ) else simplify ( value )
except KeyError :
except KeyError :
logging . debug ( " Error writing to storage: Invalid index " )
logging . debug ( " Error writing to storage: Invalid index " )
if constraint is not None :
global_state . mstate . constraints . append ( constraint )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
@ -858,12 +938,12 @@ class Instruction:
@instruction
@instruction
def msize_ ( self , global_state ) :
def msize_ ( self , global_state ) :
global_state . mstate . stack . append ( BitV ec( " msize " , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " msize " , 256 ) )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
def gas_ ( self , global_state ) :
def gas_ ( self , global_state ) :
global_state . mstate . stack . append ( BitV ec( " gas " , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " gas " , 256 ) )
return [ global_state ]
return [ global_state ]
@instruction
@instruction
@ -889,7 +969,7 @@ class Instruction:
def return_ ( self , global_state ) :
def return_ ( self , global_state ) :
state = global_state . mstate
state = global_state . mstate
offset , length = state . stack . pop ( ) , state . stack . pop ( )
offset , length = state . stack . pop ( ) , state . stack . pop ( )
return_data = [ BitV ec( " return_data " , 256 ) ]
return_data = [ global_state . new_bitv ec( " return_data " , 256 ) ]
try :
try :
return_data = state . memory [ util . get_concrete_int ( offset ) : util . get_concrete_int ( offset + length ) ]
return_data = state . memory [ util . get_concrete_int ( offset ) : util . get_concrete_int ( offset + length ) ]
except AttributeError :
except AttributeError :
@ -930,9 +1010,9 @@ class Instruction:
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
)
)
# TODO: decide what to do in this case
# TODO: decide what to do in this case
global_state . mstate . stack . append ( BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
return [ global_state ]
return [ global_state ]
global_state . mstate . stack . append ( BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
if 0 < int ( callee_address , 16 ) < 5 :
if 0 < int ( callee_address , 16 ) < 5 :
logging . info ( " Native contract called: " + callee_address )
logging . info ( " Native contract called: " + callee_address )
@ -954,7 +1034,7 @@ class Instruction:
except natives . NativeContractException :
except natives . NativeContractException :
contract_list = [ ' ecerecover ' , ' sha256 ' , ' ripemd160 ' , ' identity ' ]
contract_list = [ ' ecerecover ' , ' sha256 ' , ' ripemd160 ' , ' identity ' ]
for i in range ( mem_out_sz ) :
for i in range ( mem_out_sz ) :
global_state . mstate . memory [ mem_out_start + i ] = BitV ec( contract_list [ call_address_int - 1 ] +
global_state . mstate . memory [ mem_out_start + i ] = global_state . new_bitv ec( contract_list [ call_address_int - 1 ] +
" ( " + str ( call_data ) + " ) " , 256 )
" ( " + str ( call_data ) + " ) " , 256 )
return [ global_state ]
return [ global_state ]
@ -968,11 +1048,11 @@ class Instruction:
transaction = MessageCallTransaction ( global_state . world_state ,
transaction = MessageCallTransaction ( global_state . world_state ,
callee_account ,
callee_account ,
BitVecVal ( int ( environment . active_account . address , 16 ) , 256 ) ,
BitVecVal ( int ( environment . active_account . address , 16 ) , 256 ) ,
call_data ,
call_data = call_data ,
environment . gasprice ,
gas_price = environment . gasprice ,
value ,
call_value = value ,
environment . origin ,
origin = environment . origin ,
call_data_type )
call_data_type = call_data_type )
raise TransactionStartSignal ( transaction , self . op_code )
raise TransactionStartSignal ( transaction , self . op_code )
@instruction
@instruction
@ -986,12 +1066,12 @@ class Instruction:
logging . info (
logging . info (
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
)
)
global_state . mstate . stack . append ( BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
return [ global_state ]
return [ global_state ]
if global_state . last_return_data is None :
if global_state . last_return_data is None :
# Put return value on stack
# Put return value on stack
return_value = BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
return_value = global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
global_state . mstate . stack . append ( return_value )
global_state . mstate . stack . append ( return_value )
global_state . mstate . constraints . append ( return_value == 0 )
global_state . mstate . constraints . append ( return_value == 0 )
@ -1001,7 +1081,7 @@ class Instruction:
memory_out_offset = util . get_concrete_int ( memory_out_offset ) if isinstance ( memory_out_offset , ExprRef ) else memory_out_offset
memory_out_offset = util . get_concrete_int ( memory_out_offset ) if isinstance ( memory_out_offset , ExprRef ) else memory_out_offset
memory_out_size = util . get_concrete_int ( memory_out_size ) if isinstance ( memory_out_size , ExprRef ) else memory_out_size
memory_out_size = util . get_concrete_int ( memory_out_size ) if isinstance ( memory_out_size , ExprRef ) else memory_out_size
except AttributeError :
except AttributeError :
global_state . mstate . stack . append ( BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
return [ global_state ]
return [ global_state ]
# Copy memory
# Copy memory
@ -1010,7 +1090,7 @@ class Instruction:
global_state . mstate . memory [ i + memory_out_offset ] = global_state . last_return_data [ i ]
global_state . mstate . memory [ i + memory_out_offset ] = global_state . last_return_data [ i ]
# Put return value on stack
# Put return value on stack
return_value = BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
return_value = global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
global_state . mstate . stack . append ( return_value )
global_state . mstate . stack . append ( return_value )
global_state . mstate . constraints . append ( return_value == 1 )
global_state . mstate . constraints . append ( return_value == 1 )
@ -1028,18 +1108,18 @@ class Instruction:
logging . info (
logging . info (
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
)
)
global_state . mstate . stack . append ( BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
return [ global_state ]
return [ global_state ]
transaction = MessageCallTransaction ( global_state . world_state ,
transaction = MessageCallTransaction ( global_state . world_state ,
environment . active_account ,
environment . active_account ,
environment . address ,
environment . address ,
call_data ,
call_data = call_data ,
environment . gasprice ,
gas_price = environment . gasprice ,
value ,
call_value = value ,
environment . origin ,
origin = environment . origin ,
call_data_type ,
call_data_type = call_data_type ,
callee_account . code
code = c allee_account . code
)
)
raise TransactionStartSignal ( transaction , self . op_code )
raise TransactionStartSignal ( transaction , self . op_code )
@ -1054,12 +1134,12 @@ class Instruction:
logging . info (
logging . info (
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
)
)
global_state . mstate . stack . append ( BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
return [ global_state ]
return [ global_state ]
if global_state . last_return_data is None :
if global_state . last_return_data is None :
# Put return value on stack
# Put return value on stack
return_value = BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
return_value = global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
global_state . mstate . stack . append ( return_value )
global_state . mstate . stack . append ( return_value )
global_state . mstate . constraints . append ( return_value == 0 )
global_state . mstate . constraints . append ( return_value == 0 )
@ -1069,7 +1149,7 @@ class Instruction:
memory_out_offset = util . get_concrete_int ( memory_out_offset ) if isinstance ( memory_out_offset , ExprRef ) else memory_out_offset
memory_out_offset = util . get_concrete_int ( memory_out_offset ) if isinstance ( memory_out_offset , ExprRef ) else memory_out_offset
memory_out_size = util . get_concrete_int ( memory_out_size ) if isinstance ( memory_out_size , ExprRef ) else memory_out_size
memory_out_size = util . get_concrete_int ( memory_out_size ) if isinstance ( memory_out_size , ExprRef ) else memory_out_size
except AttributeError :
except AttributeError :
global_state . mstate . stack . append ( BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
return [ global_state ]
return [ global_state ]
# Copy memory
# Copy memory
@ -1078,7 +1158,7 @@ class Instruction:
global_state . mstate . memory [ i + memory_out_offset ] = global_state . last_return_data [ i ]
global_state . mstate . memory [ i + memory_out_offset ] = global_state . last_return_data [ i ]
# Put return value on stack
# Put return value on stack
return_value = BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
return_value = global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
global_state . mstate . stack . append ( return_value )
global_state . mstate . stack . append ( return_value )
global_state . mstate . constraints . append ( return_value == 1 )
global_state . mstate . constraints . append ( return_value == 1 )
@ -1097,18 +1177,18 @@ class Instruction:
logging . info (
logging . info (
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
)
)
global_state . mstate . stack . append ( BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
return [ global_state ]
return [ global_state ]
transaction = MessageCallTransaction ( global_state . world_state ,
transaction = MessageCallTransaction ( global_state . world_state ,
environment . active_account ,
environment . active_account ,
environment . sender ,
environment . sender ,
call_data ,
call_data ,
environment . gasprice ,
gas_price = environment . gasprice ,
environment . callvalue ,
call_value = environment . callvalue ,
environment . origin ,
origin = environment . origin ,
call_data_type ,
call_data_type = call_data_type ,
callee_account . code
code = c allee_account . code
)
)
raise TransactionStartSignal ( transaction , self . op_code )
raise TransactionStartSignal ( transaction , self . op_code )
@ -1124,12 +1204,12 @@ class Instruction:
logging . info (
logging . info (
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
" Could not determine required parameters for call, putting fresh symbol on the stack. \n {} " . format ( e )
)
)
global_state . mstate . stack . append ( BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
return [ global_state ]
return [ global_state ]
if global_state . last_return_data is None :
if global_state . last_return_data is None :
# Put return value on stack
# Put return value on stack
return_value = BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
return_value = global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
global_state . mstate . stack . append ( return_value )
global_state . mstate . stack . append ( return_value )
global_state . mstate . constraints . append ( return_value == 0 )
global_state . mstate . constraints . append ( return_value == 0 )
@ -1141,7 +1221,7 @@ class Instruction:
memory_out_size = util . get_concrete_int ( memory_out_size ) if isinstance ( memory_out_size ,
memory_out_size = util . get_concrete_int ( memory_out_size ) if isinstance ( memory_out_size ,
ExprRef ) else memory_out_size
ExprRef ) else memory_out_size
except AttributeError :
except AttributeError :
global_state . mstate . stack . append ( BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
return [ global_state ]
return [ global_state ]
# Copy memory
# Copy memory
@ -1151,7 +1231,7 @@ class Instruction:
global_state . mstate . memory [ i + memory_out_offset ] = global_state . last_return_data [ i ]
global_state . mstate . memory [ i + memory_out_offset ] = global_state . last_return_data [ i ]
# Put return value on stack
# Put return value on stack
return_value = BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
return_value = global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 )
global_state . mstate . stack . append ( return_value )
global_state . mstate . stack . append ( return_value )
global_state . mstate . constraints . append ( return_value == 1 )
global_state . mstate . constraints . append ( return_value == 1 )
@ -1161,5 +1241,6 @@ class Instruction:
def staticcall_ ( self , global_state ) :
def staticcall_ ( self , global_state ) :
# TODO: implement me
# TODO: implement me
instr = global_state . get_current_instruction ( )
instr = global_state . get_current_instruction ( )
global_state . mstate . stack . append ( BitV ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
global_state . mstate . stack . append ( global_state . new_bitv ec( " retval_ " + str ( instr [ ' address ' ] ) , 256 ) )
return [ global_state ]
return [ global_state ]