[go: up one dir, main page]

Etherlink: Remove maximum gas limit condition

TODO

  • add item in CHANGELOG
  • fix remaining tests
  • update commit messages if required

What

This MR removes the maximum execution gas limit validation that rejects transactions with over-estimated gas limit.

Part of L2-18

Why

Etherlink transactions have two distinct fee components:

  • Inclusion fees (DA fees) - Cost based on transaction data size
  • Execution fees - Cost based on computational work performed

The estimateGas RPC returns the sum of both fee types for any given transaction.

As demand increases and more execution gas is used in a shorter time, Etherlink increases the gas price to increase the execution fee but not the inclusion fee. https://docs.etherlink.com/network/fees/#execution-fee

Current issue: The validation logic in validate.ml valides execution fees as follows:

tx_execution_fees = gas_limit(tx) - inclusion_fees(tx)
validate (tx_execution_fees <= MAXIMUM_GAS_LIMIT)

where:

  • inclusion_fees(tx) = exact inclusion fees required (source)
  • MAXIMUM_GAS_LIMIT = 30M (source)
  • gas_limit(tx) = user-provided gas limit

Note: here for the sake of simplicity we use MAXIMUM_GAS_LIMIT but it would be MAXIMUM_GAS_PER_TRANSACTION if provided when configuring the kernel.

Users commonly over-estimate gas limits to ensure their transactions succeed. However, this creates an unintended consequence as over-estimation inflates the calculated inclusion fees, causing valid transactions to be rejected.

Notably, when deploying substantial contracts:

  • Inclusion fees become significant
  • Even modest percentage margins cause large absolute increases

Example

Here is an example where the user relies on a 150% over-approximation of the gas estimation and hits the maximum allowed execution fee.

Component Actual Need User Estimate (150% over-approximation)
Gas limit 60M 90M
Inclusion fees 55M 55M (unchanged)
Execution fees 5M 35M

How

  1. Remove execution fee maximum validation in evm node (validate.ml) but keeps inclusion fee minimum validation.
  2. Eliminate the same validation in kernel (blocks.rs).
  3. Update can_fit_in_reboot in kernel (blocks.rs) to bound the gas limit provided using evm limits.
  4. Bound the gas limit in apply.rs using evm limits.

Why I think it is safe

  • Inclusion fee validation ensures gas covers minimum required data costs
  • The can_fit_in_reboot will still be operating as expected: asking for a reboot in case of high gas limit, as it is currently done.
  • Applying a transaction is still capped at MAXIMUM_GAS_LIMIT (or maximum_gas_per_transaction if provided) via min(gas, limits.maximum_gas_limit) (source)

This should ensure no transaction can actually consume more than 30M (or maximum_gas_per_transaction if provided) gas during execution, regardless of the user-provided gas limit.

Manual testing

1. Test relaxed maximum gas limit validation

  1. Build the kernel and start sandbox EVM node:
make -f etherlink.mk EVM_KERNEL_FEATURES=debug build && make octez-evm-node && \
TEZOS_EVENTS_CONFIG="file-descriptor-stdout://?section-prefix=evm_node:debug&colors=true&advertise-levels=true&format=pp-short" \
./octez-evm-node run sandbox --network testnet --init-from-snapshot \
--data-dir working-dir/sandbox --config-file working-dir/sandbox-config.json \
--fund 0x9b49c988b5817Be31DfB00F7a5a4671772dCce2B --kernel evm_kernel.wasm \
--kernel-verbosity debug -v &> debug.log
  1. Send transaction with excessive gas limit:
cast send --rpc-url 127.0.0.1:8545 --gas-limit 60000000 --private-key 0x9722f6cc9ff938e63f8ccb74c3daa6b45837e5c5e3835ac08c44c50ab5f39dc0 0x6ce4d79d4E77402e1ef3417Fdda433aA744C6e1c 
 
blockHash            0x26a900d2288bb82a1eb657abef813503b70aa8bc99d13039222f1c1867bab324
blockNumber          19512291
contractAddress      
cumulativeGasUsed    621000
effectiveGasPrice    1000000000
from                 0x6ce4d79d4E77402e1ef3417Fdda433aA744C6e1c
gasUsed              621000
logs                 []
logsBloom            0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
root                 
status               1 (success)
transactionHash      0x0f1be52921fbcb4a82db0ad6151f8e3d44be60f2dff961995630693662ecee60
transactionIndex     0
type                 2
blobGasPrice         
blobGasUsed          
to                   0x6ce4d79d4E77402e1ef3417Fdda433aA744C6e1c
  1. Transaction should be confirmed
$ grep -B1 confirmed debug.log | grep -A1 0f1be52921fbcb
May 31 14:07:56.146  DEBUG │ transaction 0f1be52921fbcb4a82db0ad6151f8e3d44be60f2dff961995630693662ecee60
May 31 14:07:56.146  DEBUG │   confirmed

2. Test out of gas still applying

  1. Deploy the following SimpleComputeBurner.sol contract
$ solc --bin --abi SimpleComputeBurner.sol -o build/
Compiler run successful. Artifact(s) can be found in directory "build/".
$ cast send \                                       
  --private-key 0x9722f6cc9ff938e63f8ccb74c3daa6b45837e5c5e3835ac08c44c50ab5f39dc0 \
  --create   $(cat build/SimpleComputeBurner.bin)
...
contractAddress      0x04A606985CA06343bE8caD2C9EE3624aa16E698E
...
  1. Run the following highly gas-consuming transaction
$ cast send --private-key 0x9722f6cc9ff938e63f8ccb74c3daa6b45837e5c5e3835ac08c44c50ab5f39dc0  0xdF161529E1fcf74CFf3342790E6Ca536b05b0a95 "burnGas(uint256)" 100000
Error: Failed to estimate gas: Max retries exceeded server returned an error response: error code -32005: The transaction failed: Error(OutOfGas).
$ cast send --gas-limit 1000000000 --private-key 0x9722f6cc9ff938e63f8ccb74c3daa6b45837e5c5e3835ac08c44c50ab5f39dc0  0xdF161529E1fcf74CFf3342790E6Ca536b05b0a95 "burnGas(uint256)" 100000
 
blockHash            0xb540126fcc2618c69b95b5a1324282bde31a7819a84993b5e63ecb40dc38d4b4
blockNumber          19513901
contractAddress      
cumulativeGasUsed    30744000
effectiveGasPrice    1000000000
from                 0x6ce4d79d4E77402e1ef3417Fdda433aA744C6e1c
gasUsed              30744000
logs                 []
logsBloom            0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
root                 
status               0 (failed)
transactionHash      0x3968e747a31c6285079bb3a5b5b05083d10711929c3cea15689b5bff684a17ca
transactionIndex     0
type                 2
blobGasPrice         
blobGasUsed          
to                   0xdF161529E1fcf74CFf3342790E6Ca536b05b0a95
  1. In the EVM node logs you can note the transaction has been executed and fails because of an OutOfGas error.
May 31 16:31:10.440  DEBUG │   {"jsonrpc":"2.0","result":{"type":"0x2","chainId":"0x1f47b","hash":"0x2c2e24a1546133a70452ba2a8950425f853f89cf3dbbd801202fc7fcee823cce","nonce":"0x4b4ea","blockHash":"0xb190fbbf64132acf78fe46a5ff1b18cdf3f5dc1372140460b845c449be6651bc","blockNumber":"0x129c249","transactionIndex":"0x0","from":"0x6ce4d79d4e77402e1ef3417fdda433aa744c6e1c","to":"0xdf161529e1fcf74cff3342790e6ca536b05b0a95","value":"0x0","gas":"0x3b9aca00","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","accessList":[],"input":"0x4ad5d16f00000000000000000000000000000000000000000000000000000000000186a0","v":"0x1","r":"0x0b41dc7edac47d9edeaaf318bb7778a7012093950469ee6bcfc4825a9298d219","s":"0x7e3ca0238542109615633a12d5884b5e9662aac8f6f554f976c9dcc5418c55f1"},"id":20}
...
May 31 16:31:10.829  DEBUG │   {"jsonrpc":"2.0","error":{"code":-32003,"message":"The transaction failed:
May 31 16:31:10.829  DEBUG │   Error(OutOfGas)."},"id":21}
Edited by Paul Laforgue

Merge request reports

Loading