Skip to content

Commit

Permalink
test(evm-cli): more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Unique-Divine committed Aug 22, 2024
1 parent fbee573 commit 81a2af4
Show file tree
Hide file tree
Showing 8 changed files with 406 additions and 70 deletions.
11 changes: 6 additions & 5 deletions app/evmante/evmante_sigverify.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ func NewEthSigVerificationDecorator(k EVMKeeper) EthSigVerificationDecorator {
}
}

// AnteHandle validates checks that the registered chain id is the same as the one on the message, and
// that the signer address matches the one defined on the message.
// It's not skipped for RecheckTx, because it set `From` address which is critical from other ante handler to work.
// Failure in RecheckTx will prevent tx to be included into block, especially when CheckTx succeed, in which case user
// won't see the error message.
// AnteHandle validates checks that the registered chain id is the same as the
// one on the message, and that the signer address matches the one defined on the
// message. It's not skipped for RecheckTx, because it set `From` address which
// is critical from other ante handler to work. Failure in RecheckTx will prevent
// tx to be included into block, especially when CheckTx succeed, in which case
// user won't see the error message.
func (esvd EthSigVerificationDecorator) AnteHandle(
ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler,
) (newCtx sdk.Context, err error) {
Expand Down
115 changes: 115 additions & 0 deletions x/evm/cli/cli_setup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package cli_test

import (
"context"
"io"
"testing"

"github.com/stretchr/testify/suite"

rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock"
sdkclient "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdktestutil "github.com/cosmos/cosmos-sdk/testutil"
sdktestutilcli "github.com/cosmos/cosmos-sdk/testutil/cli"
testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil"

svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"

"github.com/NibiruChain/nibiru/x/evm/cli"
"github.com/NibiruChain/nibiru/x/evm/evmmodule"
)

type Suite struct {
suite.Suite

keyring keyring.Keyring
encCfg testutilmod.TestEncodingConfig
baseCtx sdkclient.Context
clientCtx sdkclient.Context

testAcc sdktestutil.TestAccount
}

func (s *Suite) SetupSuite() {
s.encCfg = testutilmod.MakeTestEncodingConfig(evmmodule.AppModuleBasic{})
s.keyring = keyring.NewInMemory(s.encCfg.Codec)
s.baseCtx = sdkclient.Context{}.
WithKeyring(s.keyring).
WithTxConfig(s.encCfg.TxConfig).
WithCodec(s.encCfg.Codec).
WithClient(sdktestutilcli.MockTendermintRPC{Client: rpcclientmock.Client{}}).
WithAccountRetriever(sdkclient.MockAccountRetriever{}).
WithOutput(io.Discard).
WithChainID("test-chain")

s.clientCtx = s.baseCtx

testAccs := sdktestutil.CreateKeyringAccounts(s.T(), s.keyring, 1)
s.testAcc = testAccs[0]
}

func TestSuite(t *testing.T) {
suite.Run(t, new(Suite))
}

// Flags for broadcasting transactions
func commonTxArgs() []string {
return []string{
"--yes=true", // skip confirmation
"--broadcast-mode=sync",
"--fees=1unibi",
"--chain-id=test-chain",
}
}

type TestCase struct {
name string
args []string
extraArgs []string
wantErr string
}

func (tc TestCase) NewCtx(s *Suite) sdkclient.Context {
return s.baseCtx
}

func (tc TestCase) RunTxCmd(s *Suite) {
s.Run(tc.name, func() {
ctx := svrcmd.CreateExecuteContext(context.Background())

cmd := cli.GetTxCmd()
cmd.SetContext(ctx)
args := append(tc.args, commonTxArgs()...)
cmd.SetArgs(append(args, tc.extraArgs...))

s.Require().NoError(sdkclient.SetCmdClientContextHandler(tc.NewCtx(s), cmd))

err := cmd.Execute()
if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr)
return
}
s.Require().NoError(err)
})
}

func (tc TestCase) RunQueryCmd(s *Suite) {
s.Run(tc.name, func() {
ctx := svrcmd.CreateExecuteContext(context.Background())

cmd := cli.GetQueryCmd()
cmd.SetContext(ctx)
args := tc.args // don't append common tx args
cmd.SetArgs(append(args, tc.extraArgs...))

s.Require().NoError(sdkclient.SetCmdClientContextHandler(tc.NewCtx(s), cmd))

err := cmd.Execute()
if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr)
return
}
s.Require().NoError(err)
})
}
173 changes: 173 additions & 0 deletions x/evm/cli/cli_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package cli_test

import (
"fmt"
"math/big"

// "github.com/NibiruChain/nibiru/x/common/testutil"
"github.com/NibiruChain/nibiru/x/evm"
"github.com/NibiruChain/nibiru/x/evm/evmtest"
gethcommon "github.com/ethereum/go-ethereum/common"
)

var (
dummyAccs = evmtest.NewEthAccInfos(3)
dummyEthAddr = dummyAccs[1].EthAddr.Hex()
dummyFuntoken = evm.NewFunToken(
gethcommon.BigToAddress(big.NewInt(123)),
"ibc/testtoken",
false,
)
)

func (s *Suite) TestCmdSendFunTokenToEvm() {
testCases := []TestCase{
{
name: "happy: send-funtoken-to-erc20",
args: []string{
"send-funtoken-to-erc20",
dummyEthAddr,
fmt.Sprintf("%d%s", 123, dummyFuntoken.BankDenom),
},
extraArgs: []string{fmt.Sprintf("--from=%s", s.testAcc.Address)},
wantErr: "",
},
{
name: "sad: coin format",
args: []string{
"send-funtoken-to-erc20",
dummyAccs[1].EthAddr.Hex(),
fmt.Sprintf("%s %d", dummyFuntoken.BankDenom, 123),
},
extraArgs: []string{fmt.Sprintf("--from=%s", s.testAcc.Address)},
wantErr: "invalid decimal coin expression",
},
}

for _, tc := range testCases {
tc.RunTxCmd(s)
}
}

func (s *Suite) TestCmdCreateFunToken() {
testCases := []TestCase{
{
name: "happy: create-funtoken (erc20)",
args: []string{
"create-funtoken",
fmt.Sprintf("--erc20=%s", dummyEthAddr),
},
extraArgs: []string{fmt.Sprintf("--from=%s", s.testAcc.Address)},
wantErr: "",
},
{
name: "happy: create-funtoken (bank coin)",
args: []string{
"create-funtoken",
fmt.Sprintf("--bank-denom=%s", dummyFuntoken.BankDenom),
},
extraArgs: []string{fmt.Sprintf("--from=%s", s.testAcc.Address)},
wantErr: "",
},
{
name: "sad: too many args",
args: []string{
"create-funtoken",
fmt.Sprintf("--erc20=%s", dummyEthAddr),
fmt.Sprintf("--bank-denom=%s", dummyFuntoken.BankDenom),
},
extraArgs: []string{fmt.Sprintf("--from=%s", s.testAcc.Address)},
wantErr: "exactly one of the flags --bank-denom or --erc20 must be specified",
},
}

for _, tc := range testCases {
tc.RunTxCmd(s)
}
}

func (s *Suite) TestCmdQueryAccount() {
testCases := []TestCase{
{
name: "happy: query account (bech32)",
args: []string{
"account",
dummyAccs[0].NibiruAddr.String(),
},
wantErr: "",
},
{
name: "happy: query account (eth hex)",
args: []string{
"account",
dummyAccs[0].EthAddr.Hex(),
},
wantErr: "",
},
{
name: "happy: query account (eth hex) --offline",
args: []string{
"account",
dummyAccs[0].EthAddr.Hex(),
"--offline",
},
wantErr: "",
},
{
name: "happy: query account (bech32) --offline",
args: []string{
"account",
dummyAccs[0].NibiruAddr.String(),
"--offline",
},
wantErr: "",
},
{
name: "sad: too many args",
args: []string{
"funtoken",
"arg1",
"arg2",
},
wantErr: "accepts 1 arg",
},
}

for _, tc := range testCases {
tc.RunQueryCmd(s)
}
}

func (s *Suite) TestCmdQueryFunToken() {
testCases := []TestCase{
{
name: "happy: query funtoken (bank coin denom)",
args: []string{
"funtoken",
dummyFuntoken.BankDenom,
},
wantErr: "",
},
{
name: "happy: query funtoken (erc20 addr)",
args: []string{
"funtoken",
dummyFuntoken.Erc20Addr.String(),
},
wantErr: "",
},
{
name: "sad: too many args",
args: []string{
"funtoken",
"arg1",
"arg2",
},
wantErr: "accepts 1 arg",
},
}

for _, tc := range testCases {
tc.RunQueryCmd(s)
}
}
40 changes: 37 additions & 3 deletions x/evm/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import (
"github.com/cosmos/cosmos-sdk/version"
"github.com/spf13/cobra"

"github.com/NibiruChain/nibiru/eth"
"github.com/NibiruChain/nibiru/x/evm"
sdk "github.com/cosmos/cosmos-sdk/types"
gethcommon "github.com/ethereum/go-ethereum/common"
)

// GetQueryCmd returns a cli command for this module's queries
Expand Down Expand Up @@ -84,15 +87,46 @@ func CmdQueryAccount() *cobra.Command {
}
queryClient := evm.NewQueryClient(clientCtx)

res, err := queryClient.EthAccount(cmd.Context(), &evm.QueryEthAccountRequest{
req := &evm.QueryEthAccountRequest{
Address: args[0],
})
}

isBech32, err := req.Validate()
fmt.Printf("TODO: UD-DEBUG: req.String(): %v\n", req.String())
fmt.Printf("TODO: UD-DEBUG: err: %v\n", err)
if err != nil {
return err
}
return clientCtx.PrintProto(res)

offline, _ := cmd.Flags().GetBool("offline")

if offline {
var addrEth gethcommon.Address
var addrBech32 sdk.AccAddress

if isBech32 {
addrBech32 = sdk.MustAccAddressFromBech32(req.Address)
addrEth = eth.NibiruAddrToEthAddr(addrBech32)
} else {
addrEth = gethcommon.HexToAddress(req.Address)
addrBech32 = eth.EthAddrToNibiruAddr(addrEth)
}

resp := new(evm.QueryEthAccountResponse)
resp.EthAddress = addrEth.Hex()
resp.Bech32Address = addrBech32.String()
return clientCtx.PrintProto(resp)
}

resp, err := queryClient.EthAccount(cmd.Context(), req)
if err != nil {
return fmt.Errorf("consider using the \"--offline\" flag: %w", err)
}

return clientCtx.PrintProto(resp)
},
}
cmd.Flags().Bool("offline", false, "Skip the query and only return addresses.")
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
Loading

0 comments on commit 81a2af4

Please sign in to comment.