def test_resending_mined_transaction_raises( deploy_client: JSONRPCClient) -> None: """ If a mined transaction is re-sent the exception `EthereumNonceTooLow` is raised. """ # Use a _fixed_ gas price strategy so that both transactions are identical. deploy_client.web3.eth.setGasPriceStrategy( make_fixed_gas_price_strategy(GasPrice(2000000000))) contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.address assert len(deploy_client.web3.eth.getCode(address)) > 0 # Create a new instance of the JSONRPCClient, this will store the current available nonce client_invalid_nonce = JSONRPCClient(deploy_client.web3, deploy_client.privkey) estimated_transaction = deploy_client.estimate_gas(contract_proxy, "ret", {}) assert estimated_transaction, "Gas estimation should not fail here" transaction_hash = deploy_client.transact(estimated_transaction) deploy_client.poll_transaction(transaction_hash) # At this point `client_invalid_nonce` has a nonce that is `1` too low, # since a transaction was sent using `deploy_client` above and these two # instances share the same underlying private key. # # Note that the same function is called in this test. with pytest.raises(EthereumNonceTooLow): proxy_invalid = client_invalid_nonce.new_contract_proxy( abi=contract_proxy.abi, contract_address=contract_proxy.address) estimated_transaction_invalid = deploy_client.estimate_gas( proxy_invalid, "ret", {}) msg = "ret always succed, gas estimation should have succeed." assert estimated_transaction_invalid, msg client_invalid_nonce.transact(estimated_transaction_invalid)
def test_reusing_nonce_with_lower_gas_raises( deploy_client: JSONRPCClient) -> None: """ If a _new_ transaction is sent but with a lower gas the exception `ReplacementTransactionUnderpriced` is raised. """ # Use a _decreasing_ gas price strategy so that the second transactions is # lower than the first. deploy_client.web3.eth.setGasPriceStrategy( make_decreasing_gas_price_strategy(GasPrice(2000000000))) contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.address assert len(deploy_client.web3.eth.getCode(address)) > 0 client_invalid_nonce = JSONRPCClient(web3=deploy_client.web3, privkey=deploy_client.privkey) estimated_transaction = deploy_client.estimate_gas(contract_proxy, "ret", {}) assert estimated_transaction, "Gas estimation should not fail here" deploy_client.transact(estimated_transaction) # At this point `client_invalid_nonce` has a nonce that is `1` too low, # since a transaction was sent using `deploy_client` above and these two # instances share the same underlying private key. # # Note that the same function is called in this test but the gas is decreasing. with pytest.raises(ReplacementTransactionUnderpriced): proxy_invalid = client_invalid_nonce.new_contract_proxy( abi=contract_proxy.abi, contract_address=contract_proxy.address) estimated_transaction = client_invalid_nonce.estimate_gas( proxy_invalid, "ret_str", {}) assert estimated_transaction, "ret_str never fails, gas estimation must succeed." client_invalid_nonce.transact(estimated_transaction)
def test_reusing_nonce_with_lower_gas_raises( deploy_client: JSONRPCClient) -> None: """ If a _new_ transaction is sent but with a lower gas the exception `ReplacementTransactionUnderpriced` is raised. """ # Use a _decreasing_ gas price strategy so that the second transactions is # lower than the first. deploy_client.web3.eth.setGasPriceStrategy( make_decreasing_gas_price_strategy(GasPrice(2000000000))) contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.contract_address assert len(deploy_client.web3.eth.getCode( to_checksum_address(address))) > 0 client_invalid_nonce = JSONRPCClient(web3=deploy_client.web3, privkey=deploy_client.privkey) check_block = deploy_client.get_checking_block() gas_estimate = contract_proxy.estimate_gas(check_block, "ret") assert gas_estimate, "Gas estimation should not fail here" startgas = safe_gas_limit(gas_estimate) contract_proxy.transact("ret", startgas) # At this point `client_invalid_nonce` has a nonce that is `1` too low, # since a transaction was sent using `deploy_client` above and these two # instances share the same underlying private key. # # Note that the same function is called in this test but the gas is decreasing. with pytest.raises(ReplacementTransactionUnderpriced): client_invalid_nonce.new_contract_proxy( abi=contract_proxy.contract.abi, contract_address=contract_proxy.contract_address).transact( "ret_str", contract_proxy.estimate_gas(check_block, "ret_str"))
def test_filter_end_block_inclusive(deploy_client): """ A filter includes events from the block given in from_block until and including end_block. """ contract_proxy = deploy_rpc_test_contract(deploy_client, "RpcTest") check_block = deploy_client.get_checking_block() # call the create event function twice and wait for confirmation each time startgas = safe_gas_limit(contract_proxy.estimate_gas(check_block, "createEvent", 1)) transaction_1 = contract_proxy.transact("createEvent", startgas, 1) deploy_client.poll(transaction_1) transaction_2 = contract_proxy.transact("createEvent", startgas, 2) deploy_client.poll(transaction_2) result_1 = deploy_client.get_filter_events(contract_proxy.contract_address) block_number_events = get_list_of_block_numbers(result_1) block_number_event_1 = block_number_events[0] block_number_event_2 = block_number_events[1] # inclusive to_block should return first event result_2 = deploy_client.get_filter_events( contract_proxy.contract_address, to_block=block_number_event_1 ) assert get_list_of_block_numbers(result_2) == [block_number_event_1] # this should include the second event result_3 = deploy_client.get_filter_events( contract_proxy.contract_address, to_block=block_number_event_2 ) assert get_list_of_block_numbers(result_3) == block_number_events
def test_reusing_nonce_from_a_mined_transaction_raises( deploy_client: JSONRPCClient) -> None: """ If a _new_ transaction is sent with an old nonce the exception `EthereumNonceTooLow` is raised. """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") # Create a new instance of the JSONRPCClient, this will store the current available nonce client_invalid_nonce = JSONRPCClient(deploy_client.web3, deploy_client.privkey) estimated_transaction = deploy_client.estimate_gas(contract_proxy, "ret", {}) msg = "ret always succed, gas estimation should have succeed." assert estimated_transaction, msg transaction_hash = deploy_client.transact(estimated_transaction) # Wait for the transaction to be mined (concurrent transactions are tested # by test_local_transaction_with_zero_gasprice_is_mined) deploy_client.poll_transaction(transaction_hash) # At this point `client_invalid_nonce` has a nonce that is `1` too low, # since a transaction was sent using `deploy_client` above and these two # instances share the same underlying private key. # # Note that a different function is called in this test. with pytest.raises(EthereumNonceTooLow): proxy_invalid = client_invalid_nonce.new_contract_proxy( abi=contract_proxy.abi, contract_address=contract_proxy.address) estimated_transaction_invalid = deploy_client.estimate_gas( proxy_invalid, "ret_str", {}) msg = "ret_str always succed, gas estimation should have succeed." assert estimated_transaction_invalid, msg client_invalid_nonce.transact(estimated_transaction_invalid)
def test_resending_mined_transaction_raises( deploy_client: JSONRPCClient) -> None: """ If a mined transaction is re-sent the exception `EthereumNonceTooLow` is raised. """ # Use a _fixed_ gas price strategy so that both transactions are identical. deploy_client.web3.eth.setGasPriceStrategy( make_fixed_gas_price_strategy(GasPrice(2000000000))) contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.contract_address assert len(deploy_client.web3.eth.getCode( to_checksum_address(address))) > 0 # Create a new instance of the JSONRPCClient, this will store the current available nonce client_invalid_nonce = JSONRPCClient(deploy_client.web3, deploy_client.privkey) check_block = deploy_client.get_checking_block() gas_estimate = contract_proxy.estimate_gas(check_block, "ret") assert gas_estimate, "Gas estimation should not fail here" startgas = safe_gas_limit(gas_estimate) txhash = contract_proxy.transact("ret", startgas) deploy_client.poll(txhash) # At this point `client_invalid_nonce` has a nonce that is `1` too low, # since a transaction was sent using `deploy_client` above and these two # instances share the same underlying private key. # # Note that the same function is called in this test. with pytest.raises(EthereumNonceTooLow): client_invalid_nonce.new_contract_proxy( abi=contract_proxy.contract.abi, contract_address=contract_proxy.contract_address).transact( "ret", startgas)
def test_reusing_nonce_from_a_mined_transaction_raises( deploy_client: JSONRPCClient) -> None: """ If a _new_ transaction is sent with an old nonce the exception `EthereumNonceTooLow` is raised. """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") # Create a new instance of the JSONRPCClient, this will store the current available nonce client_invalid_nonce = JSONRPCClient(deploy_client.web3, deploy_client.privkey) check_block = deploy_client.get_checking_block() txhash = contract_proxy.transact( "ret", contract_proxy.estimate_gas(check_block, "ret")) # Wait for the transaction to be mined (concurrent transactions are tested # by test_local_transaction_with_zero_gasprice_is_mined) deploy_client.poll(txhash) # At this point `client_invalid_nonce` has a nonce that is `1` too low, # since a transaction was sent using `deploy_client` above and these two # instances share the same underlying private key. # # Note that a different function is called in this test. with pytest.raises(EthereumNonceTooLow): client_invalid_nonce.new_contract_proxy( abi=contract_proxy.contract.abi, contract_address=contract_proxy.contract_address).transact( "ret_str", contract_proxy.estimate_gas(check_block, "ret_str"))
def test_local_transaction_with_zero_gasprice_is_mined( deploy_client: JSONRPCClient) -> None: """ If a transaction is sent through the eth_sendRawTransaction interface, directly to the miner, with a gas price of zero, it is considered local and mined anyways. """ normal_gas_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") gas_price = GasPrice(0) gas_price_strategy = make_fixed_gas_price_strategy(gas_price) deploy_client.web3.eth.setGasPriceStrategy(gas_price_strategy) zero_gas_proxy = deploy_client.new_contract_proxy( abi=normal_gas_proxy.contract.abi, contract_address=normal_gas_proxy.contract_address) address = normal_gas_proxy.contract_address assert len(deploy_client.web3.eth.getCode( to_checksum_address(address))) > 0 check_block = deploy_client.get_checking_block() gas_estimate = zero_gas_proxy.estimate_gas(check_block, "ret") assert gas_estimate, "Gas estimation should not fail here" zerogas_txhash = zero_gas_proxy.transact("ret", gas_estimate) zerogas_receipt = deploy_client.poll(zerogas_txhash) zerogas_tx = deploy_client.web3.eth.getTransaction(zerogas_txhash) msg = "Even thought the transaction had a zero gas price, it is not removed from the pool" assert zerogas_tx is not None, msg msg = "Even though the transaction had gas price of zero, it did get mined." assert zerogas_receipt["status"] != RECEIPT_FAILURE_CODE, msg
def test_filter_start_block_inclusive(deploy_client: JSONRPCClient) -> None: """ A filter includes events from the block given in from_block """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") # call the create event function twice and wait for confirmation each time estimated_transaction1 = deploy_client.estimate_gas( contract_proxy, "createEvent", {}, 1) assert estimated_transaction1 transaction_1 = deploy_client.transact(estimated_transaction1) deploy_client.poll_transaction(transaction_1) estimated_transaction2 = deploy_client.estimate_gas( contract_proxy, "createEvent", {}, 1) assert estimated_transaction2 transaction_2 = deploy_client.transact(estimated_transaction2) deploy_client.poll_transaction(transaction_2) result_1 = deploy_client.get_filter_events(contract_proxy.address) block_number_events = get_list_of_block_numbers(result_1) block_number_event_1 = block_number_events[0] block_number_event_2 = block_number_events[1] # inclusive from_block should return both events result_2 = deploy_client.get_filter_events(contract_proxy.address, from_block=block_number_event_1) assert get_list_of_block_numbers(result_2) == block_number_events # a higher from_block must not contain the first event result_3 = deploy_client.get_filter_events( contract_proxy.address, from_block=block_number_event_1 + 1) assert get_list_of_block_numbers(result_3) == [block_number_event_2]
def test_filter_end_block_inclusive(deploy_client: JSONRPCClient) -> None: """A filter includes events from the block given in from_block until and including end_block.""" contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") # call the create event function twice and wait for confirmation each time estimated_transaction1 = deploy_client.estimate_gas( contract_proxy, "createEvent", {}, 1) assert estimated_transaction1 transaction_1 = deploy_client.transact(estimated_transaction1) deploy_client.poll_transaction(transaction_1) estimated_transaction2 = deploy_client.estimate_gas( contract_proxy, "createEvent", {}, 1) assert estimated_transaction2 transaction_2 = deploy_client.transact(estimated_transaction2) deploy_client.poll_transaction(transaction_2) result_1 = deploy_client.get_filter_events(contract_proxy.address) block_number_events = get_list_of_block_numbers(result_1) block_number_event_1 = block_number_events[0] block_number_event_2 = block_number_events[1] # inclusive to_block should return first event result_2 = deploy_client.get_filter_events(contract_proxy.address, to_block=block_number_event_1) assert get_list_of_block_numbers(result_2) == [block_number_event_1] # this should include the second event result_3 = deploy_client.get_filter_events(contract_proxy.address, to_block=block_number_event_2) assert get_list_of_block_numbers(result_3) == block_number_events
def test_estimate_gas_fails_if_startgas_is_higher_than_blockgaslimit( deploy_client: JSONRPCClient, ) -> None: """ Gas estimation fails if the transaction execution requires more gas than the block's gas limit. """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcWithStorageTest") latest_block_hash = deploy_client.blockhash_from_blocknumber(BLOCK_ID_LATEST) current_gas_limit = deploy_client.get_block(latest_block_hash)["gasLimit"] # This number of iterations is an over estimation to accomodate for races, # this cannot be significantly large because on parity it is a blocking # call. number_iterations = current_gas_limit // SSTORE_COST # This race condition cannot be fixed because geth does not support # block_identifier for eth_estimateGas. The test should not be flaky # because number_iterations is order of magnitudes larger then it needs to # be estimated_transaction = deploy_client.estimate_gas( contract_proxy, "waste_storage", {}, number_iterations ) msg = "estimate_gas must return empty if sending the transaction would fail" assert estimated_transaction is None, msg
def test_parity_request_pruned_data_raises_an_exception( deploy_client: JSONRPCClient) -> None: """ Interacting with an old block identifier with a pruning client throws. """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcWithStorageTest") iterations = 1000 def send_transaction() -> TransactionMined: estimated_transaction = deploy_client.estimate_gas( contract_proxy, "waste_storage", {}, iterations) assert estimated_transaction transaction = deploy_client.transact(estimated_transaction) return deploy_client.poll_transaction(transaction) first_receipt = send_transaction().receipt pruned_block_number = first_receipt["blockNumber"] for _ in range(10): send_transaction() with pytest.raises(ValueError): contract_proxy.functions.const().call( block_identifier=pruned_block_number) with pytest.raises(ValueError): contract_proxy.functions.get(1).call( block_identifier=pruned_block_number) with pytest.raises(ValueError): check_address_has_code( deploy_client, to_canonical_address(contract_proxy.address), "RpcWithStorageTest", given_block_identifier=pruned_block_number, )
def test_estimate_gas_defaults_to_pending(deploy_client: JSONRPCClient) -> None: """Estimating gas without an explicit block identifier always return an usable value. This test makes sure that the gas estimation works as expected (IOW, it will produce a value that can be used for start_gas and the transaction will be mined). This test was added because the clients Geth and Parity diverge in their estimate_gas interface. Geth never accepts a block_identifier for eth_estimateGas, and Parity rejects anything but `latest` if it is run with `--pruning=fast`. """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcWithStorageTest") estimated_first_transaction = deploy_client.estimate_gas( contract_proxy, "gas_increase_exponential", {} ) assert estimated_first_transaction, "gas estimation should not have failed" first_tx = deploy_client.transact(estimated_first_transaction) estimated_second_transaction = deploy_client.estimate_gas( contract_proxy, "gas_increase_exponential", {} ) assert estimated_second_transaction, "gas estimation should not have failed" second_tx = deploy_client.transact(estimated_second_transaction) first_receipt = deploy_client.poll_transaction(first_tx).receipt second_receipt = deploy_client.poll_transaction(second_tx).receipt assert second_receipt["gasLimit"] < deploy_client.get_block(BLOCK_ID_LATEST)["gasLimit"] assert first_receipt["status"] != RECEIPT_FAILURE_CODE assert second_receipt["status"] != RECEIPT_FAILURE_CODE
def test_resending_pending_transaction_raises(deploy_client: JSONRPCClient) -> None: """ If a pending transaction is re-sent the exception `EthereumNonceTooLow` is raised. This tests is only sufficient because of the companion test `test_resending_mined_transaction_raises` which shows that if the transaction has been mined a different exception is raised. """ # Use a _fixed_ gas price strategy so that both transactions are identical. deploy_client.web3.eth.setGasPriceStrategy(make_fixed_gas_price_strategy(GasPrice(2000000000))) contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.contract_address assert len(deploy_client.web3.eth.getCode(to_checksum_address(address))) > 0 # Create a new instance of the JSONRPCClient, this will store the current available nonce client_invalid_nonce = JSONRPCClient(web3=deploy_client.web3, privkey=deploy_client.privkey) check_block = deploy_client.get_checking_block() gas_estimate = contract_proxy.estimate_gas(check_block, "ret") assert gas_estimate, "Gas estimation should not fail here" startgas = safe_gas_limit(gas_estimate) # At this point `client_invalid_nonce` has a nonce that is `1` too low, # since a transaction was sent using `deploy_client` above and these two # instances share the same underlying private key. # # Note that it is assumed this runs fast enough so that the first transaction is not # mined before second is sent. contract_proxy.transact("ret", startgas) with pytest.raises(EthereumNonceTooLow): client_invalid_nonce.new_contract_proxy( abi=contract_proxy.contract.abi, contract_address=contract_proxy.contract_address ).transact("ret", startgas)
def test_parity_request_prunned_data_raises_an_exception(deploy_client): """ Interacting with an old block identifier with a pruning client throws. """ contract_proxy = deploy_rpc_test_contract(deploy_client, "RpcWithStorageTest") iterations = 1000 def send_transaction(): check_block = deploy_client.get_checking_block() startgas = contract_proxy.estimate_gas(check_block, "waste_storage", iterations) startgas = safe_gas_limit(startgas) transaction = contract_proxy.transact("waste_storage", startgas, iterations) deploy_client.poll(transaction) return deploy_client.get_transaction_receipt(transaction) first_receipt = send_transaction() pruned_block_number = first_receipt["blockNumber"] for _ in range(10): send_transaction() with pytest.raises(ValueError): contract_proxy.contract.functions.const().call( block_identifier=pruned_block_number) with pytest.raises(ValueError): contract_proxy.contract.functions.get(1).call( block_identifier=pruned_block_number)
def test_filter_start_block_inclusive(deploy_client): """ A filter includes events from the block given in from_block """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") check_block = deploy_client.get_checking_block() # call the create event function twice and wait for confirmation each time startgas = safe_gas_limit(contract_proxy.estimate_gas(check_block, "createEvent", 1)) transaction_1 = contract_proxy.transact("createEvent", startgas, 1) deploy_client.poll(transaction_1) transaction_2 = contract_proxy.transact("createEvent", startgas, 2) deploy_client.poll(transaction_2) result_1 = deploy_client.get_filter_events(contract_proxy.contract_address) block_number_events = get_list_of_block_numbers(result_1) block_number_event_1 = block_number_events[0] block_number_event_2 = block_number_events[1] # inclusive from_block should return both events result_2 = deploy_client.get_filter_events( contract_proxy.contract_address, from_block=block_number_event_1 ) assert get_list_of_block_numbers(result_2) == block_number_events # a higher from_block must not contain the first event result_3 = deploy_client.get_filter_events( contract_proxy.contract_address, from_block=block_number_event_1 + 1 ) assert get_list_of_block_numbers(result_3) == [block_number_event_2]
def test_call_throws(deploy_client): """ A JSON RPC call to a function that throws/gets reverted returns the empty string. """ contract_proxy = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.contract_address assert len(deploy_client.web3.eth.getCode(to_checksum_address(address))) > 0 call = contract_proxy.contract.functions.fail().call assert call() == []
def test_estimate_gas_fail(deploy_client): """ A JSON RPC estimate gas call for a throwing transaction returns None""" contract_proxy = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.contract_address assert len(deploy_client.web3.eth.getCode(to_checksum_address(address))) > 0 check_block = deploy_client.get_checking_block() assert not contract_proxy.estimate_gas(check_block, "fail")
def test_call_throws(deploy_client: JSONRPCClient) -> None: """ A JSON RPC call to a function that throws/gets reverted returns the empty string. """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.address assert len(deploy_client.web3.eth.getCode(address)) > 0 call = contract_proxy.functions.fail_assert().call assert call() == [] call = contract_proxy.functions.fail_require().call assert call() == []
def test_estimate_gas_fail(deploy_client: JSONRPCClient) -> None: """ A JSON RPC estimate gas call for a throwing transaction returns None""" contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.address assert len(deploy_client.web3.eth.getCode(address)) > 0 msg = "Estimate gas should return None if the transaction hit an assert" assert deploy_client.estimate_gas(contract_proxy, "fail_assert", {}) is None, msg msg = "Estimate gas should return None if the transaction hit a revert." assert deploy_client.estimate_gas(contract_proxy, "fail_require", {}) is None, msg
def test_call_works_with_blockhash(deploy_client): """ A JSON RPC call works with a block number or blockhash. """ contract_proxy, receipt = deploy_rpc_test_contract(deploy_client, "RpcTest") deploy_blockhash = receipt["blockHash"] assert contract_proxy.contract.functions.ret().call( block_identifier=deploy_blockhash) == 1 deploy_block = receipt["blockNumber"] assert contract_proxy.contract.functions.ret().call( block_identifier=deploy_block) == 1
def test_call_with_a_block_number_before_smart_contract_deployed( deploy_client: JSONRPCClient, ) -> None: """ A JSON RPC call using a block number where the smart contract was not yet deployed should raise. """ contract_proxy, receipt = deploy_rpc_test_contract(deploy_client, "RpcTest") deploy_block = receipt["blockNumber"] assert contract_proxy.functions.ret().call( block_identifier=deploy_block) == 1 with pytest.raises(BadFunctionCallOutput): contract_proxy.functions.ret().call(block_identifier=deploy_block - 1)
def test_estimate_gas_fail(deploy_client): """ A JSON RPC estimate gas call for a throwing transaction returns None""" contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.contract_address assert len(deploy_client.web3.eth.getCode(to_checksum_address(address))) > 0 check_block = deploy_client.get_checking_block() msg = "Estimate gas should return None if the transaction hit an assert" assert contract_proxy.estimate_gas(check_block, "fail_assert") is None, msg msg = "Estimate gas should return None if the transaction hit a revert." assert contract_proxy.estimate_gas(check_block, "fail_require") is None, msg
def test_transact_opcode(deploy_client: JSONRPCClient) -> None: """ The receipt status field of a transaction that did not throw is 0x1 """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.contract_address assert len(deploy_client.web3.eth.getCode( to_checksum_address(address))) > 0 check_block = deploy_client.get_checking_block() startgas = contract_proxy.estimate_gas(check_block, "ret") * 2 transaction = contract_proxy.transact("ret", startgas) receipt = deploy_client.poll(transaction) assert check_transaction_threw(receipt=receipt) is None, "must be empty"
def test_transact_throws_opcode(deploy_client: JSONRPCClient) -> None: """ The receipt status field of a transaction that hit an assert or require is 0x0 """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.address assert len(deploy_client.web3.eth.getCode(address)) > 0 # the method always fails, so the gas estimation returns 0 here, using a # hardcoded a value to circumvent gas estimation. estimated_gas = safe_gas_limit(22000) gas_price = gas_price_for_fast_transaction(deploy_client.web3) block = deploy_client.get_block(BLOCK_ID_LATEST) estimated_transaction_fail_assert = TransactionEstimated( from_address=address, data=SmartContractCall(contract_proxy, "fail_assert", (), {}, value=0), eth_node=deploy_client.eth_node, extra_log_details={}, estimated_gas=estimated_gas, gas_price=gas_price, approximate_block=(block["hash"], block["number"]), ) transaction_fail_assert_sent = deploy_client.transact( estimated_transaction_fail_assert) transaction_fail_assert_mined = deploy_client.poll_transaction( transaction_fail_assert_sent) msg = "Transaction must have failed" assert not was_transaction_successfully_mined( transaction_fail_assert_mined), msg estimated_transaction_fail_require = TransactionEstimated( from_address=address, data=SmartContractCall(contract_proxy, "fail_require", (), {}, value=0), eth_node=deploy_client.eth_node, extra_log_details={}, estimated_gas=estimated_gas, gas_price=gas_price, approximate_block=(block["hash"], block["number"]), ) transaction_fail_require_sent = deploy_client.transact( estimated_transaction_fail_require) transaction_fail_require_mined = deploy_client.poll_transaction( transaction_fail_require_sent) msg = "Transaction must have failed" assert not was_transaction_successfully_mined( transaction_fail_require_mined), msg
def test_transact_opcode(deploy_client: JSONRPCClient) -> None: """ The receipt status field of a transaction that did not throw is 0x1 """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.address assert len(deploy_client.web3.eth.getCode(address)) > 0 estimated_transaction = deploy_client.estimate_gas(contract_proxy, "ret", {}) assert estimated_transaction estimated_transaction.estimated_gas *= 2 transaction_sent = deploy_client.transact(estimated_transaction) transaction_mined = deploy_client.poll_transaction(transaction_sent) assert was_transaction_successfully_mined( transaction_mined), "Transaction must be succesfull"
def test_transact_fails_if_the_account_does_not_have_enough_eth_to_pay_for_the_gas( deploy_client: JSONRPCClient, ) -> None: """ The gas estimation does not fail if the transaction execution requires more gas then the account's eth balance. However sending the transaction will. """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") estimated_transaction = deploy_client.estimate_gas(contract_proxy, "loop", {}, 1000) assert estimated_transaction, "The gas estimation should not have failed." burn_eth(deploy_client, amount_to_leave=estimated_transaction.estimated_gas // 2) with pytest.raises(InsufficientEth): deploy_client.transact(estimated_transaction)
def test_transact_throws_opcode(deploy_client): """ The receipt status field of a transaction that threw is 0x0 """ contract_proxy = deploy_rpc_test_contract(deploy_client, "RpcTest") address = contract_proxy.contract_address assert len(deploy_client.web3.eth.getCode( to_checksum_address(address))) > 0 # the gas estimation returns 0 here, so hardcode a value startgas = safe_gas_limit(22_000) transaction = contract_proxy.transact("fail", startgas) deploy_client.poll(transaction) assert check_transaction_threw(deploy_client, transaction), "must not be empty"
def test_call_which_returns_a_string_before_smart_contract_deployed( deploy_client): """ A JSON RPC call using a block number where the smart contract was not yet deployed should raise, even if the ABI of the function returns an empty string. """ contract_proxy, receipt = deploy_rpc_test_contract(deploy_client, "RpcTest") deploy_block = receipt["blockNumber"] assert contract_proxy.contract.functions.ret_str().call( block_identifier=deploy_block) == "" with pytest.raises(BadFunctionCallOutput): contract_proxy.contract.functions.ret_str().call( block_identifier=deploy_block - 1)
def test_transact_fails_if_the_account_does_not_have_enough_eth_to_pay_for_the_gas( deploy_client: JSONRPCClient) -> None: """ The gas estimation does not fail if the transaction execution requires more gas then the account's eth balance. However sending the transaction will. """ contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcTest") check_block = deploy_client.get_checking_block() startgas = contract_proxy.estimate_gas(check_block, "loop", 1000) assert startgas, "The gas estimation should not have failed." burn_eth(deploy_client, amount_to_leave=startgas // 2) with pytest.raises(InsufficientEth): contract_proxy.transact("loop", startgas, 1000)