From fe48802e27b76339c9c53628141535dd34ea2f9d Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 4 Mar 2026 17:28:49 -0500 Subject: [PATCH 1/9] align gas calculation --- .../precompiles/bank/testdata/BankCaller.sol | 10 +++ precompiles/bank/testdata/BankCaller.json | 28 +++++++- precompiles/bank/testdata/BankCaller.sol | 10 +++ precompiles/common/precompile.go | 7 +- .../precompiles/bank/test_integration.go | 64 +++++++++++++++++++ 5 files changed, 115 insertions(+), 4 deletions(-) diff --git a/contracts/solidity/precompiles/bank/testdata/BankCaller.sol b/contracts/solidity/precompiles/bank/testdata/BankCaller.sol index 7322fe118..f9ed0a7b0 100644 --- a/contracts/solidity/precompiles/bank/testdata/BankCaller.sol +++ b/contracts/solidity/precompiles/bank/testdata/BankCaller.sol @@ -16,4 +16,14 @@ contract BankCaller { function callSupplyOf(address erc20Address) external view returns (uint256) { return IBANK_CONTRACT.supplyOf(erc20Address); } + + // Calls totalSupply with explicit gas forwarding and measures the gas consumed + // by the inner call. Returns whether the call succeeded and the actual gas used. + function callTotalSupplyWithGas(uint256 gasForward) external view returns (bool success, uint256 innerGasUsed) { + uint256 gasBefore = gasleft(); + (success, ) = IBANK_PRECOMPILE_ADDRESS.staticcall{gas: gasForward}( + abi.encodeWithSelector(IBank.totalSupply.selector) + ); + innerGasUsed = gasBefore - gasleft(); + } } \ No newline at end of file diff --git a/precompiles/bank/testdata/BankCaller.json b/precompiles/bank/testdata/BankCaller.json index 049940cd2..ae0f8dfef 100644 --- a/precompiles/bank/testdata/BankCaller.json +++ b/precompiles/bank/testdata/BankCaller.json @@ -77,10 +77,34 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasForward", + "type": "uint256" + } + ], + "name": "callTotalSupplyWithGas", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "innerGasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" } ], - "bytecode": "0x6080806040523461001657610378908161001c8239f35b600080fdfe60806040908082526004918236101561001757600080fd5b600091823560e01c90816389129c681461016257508063acab2f94146100e95763bba60ca01461004657600080fd5b346100e557602092836003193601126100e15780356001600160a01b038116908190036100dd578251631890039360e21b81529182015283816024816108045afa9283156100d257809361009d575b505051908152f35b909192508382813d83116100cb575b6100b68183610234565b810103126100c8575051903880610095565b80fd5b503d6100ac565b8251903d90823e3d90fd5b8380fd5b8280fd5b5080fd5b508290346100e157826003193601126100e15782815180936318160ddd60e01b8252816108045afa918215610158578361012f9493610133575b505051918291826101e1565b0390f35b6101509293503d8091833e6101488183610234565b81019061026c565b908380610123565b81513d85823e3d90fd5b92939050346100dd5760203660031901126100dd5780356001600160a01b03811691908290036101dd576327e235e360e01b845283015282826024816108045afa918215610158578361012f94936101c057505051918291826101e1565b6101d59293503d8091833e6101488183610234565b903880610123565b8480fd5b60208082019080835283518092528060408094019401926000905b83821061020b57505050505090565b845180516001600160a01b031687528301518684015294850194938201936001909101906101fc565b90601f8019910116810190811067ffffffffffffffff82111761025657604052565b634e487b7160e01b600052604160045260246000fd5b6020808284031261032857815167ffffffffffffffff9283821161032857019083601f83011215610328578151838111610256576040938451956102b5848460051b0188610234565b828752838088019360061b86010194818611610328578401925b8584106102e0575050505050505090565b8684830312610328578651908782018281108582111761032d5788528451906001600160a01b0382168203610328578287928a945282870151838201528152019301926102cf565b600080fd5b60246000634e487b7160e01b81526041600452fdfea2646970667358221220069405aa45fc21b29f725237543db2b8600a62c69a04e7a4c44dce45d314303e64736f6c63430008140033", - "deployedBytecode": "0x60806040908082526004918236101561001757600080fd5b600091823560e01c90816389129c681461016257508063acab2f94146100e95763bba60ca01461004657600080fd5b346100e557602092836003193601126100e15780356001600160a01b038116908190036100dd578251631890039360e21b81529182015283816024816108045afa9283156100d257809361009d575b505051908152f35b909192508382813d83116100cb575b6100b68183610234565b810103126100c8575051903880610095565b80fd5b503d6100ac565b8251903d90823e3d90fd5b8380fd5b8280fd5b5080fd5b508290346100e157826003193601126100e15782815180936318160ddd60e01b8252816108045afa918215610158578361012f9493610133575b505051918291826101e1565b0390f35b6101509293503d8091833e6101488183610234565b81019061026c565b908380610123565b81513d85823e3d90fd5b92939050346100dd5760203660031901126100dd5780356001600160a01b03811691908290036101dd576327e235e360e01b845283015282826024816108045afa918215610158578361012f94936101c057505051918291826101e1565b6101d59293503d8091833e6101488183610234565b903880610123565b8480fd5b60208082019080835283518092528060408094019401926000905b83821061020b57505050505090565b845180516001600160a01b031687528301518684015294850194938201936001909101906101fc565b90601f8019910116810190811067ffffffffffffffff82111761025657604052565b634e487b7160e01b600052604160045260246000fd5b6020808284031261032857815167ffffffffffffffff9283821161032857019083601f83011215610328578151838111610256576040938451956102b5848460051b0188610234565b828752838088019360061b86010194818611610328578401925b8584106102e0575050505050505090565b8684830312610328578651908782018281108582111761032d5788528451906001600160a01b0382168203610328578287928a945282870151838201528152019301926102cf565b600080fd5b60246000634e487b7160e01b81526041600452fdfea2646970667358221220069405aa45fc21b29f725237543db2b8600a62c69a04e7a4c44dce45d314303e64736f6c63430008140033", + "bytecode": "0x608080604052346100165761045b908161001c8239f35b600080fdfe60806040908082526004908136101561001757600080fd5b600090813560e01c90816389129c681461024557508063acab2f94146101cd578063bba60ca01461012b5763d47052031461005157600080fd5b34610128576020366003190112610128575a90835192602084016318160ddd60e01b81528185528585019467ffffffffffffffff95818110878211176101155787525183918291906108048535fa933d1561010f573d9081116100fc578551906100c5601f8201601f191660200183610317565b81528260203d92013e5b5a83039283116100e9575050825191151582526020820152f35b634e487b7160e01b825260119052602490fd5b634e487b7160e01b835260418252602483fd5b506100cf565b634e487b7160e01b855260418452602485fd5b80fd5b5082346101c957602092836003193601126101c55780356001600160a01b038116908190036101c1578251631890039360e21b81529182015283816024816108045afa9283156101b6578093610184575b505051908152f35b909192508382813d83116101af575b61019d8183610317565b8101031261012857505190838061017c565b503d610193565b8251903d90823e3d90fd5b8380fd5b8280fd5b5080fd5b5091346101c557826003193601126101c55782815180936318160ddd60e01b8252816108045afa91821561023b57836102129493610216575b505051918291826102c4565b0390f35b6102339293503d8091833e61022b8183610317565b81019061034f565b903880610206565b81513d85823e3d90fd5b90508383346101c15760203660031901126101c15780356001600160a01b03811691908290036102c0576327e235e360e01b845283015282826024816108045afa91821561023b578361021294936102a357505051918291826102c4565b6102b89293503d8091833e61022b8183610317565b908380610206565b8480fd5b60208082019080835283518092528060408094019401926000905b8382106102ee57505050505090565b845180516001600160a01b031687528301518684015294850194938201936001909101906102df565b90601f8019910116810190811067ffffffffffffffff82111761033957604052565b634e487b7160e01b600052604160045260246000fd5b6020808284031261040b57815167ffffffffffffffff9283821161040b57019083601f8301121561040b57815183811161033957604093845195610398848460051b0188610317565b828752838088019360061b8601019481861161040b578401925b8584106103c3575050505050505090565b868483031261040b57865190878201828110858211176104105788528451906001600160a01b038216820361040b578287928a945282870151838201528152019301926103b2565b600080fd5b60246000634e487b7160e01b81526041600452fdfea26469706673582212206291c412c52d95f56ebd6bcace337eb3149a918c5ed8398ed4845c859755136a64736f6c63430008140033", + "deployedBytecode": "0x60806040908082526004908136101561001757600080fd5b600090813560e01c90816389129c681461024557508063acab2f94146101cd578063bba60ca01461012b5763d47052031461005157600080fd5b34610128576020366003190112610128575a90835192602084016318160ddd60e01b81528185528585019467ffffffffffffffff95818110878211176101155787525183918291906108048535fa933d1561010f573d9081116100fc578551906100c5601f8201601f191660200183610317565b81528260203d92013e5b5a83039283116100e9575050825191151582526020820152f35b634e487b7160e01b825260119052602490fd5b634e487b7160e01b835260418252602483fd5b506100cf565b634e487b7160e01b855260418452602485fd5b80fd5b5082346101c957602092836003193601126101c55780356001600160a01b038116908190036101c1578251631890039360e21b81529182015283816024816108045afa9283156101b6578093610184575b505051908152f35b909192508382813d83116101af575b61019d8183610317565b8101031261012857505190838061017c565b503d610193565b8251903d90823e3d90fd5b8380fd5b8280fd5b5080fd5b5091346101c557826003193601126101c55782815180936318160ddd60e01b8252816108045afa91821561023b57836102129493610216575b505051918291826102c4565b0390f35b6102339293503d8091833e61022b8183610317565b81019061034f565b903880610206565b81513d85823e3d90fd5b90508383346101c15760203660031901126101c15780356001600160a01b03811691908290036102c0576327e235e360e01b845283015282826024816108045afa91821561023b578361021294936102a357505051918291826102c4565b6102b89293503d8091833e61022b8183610317565b908380610206565b8480fd5b60208082019080835283518092528060408094019401926000905b8382106102ee57505050505090565b845180516001600160a01b031687528301518684015294850194938201936001909101906102df565b90601f8019910116810190811067ffffffffffffffff82111761033957604052565b634e487b7160e01b600052604160045260246000fd5b6020808284031261040b57815167ffffffffffffffff9283821161040b57019083601f8301121561040b57815183811161033957604093845195610398848460051b0188610317565b828752838088019360061b8601019481861161040b578401925b8584106103c3575050505050505090565b868483031261040b57865190878201828110858211176104105788528451906001600160a01b038216820361040b578287928a945282870151838201528152019301926103b2565b600080fd5b60246000634e487b7160e01b81526041600452fdfea26469706673582212206291c412c52d95f56ebd6bcace337eb3149a918c5ed8398ed4845c859755136a64736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/precompiles/bank/testdata/BankCaller.sol b/precompiles/bank/testdata/BankCaller.sol index 7322fe118..f9ed0a7b0 100644 --- a/precompiles/bank/testdata/BankCaller.sol +++ b/precompiles/bank/testdata/BankCaller.sol @@ -16,4 +16,14 @@ contract BankCaller { function callSupplyOf(address erc20Address) external view returns (uint256) { return IBANK_CONTRACT.supplyOf(erc20Address); } + + // Calls totalSupply with explicit gas forwarding and measures the gas consumed + // by the inner call. Returns whether the call succeeded and the actual gas used. + function callTotalSupplyWithGas(uint256 gasForward) external view returns (bool success, uint256 innerGasUsed) { + uint256 gasBefore = gasleft(); + (success, ) = IBANK_PRECOMPILE_ADDRESS.staticcall{gas: gasForward}( + abi.encodeWithSelector(IBank.totalSupply.selector) + ); + innerGasUsed = gasBefore - gasleft(); + } } \ No newline at end of file diff --git a/precompiles/common/precompile.go b/precompiles/common/precompile.go index 242d525b3..488ef9379 100644 --- a/precompiles/common/precompile.go +++ b/precompiles/common/precompile.go @@ -48,6 +48,9 @@ func (p Precompile) RequiredGas(input []byte, isTransaction bool) uint64 { func (p Precompile) RunNativeAction(evm *vm.EVM, contract *vm.Contract, action NativeAction) ([]byte, error) { bz, err := p.runNativeAction(evm, contract, action) if err != nil { + if errors.Is(err, vm.ErrOutOfGas) { + return nil, vm.ErrOutOfGas + } return ReturnRevertError(evm, err) } @@ -84,14 +87,14 @@ func (p Precompile) runNativeAction(evm *vm.EVM, contract *vm.Contract, action N initialGas := ctx.GasMeter().GasConsumed() - defer HandleGasError(ctx, contract, initialGas, &err)() - // set the default SDK gas configuration to track gas usage // we are changing the gas meter type, so it panics gracefully when out of gas ctx = ctx.WithGasMeter(storetypes.NewGasMeter(contract.Gas)). WithKVGasConfig(p.KvGasConfig). WithTransientKVGasConfig(p.TransientKVGasConfig) + defer HandleGasError(ctx, contract, initialGas, &err)() + // we need to consume the gas that was already used by the EVM ctx.GasMeter().ConsumeGas(initialGas, "creating a new gas meter") diff --git a/tests/integration/precompiles/bank/test_integration.go b/tests/integration/precompiles/bank/test_integration.go index 258d96694..0f96e720a 100644 --- a/tests/integration/precompiles/bank/test_integration.go +++ b/tests/integration/precompiles/bank/test_integration.go @@ -1,6 +1,8 @@ package bank import ( + storetypes "cosmossdk.io/store/types" + "fmt" "math/big" "testing" @@ -248,6 +250,68 @@ func TestIntegrationSuite(t *testing.T, create network.CreateEvmApp, options ... Expect(balances[0].Amount.String()).To(Equal(cosmosEVMTotalSupply.String())) Expect(balances[1].Amount.String()).To(Equal(xmplTotalSupply.String())) }) + + It("should properly handle OOG in precompile and consume all gas", func() { + numDenoms := 5000 + // Mint denoms to make TotalSupply expensive enough to OOG. + ctx := is.network.GetContext() + for i := 0; i < numDenoms; i++ { + denom := fmt.Sprintf("token%d", i) + err = is.network.App.GetBankKeeper().MintCoins( + ctx, minttypes.ModuleName, + sdk.Coins{{Denom: denom, Amount: math.NewInt(1e18)}}, + ) + Expect(err).ToNot(HaveOccurred(), "failed to mint coin %s", denom) + } + // Commit keeper changes directly to state. + store := is.network.GetContext().MultiStore() + cms, ok := store.(storetypes.CacheMultiStore) + Expect(ok).To(BeTrue()) + cms.Write() + + Expect(is.network.NextBlock()).ToNot(HaveOccurred(), "failed to advance block") + + // Use callTotalSupplyWithGas to measure inner call gas consumption. + // Forward enough gas for the precompile to OOG iterating 5000+ denoms. + gasForward := big.NewInt(9_000_000) + + txArgs := evmtypes.EvmTxArgs{ + To: &bankCallerContractAddr, + GasLimit: 20_000_000, + } + callArgs := testutiltypes.CallArgs{ + ContractABI: bankCallerContract.ABI, + MethodName: "callTotalSupplyWithGas", + Args: []interface{}{gasForward}, + } + + res, execErr := is.factory.ExecuteContractCall(sender.Priv, txArgs, callArgs) + Expect(execErr).ToNot(HaveOccurred(), "failed to execute callTotalSupplyWithGas") + + ethRes, decErr := evmtypes.DecodeTxResponse(res.Data) + Expect(decErr).ToNot(HaveOccurred(), "failed to decode eth tx response") + Expect(ethRes.VmError).To(BeEmpty(), "outer call should not revert") + + // Unpack: (bool success, uint256 innerGasUsed) + out, unpackErr := bankCallerContract.ABI.Unpack("callTotalSupplyWithGas", ethRes.Ret) + Expect(unpackErr).ToNot(HaveOccurred(), "failed to unpack result") + + innerSuccess := out[0].(bool) + innerGasUsed := out[1].(*big.Int) + + fmt.Printf("\nInner call: success=%v, innerGasUsed=%s, gasForwarded=%s, txGasUsed=%d\n", + innerSuccess, innerGasUsed.String(), gasForward.String(), ethRes.GasUsed) + + // The inner call should have failed (OOG with 5000 denoms). + Expect(innerSuccess).To(BeFalse(), "inner call should OOG with insufficient gas for 5000 denoms") + + // The inner call should have consumed all (or nearly all) forwarded gas. + // With correct gas accounting, innerGasUsed ≈ gasForward. + // With the bug, innerGasUsed would be ~3k (only EVM overhead, no precompile charge). + Expect(innerGasUsed.Uint64()).To(BeNumerically(">=", gasForward.Uint64()*90/100), + "inner OOG call should consume all forwarded gas, got %s out of %s", innerGasUsed.String(), gasForward.String()) + }) + }) Context("supplyOf query", func() { From 68721385febec35069edfdb20fd07d73b6ab7498 Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 4 Mar 2026 17:30:01 -0500 Subject: [PATCH 2/9] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56954aef9..c36ce609e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ Follow the [migration document](docs/migrations/v0.5.x_to_v0.6.0.md) for upgrade ### BUG FIXES +- Align precompile gas calculation with expected EVM gas semantics. + ## v0.5.1 ### DEPENDENCIES From 5b0bee3e745c0871fc87ca235dd6b34d71e4bf7e Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 5 Mar 2026 16:39:15 -0500 Subject: [PATCH 3/9] lint --- tests/integration/precompiles/bank/test_integration.go | 3 +-- x/vm/statedb/statedb.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/integration/precompiles/bank/test_integration.go b/tests/integration/precompiles/bank/test_integration.go index 0f96e720a..335d78452 100644 --- a/tests/integration/precompiles/bank/test_integration.go +++ b/tests/integration/precompiles/bank/test_integration.go @@ -1,7 +1,6 @@ package bank import ( - storetypes "cosmossdk.io/store/types" "fmt" "math/big" "testing" @@ -27,6 +26,7 @@ import ( evmtypes "github.com/cosmos/evm/x/vm/types" "cosmossdk.io/math" + storetypes "cosmossdk.io/store/types" sdk "github.com/cosmos/cosmos-sdk/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" @@ -311,7 +311,6 @@ func TestIntegrationSuite(t *testing.T, create network.CreateEvmApp, options ... Expect(innerGasUsed.Uint64()).To(BeNumerically(">=", gasForward.Uint64()*90/100), "inner OOG call should consume all forwarded gas, got %s out of %s", innerGasUsed.String(), gasForward.String()) }) - }) Context("supplyOf query", func() { diff --git a/x/vm/statedb/statedb.go b/x/vm/statedb/statedb.go index d10d1cd39..b3ba592e2 100644 --- a/x/vm/statedb/statedb.go +++ b/x/vm/statedb/statedb.go @@ -438,7 +438,7 @@ func (s *StateDB) setStateObject(object *stateObject) { // to the precompile call. func (s *StateDB) AddPrecompileFn(snapshot int) error { // Capture events before the precompile call - var prevEvents sdk.Events = s.cacheCtx.EventManager().Events() + prevEvents := s.cacheCtx.EventManager().Events() s.journal.append(precompileCallChange{ snapshot: snapshot, From 3adb1abacb023443cafc68a96f5c6784145ad553 Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 5 Mar 2026 20:18:04 -0500 Subject: [PATCH 4/9] fix tests --- .../precompiles/staking/test_staking.go | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/tests/integration/precompiles/staking/test_staking.go b/tests/integration/precompiles/staking/test_staking.go index 9bc4c7155..23088e343 100644 --- a/tests/integration/precompiles/staking/test_staking.go +++ b/tests/integration/precompiles/staking/test_staking.go @@ -132,6 +132,7 @@ func (s *PrecompileTestSuite) TestRun() { gas uint64 readOnly bool expPass bool + expRevert bool // true if error returns ABI-encoded revert reason bytes (not OOG) errContains string }{ { @@ -149,6 +150,7 @@ func (s *PrecompileTestSuite) TestRun() { 8000, false, false, + false, "out of gas", }, { @@ -166,6 +168,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -183,6 +186,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -201,6 +205,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "failed to redelegate tokens", }, { @@ -241,6 +246,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -257,6 +263,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -275,6 +282,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -313,6 +321,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, false, true, + false, "", }, { @@ -329,6 +338,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, true, true, + false, "", }, { @@ -367,6 +377,7 @@ func (s *PrecompileTestSuite) TestRun() { 1000000, true, true, + false, "", }, { @@ -384,6 +395,7 @@ func (s *PrecompileTestSuite) TestRun() { 21295, // use enough gas to avoid out of gas error true, false, + true, "write protection", }, { @@ -394,6 +406,7 @@ func (s *PrecompileTestSuite) TestRun() { 21295, // use enough gas to avoid out of gas error false, false, + true, "no method with id", }, } @@ -457,14 +470,16 @@ func (s *PrecompileTestSuite) TestRun() { if tc.expPass { s.Require().NoError(err, "expected no error when running the precompile") s.Require().NotNil(bz, "expected returned bytes not to be nil") + } else if tc.expRevert { + s.Require().ErrorIs(err, vm.ErrExecutionReverted) + s.Require().NotNil(bz, "expected revert reason bytes") + revertErr := evmtypes.NewExecErrorWithReason(bz) + s.Require().ErrorContains(revertErr, tc.errContains) } else { - s.Require().Error(err, "expected error to be returned when running the precompile") - s.Require().NotNil(bz, "expected returned bytes to be nil") - execRevertErr := evmtypes.NewExecErrorWithReason(bz) - s.Require().ErrorContains(execRevertErr, tc.errContains) + s.Require().ErrorIs(err, vm.ErrOutOfGas) + s.Require().Nil(bz, "expected nil bytes on out of gas") consumed := ctx.GasMeter().GasConsumed() - // LessThanOrEqual because the gas is consumed before the error is returned - s.Require().LessOrEqual(tc.gas, consumed, "expected gas consumed to be equal to gas limit") + s.Require().LessOrEqual(tc.gas, consumed, "expected all gas to be consumed on OOG") } }) } From 11147e5a609e8e88906922bfa5f1520990b24abc Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 5 Mar 2026 20:19:44 -0500 Subject: [PATCH 5/9] fix test --- tests/integration/precompiles/staking/test_staking.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/precompiles/staking/test_staking.go b/tests/integration/precompiles/staking/test_staking.go index 23088e343..3c2573d56 100644 --- a/tests/integration/precompiles/staking/test_staking.go +++ b/tests/integration/precompiles/staking/test_staking.go @@ -479,7 +479,7 @@ func (s *PrecompileTestSuite) TestRun() { s.Require().ErrorIs(err, vm.ErrOutOfGas) s.Require().Nil(bz, "expected nil bytes on out of gas") consumed := ctx.GasMeter().GasConsumed() - s.Require().LessOrEqual(tc.gas, consumed, "expected all gas to be consumed on OOG") + s.Require().Equal(tc.gas, consumed, "expected all gas to be consumed on OOG") } }) } From 53c85b270fe2fcfd24a875e998a751d66c3e13fc Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 6 Mar 2026 10:40:18 -0500 Subject: [PATCH 6/9] Revert "fix test" This reverts commit 11147e5a609e8e88906922bfa5f1520990b24abc. --- tests/integration/precompiles/staking/test_staking.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/precompiles/staking/test_staking.go b/tests/integration/precompiles/staking/test_staking.go index 3c2573d56..23088e343 100644 --- a/tests/integration/precompiles/staking/test_staking.go +++ b/tests/integration/precompiles/staking/test_staking.go @@ -479,7 +479,7 @@ func (s *PrecompileTestSuite) TestRun() { s.Require().ErrorIs(err, vm.ErrOutOfGas) s.Require().Nil(bz, "expected nil bytes on out of gas") consumed := ctx.GasMeter().GasConsumed() - s.Require().Equal(tc.gas, consumed, "expected all gas to be consumed on OOG") + s.Require().LessOrEqual(tc.gas, consumed, "expected all gas to be consumed on OOG") } }) } From 3888082219a2c1b55b4495b60afa71e99de1b53c Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 5 Mar 2026 19:31:07 -0500 Subject: [PATCH 7/9] solhint --- contracts/solidity/ContractCreationTester.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/solidity/ContractCreationTester.sol b/contracts/solidity/ContractCreationTester.sol index e59900625..3b2317100 100644 --- a/contracts/solidity/ContractCreationTester.sol +++ b/contracts/solidity/ContractCreationTester.sol @@ -195,7 +195,8 @@ contract ContractCreationTester { uint256 successCreationValue ) external payable { // 1. Try to create contract (will revert after creation, catch it) - try this.createAndRevert{value: revertCreationValue}(revertCreationValue) returns (SimpleReceiver newContract1) { + try this.createAndRevert{value: revertCreationValue} + (revertCreationValue) returns (SimpleReceiver newContract1) { // This won't execute because createAndRevert reverts createdContracts.push(address(newContract1)); emit ContractCreated(address(newContract1), revertCreationValue); From 5cf6efe277b5580c842fb18b049ecb270bdaed22 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 6 Mar 2026 10:45:17 -0500 Subject: [PATCH 8/9] lint --- tests/integration/precompiles/staking/test_staking.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/integration/precompiles/staking/test_staking.go b/tests/integration/precompiles/staking/test_staking.go index 23088e343..f0f46cff8 100644 --- a/tests/integration/precompiles/staking/test_staking.go +++ b/tests/integration/precompiles/staking/test_staking.go @@ -467,15 +467,16 @@ func (s *PrecompileTestSuite) TestRun() { bz, err := s.precompile.Run(evm, contract, tc.readOnly) // Check results - if tc.expPass { + switch { + case tc.expPass: s.Require().NoError(err, "expected no error when running the precompile") s.Require().NotNil(bz, "expected returned bytes not to be nil") - } else if tc.expRevert { + case tc.expRevert: s.Require().ErrorIs(err, vm.ErrExecutionReverted) s.Require().NotNil(bz, "expected revert reason bytes") revertErr := evmtypes.NewExecErrorWithReason(bz) s.Require().ErrorContains(revertErr, tc.errContains) - } else { + default: s.Require().ErrorIs(err, vm.ErrOutOfGas) s.Require().Nil(bz, "expected nil bytes on out of gas") consumed := ctx.GasMeter().GasConsumed() From 4d94cf746a115f2fc18e075b66b0be83a5f8f605 Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 11 Mar 2026 19:11:32 -0400 Subject: [PATCH 9/9] make systemtest time 3s instead of 5s to hit blocktime --- tests/systemtests/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/systemtests/Makefile b/tests/systemtests/Makefile index b0aa5b041..aaee32b7a 100644 --- a/tests/systemtests/Makefile +++ b/tests/systemtests/Makefile @@ -9,4 +9,4 @@ test: go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run TestExceptions --wait-time=$(WAIT_TIME) --block-time=8s --binary evmd --chain-id local-4221 go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run TestEIP7702 --wait-time=$(WAIT_TIME) --block-time=5s --binary evmd --chain-id local-4221 go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run TestEIP712 --wait-time=$(WAIT_TIME) --block-time=5s --binary evmd --chain-id local-4221 - go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run 'TestChainUpgrade|TestEth' --wait-time=$(WAIT_TIME) --block-time=5s --binary evmd --chain-id local-4221 + go test -failfast -timeout=30m -p=1 -mod=readonly -tags='system_test' -v ./... -run 'TestChainUpgrade|TestEth' --wait-time=$(WAIT_TIME) --block-time=3s --binary evmd --chain-id local-4221