From 4dc76b3af01227567d6e78defcdca57dc8dbc816 Mon Sep 17 00:00:00 2001 From: HuangYi Date: Fri, 10 Dec 2021 15:14:51 +0800 Subject: [PATCH] Problem: no integration test for EIP-1559 feature Closes: #245 Solution: - enable eip-1559 in integration test devnets - test dynamic fee tx and the fee calculation logic - test base fee adjustment lower initial base fee fix statesync test fix gravity test fix base fee adjustment --- integration_tests/test_basic.py | 12 +++-- integration_tests/test_eip1559.py | 67 +++++++++++++++++++++++++ integration_tests/test_gravity.py | 4 +- integration_tests/utils.py | 24 +++++++++ scripts/cronos-devnet.yaml | 5 +- scripts/cronos-experimental-devnet.yaml | 3 ++ scripts/geth-genesis.json | 6 ++- 7 files changed, 111 insertions(+), 10 deletions(-) create mode 100644 integration_tests/test_eip1559.py diff --git a/integration_tests/test_basic.py b/integration_tests/test_basic.py index 1f430e35c8..6f41829d0c 100644 --- a/integration_tests/test_basic.py +++ b/integration_tests/test_basic.py @@ -69,7 +69,7 @@ def test_events(cluster, suspend_capture): def test_minimal_gas_price(cronos): w3 = cronos.w3 gas_price = w3.eth.gas_price - assert gas_price == 5000000000000 + # assert gas_price == 5000000000000 tx = { "to": "0x0000000000000000000000000000000000000000", "value": 10000, @@ -133,7 +133,7 @@ def test_statesync(cronos): # Do an ethereum transfer tx_value = 10000 gas_price = w3.eth.gas_price - initial_balance = 10000000000000000000000 + initial_balance = w3.eth.get_balance(ADDRS["community"]) tx = {"to": ADDRS["community"], "value": tx_value, "gasPrice": gas_price} txhash_0 = send_transaction(w3, tx, KEYS["validator"])["transactionHash"].hex() @@ -226,11 +226,12 @@ def test_statesync(cronos): def test_transaction(cronos): w3 = cronos.w3 + gas_price = w3.eth.gas_price # send transaction txhash_1 = send_transaction( w3, - {"to": ADDRS["community"], "value": 10000, "gasPrice": w3.eth.gas_price}, + {"to": ADDRS["community"], "value": 10000, "gasPrice": gas_price}, KEYS["validator"], )["transactionHash"] tx1 = w3.eth.get_transaction(txhash_1) @@ -245,7 +246,7 @@ def test_transaction(cronos): { "to": ADDRS["community"], "value": 10000, - "gasPrice": w3.eth.gas_price, + "gasPrice": gas_price, "nonce": w3.eth.get_transaction_count(ADDRS["validator"]) - 1, }, KEYS["validator"], @@ -291,7 +292,8 @@ def test_transaction(cronos): }, KEYS["validator"], )["transactionHash"] - assert "insufficient fee" in str(exc) + # FIXME https://github.com/tharsis/ethermint/pull/911 + assert "invalid base fee" in str(exc) # check all failed transactions are not included in blockchain assert w3.eth.get_block_number() == initial_block_number diff --git a/integration_tests/test_eip1559.py b/integration_tests/test_eip1559.py new file mode 100644 index 0000000000..9c585df64a --- /dev/null +++ b/integration_tests/test_eip1559.py @@ -0,0 +1,67 @@ +from .utils import ADDRS, KEYS, send_transaction, w3_wait_for_block + + +def adjust_base_fee(parent_fee, gas_limit, gas_used): + "spec: https://eips.ethereum.org/EIPS/eip-1559#specification" + change_denominator = 8 + elasticity_multiplier = 2 + gas_target = gas_limit // elasticity_multiplier + + delta = parent_fee * (gas_target - gas_used) // gas_target // change_denominator + return parent_fee - delta + + +def test_dynamic_fee_tx(cluster): + """ + test basic eip-1559 tx works: + - tx fee calculation is compliant to go-ethereum + - base fee adjustment is compliant to go-ethereum + """ + w3 = cluster.w3 + amount = 10000 + before = w3.eth.get_balance(ADDRS["community"]) + tip_price = 1 + max_price = 1000000000000 + tip_price + tx = { + "to": "0x0000000000000000000000000000000000000000", + "value": amount, + "gas": 21000, + "maxFeePerGas": max_price, + "maxPriorityFeePerGas": tip_price, + } + txreceipt = send_transaction(w3, tx, KEYS["community"]) + assert txreceipt.status == 1 + blk = w3.eth.get_block(txreceipt.blockNumber) + assert txreceipt.effectiveGasPrice == blk.baseFeePerGas + tip_price + + fee_expected = txreceipt.gasUsed * txreceipt.effectiveGasPrice + after = w3.eth.get_balance(ADDRS["community"]) + fee_deducted = before - after - amount + assert fee_deducted == fee_expected + + assert blk.gasUsed == txreceipt.gasUsed # we are the only tx in the block + + # check the next block's base fee is adjusted accordingly + w3_wait_for_block(w3, txreceipt.blockNumber + 1) + next_base_price = w3.eth.get_block(txreceipt.blockNumber + 1).baseFeePerGas + + assert next_base_price == adjust_base_fee( + blk.baseFeePerGas, blk.gasLimit, blk.gasUsed + ) + + +def test_base_fee_adjustment(cluster): + """ + verify base fee adjustment of three continuous empty blocks + """ + w3 = cluster.w3 + begin = w3.eth.block_number + w3_wait_for_block(w3, begin + 3) + + blk = w3.eth.get_block(begin) + parent_fee = blk.baseFeePerGas + + for i in range(3): + fee = w3.eth.get_block(begin + 1 + i).baseFeePerGas + assert fee == adjust_base_fee(parent_fee, blk.gasLimit, 0) + parent_fee = fee diff --git a/integration_tests/test_gravity.py b/integration_tests/test_gravity.py index 44514828a9..74df021a17 100644 --- a/integration_tests/test_gravity.py +++ b/integration_tests/test_gravity.py @@ -83,7 +83,9 @@ def geth(tmp_path_factory): @pytest.fixture(scope="module", params=[True, False]) def cronos(request, tmp_path_factory): - "start-cronos" + """start-cronos + params: enable_auto_deployment + """ yield from setup_cronos_experimental( tmp_path_factory.mktemp("cronos_experimental"), 26700, request.param ) diff --git a/integration_tests/utils.py b/integration_tests/utils.py index 01bc4635a0..0b06d9b8c2 100644 --- a/integration_tests/utils.py +++ b/integration_tests/utils.py @@ -137,6 +137,30 @@ def wait_for_ipc(path, timeout=40.0): ) +def w3_wait_for_block(w3, height, timeout=240): + for i in range(timeout * 2): + try: + current_height = w3.eth.block_number + except AssertionError as e: + print(f"get current block number failed: {e}", file=sys.stderr) + else: + if current_height >= height: + break + print("current block height", current_height) + time.sleep(0.5) + else: + raise TimeoutError(f"wait for block {height} timeout") + + +def w3_wait_for_new_blocks(w3, n): + begin_height = w3.eth.block_number + while True: + time.sleep(0.5) + cur_height = w3.eth.block_number + if cur_height - begin_height >= n: + break + + def cluster_fixture( config_path, worker_index, diff --git a/scripts/cronos-devnet.yaml b/scripts/cronos-devnet.yaml index ea210bcc13..0ab29b4061 100644 --- a/scripts/cronos-devnet.yaml +++ b/scripts/cronos-devnet.yaml @@ -3,7 +3,7 @@ cronos_777-1: cmd: cronosd start-flags: "--trace" app-config: - minimum-gas-prices: 5000000000000basetcro + minimum-gas-prices: 0basetcro json-rpc: address: "0.0.0.0:{EVMRPC_PORT}" ws-address: "0.0.0.0:{EVMRPC_PORT_WS}" @@ -53,4 +53,5 @@ cronos_777-1: send_enabled: true feemarket: params: - no_base_fee: true + no_base_fee: false + initial_base_fee: 100000000000 diff --git a/scripts/cronos-experimental-devnet.yaml b/scripts/cronos-experimental-devnet.yaml index 6157460750..163eba2294 100644 --- a/scripts/cronos-experimental-devnet.yaml +++ b/scripts/cronos-experimental-devnet.yaml @@ -33,6 +33,9 @@ cronos_777-1: evm: params: evm_denom: basetcro + feemarket: + params: + no_base_fee: true cronos: params: cronos_admin: crc12luku6uxehhak02py4rcz65zu0swh7wjsrw0pp diff --git a/scripts/geth-genesis.json b/scripts/geth-genesis.json index 8a10b42134..33c0b05790 100644 --- a/scripts/geth-genesis.json +++ b/scripts/geth-genesis.json @@ -13,6 +13,7 @@ "muirGlacierBlock": 0, "berlinBlock": 0, "yoloV3Block": 0, + "londonBlock": 0, "clique": { "period": 2, "epoch": 30000 @@ -21,7 +22,7 @@ "nonce": "0x0", "timestamp": "0x60ed6d23", "extraData": "0x000000000000000000000000000000000000000000000000000000000000000057f96e6b86cdefdb3d412547816a82e3e0ebf9d20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "0x47b760", + "gasLimit": "0x4db9760", "difficulty": "0x1", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase": "0x0000000000000000000000000000000000000000", @@ -35,5 +36,6 @@ }, "number": "0x0", "gasUsed": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": "100000000000" }