From e8ea49f273045c53621090437ae907ec1d44afae Mon Sep 17 00:00:00 2001 From: Tony Chen Date: Fri, 27 Feb 2026 22:37:08 +0800 Subject: [PATCH] do not create receipts for invisible txs --- app/ante/evm_delivertx.go | 1 + go.work.sum | 1 + x/evm/ante/basic.go | 1 + x/evm/keeper/abci.go | 3 +++ x/evm/keeper/abci_test.go | 53 +++++++++++++++++++++++++++++++++++++++ x/evm/keeper/deferred.go | 12 +++++++++ x/evm/types/keys.go | 1 + 7 files changed, 72 insertions(+) create mode 100644 x/evm/keeper/abci_test.go diff --git a/app/ante/evm_delivertx.go b/app/ante/evm_delivertx.go index ade1cd426a..1b0be6c2ec 100644 --- a/app/ante/evm_delivertx.go +++ b/app/ante/evm_delivertx.go @@ -90,6 +90,7 @@ func DecorateNonceCallback(ctx sdk.Context, ek *evmkeeper.Keeper, evmAddr common // bump nonce if it is for some reason not incremented (e.g. ante failure) if ek.GetNonce(callCtx, evmAddr) == startingNonce { ek.SetNonce(callCtx, evmAddr, startingNonce+1) + ek.SetNonceBumped(callCtx) } }) } diff --git a/go.work.sum b/go.work.sum index 3f32e91e14..cbbe309371 100644 --- a/go.work.sum +++ b/go.work.sum @@ -948,6 +948,7 @@ github.com/kataras/pio v0.0.11 h1:kqreJ5KOEXGMwHAWHDwIl+mjfNCPhAwZPa8gK7MKlyw= github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= diff --git a/x/evm/ante/basic.go b/x/evm/ante/basic.go index 11d9c3dfea..b163b0395b 100644 --- a/x/evm/ante/basic.go +++ b/x/evm/ante/basic.go @@ -34,6 +34,7 @@ func (gl BasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, n // bump nonce if it is for some reason not incremented (e.g. ante failure) if gl.k.GetNonce(callCtx, msg.Derived.SenderEVMAddr) == startingNonce { gl.k.SetNonce(callCtx, msg.Derived.SenderEVMAddr, startingNonce+1) + gl.k.SetNonceBumped(callCtx) } }) } diff --git a/x/evm/keeper/abci.go b/x/evm/keeper/abci.go index c742a6d9ab..fc1f1ade24 100644 --- a/x/evm/keeper/abci.go +++ b/x/evm/keeper/abci.go @@ -101,6 +101,9 @@ func (k *Keeper) EndBlock(ctx sdk.Context, height int64, blockGasUsed int64) { for _, deferredInfo := range evmTxDeferredInfoList { txHash := common.BytesToHash(deferredInfo.TxHash) if deferredInfo.Error != "" && txHash.Cmp(ethtypes.EmptyTxsHash) != 0 { + if !k.GetNonceBumped(ctx, deferredInfo.TxIndex) { + continue + } _ = k.SetTransientReceipt(ctx, txHash, &types.Receipt{ TxHashHex: txHash.Hex(), TransactionIndex: deferredInfo.TxIndex, diff --git a/x/evm/keeper/abci_test.go b/x/evm/keeper/abci_test.go new file mode 100644 index 0000000000..032c6a9386 --- /dev/null +++ b/x/evm/keeper/abci_test.go @@ -0,0 +1,53 @@ +package keeper_test + +import ( + "testing" + + "github.com/sei-protocol/sei-chain/app" + abci "github.com/sei-protocol/sei-chain/sei-tendermint/abci/types" + "github.com/sei-protocol/sei-chain/x/evm/types" + "github.com/stretchr/testify/require" +) + +func TestEndBlock_NoReceiptForNonceMismatch(t *testing.T) { + a := app.Setup(t, false, false, false) + k := a.EvmKeeper + ctx := a.GetContextForDeliverTx([]byte{}).WithBlockHeight(8) + + msg := mockEVMTransactionMessage(t) + etx, _ := msg.AsTransaction() + txHash := etx.Hash() + + k.BeginBlock(ctx) + k.SetMsgs([]*types.MsgEVMTransaction{msg}) + k.SetTxResults([]*abci.ExecTxResult{{Code: 1, Log: "nonce mismatch"}}) + // No SetNonceBumped call — simulates a tx where startingNonce != txNonce, + // so the nonce bump callback was never registered/executed. + k.EndBlock(ctx, 0, 0) + + _, err := k.GetTransientReceipt(ctx, txHash, 0) + require.Error(t, err, "should not create a receipt when nonce was not bumped") +} + +func TestEndBlock_ReceiptCreatedWhenNonceBumped(t *testing.T) { + a := app.Setup(t, false, false, false) + k := a.EvmKeeper + ctx := a.GetContextForDeliverTx([]byte{}).WithBlockHeight(8) + + msg := mockEVMTransactionMessage(t) + etx, _ := msg.AsTransaction() + txHash := etx.Hash() + + k.BeginBlock(ctx) + k.SetMsgs([]*types.MsgEVMTransaction{msg}) + k.SetTxResults([]*abci.ExecTxResult{{Code: 1, Log: "some ante error"}}) + // Simulate that the nonce bump callback ran (startingNonce == txNonce). + k.SetNonceBumped(ctx.WithTxIndex(0)) + k.EndBlock(ctx, 0, 0) + + receipt, err := k.GetTransientReceipt(ctx, txHash, 0) + require.NoError(t, err, "should create a receipt when nonce was bumped") + require.Equal(t, txHash.Hex(), receipt.TxHashHex) + require.Equal(t, "some ante error", receipt.VmError) + require.Equal(t, uint64(8), receipt.BlockNumber) +} diff --git a/x/evm/keeper/deferred.go b/x/evm/keeper/deferred.go index 8509fa93a6..31d302d0e5 100644 --- a/x/evm/keeper/deferred.go +++ b/x/evm/keeper/deferred.go @@ -67,6 +67,18 @@ func (k *Keeper) AppendToEvmTxDeferredInfo(ctx sdk.Context, bloom ethtypes.Bloom prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.DeferredInfoPrefix).Set(key, bz) } +func (k *Keeper) SetNonceBumped(ctx sdk.Context) { + key := make([]byte, 8) + binary.BigEndian.PutUint64(key, uint64(ctx.TxIndex())) //nolint:gosec + prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.NonceBumpPrefix).Set(key, []byte{1}) +} + +func (k *Keeper) GetNonceBumped(ctx sdk.Context, txIndex uint32) bool { + key := make([]byte, 8) + binary.BigEndian.PutUint64(key, uint64(txIndex)) + return prefix.NewStore(ctx.TransientStore(k.transientStoreKey), types.NonceBumpPrefix).Has(key) +} + func (k *Keeper) GetEVMTxDeferredInfo(ctx sdk.Context) (*types.DeferredInfo, bool) { key := make([]byte, 8) binary.BigEndian.PutUint64(key, uint64(ctx.TxIndex())) //nolint:gosec diff --git a/x/evm/types/keys.go b/x/evm/types/keys.go index e125b69a02..4f051feb3b 100644 --- a/x/evm/types/keys.go +++ b/x/evm/types/keys.go @@ -62,6 +62,7 @@ var ( NextBaseFeePerGasPrefix = []byte{0x1c} EvmOnlyBlockBloomPrefix = []byte{0x1d} ZeroStorageCleanupCheckpointKey = []byte{0x1e} + NonceBumpPrefix = []byte{0x1f} // transient ) var (