def extract_tmp_call(ins): assert isinstance(ins, TmpCall) if isinstance(ins.called, Variable) and isinstance(ins.called.type, FunctionType): call = InternalDynamicCall(ins.lvalue, ins.called, ins.called.type) call.call_id = ins.call_id return call if isinstance(ins.ori, Member): if isinstance(ins.ori.variable_left, Contract): st = ins.ori.variable_left.get_structure_from_name( ins.ori.variable_right) if st: op = NewStructure(st, ins.lvalue) op.call_id = ins.call_id return op libcall = LibraryCall(ins.ori.variable_left, ins.ori.variable_right, ins.nbr_arguments, ins.lvalue, ins.type_call) libcall.call_id = ins.call_id return libcall msgcall = HighLevelCall(ins.ori.variable_left, ins.ori.variable_right, ins.nbr_arguments, ins.lvalue, ins.type_call) msgcall.call_id = ins.call_id return msgcall if isinstance(ins.ori, TmpCall): r = extract_tmp_call(ins.ori) return r if isinstance(ins.called, SolidityVariableComposed): if str(ins.called) == 'block.blockhash': ins.called = SolidityFunction('blockhash(uint256)') elif str(ins.called) == 'this.balance': return SolidityCall(SolidityFunction('this.balance()'), ins.nbr_arguments, ins.lvalue, ins.type_call) if isinstance(ins.called, SolidityFunction): return SolidityCall(ins.called, ins.nbr_arguments, ins.lvalue, ins.type_call) if isinstance(ins.ori, TmpNewElementaryType): return NewElementaryType(ins.ori.type, ins.lvalue) if isinstance(ins.ori, TmpNewContract): op = NewContract(Constant(ins.ori.contract_name), ins.lvalue) op.call_id = ins.call_id return op if isinstance(ins.ori, TmpNewArray): return NewArray(ins.ori.depth, ins.ori.array_type, ins.lvalue) if isinstance(ins.called, Structure): op = NewStructure(ins.called, ins.lvalue) op.call_id = ins.call_id return op if isinstance(ins.called, Event): return EventCall(ins.called.name) raise Exception('Not extracted {} {}'.format(type(ins.called), ins))
def convert_to_solidity_func(ir): """ Must be called after can_be_solidity_func :param ir: :return: """ call = SolidityFunction('abi.{}()'.format(ir.function_name)) new_ir = SolidityCall(call, ir.nbr_arguments, ir.lvalue, ir.type_call) new_ir.arguments = ir.arguments new_ir.set_expression(ir.expression) if isinstance(call.return_type, list) and len(call.return_type) == 1: new_ir.lvalue.set_type(call.return_type[0]) else: new_ir.lvalue.set_type(call.return_type) return new_ir
def convert_to_low_level(ir): """ Convert to a transfer/send/or low level call The funciton assume to receive a correct IR The checks must be done by the caller Additionally convert abi... to solidityfunction """ if ir.function_name == 'transfer': assert len(ir.arguments) == 1 ir = Transfer(ir.destination, ir.arguments[0]) return ir elif ir.function_name == 'send': assert len(ir.arguments) == 1 ir = Send(ir.destination, ir.arguments[0], ir.lvalue) ir.lvalue.set_type(ElementaryType('bool')) return ir elif ir.destination.name == 'abi' and ir.function_name in ['encode', 'encodePacked', 'encodeWithSelector', 'encodeWithSignature', 'decode']: call = SolidityFunction('abi.{}()'.format(ir.function_name)) new_ir = SolidityCall(call, ir.nbr_arguments, ir.lvalue, ir.type_call) new_ir.arguments = ir.arguments if isinstance(call.return_type, list) and len(call.return_type) == 1: new_ir.lvalue.set_type(call.return_type[0]) else: new_ir.lvalue.set_type(call.return_type) return new_ir elif ir.function_name in ['call', 'delegatecall', 'callcode', 'staticcall']: new_ir = LowLevelCall(ir.destination, ir.function_name, ir.nbr_arguments, ir.lvalue, ir.type_call) new_ir.call_gas = ir.call_gas new_ir.call_value = ir.call_value new_ir.arguments = ir.arguments new_ir.lvalue.set_type(ElementaryType('bool')) return new_ir logger.error('Incorrect conversion to low level {}'.format(ir)) exit(-1)
def copy_ir(ir, local_variables_instances, state_variables_instances, temporary_variables_instances, reference_variables_instances, all_local_variables_instances): ''' Args: ir (Operation) local_variables_instances(dict(str -> LocalVariable)) state_variables_instances(dict(str -> StateVariable)) temporary_variables_instances(dict(int -> Variable)) reference_variables_instances(dict(int -> Variable)) Note: temporary and reference can be indexed by int, as they dont need phi functions ''' def get(variable): if isinstance(variable, LocalVariable): if variable.name in local_variables_instances: return local_variables_instances[variable.name] new_var = LocalIRVariable(variable) local_variables_instances[variable.name] = new_var all_local_variables_instances[variable.name] = new_var return new_var if isinstance( variable, StateVariable ) and variable.canonical_name in state_variables_instances: return state_variables_instances[variable.canonical_name] elif isinstance(variable, ReferenceVariable): if not variable.index in reference_variables_instances: new_variable = ReferenceVariable(variable.node, index=variable.index) if variable.points_to: new_variable.points_to = get(variable.points_to) new_variable.set_type(variable.type) reference_variables_instances[variable.index] = new_variable return reference_variables_instances[variable.index] elif isinstance(variable, TemporaryVariable): if not variable.index in temporary_variables_instances: new_variable = TemporaryVariable(variable.node, index=variable.index) new_variable.set_type(variable.type) temporary_variables_instances[variable.index] = new_variable return temporary_variables_instances[variable.index] return variable def get_variable(ir, f): variable = f(ir) variable = get(variable) return variable def get_arguments(ir): arguments = [] for arg in ir.arguments: arg = get(arg) arguments.append(arg) return arguments def get_rec_values(ir, f): # Use by InitArray and NewArray # Potential recursive array(s) ori_init_values = f(ir) def traversal(values): ret = [] for v in values: if isinstance(v, list): v = traversal(v) else: v = get(v) ret.append(v) return ret return traversal(ori_init_values) if isinstance(ir, Assignment): lvalue = get_variable(ir, lambda x: ir.lvalue) rvalue = get_variable(ir, lambda x: ir.rvalue) variable_return_type = ir.variable_return_type return Assignment(lvalue, rvalue, variable_return_type) elif isinstance(ir, Balance): lvalue = get_variable(ir, lambda x: ir.lvalue) value = get_variable(ir, lambda x: ir.value) return Balance(value, lvalue) elif isinstance(ir, Binary): lvalue = get_variable(ir, lambda x: ir.lvalue) variable_left = get_variable(ir, lambda x: ir.variable_left) variable_right = get_variable(ir, lambda x: ir.variable_right) operation_type = ir.type return Binary(lvalue, variable_left, variable_right, operation_type) elif isinstance(ir, Condition): val = get_variable(ir, lambda x: ir.value) return Condition(val) elif isinstance(ir, Delete): lvalue = get_variable(ir, lambda x: ir.lvalue) variable = get_variable(ir, lambda x: ir.variable) return Delete(lvalue, variable) elif isinstance(ir, EventCall): name = ir.name return EventCall(name) elif isinstance(ir, HighLevelCall): # include LibraryCall destination = get_variable(ir, lambda x: ir.destination) function_name = ir.function_name nbr_arguments = ir.nbr_arguments lvalue = get_variable(ir, lambda x: ir.lvalue) type_call = ir.type_call if isinstance(ir, LibraryCall): new_ir = LibraryCall(destination, function_name, nbr_arguments, lvalue, type_call) else: new_ir = HighLevelCall(destination, function_name, nbr_arguments, lvalue, type_call) new_ir.call_id = ir.call_id new_ir.call_value = get_variable(ir, lambda x: ir.call_value) new_ir.call_gas = get_variable(ir, lambda x: ir.call_gas) new_ir.arguments = get_arguments(ir) new_ir.function = ir.function return new_ir elif isinstance(ir, Index): lvalue = get_variable(ir, lambda x: ir.lvalue) variable_left = get_variable(ir, lambda x: ir.variable_left) variable_right = get_variable(ir, lambda x: ir.variable_right) index_type = ir.index_type return Index(lvalue, variable_left, variable_right, index_type) elif isinstance(ir, InitArray): lvalue = get_variable(ir, lambda x: ir.lvalue) init_values = get_rec_values(ir, lambda x: ir.init_values) return InitArray(init_values, lvalue) elif isinstance(ir, InternalCall): function = ir.function nbr_arguments = ir.nbr_arguments lvalue = get_variable(ir, lambda x: ir.lvalue) type_call = ir.type_call new_ir = InternalCall(function, nbr_arguments, lvalue, type_call) new_ir.arguments = get_arguments(ir) return new_ir elif isinstance(ir, InternalDynamicCall): lvalue = get_variable(ir, lambda x: ir.lvalue) function = ir.function function_type = ir.function_type new_ir = InternalDynamicCall(lvalue, function, function_type) new_ir.arguments = get_arguments(ir) return new_ir elif isinstance(ir, LowLevelCall): destination = get_variable(ir, lambda x: x.destination) function_name = ir.function_name nbr_arguments = ir.nbr_arguments lvalue = get_variable(ir, lambda x: ir.lvalue) type_call = ir.type_call new_ir = LowLevelCall(destination, function_name, nbr_arguments, lvalue, type_call) new_ir.call_id = ir.call_id new_ir.call_value = get_variable(ir, lambda x: ir.call_value) new_ir.call_gas = get_variable(ir, lambda x: ir.call_gas) new_ir.arguments = get_arguments(ir) return new_ir elif isinstance(ir, Member): lvalue = get_variable(ir, lambda x: ir.lvalue) variable_left = get_variable(ir, lambda x: ir.variable_left) variable_right = get_variable(ir, lambda x: ir.variable_right) return Member(variable_left, variable_right, lvalue) elif isinstance(ir, NewArray): depth = ir.depth array_type = ir.array_type lvalue = get_variable(ir, lambda x: ir.lvalue) new_ir = NewArray(depth, array_type, lvalue) new_ir.arguments = get_rec_values(ir, lambda x: ir.arguments) return new_ir elif isinstance(ir, NewElementaryType): new_type = ir.type lvalue = get_variable(ir, lambda x: ir.lvalue) new_ir = NewElementaryType(new_type, lvalue) new_ir.arguments = get_arguments(ir) return new_ir elif isinstance(ir, NewContract): contract_name = ir.contract_name lvalue = get_variable(ir, lambda x: ir.lvalue) new_ir = NewContract(contract_name, lvalue) new_ir.arguments = get_arguments(ir) return new_ir elif isinstance(ir, NewStructure): structure = ir.structure lvalue = get_variable(ir, lambda x: ir.lvalue) new_ir = NewStructure(structure, lvalue) new_ir.arguments = get_arguments(ir) return new_ir elif isinstance(ir, Push): array = get_variable(ir, lambda x: ir.array) lvalue = get_variable(ir, lambda x: ir.lvalue) return Push(array, lvalue) elif isinstance(ir, Return): value = [get_variable(x, lambda y: y) for x in ir.values] return Return(value) elif isinstance(ir, Send): destination = get_variable(ir, lambda x: ir.destination) value = get_variable(ir, lambda x: ir.call_value) lvalue = get_variable(ir, lambda x: ir.lvalue) return Send(destination, value, lvalue) elif isinstance(ir, SolidityCall): function = ir.function nbr_arguments = ir.nbr_arguments lvalue = get_variable(ir, lambda x: ir.lvalue) type_call = ir.type_call new_ir = SolidityCall(function, nbr_arguments, lvalue, type_call) new_ir.arguments = get_arguments(ir) return new_ir elif isinstance(ir, Transfer): destination = get_variable(ir, lambda x: ir.destination) value = get_variable(ir, lambda x: ir.call_value) return Transfer(destination, value) elif isinstance(ir, TypeConversion): lvalue = get_variable(ir, lambda x: ir.lvalue) variable = get_variable(ir, lambda x: ir.variable) variable_type = ir.type return TypeConversion(lvalue, variable, variable_type) elif isinstance(ir, Unary): lvalue = get_variable(ir, lambda x: ir.lvalue) rvalue = get_variable(ir, lambda x: ir.rvalue) operation_type = ir.type return Unary(lvalue, rvalue, operation_type) elif isinstance(ir, Unpack): lvalue = get_variable(ir, lambda x: ir.lvalue) tuple_var = ir.tuple idx = ir.index return Unpack(lvalue, tuple_var, idx) elif isinstance(ir, Length): lvalue = get_variable(ir, lambda x: ir.lvalue) value = get_variable(ir, lambda x: ir.value) return Length(value, lvalue) logger.error('Impossible ir copy on {} ({})'.format(ir, type(ir))) exit(-1)
def extract_tmp_call(ins, contract): assert isinstance(ins, TmpCall) if isinstance(ins.called, Variable) and isinstance(ins.called.type, FunctionType): call = InternalDynamicCall(ins.lvalue, ins.called, ins.called.type) call.set_expression(ins.expression) call.call_id = ins.call_id return call if isinstance(ins.ori, Member): # If there is a call on an inherited contract, it is an internal call or an event if ins.ori.variable_left in contract.inheritance + [contract]: if str(ins.ori.variable_right) in [f.name for f in contract.functions]: internalcall = InternalCall((ins.ori.variable_right, ins.ori.variable_left.name), ins.nbr_arguments, ins.lvalue, ins.type_call) internalcall.set_expression(ins.expression) internalcall.call_id = ins.call_id return internalcall if str(ins.ori.variable_right) in [f.name for f in contract.events]: eventcall = EventCall(ins.ori.variable_right) eventcall.set_expression(ins.expression) eventcall.call_id = ins.call_id return eventcall if isinstance(ins.ori.variable_left, Contract): st = ins.ori.variable_left.get_structure_from_name(ins.ori.variable_right) if st: op = NewStructure(st, ins.lvalue) op.set_expression(ins.expression) op.call_id = ins.call_id return op libcall = LibraryCall(ins.ori.variable_left, ins.ori.variable_right, ins.nbr_arguments, ins.lvalue, ins.type_call) libcall.set_expression(ins.expression) libcall.call_id = ins.call_id return libcall msgcall = HighLevelCall(ins.ori.variable_left, ins.ori.variable_right, ins.nbr_arguments, ins.lvalue, ins.type_call) msgcall.call_id = ins.call_id if ins.call_gas: msgcall.call_gas = ins.call_gas if ins.call_value: msgcall.call_value = ins.call_value msgcall.set_expression(ins.expression) return msgcall if isinstance(ins.ori, TmpCall): r = extract_tmp_call(ins.ori, contract) r.set_node(ins.node) return r if isinstance(ins.called, SolidityVariableComposed): if str(ins.called) == 'block.blockhash': ins.called = SolidityFunction('blockhash(uint256)') elif str(ins.called) == 'this.balance': s = SolidityCall(SolidityFunction('this.balance()'), ins.nbr_arguments, ins.lvalue, ins.type_call) s.set_expression(ins.expression) return s if isinstance(ins.called, SolidityFunction): s = SolidityCall(ins.called, ins.nbr_arguments, ins.lvalue, ins.type_call) s.set_expression(ins.expression) return s if isinstance(ins.ori, TmpNewElementaryType): n = NewElementaryType(ins.ori.type, ins.lvalue) n.set_expression(ins.expression) return n if isinstance(ins.ori, TmpNewContract): op = NewContract(Constant(ins.ori.contract_name), ins.lvalue) op.set_expression(ins.expression) op.call_id = ins.call_id return op if isinstance(ins.ori, TmpNewArray): n = NewArray(ins.ori.depth, ins.ori.array_type, ins.lvalue) n.set_expression(ins.expression) return n if isinstance(ins.called, Structure): op = NewStructure(ins.called, ins.lvalue) op.set_expression(ins.expression) op.call_id = ins.call_id op.set_expression(ins.expression) return op if isinstance(ins.called, Event): e = EventCall(ins.called.name) e.set_expression(ins.expression) return e if isinstance(ins.called, Contract): # Called a base constructor, where there is no constructor if ins.called.constructor is None: return Nop() # Case where: # contract A{ constructor(uint) } # contract B is A {} # contract C is B{ constructor() A(10) B() {} # C calls B(), which does not exist # Ideally we should compare here for the parameters types too if len(ins.called.constructor.parameters) != ins.nbr_arguments: return Nop() internalcall = InternalCall(ins.called.constructor, ins.nbr_arguments, ins.lvalue, ins.type_call) internalcall.call_id = ins.call_id internalcall.set_expression(ins.expression) return internalcall raise Exception('Not extracted {} {}'.format(type(ins.called), ins))
def copy_ir(ir, *instances): ''' Args: ir (Operation) local_variables_instances(dict(str -> LocalVariable)) state_variables_instances(dict(str -> StateVariable)) temporary_variables_instances(dict(int -> Variable)) reference_variables_instances(dict(int -> Variable)) Note: temporary and reference can be indexed by int, as they dont need phi functions ''' if isinstance(ir, Assignment): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) rvalue = get_variable(ir, lambda x: x.rvalue, *instances) variable_return_type = ir.variable_return_type return Assignment(lvalue, rvalue, variable_return_type) elif isinstance(ir, Balance): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) value = get_variable(ir, lambda x: x.value, *instances) return Balance(value, lvalue) elif isinstance(ir, Binary): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) variable_left = get_variable(ir, lambda x: x.variable_left, *instances) variable_right = get_variable(ir, lambda x: x.variable_right, *instances) operation_type = ir.type return Binary(lvalue, variable_left, variable_right, operation_type) elif isinstance(ir, Condition): val = get_variable(ir, lambda x: x.value, *instances) return Condition(val) elif isinstance(ir, Delete): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) variable = get_variable(ir, lambda x: x.variable, *instances) return Delete(lvalue, variable) elif isinstance(ir, EventCall): name = ir.name return EventCall(name) elif isinstance(ir, HighLevelCall): # include LibraryCall destination = get_variable(ir, lambda x: x.destination, *instances) function_name = ir.function_name nbr_arguments = ir.nbr_arguments lvalue = get_variable(ir, lambda x: x.lvalue, *instances) type_call = ir.type_call if isinstance(ir, LibraryCall): new_ir = LibraryCall(destination, function_name, nbr_arguments, lvalue, type_call) else: new_ir = HighLevelCall(destination, function_name, nbr_arguments, lvalue, type_call) new_ir.call_id = ir.call_id new_ir.call_value = get_variable(ir, lambda x: x.call_value, *instances) new_ir.call_gas = get_variable(ir, lambda x: x.call_gas, *instances) new_ir.arguments = get_arguments(ir, *instances) new_ir.function = ir.function return new_ir elif isinstance(ir, Index): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) variable_left = get_variable(ir, lambda x: x.variable_left, *instances) variable_right = get_variable(ir, lambda x: x.variable_right, *instances) index_type = ir.index_type return Index(lvalue, variable_left, variable_right, index_type) elif isinstance(ir, InitArray): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) init_values = get_rec_values(ir, lambda x: x.init_values, *instances) return InitArray(init_values, lvalue) elif isinstance(ir, InternalCall): function = ir.function nbr_arguments = ir.nbr_arguments lvalue = get_variable(ir, lambda x: x.lvalue, *instances) type_call = ir.type_call new_ir = InternalCall(function, nbr_arguments, lvalue, type_call) new_ir.arguments = get_arguments(ir, *instances) return new_ir elif isinstance(ir, InternalDynamicCall): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) function = get_variable(ir, lambda x: x.function, *instances) function_type = ir.function_type new_ir = InternalDynamicCall(lvalue, function, function_type) new_ir.arguments = get_arguments(ir, *instances) return new_ir elif isinstance(ir, LowLevelCall): destination = get_variable(ir, lambda x: x.destination, *instances) function_name = ir.function_name nbr_arguments = ir.nbr_arguments lvalue = get_variable(ir, lambda x: x.lvalue, *instances) type_call = ir.type_call new_ir = LowLevelCall(destination, function_name, nbr_arguments, lvalue, type_call) new_ir.call_id = ir.call_id new_ir.call_value = get_variable(ir, lambda x: x.call_value, *instances) new_ir.call_gas = get_variable(ir, lambda x: x.call_gas, *instances) new_ir.arguments = get_arguments(ir, *instances) return new_ir elif isinstance(ir, Member): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) variable_left = get_variable(ir, lambda x: x.variable_left, *instances) variable_right = get_variable(ir, lambda x: x.variable_right, *instances) return Member(variable_left, variable_right, lvalue) elif isinstance(ir, NewArray): depth = ir.depth array_type = ir.array_type lvalue = get_variable(ir, lambda x: x.lvalue, *instances) new_ir = NewArray(depth, array_type, lvalue) new_ir.arguments = get_rec_values(ir, lambda x: x.arguments, *instances) return new_ir elif isinstance(ir, NewElementaryType): new_type = ir.type lvalue = get_variable(ir, lambda x: x.lvalue, *instances) new_ir = NewElementaryType(new_type, lvalue) new_ir.arguments = get_arguments(ir, *instances) return new_ir elif isinstance(ir, NewContract): contract_name = ir.contract_name lvalue = get_variable(ir, lambda x: x.lvalue, *instances) new_ir = NewContract(contract_name, lvalue) new_ir.arguments = get_arguments(ir, *instances) return new_ir elif isinstance(ir, NewStructure): structure = ir.structure lvalue = get_variable(ir, lambda x: x.lvalue, *instances) new_ir = NewStructure(structure, lvalue) new_ir.arguments = get_arguments(ir, *instances) return new_ir elif isinstance(ir, Push): array = get_variable(ir, lambda x: x.array, *instances) lvalue = get_variable(ir, lambda x: x.lvalue, *instances) return Push(array, lvalue) elif isinstance(ir, Return): values = get_rec_values(ir, lambda x: x.values, *instances) return Return(values) elif isinstance(ir, Send): destination = get_variable(ir, lambda x: x.destination, *instances) value = get_variable(ir, lambda x: x.call_value, *instances) lvalue = get_variable(ir, lambda x: x.lvalue, *instances) return Send(destination, value, lvalue) elif isinstance(ir, SolidityCall): function = ir.function nbr_arguments = ir.nbr_arguments lvalue = get_variable(ir, lambda x: x.lvalue, *instances) type_call = ir.type_call new_ir = SolidityCall(function, nbr_arguments, lvalue, type_call) new_ir.arguments = get_arguments(ir, *instances) return new_ir elif isinstance(ir, Transfer): destination = get_variable(ir, lambda x: x.destination, *instances) value = get_variable(ir, lambda x: x.call_value, *instances) return Transfer(destination, value) elif isinstance(ir, TypeConversion): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) variable = get_variable(ir, lambda x: x.variable, *instances) variable_type = ir.type return TypeConversion(lvalue, variable, variable_type) elif isinstance(ir, Unary): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) rvalue = get_variable(ir, lambda x: x.rvalue, *instances) operation_type = ir.type return Unary(lvalue, rvalue, operation_type) elif isinstance(ir, Unpack): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) tuple_var = get_variable(ir, lambda x: x.tuple, *instances) idx = ir.index return Unpack(lvalue, tuple_var, idx) elif isinstance(ir, Length): lvalue = get_variable(ir, lambda x: x.lvalue, *instances) value = get_variable(ir, lambda x: x.value, *instances) return Length(value, lvalue) logger.error('Impossible ir copy on {} ({})'.format(ir, type(ir))) exit(-1)
def _post_member_access(self, expression): expr = get(expression.expression) # Look for type(X).max / min # Because we looked at the AST structure, we need to look into the nested expression # Hopefully this is always on a direct sub field, and there is no weird construction if isinstance(expression.expression, CallExpression) and expression.member_name in [ "min", "max", ]: if isinstance(expression.expression.called, Identifier): if expression.expression.called.value == SolidityFunction( "type()"): assert len(expression.expression.arguments) == 1 val = TemporaryVariable(self._node) type_expression_found = expression.expression.arguments[0] assert isinstance(type_expression_found, ElementaryTypeNameExpression) type_found = type_expression_found.type if expression.member_name == "min:": op = Assignment( val, Constant(str(type_found.min), type_found), type_found, ) else: op = Assignment( val, Constant(str(type_found.max), type_found), type_found, ) self._result.append(op) set_val(expression, val) return # This does not support solidity 0.4 contract_name.balance if (isinstance(expr, Variable) and expr.type == ElementaryType("address") and expression.member_name in ["balance", "code", "codehash"]): val = TemporaryVariable(self._node) name = expression.member_name + "(address)" sol_func = SolidityFunction(name) s = SolidityCall( sol_func, 1, val, sol_func.return_type, ) s.set_expression(expression) s.arguments.append(expr) self._result.append(s) set_val(expression, val) return if isinstance(expr, TypeAlias) and expression.member_name in [ "wrap", "unwrap" ]: # The logic is be handled by _post_call_expression set_val(expression, expr) return # Early lookup to detect user defined types from other contracts definitions # contract A { type MyInt is int} # contract B { function f() public{ A.MyInt test = A.MyInt.wrap(1);}} # The logic is handled by _post_call_expression if isinstance(expr, Contract): if expression.member_name in expr.file_scope.user_defined_types: set_val( expression, expr.file_scope.user_defined_types[expression.member_name]) return val = ReferenceVariable(self._node) member = Member(expr, Constant(expression.member_name), val) member.set_expression(expression) self._result.append(member) set_val(expression, val)
def extract_tmp_call(ins, contract): assert isinstance(ins, TmpCall) if isinstance(ins.called, Variable) and isinstance(ins.called.type, FunctionType): call = InternalDynamicCall(ins.lvalue, ins.called, ins.called.type) call.call_id = ins.call_id return call if isinstance(ins.ori, Member): # If there is a call on an inherited contract, it is an internal call or an event if ins.ori.variable_left in contract.inheritance + [contract]: if str(ins.ori.variable_right) in [f.name for f in contract.functions]: internalcall = InternalCall((ins.ori.variable_right, ins.ori.variable_left.name), ins.nbr_arguments, ins.lvalue, ins.type_call) internalcall.call_id = ins.call_id return internalcall if str(ins.ori.variable_right) in [f.name for f in contract.events]: eventcall = EventCall(ins.ori.variable_right) eventcall.call_id = ins.call_id return eventcall if isinstance(ins.ori.variable_left, Contract): st = ins.ori.variable_left.get_structure_from_name(ins.ori.variable_right) if st: op = NewStructure(st, ins.lvalue) op.call_id = ins.call_id return op libcall = LibraryCall(ins.ori.variable_left, ins.ori.variable_right, ins.nbr_arguments, ins.lvalue, ins.type_call) libcall.call_id = ins.call_id return libcall msgcall = HighLevelCall(ins.ori.variable_left, ins.ori.variable_right, ins.nbr_arguments, ins.lvalue, ins.type_call) msgcall.call_id = ins.call_id return msgcall if isinstance(ins.ori, TmpCall): r = extract_tmp_call(ins.ori, contract) return r if isinstance(ins.called, SolidityVariableComposed): if str(ins.called) == 'block.blockhash': ins.called = SolidityFunction('blockhash(uint256)') elif str(ins.called) == 'this.balance': return SolidityCall(SolidityFunction('this.balance()'), ins.nbr_arguments, ins.lvalue, ins.type_call) if isinstance(ins.called, SolidityFunction): return SolidityCall(ins.called, ins.nbr_arguments, ins.lvalue, ins.type_call) if isinstance(ins.ori, TmpNewElementaryType): return NewElementaryType(ins.ori.type, ins.lvalue) if isinstance(ins.ori, TmpNewContract): op = NewContract(Constant(ins.ori.contract_name), ins.lvalue) op.call_id = ins.call_id return op if isinstance(ins.ori, TmpNewArray): return NewArray(ins.ori.depth, ins.ori.array_type, ins.lvalue) if isinstance(ins.called, Structure): op = NewStructure(ins.called, ins.lvalue) op.call_id = ins.call_id return op if isinstance(ins.called, Event): return EventCall(ins.called.name) if isinstance(ins.called, Contract): # Called a base constructor, where there is no constructor if ins.called.constructor is None: return Nop() internalcall = InternalCall(ins.called.constructor, ins.nbr_arguments, ins.lvalue, ins.type_call) internalcall.call_id = ins.call_id return internalcall raise Exception('Not extracted {} {}'.format(type(ins.called), ins))