def build_evm_message(self, transaction: BaseOrSpoofTransaction) -> Message: gas_fee = transaction.gas * transaction.gas_price # Buy Gas self.vm_state.account_db.delta_balance(transaction.sender, -1 * gas_fee) # Increment Nonce self.vm_state.account_db.increment_nonce(transaction.sender) # Setup VM Message message_gas = transaction.gas - transaction.intrinsic_gas if transaction.to == CREATE_CONTRACT_ADDRESS: contract_address = generate_contract_address( transaction.sender, self.vm_state.account_db.get_nonce(transaction.sender) - 1, ) data = b'' code = transaction.data else: contract_address = None data = transaction.data code = self.vm_state.account_db.get_code(transaction.to) self.vm_state.logger.debug2( ("TRANSACTION: sender: %s | to: %s | value: %s | gas: %s | " "gas-price: %s | s: %s | r: %s | v: %s | data-hash: %s"), encode_hex(transaction.sender), encode_hex(transaction.to), transaction.value, transaction.gas, transaction.gas_price, transaction.s, transaction.r, transaction.v, encode_hex(keccak(transaction.data)), ) message = Message( gas=message_gas, to=transaction.to, sender=transaction.sender, value=transaction.value, data=data, code=code, create_address=contract_address, ) return message
def deploy_contract(vm, bytecode: bytes): sender, priv = accounts.pair(1) nonce = vm.state.account_db.get_nonce(sender) contract = generate_contract_address(sender, nonce) tx = vm.create_unsigned_transaction( nonce=nonce, gas_price=1, gas=3141592, to=b'', value=0, data=bytecode, ).as_signed_transaction(priv) vm.state.apply_transaction(tx) return contract
def generate_contract_address(self, stack_data: CreateOpcodeStackData, call_data: bytes, computation: BaseComputation) -> Address: creation_nonce = computation.state.account_db.get_nonce( computation.msg.storage_address) computation.state.account_db.increment_nonce( computation.msg.storage_address) contract_address = generate_contract_address( computation.msg.storage_address, creation_nonce, ) return contract_address
def __call__(self, computation): computation.consume_gas(self.gas_cost, reason=self.mnemonic) value, start_position, size = computation.stack_pop( num_items=3, type_hint=constants.UINT256, ) computation.extend_memory(start_position, size) insufficient_funds = computation.state.account_db.get_balance( computation.msg.storage_address) < value stack_too_deep = computation.msg.depth + 1 > constants.STACK_DEPTH_LIMIT if insufficient_funds or stack_too_deep: computation.stack_push(0) return call_data = computation.memory_read(start_position, size) create_msg_gas = self.max_child_gas_modifier( computation.get_gas_remaining()) computation.consume_gas(create_msg_gas, reason="CREATE") creation_nonce = computation.state.account_db.get_nonce( computation.msg.storage_address) computation.state.account_db.increment_nonce( computation.msg.storage_address) contract_address = generate_contract_address( computation.msg.storage_address, creation_nonce, ) is_collision = computation.state.account_db.account_has_code_or_nonce( contract_address) if is_collision: self.logger.trace( "Address collision while creating contract: %s", encode_hex(contract_address), ) computation.stack_push(0) return child_msg = computation.prepare_child_message( gas=create_msg_gas, to=constants.CREATE_CONTRACT_ADDRESS, value=value, data=b'', code=call_data, create_address=contract_address, ) child_computation = computation.apply_child_computation(child_msg) if child_computation.is_error: computation.stack_push(0) else: computation.stack_push(contract_address) computation.return_gas(child_computation.get_gas_remaining())