def create_contract(self, data: str, value: int = 0, debug: int = 0, **kwargs) -> Address: """ Creates a new smart contract. :param data: The data field. Must include constructor code in order for new contract to be created. :param value: The value to be sent alongside the transaction. :param debug: Signalizes whether the user wants the current transaction to be debugged or just send it out. :return: The address under which the newly created contract is located. """ nonce = self.vm.state.get_nonce(MASTER_ADDRESS) MyComputation.debug_mode = debug MyComputation.kwargs = kwargs MyComputation.call_depth = 0 block, receipt, computation = self._make_transaction( nonce, DEFAULT_GAS_PRICE, DEFAULT_TRANSACTION_GAS_AMOUNT, constants.CREATE_CONTRACT_ADDRESS, value, decode_hex(data)) logger.info( "Created contract with {b}, receipt {r}, and computation {c}". format(b=block, r=receipt, c=computation)) self._mine_block() if computation.is_error: return Address(b'') else: return generate_contract_address(MASTER_ADDRESS, nonce)
def build_evm_message(self, transaction: SignedTransactionAPI) -> MessageAPI: # Use vm_state.get_gas_price instead of transaction_context.gas_price so # that we can run get_transaction_result (aka~ eth_call) and estimate_gas. # Both work better if the GASPRICE opcode returns the original real price, # but the sender's balance doesn't actually deduct the gas. This get_gas_price() # will return 0 for eth_call, but transaction_context.gas_price will return # the same value as the GASPRICE opcode. gas_fee = transaction.gas * self.vm_state.get_gas_price(transaction) # Buy Gas self.vm_state.delta_balance(transaction.sender, -1 * gas_fee) # Increment Nonce self.vm_state.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.get_nonce(transaction.sender) - 1, ) data = b'' code = transaction.data else: contract_address = None data = transaction.data code = self.vm_state.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 | y_parity: %s | data-hash: %s" ), encode_hex(transaction.sender), encode_hex(transaction.to), transaction.value, transaction.gas, transaction.gas_price, transaction.s, transaction.r, transaction.y_parity, 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 build_delegation_evm_message(self, transaction: SignedTransactionAPI) -> MessageAPI: ### DAEJUN changed ### # gas_fee = transaction.gas * transaction.gas_price gas_fee = 0 ### DAEJUN changed ### # Buy Gas self.vm_state.delta_balance(transaction.sender, -1 * gas_fee) # Increment Nonce self.vm_state.increment_nonce(transaction.sender) # Setup VM Message # VM에 최초로 전달하는 가스량. 그냥 두면 된다. message_gas = transaction.gas - transaction.intrinsic_gas if transaction.to == CREATE_CONTRACT_ADDRESS: contract_address = generate_contract_address( transaction.sender, self.vm_state.get_nonce(transaction.sender) - 1, ) data = b'' code = transaction.data else: contract_address = None data = transaction.data code = self.vm_state.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 | y_parity: %s | data-hash: %s" ), encode_hex(transaction.sender), encode_hex(transaction.to), transaction.value, transaction.gas, transaction.gas_price, transaction.s, transaction.r, transaction.y_parity, 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 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 generate_contract_address(self, stack_data: CreateOpcodeStackData, call_data: bytes, computation: ComputationAPI) -> Address: creation_nonce = computation.state.get_nonce( computation.msg.storage_address) computation.state.increment_nonce(computation.msg.storage_address) contract_address = generate_contract_address( computation.msg.storage_address, creation_nonce, ) return contract_address
def deploy_storage_churn_contract(chain, nonce=0): deploy_tx = chain.create_unsigned_transaction( nonce=nonce, gas_price=1234, gas=3000000, to=b'', value=0, data=decode_hex( "608060405234801561001057600080fd5b50600160008080815260200190815260200160002081905550610336806100386000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634903b0d114610051578063622ff59a14610093578063adbd8315146100c1578063ef6537b5146100ef575b600080fd5b61007d6004803603602081101561006757600080fd5b810190808035906020019092919050505061011d565b6040518082815260200191505060405180910390f35b6100bf600480360360208110156100a957600080fd5b8101908080359060200190929190505050610135565b005b6100ed600480360360208110156100d757600080fd5b810190808035906020019092919050505061020e565b005b61011b6004803603602081101561010557600080fd5b8101908080359060200190929190505050610265565b005b60006020528060005260406000206000915090505481565b3073ffffffffffffffffffffffffffffffffffffffff1663adbd8315826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561018857600080fd5b505af115801561019c573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff1663adbd8315826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156101f357600080fd5b505af1158015610207573d6000803e3d6000fd5b5050505050565b60008090505b81811015610260576000806000838152602001908152602001600020541115610253576000808281526020019081526020016000206000905550610262565b8080600101915050610214565b505b50565b60008090505b818110156102e457600160008083815260200190815260200160002054036000806001840181526020019081526020016000205414156102d757600080828152602001908152602001600020546000806001840181526020019081526020016000208190555050610307565b808060010191505061026b565b506001600080808152602001908152602001600020600082825401925050819055505b5056fea165627a7a72305820dba28f294357644493dce42aff2ea2bf5f72e20dcb00a6ed4094dd313bf8f5220029" ), # noqa: E501 ) chain.apply_transaction(deploy_tx.as_signed_transaction(FUNDED_ACCT)) chain.mine_block() return generate_contract_address( FUNDED_ACCT.public_key.to_canonical_address(), nonce)
def _add_nymph_contract(chain, nonce): deploy_tx = chain.create_unsigned_transaction( nonce=nonce, gas_price=1234, gas=123457, to=b'', value=0, data=decode_hex( "6080604052348015600f57600080fd5b50607a8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80635969aa8414602d575b600080fd5b60336035565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea165627a7a72305820cc81a4355ab2bb255e1233528ced5013be67280d530689ba007ed9f206230c740029" ), # noqa: E501 ) _, _, computation = chain.apply_transaction( deploy_tx.as_signed_transaction(FUNDED_ACCT)) assert computation.is_success return generate_contract_address( FUNDED_ACCT.public_key.to_canonical_address(), nonce)
def add_nymph_contract(chain, nonce, variant=0): if variant not in range(len(NYMPH_BYTECODES)): raise ValueError(f"Unrecognized Nymph variant {variant}") deploy_tx = chain.create_unsigned_transaction( nonce=nonce, gas_price=1234, gas=123457, to=b'', value=0, data=NYMPH_BYTECODES[variant], ) _, _, computation = chain.apply_transaction( deploy_tx.as_signed_transaction(FUNDED_ACCT)) computation.raise_if_error() return generate_contract_address( FUNDED_ACCT.public_key.to_canonical_address(), nonce)
def mk_contract_address(address: Union[str, bytes], nonce: int) -> str: return to_checksum_address( generate_contract_address(to_canonical_address(address), nonce) )