diff --git a/app/evmante_eth.go b/app/evmante_eth.go index a178d918c..1f020094b 100644 --- a/app/evmante_eth.go +++ b/app/evmante_eth.go @@ -21,18 +21,18 @@ import ( ) var ( - _ sdk.AnteDecorator = (*EthGasConsumeDecorator)(nil) - _ sdk.AnteDecorator = (*EthAccountVerificationDecorator)(nil) + _ sdk.AnteDecorator = (*AnteDecEthGasConsume)(nil) + _ sdk.AnteDecorator = (*AnteDecVerifyEthAcc)(nil) ) -// EthAccountVerificationDecorator validates an account balance checks -type EthAccountVerificationDecorator struct { +// AnteDecVerifyEthAcc validates an account balance checks +type AnteDecVerifyEthAcc struct { AppKeepers } -// NewEthAccountVerificationDecorator creates a new EthAccountVerificationDecorator -func NewEthAccountVerificationDecorator(k AppKeepers) EthAccountVerificationDecorator { - return EthAccountVerificationDecorator{ +// NewAnteDecVerifyEthAcc creates a new EthAccountVerificationDecorator +func NewAnteDecVerifyEthAcc(k AppKeepers) AnteDecVerifyEthAcc { + return AnteDecVerifyEthAcc{ AppKeepers: k, } } @@ -43,7 +43,7 @@ func NewEthAccountVerificationDecorator(k AppKeepers) EthAccountVerificationDeco // - any of the msgs is not a MsgEthereumTx // - from address is empty // - account balance is lower than the transaction cost -func (avd EthAccountVerificationDecorator) AnteHandle( +func (avd AnteDecVerifyEthAcc) AnteHandle( ctx sdk.Context, tx sdk.Tx, simulate bool, @@ -90,9 +90,9 @@ func (avd EthAccountVerificationDecorator) AnteHandle( return next(ctx, tx, simulate) } -// EthGasConsumeDecorator validates enough intrinsic gas for the transaction and +// AnteDecEthGasConsume validates enough intrinsic gas for the transaction and // gas consumption. -type EthGasConsumeDecorator struct { +type AnteDecEthGasConsume struct { AppKeepers // bankKeeper anteutils.BankKeeper // distributionKeeper anteutils.DistributionKeeper @@ -101,12 +101,12 @@ type EthGasConsumeDecorator struct { maxGasWanted uint64 } -// NewEthGasConsumeDecorator creates a new EthGasConsumeDecorator -func NewEthGasConsumeDecorator( +// NewAnteDecEthGasConsume creates a new EthGasConsumeDecorator +func NewAnteDecEthGasConsume( keepers AppKeepers, maxGasWanted uint64, -) EthGasConsumeDecorator { - return EthGasConsumeDecorator{ +) AnteDecEthGasConsume { + return AnteDecEthGasConsume{ AppKeepers: keepers, maxGasWanted: maxGasWanted, } @@ -129,7 +129,7 @@ func NewEthGasConsumeDecorator( // - transaction or block gas meter runs out of gas // - sets the gas meter limit // - gas limit is greater than the block gas meter limit -func (egcd EthGasConsumeDecorator) AnteHandle( +func (egcd AnteDecEthGasConsume) AnteHandle( ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler, ) (sdk.Context, error) { gasWanted := uint64(0) @@ -242,7 +242,7 @@ func (egcd EthGasConsumeDecorator) AnteHandle( // deductFee checks if the fee payer has enough funds to pay for the fees and deducts them. // If the spendable balance is not enough, it tries to claim enough staking rewards to cover the fees. -func (egcd EthGasConsumeDecorator) deductFee(ctx sdk.Context, fees sdk.Coins, feePayer sdk.AccAddress) error { +func (egcd AnteDecEthGasConsume) deductFee(ctx sdk.Context, fees sdk.Coins, feePayer sdk.AccAddress) error { if fees.IsZero() { return nil } @@ -335,14 +335,14 @@ func (ctd CanTransferDecorator) AnteHandle( return next(ctx, tx, simulate) } -// EthIncrementSenderSequenceDecorator increments the sequence of the signers. -type EthIncrementSenderSequenceDecorator struct { +// AnteDecEthIncrementSenderSequence increments the sequence of the signers. +type AnteDecEthIncrementSenderSequence struct { AppKeepers } -// NewEthIncrementSenderSequenceDecorator creates a new EthIncrementSenderSequenceDecorator. -func NewEthIncrementSenderSequenceDecorator(k AppKeepers) EthIncrementSenderSequenceDecorator { - return EthIncrementSenderSequenceDecorator{ +// NewAnteDecEthIncrementSenderSequence creates a new EthIncrementSenderSequenceDecorator. +func NewAnteDecEthIncrementSenderSequence(k AppKeepers) AnteDecEthIncrementSenderSequence { + return AnteDecEthIncrementSenderSequence{ AppKeepers: k, } } @@ -350,7 +350,7 @@ func NewEthIncrementSenderSequenceDecorator(k AppKeepers) EthIncrementSenderSequ // AnteHandle handles incrementing the sequence of the signer (i.e. sender). If the transaction is a // contract creation, the nonce will be incremented during the transaction execution and not within // this AnteHandler decorator. -func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { +func (issd AnteDecEthIncrementSenderSequence) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { for _, msg := range tx.GetMsgs() { msgEthTx, ok := msg.(*evm.MsgEthereumTx) if !ok { diff --git a/app/evmante_handler.go b/app/evmante_handler.go index 0d958f363..2ab2557ff 100644 --- a/app/evmante_handler.go +++ b/app/evmante_handler.go @@ -20,10 +20,10 @@ func NewAnteHandlerEVM( NewEthMinGasPriceDecorator(k), NewEthValidateBasicDecorator(k), NewEthSigVerificationDecorator(k), - NewEthAccountVerificationDecorator(k), + NewAnteDecVerifyEthAcc(k), NewCanTransferDecorator(k), - NewEthGasConsumeDecorator(k, options.MaxTxGasWanted), - NewEthIncrementSenderSequenceDecorator(k), + NewAnteDecEthGasConsume(k, options.MaxTxGasWanted), + NewAnteDecEthIncrementSenderSequence(k), NewGasWantedDecorator(k), // emit eth tx hash and index at the very last ante handler. NewEthEmitEventDecorator(k), diff --git a/app/evmante_test.go b/app/evmante_test.go index eddbf14b3..dfcdb9e23 100644 --- a/app/evmante_test.go +++ b/app/evmante_test.go @@ -1,74 +1,101 @@ package app_test -// import ( -// "strconv" +import ( + "math/big" -// gethcore "github.com/ethereum/go-ethereum/core/types" -// gethparams "github.com/ethereum/go-ethereum/params" + sdk "github.com/cosmos/cosmos-sdk/types" -// "github.com/NibiruChain/nibiru/x/evm/evmtest" -// ) + gethparams "github.com/ethereum/go-ethereum/params" -// func (s *TestSuite) TestMsgEthereumTx_SimpleTransfer() { -// testCases := []struct { -// name string -// scenario func() -// }{ -// { -// name: "happy: AccessListTx", -// scenario: func() { -// deps := evmtest.NewTestDeps() -// ethAcc := deps.Sender + "github.com/NibiruChain/nibiru/app" + "github.com/NibiruChain/nibiru/x/evm" + "github.com/NibiruChain/nibiru/x/evm/evmtest" -// s.T().Log("create eth tx msg") -// var innerTxData []byte = nil -// var accessList gethcore.AccessList = nil -// ethTxMsg, err := evmtest.NewEthTxMsgFromTxData( -// &deps, -// gethcore.AccessListTxType, -// innerTxData, -// deps.StateDB().GetNonce(ethAcc.EthAddr), -// accessList, -// ) -// s.NoError(err) + "github.com/NibiruChain/nibiru/x/evm/statedb" +) -// resp, err := deps.Chain.EvmKeeper.EthereumTx(deps.GoCtx(), ethTxMsg) -// s.Require().NoError(err) +var NextNoOpAnteHandler sdk.AnteHandler = func( + ctx sdk.Context, tx sdk.Tx, simulate bool, +) (newCtx sdk.Context, err error) { + return ctx, nil +} -// gasUsed := strconv.FormatUint(resp.GasUsed, 10) -// wantGasUsed := strconv.FormatUint(gethparams.TxGas, 10) -// s.Equal(gasUsed, wantGasUsed) -// }, -// }, -// { -// name: "happy: LegacyTx", -// scenario: func() { -// deps := evmtest.NewTestDeps() -// ethAcc := deps.Sender +func (s *TestSuite) TestAnteDecoratorVerifyEthAcc_CheckTx() { + happyCreateContractTx := func(deps *evmtest.TestDeps) *evm.MsgEthereumTx { + ethContractCreationTxParams := &evm.EvmTxArgs{ + ChainID: deps.Chain.EvmKeeper.EthChainID(deps.Ctx), + Nonce: 1, + Amount: big.NewInt(10), + GasLimit: 1000, + GasPrice: big.NewInt(1), + } + tx := evm.NewTx(ethContractCreationTxParams) + tx.From = deps.Sender.EthAddr.Hex() + return tx + } -// s.T().Log("create eth tx msg") -// var innerTxData []byte = nil -// var accessList gethcore.AccessList = nil -// ethTxMsg, err := evmtest.NewEthTxMsgFromTxData( -// &deps, -// gethcore.LegacyTxType, -// innerTxData, -// deps.StateDB().GetNonce(ethAcc.EthAddr), -// accessList, -// ) -// s.NoError(err) + testCases := []struct { + name string + beforeTxSetup func(deps *evmtest.TestDeps, sdb *statedb.StateDB) + txSetup func(deps *evmtest.TestDeps) *evm.MsgEthereumTx + wantErr string + }{ + { + name: "happy: sender with funds", + beforeTxSetup: func(deps *evmtest.TestDeps, sdb *statedb.StateDB) { + gasLimit := new(big.Int).SetUint64( + gethparams.TxGasContractCreation + 500, + ) + // Force account to be a smart contract + sdb.AddBalance(deps.Sender.EthAddr, gasLimit) + }, + txSetup: happyCreateContractTx, + wantErr: "", + }, + { + name: "sad: sender has insufficient gas balance", + beforeTxSetup: func(deps *evmtest.TestDeps, sdb *statedb.StateDB) {}, + txSetup: happyCreateContractTx, + wantErr: "sender balance < tx cost", + }, + { + name: "sad: sender cannot be a contract -> no contract bytecode", + beforeTxSetup: func(deps *evmtest.TestDeps, sdb *statedb.StateDB) { + // Force account to be a smart contract + sdb.SetCode(deps.Sender.EthAddr, []byte("evm bytecode stuff")) + }, + txSetup: happyCreateContractTx, + wantErr: "sender is not EOA", + }, + { + name: "sad: invalid tx", + beforeTxSetup: func(deps *evmtest.TestDeps, sdb *statedb.StateDB) {}, + txSetup: func(deps *evmtest.TestDeps) *evm.MsgEthereumTx { + return new(evm.MsgEthereumTx) + }, + wantErr: "failed to unpack tx data", + }, + } -// resp, err := deps.Chain.EvmKeeper.EthereumTx(deps.GoCtx(), ethTxMsg) -// s.Require().NoError(err) + for _, tc := range testCases { + s.Run(tc.name, func() { + deps := evmtest.NewTestDeps() + stateDB := deps.StateDB() + anteDec := app.NewAnteDecVerifyEthAcc(deps.Chain.AppKeepers) -// gasUsed := strconv.FormatUint(resp.GasUsed, 10) -// wantGasUsed := strconv.FormatUint(gethparams.TxGas, 10) -// s.Equal(gasUsed, wantGasUsed) -// }, -// }, -// } + tc.beforeTxSetup(&deps, stateDB) + tx := tc.txSetup(&deps) + s.Require().NoError(stateDB.Commit()) -// for _, tc := range testCases { -// s.Run(tc.name, tc.scenario) -// } -// } + deps.Ctx = deps.Ctx.WithIsCheckTx(true) + _, err := anteDec.AnteHandle( + deps.Ctx, tx, false, NextNoOpAnteHandler, + ) + if tc.wantErr != "" { + s.Require().ErrorContains(err, tc.wantErr) + return + } + s.Require().NoError(err) + }) + } +} diff --git a/x/common/error.go b/x/common/error.go index 2f640ce50..de3e4acac 100644 --- a/x/common/error.go +++ b/x/common/error.go @@ -184,9 +184,7 @@ func CombineErrorsFromStrings(strs ...string) (err error) { return CombineErrors(errs...) } -func ErrNilGrpcMsg() error { - return grpcstatus.Errorf(grpccodes.InvalidArgument, "nil msg") -} +var ErrNilGrpcMsg = grpcstatus.Errorf(grpccodes.InvalidArgument, "nil msg") // ErrNotImplemented: Represents an function error value. func ErrNotImplemented() error { return fmt.Errorf("fn not implemented yet") } diff --git a/x/evm/query.go b/x/evm/query.go index 79235797d..f6d9cfde6 100644 --- a/x/evm/query.go +++ b/x/evm/query.go @@ -31,7 +31,7 @@ func (m QueryTraceBlockRequest) UnpackInterfaces(unpacker codectypes.AnyUnpacker func (req *QueryEthAccountRequest) Validate() error { if req == nil { - return common.ErrNilGrpcMsg() + return common.ErrNilGrpcMsg } if err := eth.ValidateAddress(req.Address); err != nil { return status.Error( @@ -43,7 +43,7 @@ func (req *QueryEthAccountRequest) Validate() error { func (req *QueryNibiruAccountRequest) Validate() error { if req == nil { - return common.ErrNilGrpcMsg() + return common.ErrNilGrpcMsg } if err := eth.ValidateAddress(req.Address); err != nil { @@ -72,7 +72,7 @@ func (req *QueryValidatorAccountRequest) Validate() ( func (req *QueryBalanceRequest) Validate() error { if req == nil { - return common.ErrNilGrpcMsg() + return common.ErrNilGrpcMsg } if err := eth.ValidateAddress(req.Address); err != nil { @@ -86,7 +86,7 @@ func (req *QueryBalanceRequest) Validate() error { func (req *QueryStorageRequest) Validate() error { if req == nil { - return common.ErrNilGrpcMsg() + return common.ErrNilGrpcMsg } if err := eth.ValidateAddress(req.Address); err != nil { return status.Error( @@ -99,7 +99,7 @@ func (req *QueryStorageRequest) Validate() error { func (req *QueryCodeRequest) Validate() error { if req == nil { - return common.ErrNilGrpcMsg() + return common.ErrNilGrpcMsg } if err := eth.ValidateAddress(req.Address); err != nil { @@ -113,14 +113,14 @@ func (req *QueryCodeRequest) Validate() error { func (req *EthCallRequest) Validate() error { if req == nil { - return common.ErrNilGrpcMsg() + return common.ErrNilGrpcMsg } return nil } func (req *QueryTraceTxRequest) Validate() error { if req == nil { - return common.ErrNilGrpcMsg() + return common.ErrNilGrpcMsg } if req.TraceConfig != nil && req.TraceConfig.Limit < 0 { @@ -131,7 +131,7 @@ func (req *QueryTraceTxRequest) Validate() error { func (req *QueryTraceBlockRequest) Validate() error { if req == nil { - return common.ErrNilGrpcMsg() + return common.ErrNilGrpcMsg } if req.TraceConfig != nil && req.TraceConfig.Limit < 0 { diff --git a/x/evm/query_test.go b/x/evm/query_test.go index f32a9704b..7c6e54992 100644 --- a/x/evm/query_test.go +++ b/x/evm/query_test.go @@ -53,6 +53,6 @@ func (s *TestSuite) TestNilQueries() { }, } { err := testCase() - s.Require().ErrorContains(err, common.ErrNilGrpcMsg().Error()) + s.Require().ErrorContains(err, common.ErrNilGrpcMsg.Error()) } } diff --git a/x/tokenfactory/keeper/msg_server.go b/x/tokenfactory/keeper/msg_server.go index 5a56b5c50..0b82ddec7 100644 --- a/x/tokenfactory/keeper/msg_server.go +++ b/x/tokenfactory/keeper/msg_server.go @@ -13,7 +13,7 @@ import ( var _ types.MsgServer = (*Keeper)(nil) -var errNilMsg error = common.ErrNilGrpcMsg() +var errNilMsg error = common.ErrNilGrpcMsg func (k Keeper) CreateDenom( goCtx context.Context, txMsg *types.MsgCreateDenom,