|
| 1 | +from eth_utils import ValidationError |
| 2 | +import pytest |
| 3 | + |
| 4 | +from eth._utils.address import force_bytes_to_address |
| 5 | +from eth.chains.base import MiningChain |
| 6 | +from eth.constants import GAS_TX |
| 7 | +from eth.tools.factories.transaction import new_fee_burn_transaction |
| 8 | +from eth.vm.forks import LondonVM |
| 9 | + |
| 10 | + |
| 11 | +@pytest.fixture |
| 12 | +def london_plus_miner(chain_without_block_validation): |
| 13 | + if not isinstance(chain_without_block_validation, MiningChain): |
| 14 | + pytest.skip("This test is only meant to run with mining capability") |
| 15 | + return |
| 16 | + |
| 17 | + valid_vms = ( |
| 18 | + LondonVM, |
| 19 | + ) |
| 20 | + vm = chain_without_block_validation.get_vm() |
| 21 | + if isinstance(vm, valid_vms): |
| 22 | + return chain_without_block_validation |
| 23 | + else: |
| 24 | + pytest.skip("This test is not meant to run on pre-London VMs") |
| 25 | + |
| 26 | + |
| 27 | +ADDRESS_A = force_bytes_to_address(b'\x10\x10') |
| 28 | + |
| 29 | + |
| 30 | +def test_transaction_cost_valid(london_plus_miner, funded_address, funded_address_private_key): |
| 31 | + chain = london_plus_miner |
| 32 | + vm = chain.get_vm() |
| 33 | + base_fee_per_gas = vm.get_header().base_fee_per_gas |
| 34 | + # Make sure we're testing an interesting case |
| 35 | + assert base_fee_per_gas > 0 |
| 36 | + |
| 37 | + account_balance = vm.state.get_balance(funded_address) |
| 38 | + |
| 39 | + tx = new_fee_burn_transaction( |
| 40 | + vm, |
| 41 | + from_=funded_address, |
| 42 | + to=ADDRESS_A, |
| 43 | + private_key=funded_address_private_key, |
| 44 | + gas=GAS_TX, |
| 45 | + amount=account_balance - base_fee_per_gas * GAS_TX, |
| 46 | + max_priority_fee_per_gas=1, |
| 47 | + max_fee_per_gas=base_fee_per_gas, |
| 48 | + ) |
| 49 | + |
| 50 | + # sanity check |
| 51 | + assert vm.get_header().gas_used == 0 |
| 52 | + |
| 53 | + # There should be no validation failure when applying the transaction |
| 54 | + chain.apply_transaction(tx) |
| 55 | + |
| 56 | + # sanity check: make sure the transaction actually got applied |
| 57 | + assert chain.get_vm().get_header().gas_used > 0 |
| 58 | + |
| 59 | + |
| 60 | +def test_transaction_cost_invalid(london_plus_miner, funded_address, funded_address_private_key): |
| 61 | + chain = london_plus_miner |
| 62 | + vm = chain.get_vm() |
| 63 | + base_fee_per_gas = vm.get_header().base_fee_per_gas |
| 64 | + # Make sure we're testing an interesting case |
| 65 | + assert base_fee_per_gas > 0 |
| 66 | + |
| 67 | + account_balance = vm.state.get_balance(funded_address) |
| 68 | + |
| 69 | + tx = new_fee_burn_transaction( |
| 70 | + vm, |
| 71 | + from_=funded_address, |
| 72 | + to=ADDRESS_A, |
| 73 | + private_key=funded_address_private_key, |
| 74 | + gas=GAS_TX, |
| 75 | + amount=account_balance - base_fee_per_gas * GAS_TX + 1, |
| 76 | + max_priority_fee_per_gas=1, |
| 77 | + max_fee_per_gas=base_fee_per_gas, |
| 78 | + ) |
| 79 | + |
| 80 | + # sanity check |
| 81 | + assert vm.get_header().gas_used == 0 |
| 82 | + |
| 83 | + # The *validation* step should catch that the sender does not have enough funds. If validation |
| 84 | + # misses the problem, then we might see an InsufficientFunds, because the VM will think the |
| 85 | + # transaction is fine, then attempt to execute it, then then run out of funds. |
| 86 | + with pytest.raises(ValidationError): |
| 87 | + chain.apply_transaction(tx) |
| 88 | + |
| 89 | + # sanity check: make sure the transaction does not get applied |
| 90 | + assert chain.get_vm().get_header().gas_used == 0 |
0 commit comments