[DO-NOT-MERGE] execution: implement EIP-7976 #20613
Conversation
Raise the calldata floor cost from 10/40 (EIP-7623) to a uniform 64 gas per byte, activated with the Amsterdam (Glamsterdam) fork. This reduces the maximum possible block size by ~37% with minimal user impact. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move to gitignored agentspecs/ directory instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Avoid calling p.isAmsterdam() twice per iteration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Avoid calling p.isAmsterdam() three times; use a single local variable. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
yperbasis
left a comment
There was a problem hiding this comment.
-
Awkward overflow-variable plumbing (intrinsic_gas.go:127-132):
var overflow bool
if args.IsEIP7976 {
tokenLen, overflow = math.SafeMul(dataLen, 4)
...
}
...
dataGas, overflow := math.SafeMul(tokenLen, costPerToken)
Compiles (same-scope redeclaration with new LHS dataGas), but the outer var overflow bool exists solely to allow the IsEIP7976 branch's SafeMul. The else branch never touches it, then
the := redeclares/reassigns. Cleaner: scope overflow inside the if IsEIP7976 block, or rename the outer var. -
Overflow asymmetry (pre-existing) (intrinsic_gas.go:140):
The EIP-7976 branch uses math.SafeMul(dataLen, 4); the EIP-7623 branch still has unchecked dataLen + 3*nz. Not introduced by this PR, but while you're here it'd be trivial to harden. -
Test comment imprecision (intrinsic_gas_test.go:174-176):
// EIP-7976 should always be >= EIP-7623 for zero bytes,
// and equal or different for non-zero bytes.
EIP-7976 is strictly greater than EIP-7623 in every positive-data case (64 > 10 for zero bytes, 64 > 40 for non-zero). Suggest rewording to "strictly greater than EIP-7623 for any
non-empty calldata".
There was a problem hiding this comment.
Pull request overview
Implements EIP-7976 (Amsterdam) intrinsic-gas calldata floor changes by introducing an IsEIP7976 flag in intrinsic gas calculation and wiring it through txpool/execution paths.
Changes:
- Add
IsEIP7976to intrinsic gas calculation arguments and implement the EIP-7976 floor token/cost formula. - Propagate
IsEIP7976(Amsterdam) through txpool, txn execution, AA tx, and execution test utilities. - Add unit tests covering EIP-7976 floor cost behavior and comparison vs EIP-7623.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
txnprovider/txpool/pool.go |
Plumbs Amsterdam flag into intrinsic gas calculation and gas cap logic for txpool selection/validation. |
execution/types/aa_transaction.go |
Passes Amsterdam flag into AA intrinsic gas calculation. |
execution/tests/testutil/transaction_test_util.go |
Passes Amsterdam flag into intrinsic gas calculation used by execution tests. |
execution/protocol/txn_executor.go |
Passes Amsterdam flag into intrinsic gas calculation used by the transaction executor. |
execution/protocol/params/protocol.go |
Introduces the EIP-7976 calldata-floor per-token constant (16). |
execution/protocol/mdgas/intrinsic_gas.go |
Adds IsEIP7976 and implements the EIP-7976 floor token/cost formula. |
execution/protocol/mdgas/intrinsic_gas_test.go |
Adds unit tests for EIP-7976 floor cost and comparisons vs EIP-7623. |
Comments suppressed due to low confidence (3)
txnprovider/txpool/pool.go:998
- In
validateTx, the floor-vs-regular adjustment is gated byisPragueonly. If Amsterdam is scheduled without Prague/Bhilai, EIP-7976’s floor cost would be ignored when validating/budgeting intrinsic gas. Consider treating Amsterdam as enabling the calldata floor too (e.g.,hasCalldataFloor := isPrague || isAmsterdam) and using that for both theIntrinsicGasCalcArgsflags and theFloorGasCostvsRegularGascomparison.
IsEIP2028: true,
IsEIP3860: isEIP3860,
IsEIP7623: isPrague,
IsEIP7976: isAmsterdam,
IsEIP8037: isAmsterdam,
IsAATxn: isAATxn,
})
gas := mdgas.MdGas{
Regular: intrinsicGasResult.RegularGas,
State: intrinsicGasResult.StateGas,
}
if isPrague && intrinsicGasResult.FloorGasCost > gas.Regular {
gas.Regular = intrinsicGasResult.FloorGasCost
}
execution/tests/testutil/transaction_test_util.go:99
requiredGasonly considersFloorGasCostwhenrules.IsPragueis true. If Amsterdam (EIP-7976) can be activated without Prague in test configs, the increased calldata floor would be skipped here. Consider keying this check off the intrinsic-gas flags instead (e.g., apply the floor whenrules.IsPrague || rules.IsAmsterdam, or when the intrinsic gas calculation indicates a non-trivialFloorGasCost).
IsEIP2028: rules.IsIstanbul,
IsEIP3860: rules.IsShanghai,
IsEIP7623: rules.IsPrague,
IsEIP7976: rules.IsAmsterdam,
IsEIP8037: rules.IsAmsterdam,
})
requiredGas := intrinsicGasResult.RegularGas
if rules.IsPrague && intrinsicGasResult.FloorGasCost > requiredGas {
requiredGas = intrinsicGasResult.FloorGasCost
}
txnprovider/txpool/pool.go:804
- In
best(), the floor-vs-regular selection is still gated byisEIP7623only. If Amsterdam is enabled without Prague/Bhilai,IntrinsicGasCalcArgswill haveIsEIP7976=truebut this code will continue to budget againstRegularGasonly, potentially selecting txs that exceed the available regular gas once the EIP-7976 floor is applied. Consider using an explicithasCalldataFloor := isEIP7623 || isAmsterdamhere (and using it both when settingIsEIP7623/IsEIP7976and when comparing againstFloorGasCost).
IsEIP3860: isEIP3860,
IsEIP7623: isEIP7623,
IsEIP7976: isAmsterdam,
IsEIP8037: isAmsterdam,
IsAATxn: isAATxn,
})
intrinsicRegularGas := intrinsicGasResult.RegularGas
if isEIP7623 && intrinsicGasResult.FloorGasCost > intrinsicRegularGas {
intrinsicRegularGas = intrinsicGasResult.FloorGasCost
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| intrinsicGasResult, overflow := mdgas.IntrinsicGas(mdgas.IntrinsicGasCalcArgs{ | ||
| Data: data, | ||
| AuthorizationsLen: uint64(len(tx.Authorizations)), | ||
| AccessListLen: uint64(len(tx.AccessList)), | ||
| StorageKeysLen: uint64(tx.AccessList.StorageKeys()), | ||
| IsEIP2: rules.IsHomestead, | ||
| IsEIP2028: rules.IsIstanbul, | ||
| IsEIP3860: hasEIP3860, | ||
| IsEIP7623: rules.IsPrague, | ||
| IsEIP7976: rules.IsAmsterdam, | ||
| IsEIP8037: rules.IsAmsterdam, | ||
| IsAATxn: true, | ||
| }) |
| @@ -839,6 +839,7 @@ func (st *TxnExecutor) calcIntrinsicGas(contractCreation bool, auths []types.Aut | |||
| IsEIP2028: rules.IsIstanbul, | |||
| IsEIP3860: vmConfig.HasEip3860(rules), | |||
| IsEIP7623: rules.IsPrague, | |||
| if args.IsEIP7623 { | ||
| tokenLen := dataLen + 3*nz | ||
| dataGas, overflow := math.SafeMul(tokenLen, params.TxTotalCostFloorPerToken) | ||
| var tokenLen uint64 | ||
| var costPerToken uint64 | ||
| var overflow bool | ||
| if args.IsEIP7976 { | ||
| // EIP-7976: floor_tokens = total_bytes * 4, cost_per_token = 16 |
|
@taratorio |
closes #20543
waiting on eest tests for bal-devnet-4