Viewing run older run · latest of 12

Methodology

The proposed gas parameters come from the actual time each execution client takes to run a targeted set of benchmarks: runtimes are collected from the Benchmarkoor API by benchmarkoor-fetch and turned into gas numbers by evm-gasfit. Five stages turn a wall-clock measurement into a gas number:

  1. Benchmark data collection — synthetic blocks stress one operation at a time; Benchmarkoor records each block's runtime and opcode counts.
  2. Runtime model — an NNLS regression isolates the per-unit runtime of each opcode, per client.
  3. Glue adjustment — the overhead of the supporting opcodes that surround the target in each fixture is netted out.
  4. Runtime → gas — the adjusted runtime is converted to gas at a fixed anchor rate.
  5. Worst-case selection — the proposal takes the slowest client for each parameter, then evaluates any derived parameters.

1. Benchmark data collection

The proposed gas costs are grounded in the actual time each execution client takes to run a specific set of benchmarks. Similar to the methodology of the Gas Cost Estimator project, we generate synthetic blocks that isolate and stress individual EVM operations and use them to derive the various gas parameters.

Concretely, to benchmark a single operation, different blocks are created by varying the number of times the target operation is executed and by changing the parameter values passed to it. These test blocks come from the EEST benchmark suite. The raw data that feeds this analysis was queried from the following two Benchmarkoor suites:

The Benchmarkoor tool then runs each block and collects the metrics we need: the block's total execution time and the number of times each operation was executed. Each block is run multiple times on every client to account for variability in execution time. Runtimes are pulled from the Benchmarkoor API by benchmarkoor-fetch; the benchmarks ran on the amsterdam fork and runs are selected by the .*-full.* run-id pattern. The compute suite drives the target-opcode fits, while the stateful suite feeds the glue-opcode analysis. Each block contributes one row to the model: a measured test_runtime_ms alongside the count of every opcode it executed.

2. Runtime model (NNLS)

evm-gasfit solves one non-negative least squares (NNLS) regression per (opcode spec, model variant, client) combination. It models the measured runtime of each fixture as a linear function of how many times the target opcode runs:

test_runtime_ms = intercept + target_coef · opcount + Σ (param_i · opcount · value_i)

The target_coef — the per-unit runtime of the operation under study — is the quantity we care about. The trailing sum carries variable-cost terms: the supporting gas parameters whose cost is netted out of the fixture (for example the cold-access surcharge that rides along with a warm access) get their own fixture parameters, while a state-access operation with a single flat cost collapses to one coefficient. Combined operations such as a cold write are fit whole — as a single access-plus-write cost — and the write-only delta is recovered downstream as a derived parameter, not split out inside the regression. Parameters that are constant across all fixtures are dropped automatically — their column is indistinguishable from target_coef — and a fit is skipped entirely if there are too few observations or the opcount never varies.

The non-negativity constraint is the point of NNLS: gas costs cannot be negative, and an unconstrained fit would let correlated features take opposite signs to cancel noise. NNLS instead drives such a coefficient to exactly zero or spreads the signal across the remaining features.

Inference is a non-parametric bootstrap over the rows of the design matrix (1000 iterations). Each coefficient gets a p-value — the bootstrap share of near-zero estimates — and a 2.5 / 97.5 percentile confidence interval. A fit is flagged as a poor-fit selection when its p-value exceeds 0.05 or its R² falls below 0.5. Fits cover 6 clients:

See the runtime model page for every per-fit regression summary, or the evm-gasfit NNLS docs for the full derivation.

3. Glue adjustment

Glue adjustment is enabled. A benchmark never measures an opcode in isolation: the recorded runtime also includes the glue opcodes that set up arguments, advance the program counter, and clean the stack (pushes, dups, loads, control flow). Because NNLS attributes the entire intercept + target_coef · opcount budget to the target, glue that scales with the loop body inflates the estimate. Glue adjustment removes that overhead before the runtime is converted to gas.

evm-gasfit works from a fixed set of canonical glue opcodes, fit in dependency tiers (pure opcodes first, then cycle, then mixed tiers that lean on the already-priced ones). The adjustment runs in three steps:

adjusted_target_coef = max(0, target_coef − Σ_g ratio_g · glue_runtime_ms_g)

A glue partner only contributes to the sum when its own fit clears the same p-value (< 0.05) and R² (≥ 0.5) gates; the confidence interval shifts with it and clips at zero. Skipped fits — targets left without a glue correction — are listed under Warnings. See the glue page for the per-fit detail and the evm-gasfit glue docs for the tier structure.

4. Runtime → gas

Each adjusted runtime coefficient is converted to gas at a fixed anchor rate of 100,000,000 gas/s (100 Mgas/s) — the throughput EIP-8038 targets. With runtime_ms in milliseconds:

new_gas = ⌈ anchor_rate · runtime_ms / 1000 ⌉

Any op whose measured cost implies a slower throughput than the anchor lands above its current price and is flagged for a bump; the ceiling keeps the result an integer.

5. Worst-case selection & derived parameters

A single gas parameter is fit many times — once per client, sometimes across several fixtures. The proposal consolidates those in two passes, always erring toward the slowest observation so the cost holds on every implementation:

Finally, derived parameters (those defined in terms of others) are evaluated in declaration order against the fitted values, the fork baseline, and any new_params integer baselines, using a small arithmetic-only expression language. The client comparison shows how far the worst client sits from the rest of the field. The evm-gasfit gas-params docs cover the selection and derivation rules in full.

Parameter → model map

Every proposed value traces back to a specific set of model fits or to a formula over other parameters. The two tables below are the full provenance for this run, built directly from the fit artifacts.

Estimated parameters

Each parameter below is fit by NNLS (stage 2) over the listed model specs — the worst-case selector (stage 5) then picks the binding client and combo. Target opcodes are the operations whose runtime the fixtures stress; fixtures are the benchmark tests that feed the regression; coefficient is the regression term read off as the per-unit runtime. The exact winning combo and binding client per parameter are on the new-gas and goals pages.

ParameterPresetsTarget opcodesFixturesCoefficient
COLD_STORAGE_ACCESS cold_storage_sload, cold_storage_sstore_access SLOAD, SSTORE test_sload_bloated, test_sstore_bloated target_coef
COLD_STORAGE_WRITE cold_storage_sstore_write SSTORE test_sstore_bloated target_coef
COLD_ACCOUNT_NOCODE_ACCESS cold_account_nocode_access BALANCE, CALL, CALLCODE, DELEGATECALL, EXTCODECOPY, EXTCODEHASH, EXTCODESIZE, STATICCALL test_account_access target_coef
COLD_ACCOUNT_CODE_ACCESS cold_account_code_access BALANCE, CALL, CALLCODE, DELEGATECALL, EXTCODECOPY, EXTCODEHASH, EXTCODESIZE, STATICCALL test_account_access target_coef
COLD_ACCOUNT_NOCODE_WRITE cold_account_nocode_write CALL, CALLCODE test_account_access target_coef
COLD_ACCOUNT_CODE_WRITE cold_account_code_write CALL, CALLCODE test_account_access target_coef
WARM_ACCESS warm_account_access, warm_storage_access_sload BALANCE, CALL, CALLCODE, DELEGATECALL, EXTCODEHASH, EXTCODESIZE, STATICCALL, SLOAD test_ext_account_query_warm, test_storage_sload_same_key_benchmark target_coef

Derived parameters

These carry no per-client fit. They are evaluated in declaration order (stage 5) over the estimated parameters above, the osaka fork baseline, and the new_params integer baselines, using an arithmetic-only expression language (max, + − × ÷, integer literals). The formulas are taken verbatim from fit.yaml.

ParameterFormula
STORAGE_WRITE max(0, COLD_STORAGE_WRITE - COLD_STORAGE_ACCESS)
ACCOUNT_WRITE max(0, COLD_ACCOUNT_CODE_WRITE - COLD_ACCOUNT_CODE_ACCESS, COLD_ACCOUNT_NOCODE_WRITE - COLD_ACCOUNT_NOCODE_ACCESS)
REFUND_STORAGE_CLEAR COLD_STORAGE_WRITE * 4800 / 5000
TX_ACCESS_LIST_STORAGE_KEY COLD_STORAGE_ACCESS
TX_ACCESS_LIST_ADDRESS max(COLD_ACCOUNT_CODE_ACCESS, COLD_ACCOUNT_NOCODE_ACCESS)

Gas-cost baseline

Proposed values are compared against the osaka gas-cost table — distinct from the amsterdam fork the benchmarks ran on. The baseline is the osaka GasCosts patched with any config overrides and new_params baselines, and it is the intended cost reference for the EIP-8038 proposal.

Reproducibility

Re-run the full pipeline end to end:

make fetch     # → data/raw/    (needs a Benchmarkoor token in secrets.json)
make gasfit    # → data/gasfit/
make site      # renders this site into site/

The committed data/ directory makes the published site self-contained: every figure and table on these pages traces back to those artifacts.