Skip to content

Commit 58c5664

Browse files
joshklopclaude
andcommitted
feat(op-acceptance-tests): add EIP-7825 tx gas limit cap test
Add TestEIP7825TxGasLimitCap to verify the 2^24 transaction gas limit cap is enforced after Karst. Uses txplan to send real transactions since EIP-7825 is a tx validity rule not enforced by eth_call or eth_simulateV1. Tests both pre-karst (gas above cap allowed) and post-karst (gas above cap rejected, gas at cap succeeds). Also adds WithKarstAtGenesis deployer option and fixes the tx manager gas estimator to set callMsg.Gas to params.MaxTxGas before calling EstimateGas, which is required post-Osaka. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0b4fe1a commit 58c5664

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

op-acceptance-tests/tests/osaka_on_l2_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"github.com/ethereum-optimism/optimism/op-devstack/devtest"
99
"github.com/ethereum-optimism/optimism/op-devstack/presets"
1010
"github.com/ethereum-optimism/optimism/op-devstack/sysgo"
11+
"github.com/ethereum-optimism/optimism/op-service/eth"
12+
"github.com/ethereum-optimism/optimism/op-service/txplan"
1113
"github.com/ethereum/go-ethereum"
1214
"github.com/ethereum/go-ethereum/common"
1315
"github.com/ethereum/go-ethereum/core/vm"
@@ -116,6 +118,55 @@ func TestEIP7883ModExpGasCostIncrease(gt *testing.T) {
116118
t.Require().NoError(err, "post-fork: modexp should succeed with 600 execution gas (floor is 500)")
117119
}
118120

121+
func TestEIP7825TxGasLimitCap(gt *testing.T) {
122+
t := devtest.ParallelT(gt)
123+
testCases := map[string]struct {
124+
opt sysgo.DeployerOption
125+
expectErr bool
126+
}{
127+
"pre-karst": {
128+
opt: sysgo.WithJovianAtGenesis,
129+
},
130+
"post-karst": {
131+
opt: sysgo.WithKarstAtGenesis,
132+
expectErr: true,
133+
},
134+
}
135+
// EIP-7825 caps transaction gas at 2^24 = 16,777,216.
136+
// This is a tx validity rule enforced at the txpool/block level, not by the
137+
// EVM, so eth_call and eth_simulateV1 don't enforce it. We must send a real
138+
// transaction and verify the RPC rejects it.
139+
const maxTxGas = 1 << 24
140+
for name, testCase := range testCases {
141+
t.Run(name, func(t devtest.T) {
142+
t.Parallel()
143+
sys := presets.NewMinimal(t, presets.WithDeployerOptions(testCase.opt))
144+
145+
eoa := sys.FunderL2.NewFundedEOA(eth.OneEther)
146+
147+
planWithGasLimit := func(gas uint64) txplan.Option {
148+
return txplan.Combine(
149+
eoa.Plan(),
150+
txplan.WithGasLimit(gas),
151+
txplan.WithTo(&common.Address{}),
152+
)
153+
}
154+
155+
_, err := txplan.NewPlannedTx(planWithGasLimit(maxTxGas)).Success.Eval(t.Ctx())
156+
t.Require().NoError(err, "tx with gas at 2^24 should succeed")
157+
158+
tx := txplan.NewPlannedTx(planWithGasLimit(maxTxGas + 1))
159+
if testCase.expectErr {
160+
_, err := tx.Included.Eval(t.Ctx())
161+
t.Require().Error(err, "tx with gas above 2^24 should be rejected")
162+
} else {
163+
_, err := tx.Success.Eval(t.Ctx())
164+
t.Require().NoError(err, "tx with gas above 2^24 should succeed")
165+
}
166+
})
167+
}
168+
}
169+
119170
func TestEIP7939CLZ(gt *testing.T) {
120171
t := devtest.ParallelT(gt)
121172

op-devstack/sysgo/deployer.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ func WithKarstAtOffset(offset *uint64) DeployerOption {
6767
}
6868
}
6969

70+
func WithKarstAtGenesis(p devtest.T, _ devkeys.Keys, builder intentbuilder.Builder) {
71+
for _, l2Cfg := range builder.L2s() {
72+
l2Cfg.WithForkAtGenesis(opforks.Karst)
73+
}
74+
}
75+
7076
func WithJovianAtGenesis(p devtest.T, _ devkeys.Keys, builder intentbuilder.Builder) {
7177
for _, l2Cfg := range builder.L2s() {
7278
l2Cfg.WithForkAtGenesis(opforks.Jovian)

op-service/txmgr/txmgr.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/ethereum/go-ethereum/core/types"
2020
"github.com/ethereum/go-ethereum/crypto/kzg4844"
2121
"github.com/ethereum/go-ethereum/log"
22+
"github.com/ethereum/go-ethereum/params"
2223
"github.com/ethereum/go-ethereum/rpc"
2324
"github.com/holiman/uint256"
2425

@@ -489,6 +490,7 @@ func (m *SimpleTxManager) estimateOrValidateCandidateTxGas(ctx context.Context,
489490
}
490491
// If the gas limit is set, we can use that as the gas
491492
if candidate.GasLimit == 0 {
493+
callMsg.Gas = params.MaxTxGas
492494
gas, err := m.backend.EstimateGas(ctx, callMsg)
493495
if err != nil {
494496
return 0, fmt.Errorf("failed to estimate gas: %w", errutil.TryAddRevertReason(err))

0 commit comments

Comments
 (0)