def fix_phi(self, last_state_variables_instances, initial_state_variables_instances): for node in self.nodes: for ir in node.irs_ssa: if node == self.entry_point: if isinstance(ir.lvalue, StateIRVariable): additional = [initial_state_variables_instances[ir.lvalue.canonical_name]] additional += last_state_variables_instances[ir.lvalue.canonical_name] ir.rvalues = list(set(additional + ir.rvalues)) # function parameter else: # find index of the parameter idx = self.parameters.index(ir.lvalue.non_ssa_version) # find non ssa version of that index additional = [n.ir.arguments[idx] for n in self.reachable_from_nodes] additional = unroll(additional) additional = [a for a in additional if not isinstance(a, Constant)] ir.rvalues = list(set(additional + ir.rvalues)) if isinstance(ir, PhiCallback): callee_ir = ir.callee_ir if isinstance(callee_ir, InternalCall): last_ssa = callee_ir.function.get_last_ssa_state_variables_instances() if ir.lvalue.canonical_name in last_ssa: ir.rvalues = list(last_ssa[ir.lvalue.canonical_name]) else: ir.rvalues = [ir.lvalue] else: additional = last_state_variables_instances[ir.lvalue.canonical_name] ir.rvalues = list(set(additional + ir.rvalues)) node.irs_ssa = [ir for ir in node.irs_ssa if not self._unchange_phi(ir)]
def _detect_storage_abiencoderv2_arrays(contract): """ Detects and returns all nodes with storage-allocated abiencoderv2 arrays of arrays/structs in abi.encode, events or external calls :param contract: Contract to detect within :return: A list of tuples with (function, node) where function node has storage-allocated abiencoderv2 arrays of arrays/structs """ # Create our result set. results = set() # Loop for each function and modifier. # pylint: disable=too-many-nested-blocks for function in contract.functions_and_modifiers_declared: # Loop every node, looking for storage-allocated array of arrays/structs # in arguments to abi.encode, events or external calls for node in function.nodes: for ir in node.irs: # Call to abi.encode() if (isinstance(ir, SolidityCall) and ir.function == SolidityFunction("abi.encode()") or # Call to emit event # Call to external function isinstance(ir, (EventCall, HighLevelCall))): for arg in unroll(ir.arguments): # Check if arguments are storage allocated arrays of arrays/structs if (isinstance(arg.type, ArrayType) # Storage allocated and (isinstance(arg, StateVariable) or (isinstance(arg, LocalVariable) and arg.is_storage)) # Array of arrays or structs and isinstance(arg.type.type, (ArrayType, UserDefinedType))): results.add((function, node)) break # Return the resulting set of tuples return results
def _unroll(l): return unroll(l)