From 0c3d90f3a803d940bd259f7f255cb440c13d0350 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Wed, 25 Oct 2023 16:54:07 -0400 Subject: [PATCH 1/3] test: trackers (#1320) --- testutil/keeper/config.go | 25 +++ testutil/keeper/crosschain.go | 1 + testutil/sample/common.go | 32 ++++ .../keeper_cross_chain_tx_vote_inbound_tx.go | 1 + .../keeper/msg_server_add_to_intx_tracker.go | 70 +------ .../msg_server_add_to_intx_tracker_test.go | 176 ++++++++++++++++++ .../msg_server_add_to_outtx_tracker_test.go | 158 ++++++++++++++++ x/crosschain/keeper/verify_block_header.go | 53 ------ x/crosschain/keeper/verify_proof.go | 104 +++++++++++ x/crosschain/types/errors.go | 14 +- .../types/message_add_to_in_tx_tracker.go | 4 +- 11 files changed, 515 insertions(+), 123 deletions(-) create mode 100644 testutil/keeper/config.go create mode 100644 x/crosschain/keeper/msg_server_add_to_intx_tracker_test.go create mode 100644 x/crosschain/keeper/msg_server_add_to_outtx_tracker_test.go delete mode 100644 x/crosschain/keeper/verify_block_header.go create mode 100644 x/crosschain/keeper/verify_proof.go diff --git a/testutil/keeper/config.go b/testutil/keeper/config.go new file mode 100644 index 0000000000..9c2c63cf27 --- /dev/null +++ b/testutil/keeper/config.go @@ -0,0 +1,25 @@ +package keeper + +import sdk "github.com/cosmos/cosmos-sdk/types" + +const ( + AccountAddressPrefix = "zeta" +) + +var ( + AccountPubKeyPrefix = AccountAddressPrefix + "pub" + ValidatorAddressPrefix = AccountAddressPrefix + "valoper" + ValidatorPubKeyPrefix = AccountAddressPrefix + "valoperpub" + ConsNodeAddressPrefix = AccountAddressPrefix + "valcons" + ConsNodePubKeyPrefix = AccountAddressPrefix + "valconspub" +) + +func SetConfig(seal bool) { + config := sdk.GetConfig() + config.SetBech32PrefixForAccount(AccountAddressPrefix, AccountPubKeyPrefix) + config.SetBech32PrefixForValidator(ValidatorAddressPrefix, ValidatorPubKeyPrefix) + config.SetBech32PrefixForConsensusNode(ConsNodeAddressPrefix, ConsNodePubKeyPrefix) + if seal { + config.Seal() + } +} diff --git a/testutil/keeper/crosschain.go b/testutil/keeper/crosschain.go index f96dc7e87c..0cb2a31bb2 100644 --- a/testutil/keeper/crosschain.go +++ b/testutil/keeper/crosschain.go @@ -37,6 +37,7 @@ func CrosschainKeeperWithMocks( t testing.TB, mockOptions CrosschainMockOptions, ) (*keeper.Keeper, sdk.Context, SDKKeepers, ZetaKeepers) { + SetConfig(false) storeKey := sdk.NewKVStoreKey(types.StoreKey) memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) diff --git a/testutil/sample/common.go b/testutil/sample/common.go index a2d3c18dd7..4b1a65bd15 100644 --- a/testutil/sample/common.go +++ b/testutil/sample/common.go @@ -5,10 +5,12 @@ import ( "math/big" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rlp" "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/zeta-chain/zetacore/common" + "github.com/zeta-chain/zetacore/common/ethereum" ) func Chain(chainID int64) *common.Chain { @@ -42,3 +44,33 @@ func EthHeader() (headerRLP []byte, err error) { headerRLP, _ = rlp.EncodeToBytes(block.Header()) return } + +func Proof() (txIndex int64, block *ethtypes.Block, header ethtypes.Header, headerRLP []byte, proof *common.Proof, tx *ethtypes.Transaction, err error) { + txIndex = int64(9) + url := "https://rpc.ankr.com/eth_goerli" + client, err := ethclient.Dial(url) + if err != nil { + return + } + bn := int64(9889649) + block, err = client.BlockByNumber(context.Background(), big.NewInt(bn)) + if err != nil { + return + } + headerRLP, _ = rlp.EncodeToBytes(block.Header()) + err = rlp.DecodeBytes(headerRLP, &header) + if err != nil { + return + } + tr := ethereum.NewTrie(block.Transactions()) + var b []byte + ib := rlp.AppendUint64(b, uint64(txIndex)) + p := ethereum.NewProof() + err = tr.Prove(ib, 0, p) + if err != nil { + return + } + proof = common.NewEthereumProof(p) + tx = block.Transactions()[txIndex] + return +} diff --git a/x/crosschain/keeper/keeper_cross_chain_tx_vote_inbound_tx.go b/x/crosschain/keeper/keeper_cross_chain_tx_vote_inbound_tx.go index 8e36f2983b..d4454ba42f 100644 --- a/x/crosschain/keeper/keeper_cross_chain_tx_vote_inbound_tx.go +++ b/x/crosschain/keeper/keeper_cross_chain_tx_vote_inbound_tx.go @@ -238,6 +238,7 @@ func (k msgServer) VoteOnObservedInboundTx(goCtx context.Context, msg *types.Msg } commit() cctx.CctxStatus.ChangeStatus(types.CctxStatus_PendingOutbound, "") + k.RemoveInTxTrackerIfExists(ctx, cctx.InboundTxParams.SenderChainId, cctx.InboundTxParams.InboundTxObservedHash) return &types.MsgVoteOnObservedInboundTxResponse{}, nil } } diff --git a/x/crosschain/keeper/msg_server_add_to_intx_tracker.go b/x/crosschain/keeper/msg_server_add_to_intx_tracker.go index cb9510e9fd..3aa8644423 100644 --- a/x/crosschain/keeper/msg_server_add_to_intx_tracker.go +++ b/x/crosschain/keeper/msg_server_add_to_intx_tracker.go @@ -6,8 +6,6 @@ import ( errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" - eth "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/zeta-chain/zetacore/common" "github.com/zeta-chain/zetacore/x/crosschain/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" @@ -29,11 +27,16 @@ func (k msgServer) AddToInTxTracker(goCtx context.Context, msg *types.MsgAddToIn if !(isAdmin || isObserver) && msg.Proof != nil { txBytes, err := k.VerifyProof(ctx, msg.Proof, msg.ChainId, msg.BlockHash, msg.TxIndex) if err != nil { - return nil, types.ErrCannotVerifyProof.Wrapf(err.Error()) + return nil, types.ErrProofVerificationFail.Wrapf(err.Error()) } - err = k.VerifyInTxBody(ctx, msg, txBytes) - if err != nil { - return nil, types.ErrCannotVerifyProof.Wrapf(err.Error()) + + if common.IsEVMChain(msg.ChainId) { + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + if err != nil { + return nil, types.ErrTxBodyVerificationFail.Wrapf(err.Error()) + } + } else { + return nil, types.ErrTxBodyVerificationFail.Wrapf(fmt.Sprintf("cannot verify inTx body for chain %d", msg.ChainId)) } isProven = true } @@ -43,63 +46,10 @@ func (k msgServer) AddToInTxTracker(goCtx context.Context, msg *types.MsgAddToIn return nil, errorsmod.Wrap(observertypes.ErrNotAuthorized, fmt.Sprintf("Creator %s", msg.Creator)) } - k.Keeper.SetInTxTracker(ctx, types.InTxTracker{ + k.SetInTxTracker(ctx, types.InTxTracker{ ChainId: msg.ChainId, TxHash: msg.TxHash, CoinType: msg.CoinType, }) return &types.MsgAddToInTxTrackerResponse{}, nil } - -// https://github.com/zeta-chain/node/issues/1254 -func (k Keeper) VerifyInTxBody(ctx sdk.Context, msg *types.MsgAddToInTxTracker, txBytes []byte) error { - // get core params and tss address - coreParams, found := k.zetaObserverKeeper.GetCoreParamsByChainID(ctx, msg.ChainId) - if !found { - return types.ErrUnsupportedChain.Wrapf("core params not found for chain %d", msg.ChainId) - } - tss, err := k.GetTssAddress(ctx, &types.QueryGetTssAddressRequest{}) - if err != nil { - return err - } - - // verify message against transaction body - if common.IsEVMChain(msg.ChainId) { - err = VerifyEVMInTxBody(coreParams, msg, txBytes, tss.Eth) - } else { - return fmt.Errorf("cannot verify inTx body for chain %d", msg.ChainId) - } - return err -} - -func VerifyEVMInTxBody(coreParams *observertypes.CoreParams, msg *types.MsgAddToInTxTracker, txBytes []byte, tssEth string) error { - var txx ethtypes.Transaction - err := txx.UnmarshalBinary(txBytes) - if err != nil { - return err - } - tssAddr := eth.HexToAddress(tssEth) - if tssAddr == (eth.Address{}) { - return fmt.Errorf("tss address not found") - } - - switch msg.CoinType { - case common.CoinType_Zeta: - if txx.To().Hex() != coreParams.ConnectorContractAddress { - return fmt.Errorf("receiver is not connector contract for coin type %s", msg.CoinType) - } - return nil - case common.CoinType_ERC20: - if txx.To().Hex() != coreParams.Erc20CustodyContractAddress { - return fmt.Errorf("receiver is not erc20Custory contract for coin type %s", msg.CoinType) - } - return nil - case common.CoinType_Gas: - if txx.To().Hex() != tssAddr.Hex() { - return fmt.Errorf("receiver is not tssAddress contract for coin type %s", msg.CoinType) - } - return nil - default: - return fmt.Errorf("coin type %s not supported", msg.CoinType) - } -} diff --git a/x/crosschain/keeper/msg_server_add_to_intx_tracker_test.go b/x/crosschain/keeper/msg_server_add_to_intx_tracker_test.go new file mode 100644 index 0000000000..715635e9fe --- /dev/null +++ b/x/crosschain/keeper/msg_server_add_to_intx_tracker_test.go @@ -0,0 +1,176 @@ +//go:build TESTNET +// +build TESTNET + +package keeper_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/common" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/crosschain/keeper" + "github.com/zeta-chain/zetacore/x/crosschain/types" + observerTypes "github.com/zeta-chain/zetacore/x/observer/types" +) + +func TestMsgServer_AddToInTxTracker(t *testing.T) { + t.Run("add proof based tracker with correct proof", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + chainID := int64(5) + txIndex, block, header, headerRLP, proof, tx, err := sample.Proof() + require.NoError(t, err) + setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block) + msgServer := keeper.NewMsgServerImpl(*k) + _, err = msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ + Creator: sample.AccAddress(), + ChainId: chainID, + TxHash: tx.Hash().Hex(), + CoinType: common.CoinType_Zeta, + Proof: proof, + BlockHash: block.Hash().Hex(), + TxIndex: txIndex, + }) + require.NoError(t, err) + _, found := k.GetInTxTracker(ctx, chainID, tx.Hash().Hex()) + require.True(t, found) + }) + + t.Run("fail to add proof based tracker with wrong tx hash", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + chainID := int64(5) + txIndex, block, header, headerRLP, proof, tx, err := sample.Proof() + require.NoError(t, err) + setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block) + msgServer := keeper.NewMsgServerImpl(*k) + _, err = msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ + Creator: sample.AccAddress(), + ChainId: chainID, + TxHash: "fake_hash", + CoinType: common.CoinType_Zeta, + Proof: proof, + BlockHash: block.Hash().Hex(), + TxIndex: txIndex, + }) + require.ErrorIs(t, types.ErrTxBodyVerificationFail, err) + _, found := k.GetInTxTracker(ctx, chainID, tx.Hash().Hex()) + require.False(t, found) + }) + + t.Run("fail to add proof based tracker with wrong chain id", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + chainID := int64(5) + txIndex, block, header, headerRLP, proof, tx, err := sample.Proof() + require.NoError(t, err) + setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block) + msgServer := keeper.NewMsgServerImpl(*k) + _, err = msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ + Creator: sample.AccAddress(), + ChainId: 97, + TxHash: tx.Hash().Hex(), + CoinType: common.CoinType_Zeta, + Proof: proof, + BlockHash: block.Hash().Hex(), + TxIndex: txIndex, + }) + require.ErrorIs(t, types.ErrTxBodyVerificationFail, err) + _, found := k.GetInTxTracker(ctx, chainID, tx.Hash().Hex()) + require.False(t, found) + }) + t.Run("fail normal user submit without proof", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + tx_hash := "string" + chainID := int64(5) + msgServer := keeper.NewMsgServerImpl(*k) + _, err := msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ + Creator: sample.AccAddress(), + ChainId: chainID, + TxHash: tx_hash, + CoinType: common.CoinType_Zeta, + Proof: nil, + BlockHash: "", + TxIndex: 0, + }) + require.ErrorIs(t, observerTypes.ErrNotAuthorized, err) + _, found := k.GetInTxTracker(ctx, chainID, tx_hash) + require.False(t, found) + }) + t.Run("admin add tx tracker", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + admin := sample.AccAddress() + setAdminPolicies(ctx, zk, admin) + tx_hash := "string" + chainID := int64(5) + msgServer := keeper.NewMsgServerImpl(*k) + _, err := msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ + Creator: admin, + ChainId: chainID, + TxHash: tx_hash, + CoinType: common.CoinType_Zeta, + Proof: nil, + BlockHash: "", + TxIndex: 0, + }) + require.NoError(t, err) + _, found := k.GetInTxTracker(ctx, chainID, tx_hash) + require.True(t, found) + }) + t.Run("admin submit fake tracker", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + admin := sample.AccAddress() + setAdminPolicies(ctx, zk, admin) + tx_hash := "string" + chainID := int64(5) + msgServer := keeper.NewMsgServerImpl(*k) + _, err := msgServer.AddToInTxTracker(ctx, &types.MsgAddToInTxTracker{ + Creator: admin, + ChainId: chainID, + TxHash: "Malicious TX HASH", + CoinType: common.CoinType_Zeta, + Proof: nil, + BlockHash: "", + TxIndex: 0, + }) + require.NoError(t, err) + _, found := k.GetInTxTracker(ctx, chainID, "Malicious TX HASH") + require.True(t, found) + _, found = k.GetInTxTracker(ctx, chainID, tx_hash) + require.False(t, found) + }) +} + +func setupVerificationParams(zk keepertest.ZetaKeepers, ctx sdk.Context, tx_index int64, chainID int64, header ethtypes.Header, headerRLP []byte, block *ethtypes.Block) { + params := zk.ObserverKeeper.GetParams(ctx) + params.ObserverParams = append(params.ObserverParams, &observerTypes.ObserverParams{ + Chain: &common.Chain{ + ChainId: chainID, + ChainName: common.ChainName_goerli_testnet, + }, + BallotThreshold: sdk.OneDec(), + MinObserverDelegation: sdk.OneDec(), + IsSupported: true, + }) + zk.ObserverKeeper.SetParams(ctx, params) + zk.ObserverKeeper.SetBlockHeader(ctx, common.BlockHeader{ + Height: block.Number().Int64(), + Hash: block.Hash().Bytes(), + ParentHash: header.ParentHash.Bytes(), + ChainId: chainID, + Header: common.NewEthereumHeader(headerRLP), + }) + zk.ObserverKeeper.SetCoreParams(ctx, observerTypes.CoreParamsList{CoreParams: []*observerTypes.CoreParams{ + { + ChainId: chainID, + ConnectorContractAddress: block.Transactions()[tx_index].To().Hex(), + }, + }}) + zk.ObserverKeeper.SetCrosschainFlags(ctx, observerTypes.CrosschainFlags{ + BlockHeaderVerificationFlags: &observerTypes.BlockHeaderVerificationFlags{ + IsEthTypeChainEnabled: true, + IsBtcTypeChainEnabled: false, + }, + }) +} diff --git a/x/crosschain/keeper/msg_server_add_to_outtx_tracker_test.go b/x/crosschain/keeper/msg_server_add_to_outtx_tracker_test.go new file mode 100644 index 0000000000..c43bd45ce8 --- /dev/null +++ b/x/crosschain/keeper/msg_server_add_to_outtx_tracker_test.go @@ -0,0 +1,158 @@ +//go:build TESTNET +// +build TESTNET + +package keeper_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/common" + "github.com/zeta-chain/zetacore/common/ethereum" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/crosschain/keeper" + "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +func TestMsgServer_AddToOutTxTracker(t *testing.T) { + t.Run("add tracker admin", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + admin := sample.AccAddress() + setAdminPolicies(ctx, zk, admin) + chainID := int64(5) + txIndex, block, header, headerRLP, _, tx, err := sample.Proof() + require.NoError(t, err) + setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block) + setupTss(k, ctx) + msgServer := keeper.NewMsgServerImpl(*k) + _, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{ + Creator: admin, + ChainId: chainID, + TxHash: tx.Hash().Hex(), + Proof: nil, + BlockHash: "", + TxIndex: 0, + Nonce: 0, + }) + require.NoError(t, err) + _, found := k.GetOutTxTracker(ctx, chainID, 0) + require.True(t, found) + }) + + t.Run("fail add proof based tracker with wrong chainID", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + chainID := int64(5) + txIndex, block, header, headerRLP, proof, tx, err := sample.Proof() + require.NoError(t, err) + setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block) + setupTss(k, ctx) + msgServer := keeper.NewMsgServerImpl(*k) + _, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{ + Creator: sample.AccAddress(), + ChainId: 97, + TxHash: tx.Hash().Hex(), + Proof: proof, + BlockHash: block.Hash().Hex(), + TxIndex: txIndex, + Nonce: tx.Nonce(), + }) + require.ErrorIs(t, types.ErrTxBodyVerificationFail, err) + _, found := k.GetOutTxTracker(ctx, chainID, tx.Nonce()) + require.False(t, found) + }) + + t.Run("fail add proof based tracker with wrong nonce", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + chainID := int64(5) + txIndex, block, header, headerRLP, proof, tx, err := sample.Proof() + require.NoError(t, err) + setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block) + setupTss(k, ctx) + msgServer := keeper.NewMsgServerImpl(*k) + _, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{ + Creator: sample.AccAddress(), + ChainId: chainID, + TxHash: tx.Hash().Hex(), + Proof: proof, + BlockHash: block.Hash().Hex(), + TxIndex: txIndex, + Nonce: 1, + }) + require.ErrorIs(t, types.ErrTxBodyVerificationFail, err) + _, found := k.GetOutTxTracker(ctx, chainID, 1) + require.False(t, found) + }) + + t.Run("fail add proof based tracker with wrong tx_hash", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + chainID := int64(5) + txIndex, block, header, headerRLP, proof, tx, err := sample.Proof() + require.NoError(t, err) + setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block) + setupTss(k, ctx) + msgServer := keeper.NewMsgServerImpl(*k) + _, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{ + Creator: sample.AccAddress(), + ChainId: chainID, + TxHash: "wrong_hash", + Proof: proof, + BlockHash: block.Hash().Hex(), + TxIndex: txIndex, + Nonce: tx.Nonce(), + }) + require.ErrorIs(t, types.ErrTxBodyVerificationFail, err) + _, found := k.GetOutTxTracker(ctx, chainID, tx.Nonce()) + require.False(t, found) + }) + + t.Run("fail proof based tracker with incorrect proof", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + chainID := int64(5) + txIndex, block, header, headerRLP, _, tx, err := sample.Proof() + require.NoError(t, err) + setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block) + setupTss(k, ctx) + msgServer := keeper.NewMsgServerImpl(*k) + _, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{ + Creator: sample.AccAddress(), + ChainId: chainID, + TxHash: tx.Hash().Hex(), + Proof: common.NewEthereumProof(ethereum.NewProof()), + BlockHash: block.Hash().Hex(), + TxIndex: txIndex, + Nonce: tx.Nonce(), + }) + require.ErrorIs(t, types.ErrProofVerificationFail, err) + _, found := k.GetOutTxTracker(ctx, chainID, tx.Nonce()) + require.False(t, found) + }) + t.Run("add proof based tracker with correct proof", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + chainID := int64(5) + txIndex, block, header, headerRLP, proof, tx, err := sample.Proof() + require.NoError(t, err) + setupVerificationParams(zk, ctx, txIndex, chainID, header, headerRLP, block) + setupTss(k, ctx) + msgServer := keeper.NewMsgServerImpl(*k) + _, err = msgServer.AddToOutTxTracker(ctx, &types.MsgAddToOutTxTracker{ + Creator: sample.AccAddress(), + ChainId: chainID, + TxHash: tx.Hash().Hex(), + Proof: proof, + BlockHash: block.Hash().Hex(), + TxIndex: txIndex, + Nonce: tx.Nonce(), + }) + require.NoError(t, err) + _, found := k.GetOutTxTracker(ctx, chainID, tx.Nonce()) + require.True(t, found) + }) +} + +func setupTss(k *keeper.Keeper, ctx sdk.Context) { + k.SetTSS(ctx, types.TSS{ + TssPubkey: "zetapub1addwnpepq28c57cvcs0a2htsem5zxr6qnlvq9mzhmm76z3jncsnzz32rclangr2g35p", + }) +} diff --git a/x/crosschain/keeper/verify_block_header.go b/x/crosschain/keeper/verify_block_header.go deleted file mode 100644 index 92f389987e..0000000000 --- a/x/crosschain/keeper/verify_block_header.go +++ /dev/null @@ -1,53 +0,0 @@ -package keeper - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/zeta-chain/zetacore/common" - "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -func (k Keeper) VerifyProof(ctx sdk.Context, proof *common.Proof, chainID int64, blockHash string, txIndex int64) ([]byte, error) { - // header-based merkle proof verification must be enabled - crosschainFlags, found := k.zetaObserverKeeper.GetCrosschainFlags(ctx) - if !found { - return nil, fmt.Errorf("crosschain flags not found") - } - if crosschainFlags.BlockHeaderVerificationFlags == nil { - return nil, fmt.Errorf("block header verification flags not found") - } - if common.IsBitcoinChain(chainID) && !crosschainFlags.BlockHeaderVerificationFlags.IsBtcTypeChainEnabled { - return nil, fmt.Errorf("proof verification not enabled for bitcoin chain") - } - if common.IsEVMChain(chainID) && !crosschainFlags.BlockHeaderVerificationFlags.IsEthTypeChainEnabled { - return nil, fmt.Errorf("proof verification not enabled for evm chain") - } - - // chain must support header-based merkle proof verification - senderChain := common.GetChainFromChainID(chainID) - if senderChain == nil { - return nil, types.ErrUnsupportedChain - } - if !senderChain.SupportMerkleProof() { - return nil, fmt.Errorf("chain %d does not support block header-based verification", chainID) - } - - // get block header from the store - hashBytes, err := common.StringToHash(chainID, blockHash) - if err != nil { - return nil, fmt.Errorf("block hash %s conversion failed %s", blockHash, err) - } - res, found := k.zetaObserverKeeper.GetBlockHeader(ctx, hashBytes) - if !found { - return nil, fmt.Errorf("block header not found %s", blockHash) - } - - // verify merkle proof - txBytes, err := proof.Verify(res.Header, int(txIndex)) - if err != nil { - return nil, err - } - - return txBytes, err -} diff --git a/x/crosschain/keeper/verify_proof.go b/x/crosschain/keeper/verify_proof.go new file mode 100644 index 0000000000..c80a600078 --- /dev/null +++ b/x/crosschain/keeper/verify_proof.go @@ -0,0 +1,104 @@ +package keeper + +import ( + "fmt" + "math/big" + + sdk "github.com/cosmos/cosmos-sdk/types" + eth "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/zeta-chain/zetacore/common" + "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +func (k Keeper) VerifyProof(ctx sdk.Context, proof *common.Proof, chainID int64, blockHash string, txIndex int64) ([]byte, error) { + // header-based merkle proof verification must be enabled + crosschainFlags, found := k.zetaObserverKeeper.GetCrosschainFlags(ctx) + if !found { + return nil, fmt.Errorf("crosschain flags not found") + } + if crosschainFlags.BlockHeaderVerificationFlags == nil { + return nil, fmt.Errorf("block header verification flags not found") + } + if common.IsBitcoinChain(chainID) && !crosschainFlags.BlockHeaderVerificationFlags.IsBtcTypeChainEnabled { + return nil, fmt.Errorf("proof verification not enabled for bitcoin chain") + } + if common.IsEVMChain(chainID) && !crosschainFlags.BlockHeaderVerificationFlags.IsEthTypeChainEnabled { + return nil, fmt.Errorf("proof verification not enabled for evm chain") + } + + // chain must support header-based merkle proof verification + senderChain := common.GetChainFromChainID(chainID) + if senderChain == nil { + return nil, types.ErrUnsupportedChain + } + if !senderChain.SupportMerkleProof() { + return nil, fmt.Errorf("chain %d does not support block header-based verification", chainID) + } + + // get block header from the store + hashBytes, err := common.StringToHash(chainID, blockHash) + if err != nil { + return nil, fmt.Errorf("block hash %s conversion failed %s", blockHash, err) + } + res, found := k.zetaObserverKeeper.GetBlockHeader(ctx, hashBytes) + if !found { + return nil, fmt.Errorf("block header not found %s", blockHash) + } + + // verify merkle proof + txBytes, err := proof.Verify(res.Header, int(txIndex)) + if err != nil { + return nil, err + } + return txBytes, err +} + +func (k Keeper) VerifyEVMInTxBody(ctx sdk.Context, msg *types.MsgAddToInTxTracker, txBytes []byte) error { + var txx ethtypes.Transaction + err := txx.UnmarshalBinary(txBytes) + if err != nil { + return err + } + if txx.Hash().Hex() != msg.TxHash { + return fmt.Errorf("want tx hash %s, got %s", txx.Hash().Hex(), msg.TxHash) + } + if txx.ChainId().Cmp(big.NewInt(msg.ChainId)) != 0 { + return fmt.Errorf("want evm chain id %d, got %d", txx.ChainId(), msg.ChainId) + } + switch msg.CoinType { + case common.CoinType_Zeta: + coreParams, found := k.zetaObserverKeeper.GetCoreParamsByChainID(ctx, msg.ChainId) + if !found { + return types.ErrUnsupportedChain.Wrapf("core params not found for chain %d", msg.ChainId) + } + if txx.To().Hex() != coreParams.ConnectorContractAddress { + return fmt.Errorf("receiver is not connector contract for coin type %s", msg.CoinType) + } + return nil + case common.CoinType_ERC20: + coreParams, found := k.zetaObserverKeeper.GetCoreParamsByChainID(ctx, msg.ChainId) + if !found { + return types.ErrUnsupportedChain.Wrapf("core params not found for chain %d", msg.ChainId) + } + if txx.To().Hex() != coreParams.Erc20CustodyContractAddress { + return fmt.Errorf("receiver is not erc20Custory contract for coin type %s", msg.CoinType) + } + return nil + case common.CoinType_Gas: + tss, err := k.GetTssAddress(ctx, &types.QueryGetTssAddressRequest{}) + if err != nil { + return err + } + tssAddr := eth.HexToAddress(tss.Eth) + if tssAddr == (eth.Address{}) { + return fmt.Errorf("tss address not found") + } + if txx.To().Hex() != tssAddr.Hex() { + return fmt.Errorf("receiver is not tssAddress contract for coin type %s", msg.CoinType) + } + return nil + default: + return fmt.Errorf("coin type %s not supported", msg.CoinType) + } +} diff --git a/x/crosschain/types/errors.go b/x/crosschain/types/errors.go index c9186f9795..c1797d54b9 100644 --- a/x/crosschain/types/errors.go +++ b/x/crosschain/types/errors.go @@ -34,12 +34,10 @@ var ( ErrCannotFindCctx = errorsmod.Register(ModuleName, 1134, "cannot find cctx") ErrStatusNotPending = errorsmod.Register(ModuleName, 1135, "Status not pending") - ErrCannotFindGasParams = errorsmod.Register(ModuleName, 1136, "cannot find gas params") - ErrInvalidGasAmount = errorsmod.Register(ModuleName, 1137, "invalid gas amount") - ErrNoLiquidityPool = errorsmod.Register(ModuleName, 1138, "no liquidity pool") - ErrInvalidCoinType = errorsmod.Register(ModuleName, 1139, "invalid coin type") - ErrCannotMigrateTss = errorsmod.Register(ModuleName, 1140, "Cannot migrate TSS funds") - - ErrCannotVerifyProof = errorsmod.Register(ModuleName, 1141, "cannot verify proof") - ErrTxBodyVerificationFail = errorsmod.Register(ModuleName, 1142, "transaction body verification fail") + ErrCannotFindGasParams = errorsmod.Register(ModuleName, 1136, "cannot find gas params") + ErrInvalidGasAmount = errorsmod.Register(ModuleName, 1137, "invalid gas amount") + ErrNoLiquidityPool = errorsmod.Register(ModuleName, 1138, "no liquidity pool") + ErrInvalidCoinType = errorsmod.Register(ModuleName, 1139, "invalid coin type") + ErrCannotMigrateTss = errorsmod.Register(ModuleName, 1140, "Cannot migrate TSS funds") + ErrTxBodyVerificationFail = errorsmod.Register(ModuleName, 1141, "transaction body verification fail") ) diff --git a/x/crosschain/types/message_add_to_in_tx_tracker.go b/x/crosschain/types/message_add_to_in_tx_tracker.go index c44c15ba8c..5f15f4d735 100644 --- a/x/crosschain/types/message_add_to_in_tx_tracker.go +++ b/x/crosschain/types/message_add_to_in_tx_tracker.go @@ -51,11 +51,11 @@ func (msg *MsgAddToInTxTracker) ValidateBasic() error { return errorsmod.Wrapf(ErrInvalidChainID, "chain id (%d)", msg.ChainId) } if msg.Proof != nil && !chain.SupportMerkleProof() { - return errorsmod.Wrapf(ErrCannotVerifyProof, "chain id %d does not support proof-based trackers", msg.ChainId) + return errorsmod.Wrapf(ErrProofVerificationFail, "chain id %d does not support proof-based trackers", msg.ChainId) } _, ok := common.CoinType_value[msg.CoinType.String()] if !ok { - return errorsmod.Wrapf(ErrCannotVerifyProof, "coin-type not supported") + return errorsmod.Wrapf(ErrProofVerificationFail, "coin-type not supported") } return nil } From f9d998783db44d1d3a95127b5ae19da7cd482899 Mon Sep 17 00:00:00 2001 From: Luke Ma <867273263@qq.com> Date: Fri, 27 Oct 2023 01:45:35 +0800 Subject: [PATCH 2/3] refactor: Enhance the basic validation for MsgDeployFungibleCoinZRC20 (#1310) * add the basic validation for MsgDeployFungibleCoinZRC20 * modify erc20 decimals limit --- .../keeper/msg_server_deploy_fungible_coin_zrc20.go | 8 +++++--- .../keeper/msg_server_deploy_fungible_coin_zrc20_test.go | 2 +- x/fungible/types/message_deploy_fungible_coin_zrc20.go | 6 +++++- .../types/message_deploy_fungible_coin_zrc20_test.go | 8 ++++++++ 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20.go b/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20.go index 24ab3f5f87..76bfbba39e 100644 --- a/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20.go +++ b/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20.go @@ -37,12 +37,14 @@ func (k msgServer) DeployFungibleCoinZRC20(goCtx context.Context, msg *types.Msg var address common.Address var err error + if err = msg.ValidateBasic(); err != nil { + return nil, err + } + if msg.Creator != k.observerKeeper.GetParams(ctx).GetAdminPolicyAccount(zetaObserverTypes.Policy_Type_group2) { return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Deploy can only be executed by the correct policy account") } - if msg.Decimals > 255 { - return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "decimals must be less than 256") - } + if msg.CoinType == zetacommon.CoinType_Gas { // #nosec G701 always in range address, err = k.SetupChainGasCoinAndPool(ctx, msg.ForeignChainId, msg.Name, msg.Symbol, uint8(msg.Decimals), big.NewInt(msg.GasLimit)) diff --git a/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20_test.go b/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20_test.go index 788feba0fb..95426c9437 100644 --- a/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20_test.go +++ b/x/fungible/keeper/msg_server_deploy_fungible_coin_zrc20_test.go @@ -122,7 +122,7 @@ func TestMsgServer_DeployFungibleCoinZRC20(t *testing.T) { admin, sample.EthAddress().Hex(), chainID, - 256, + 78, "foo", "foo", common.CoinType_Gas, diff --git a/x/fungible/types/message_deploy_fungible_coin_zrc20.go b/x/fungible/types/message_deploy_fungible_coin_zrc20.go index 14d6681b3f..6b23365001 100644 --- a/x/fungible/types/message_deploy_fungible_coin_zrc20.go +++ b/x/fungible/types/message_deploy_fungible_coin_zrc20.go @@ -50,7 +50,11 @@ func (msg *MsgDeployFungibleCoinZRC20) ValidateBasic() error { return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) } if msg.GasLimit < 0 { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidGasLimit, "invalid gas limit (%s)", err) + return sdkerrors.Wrapf(sdkerrors.ErrInvalidGasLimit, "invalid gas limit") + } + + if msg.Decimals > 77 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "decimals must be less than 78") } return nil } diff --git a/x/fungible/types/message_deploy_fungible_coin_zrc20_test.go b/x/fungible/types/message_deploy_fungible_coin_zrc20_test.go index 75f50bc290..e107af7781 100644 --- a/x/fungible/types/message_deploy_fungible_coin_zrc20_test.go +++ b/x/fungible/types/message_deploy_fungible_coin_zrc20_test.go @@ -30,6 +30,14 @@ func TestMsgDeployFungibleCoinZRC4_ValidateBasic(t *testing.T) { }, err: sdkerrors.ErrInvalidGasLimit, }, + { + name: "invalid decimals", + msg: types.MsgDeployFungibleCoinZRC20{ + Creator: sample.AccAddress(), + Decimals: 78, + }, + err: sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "decimals must be less than 78"), + }, { name: "valid message", msg: types.MsgDeployFungibleCoinZRC20{ From ea9ba1271de86bc06e58d51a0de1a29650908ef5 Mon Sep 17 00:00:00 2001 From: Lucas Bertrand Date: Thu, 26 Oct 2023 15:44:28 -0700 Subject: [PATCH 3/3] fix: register codec for all messages (#1210) * codec * add msgServer * fix tests * add new missing messages --- x/crosschain/keeper/gas_payment_test.go | 18 ++++++---- .../keeper/msg_server_whitelist_erc20.go | 2 +- .../keeper/msg_server_whitelist_erc20_test.go | 21 ++++++++---- x/crosschain/keeper/test_privnet.go | 3 +- x/crosschain/types/codec.go | 12 +++++-- ...blocker_deploy_system_contracts_privnet.go | 6 ++-- .../msg_server_update_contract_bytecode.go | 2 +- ...sg_server_update_contract_bytecode_test.go | 34 +++++++++++++------ .../msg_server_update_system_contract.go | 2 +- .../msg_server_update_system_contract_test.go | 9 +++-- .../msg_server_update_zrc20_paused_status.go | 2 +- ..._server_update_zrc20_paused_status_test.go | 25 ++++++++------ .../msg_server_update_zrc20_withdraw_fee.go | 2 +- ...g_server_update_zrc20_withdraw_fee_test.go | 26 +++++++++----- x/fungible/types/codec.go | 8 +++++ x/observer/types/codec.go | 8 ++++- 16 files changed, 123 insertions(+), 57 deletions(-) diff --git a/x/crosschain/keeper/gas_payment_test.go b/x/crosschain/keeper/gas_payment_test.go index 9f771ba542..a1ad790d4a 100644 --- a/x/crosschain/keeper/gas_payment_test.go +++ b/x/crosschain/keeper/gas_payment_test.go @@ -226,12 +226,13 @@ func TestKeeper_PayGasNativeAndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin) + fungibleMsgServer := fungiblekeeper.NewMsgServerImpl(*zk.FungibleKeeper) // deploy gas coin and set fee params chainID := getValidEthChainID(t) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) zrc20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") - _, err := zk.FungibleKeeper.UpdateZRC20WithdrawFee( + _, err := fungibleMsgServer.UpdateZRC20WithdrawFee( sdk.UnwrapSDKContext(ctx), fungibletypes.NewMsgUpdateZRC20WithdrawFee(admin, zrc20.String(), sdk.NewUint(withdrawFee), math.Uint{}), ) @@ -324,12 +325,13 @@ func TestKeeper_PayGasNativeAndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin) + fungibleMsgServer := fungiblekeeper.NewMsgServerImpl(*zk.FungibleKeeper) // deploy gas coin and set fee params chainID := getValidEthChainID(t) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) zrc20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") - _, err := zk.FungibleKeeper.UpdateZRC20WithdrawFee( + _, err := fungibleMsgServer.UpdateZRC20WithdrawFee( sdk.UnwrapSDKContext(ctx), fungibletypes.NewMsgUpdateZRC20WithdrawFee(admin, zrc20.String(), sdk.NewUint(withdrawFee), math.Uint{}), ) @@ -367,6 +369,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin) + fungibleMsgServer := fungiblekeeper.NewMsgServerImpl(*zk.FungibleKeeper) // deploy gas coin, erc20 and set fee params chainID := getValidEthChainID(t) @@ -383,7 +386,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { assetAddress, "bar", ) - _, err := zk.FungibleKeeper.UpdateZRC20WithdrawFee( + _, err := fungibleMsgServer.UpdateZRC20WithdrawFee( sdk.UnwrapSDKContext(ctx), fungibletypes.NewMsgUpdateZRC20WithdrawFee(admin, gasZRC20.String(), sdk.NewUint(withdrawFee), math.Uint{}), ) @@ -490,13 +493,14 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin) + fungibleMsgServer := fungiblekeeper.NewMsgServerImpl(*zk.FungibleKeeper) // deploy gas coin, erc20 and set fee params chainID := getValidEthChainID(t) assetAddress := sample.EthAddress().String() deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) gasZRC20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foo", "foo") - _, err := zk.FungibleKeeper.UpdateZRC20WithdrawFee( + _, err := fungibleMsgServer.UpdateZRC20WithdrawFee( sdk.UnwrapSDKContext(ctx), fungibletypes.NewMsgUpdateZRC20WithdrawFee(admin, gasZRC20.String(), sdk.NewUint(withdrawFee), math.Uint{}), ) @@ -534,6 +538,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin) + fungibleMsgServer := fungiblekeeper.NewMsgServerImpl(*zk.FungibleKeeper) // deploy gas coin, erc20 and set fee params chainID := getValidEthChainID(t) @@ -550,7 +555,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { assetAddress, "bar", ) - _, err := zk.FungibleKeeper.UpdateZRC20WithdrawFee( + _, err := fungibleMsgServer.UpdateZRC20WithdrawFee( sdk.UnwrapSDKContext(ctx), fungibletypes.NewMsgUpdateZRC20WithdrawFee(admin, gasZRC20.String(), sdk.NewUint(withdrawFee), math.Uint{}), ) @@ -588,6 +593,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin) + fungibleMsgServer := fungiblekeeper.NewMsgServerImpl(*zk.FungibleKeeper) // deploy gas coin, erc20 and set fee params chainID := getValidEthChainID(t) @@ -604,7 +610,7 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { assetAddress, "bar", ) - _, err := zk.FungibleKeeper.UpdateZRC20WithdrawFee( + _, err := fungibleMsgServer.UpdateZRC20WithdrawFee( sdk.UnwrapSDKContext(ctx), fungibletypes.NewMsgUpdateZRC20WithdrawFee(admin, gasZRC20.String(), sdk.NewUint(withdrawFee), math.Uint{}), ) diff --git a/x/crosschain/keeper/msg_server_whitelist_erc20.go b/x/crosschain/keeper/msg_server_whitelist_erc20.go index bd8d7b5f60..7097f8c46b 100644 --- a/x/crosschain/keeper/msg_server_whitelist_erc20.go +++ b/x/crosschain/keeper/msg_server_whitelist_erc20.go @@ -21,7 +21,7 @@ import ( // WhitelistERC20 deploys a new zrc20, create a foreign coin object for the ERC20 // and emit a crosschain tx to whitelist the ERC20 on the external chain -func (k Keeper) WhitelistERC20(goCtx context.Context, msg *types.MsgWhitelistERC20) (*types.MsgWhitelistERC20Response, error) { +func (k msgServer) WhitelistERC20(goCtx context.Context, msg *types.MsgWhitelistERC20) (*types.MsgWhitelistERC20Response, error) { ctx := sdk.UnwrapSDKContext(goCtx) if msg.Creator != k.zetaObserverKeeper.GetParams(ctx).GetAdminPolicyAccount(zetaObserverTypes.Policy_Type_group1) { return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "Deploy can only be executed by the correct policy account") diff --git a/x/crosschain/keeper/msg_server_whitelist_erc20_test.go b/x/crosschain/keeper/msg_server_whitelist_erc20_test.go index 8a2925ddcd..7461ffc81b 100644 --- a/x/crosschain/keeper/msg_server_whitelist_erc20_test.go +++ b/x/crosschain/keeper/msg_server_whitelist_erc20_test.go @@ -10,6 +10,7 @@ import ( "github.com/zeta-chain/zetacore/common" keepertest "github.com/zeta-chain/zetacore/testutil/keeper" "github.com/zeta-chain/zetacore/testutil/sample" + crosschainkeeper "github.com/zeta-chain/zetacore/x/crosschain/keeper" "github.com/zeta-chain/zetacore/x/crosschain/types" fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" ) @@ -17,6 +18,7 @@ import ( func TestKeeper_WhitelistERC20(t *testing.T) { t.Run("can deploy and whitelist an erc20", func(t *testing.T) { k, ctx, sdkk, zk := keepertest.CrosschainKeeper(t) + msgServer := crosschainkeeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) chainID := getValidEthChainID(t) @@ -33,7 +35,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { }) erc20Address := sample.EthAddress().Hex() - res, err := k.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ + res, err := msgServer.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ Creator: admin, Erc20Address: erc20Address, ChainId: chainID, @@ -63,7 +65,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { require.Equal(t, uint64(100000), gasLimit.Uint64()) // Ensure that whitelist a new erc20 create a cctx with a different index - res, err = k.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ + res, err = msgServer.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ Creator: admin, Erc20Address: sample.EthAddress().Hex(), ChainId: chainID, @@ -79,9 +81,10 @@ func TestKeeper_WhitelistERC20(t *testing.T) { t.Run("should fail if not authorized", func(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) + msgServer := crosschainkeeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) - _, err := k.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ + _, err := msgServer.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ Creator: sample.AccAddress(), Erc20Address: sample.EthAddress().Hex(), ChainId: getValidEthChainID(t), @@ -95,12 +98,13 @@ func TestKeeper_WhitelistERC20(t *testing.T) { t.Run("should fail if invalid erc20 address", func(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) + msgServer := crosschainkeeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin) - _, err := k.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ + _, err := msgServer.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ Creator: admin, Erc20Address: "invalid", ChainId: getValidEthChainID(t), @@ -114,6 +118,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { t.Run("should fail if foreign coin already exists for the asset", func(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) + msgServer := crosschainkeeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) admin := sample.AccAddress() @@ -126,7 +131,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { fc.ForeignChainId = chainID zk.FungibleKeeper.SetForeignCoins(ctx, fc) - _, err := k.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ + _, err := msgServer.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ Creator: admin, Erc20Address: asset, ChainId: chainID, @@ -140,6 +145,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { t.Run("should fail if no tss set", func(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) + msgServer := crosschainkeeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) chainID := getValidEthChainID(t) @@ -147,7 +153,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { setAdminPolicies(ctx, zk, admin) erc20Address := sample.EthAddress().Hex() - _, err := k.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ + _, err := msgServer.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ Creator: admin, Erc20Address: erc20Address, ChainId: chainID, @@ -161,6 +167,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { t.Run("should fail if nox valid chain ID", func(t *testing.T) { k, ctx, _, zk := keepertest.CrosschainKeeper(t) + msgServer := crosschainkeeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, fungibletypes.ModuleName) admin := sample.AccAddress() @@ -168,7 +175,7 @@ func TestKeeper_WhitelistERC20(t *testing.T) { k.SetTssAndUpdateNonce(ctx, *sample.Tss()) erc20Address := sample.EthAddress().Hex() - _, err := k.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ + _, err := msgServer.WhitelistERC20(ctx, &types.MsgWhitelistERC20{ Creator: admin, Erc20Address: erc20Address, ChainId: 10000, diff --git a/x/crosschain/keeper/test_privnet.go b/x/crosschain/keeper/test_privnet.go index db2f68b2ad..a9a96a2586 100644 --- a/x/crosschain/keeper/test_privnet.go +++ b/x/crosschain/keeper/test_privnet.go @@ -15,7 +15,8 @@ func (k Keeper) TestWhitelistERC20(ctx sdk.Context) error { creator := k.zetaObserverKeeper.GetParams(ctx).GetAdminPolicyAccount(zetaObserverTypes.Policy_Type_group1) msg := types.NewMsgWhitelistERC20(creator, types.ModuleAddressEVM.Hex(), common.GoerliChain().ChainId, "test", "testerc20", 17, 90_000) - _, err := k.WhitelistERC20(goCtx, msg) + msgServer := NewMsgServerImpl(k) + _, err := msgServer.WhitelistERC20(goCtx, msg) if err != nil { panic(err) } diff --git a/x/crosschain/types/codec.go b/x/crosschain/types/codec.go index 0d9a0cf29d..02c0e849ea 100644 --- a/x/crosschain/types/codec.go +++ b/x/crosschain/types/codec.go @@ -9,24 +9,32 @@ import ( func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgAddToOutTxTracker{}, "crosschain/AddToOutTxTracker", nil) + cdc.RegisterConcrete(&MsgAddToInTxTracker{}, "crosschain/AddToInTxTracker", nil) cdc.RegisterConcrete(&MsgRemoveFromOutTxTracker{}, "crosschain/RemoveFromOutTxTracker", nil) cdc.RegisterConcrete(&MsgCreateTSSVoter{}, "crosschain/CreateTSSVoter", nil) cdc.RegisterConcrete(&MsgGasPriceVoter{}, "crosschain/GasPriceVoter", nil) cdc.RegisterConcrete(&MsgNonceVoter{}, "crosschain/NonceVoter", nil) - cdc.RegisterConcrete(&MsgVoteOnObservedOutboundTxResponse{}, "crosschain/ReceiveConfirmation", nil) - cdc.RegisterConcrete(&MsgVoteOnObservedInboundTx{}, "crosschain/SendVoter", nil) + cdc.RegisterConcrete(&MsgVoteOnObservedOutboundTx{}, "crosschain/VoteOnObservedOutboundTx", nil) + cdc.RegisterConcrete(&MsgVoteOnObservedInboundTx{}, "crosschain/VoteOnObservedInboundTx", nil) + cdc.RegisterConcrete(&MsgWhitelistERC20{}, "crosschain/WhitelistERC20", nil) + cdc.RegisterConcrete(&MsgMigrateTssFunds{}, "crosschain/MigrateTssFunds", nil) + cdc.RegisterConcrete(&MsgUpdateTssAddress{}, "crosschain/UpdateTssAddress", nil) cdc.RegisterConcrete(&MsgSetNodeKeys{}, "crosschain/SetNodeKeys", nil) } func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgAddToOutTxTracker{}, + &MsgAddToInTxTracker{}, &MsgRemoveFromOutTxTracker{}, &MsgCreateTSSVoter{}, &MsgGasPriceVoter{}, &MsgNonceVoter{}, &MsgVoteOnObservedOutboundTx{}, &MsgVoteOnObservedInboundTx{}, + &MsgWhitelistERC20{}, + &MsgMigrateTssFunds{}, + &MsgUpdateTssAddress{}, &MsgSetNodeKeys{}, ) diff --git a/x/fungible/keeper/begin_blocker_deploy_system_contracts_privnet.go b/x/fungible/keeper/begin_blocker_deploy_system_contracts_privnet.go index c806073894..cbcedd747b 100644 --- a/x/fungible/keeper/begin_blocker_deploy_system_contracts_privnet.go +++ b/x/fungible/keeper/begin_blocker_deploy_system_contracts_privnet.go @@ -116,6 +116,7 @@ func (k Keeper) BlockOneDeploySystemContracts(goCtx context.Context) error { func (k Keeper) TestUpdateSystemContractAddress(goCtx context.Context) error { ctx := sdk.UnwrapSDKContext(goCtx) + msgServer := NewMsgServerImpl(k) wzeta, err := k.GetWZetaContractAddress(ctx) if err != nil { @@ -136,13 +137,14 @@ func (k Keeper) TestUpdateSystemContractAddress(goCtx context.Context) error { } creator := k.observerKeeper.GetParams(ctx).GetAdminPolicyAccount(observertypes.Policy_Type_group1) msg := types.NewMsgUpdateSystemContract(creator, SystemContractAddress.Hex()) - _, err = k.UpdateSystemContract(ctx, msg) + _, err = msgServer.UpdateSystemContract(ctx, msg) k.Logger(ctx).Info("System contract updated", "new address", SystemContractAddress.String()) return err } func (k Keeper) TestUpdateZRC20WithdrawFee(goCtx context.Context) error { ctx := sdk.UnwrapSDKContext(goCtx) + msgServer := NewMsgServerImpl(k) foreignCoins := k.GetAllForeignCoins(ctx) creator := k.observerKeeper.GetParams(ctx).GetAdminPolicyAccount(observertypes.Policy_Type_group1) @@ -154,7 +156,7 @@ func (k Keeper) TestUpdateZRC20WithdrawFee(goCtx context.Context) error { sdk.NewUint(uint64(foreignCoin.ForeignChainId)), math.Uint{}, ) - _, err := k.UpdateZRC20WithdrawFee(ctx, msg) + _, err := msgServer.UpdateZRC20WithdrawFee(ctx, msg) if err != nil { return err } diff --git a/x/fungible/keeper/msg_server_update_contract_bytecode.go b/x/fungible/keeper/msg_server_update_contract_bytecode.go index 8664be1121..5d5e7c7950 100644 --- a/x/fungible/keeper/msg_server_update_contract_bytecode.go +++ b/x/fungible/keeper/msg_server_update_contract_bytecode.go @@ -16,7 +16,7 @@ import ( // Only a ZRC20 contract or the WZeta connector contract can be updated // IMPORTANT: the new contract bytecode must have the same storage layout as the old contract bytecode // the new contract can add new variable but cannot remove any existing variable -func (k Keeper) UpdateContractBytecode(goCtx context.Context, msg *types.MsgUpdateContractBytecode) (*types.MsgUpdateContractBytecodeResponse, error) { +func (k msgServer) UpdateContractBytecode(goCtx context.Context, msg *types.MsgUpdateContractBytecode) (*types.MsgUpdateContractBytecodeResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) // check authorization diff --git a/x/fungible/keeper/msg_server_update_contract_bytecode_test.go b/x/fungible/keeper/msg_server_update_contract_bytecode_test.go index fc5900d342..57f1c8b931 100644 --- a/x/fungible/keeper/msg_server_update_contract_bytecode_test.go +++ b/x/fungible/keeper/msg_server_update_contract_bytecode_test.go @@ -13,6 +13,7 @@ import ( zetacommon "github.com/zeta-chain/zetacore/common" keepertest "github.com/zeta-chain/zetacore/testutil/keeper" "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/fungible/keeper" "github.com/zeta-chain/zetacore/x/fungible/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) @@ -33,6 +34,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { k, ctx, sdkk, zk := keepertest.FungibleKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) admin := sample.AccAddress() + msgServer := keeper.NewMsgServerImpl(*k) // set admin policy setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) @@ -92,7 +94,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { require.NoError(t, err) // update the bytecode - res, err := k.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( + res, err := msgServer.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( admin, zrc20, newCodeAddress, @@ -133,7 +135,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { big.NewInt(90_000), ) require.NoError(t, err) - _, err = k.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( + _, err = msgServer.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( admin, zrc20, newCodeAddress, @@ -154,6 +156,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { k, ctx, sdkk, zk := keepertest.FungibleKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) admin := sample.AccAddress() + msgServer := keeper.NewMsgServerImpl(*k) // deploy a connector setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) @@ -166,7 +169,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { assertContractDeployment(t, sdkk.EvmKeeper, ctx, newConnector) // can update the bytecode of the new connector with the old connector contract - _, err = k.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( + _, err = msgServer.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( admin, newConnector, oldConnector, @@ -176,8 +179,9 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { t.Run("should fail if unauthorized", func(t *testing.T) { k, ctx, _, _ := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) - _, err := k.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( + _, err := msgServer.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( sample.AccAddress(), sample.EthAddress(), sample.EthAddress(), @@ -187,10 +191,12 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { t.Run("should fail invalid contract address", func(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) admin := sample.AccAddress() + setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) - _, err := k.UpdateContractBytecode(ctx, &types.MsgUpdateContractBytecode{ + _, err := msgServer.UpdateContractBytecode(ctx, &types.MsgUpdateContractBytecode{ Creator: admin, ContractAddress: "invalid", NewBytecodeAddress: sample.EthAddress().Hex(), @@ -202,6 +208,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ UseEVMMock: true, }) + msgServer := keeper.NewMsgServerImpl(*k) mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) @@ -213,7 +220,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { contractAddr, ).Return(nil) - _, err := k.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( + _, err := msgServer.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( admin, contractAddr, sample.EthAddress(), @@ -225,6 +232,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { t.Run("should fail neither a zrc20 nor wzeta connector", func(t *testing.T) { k, ctx, sdkk, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) admin := sample.AccAddress() @@ -232,7 +240,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { wzeta, _, _, _, _ := deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) // can't update the bytecode of the wzeta contract - _, err := k.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( + _, err := msgServer.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( admin, wzeta, sample.EthAddress(), @@ -242,6 +250,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { t.Run("should fail if system contract not found", func(t *testing.T) { k, ctx, sdkk, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) admin := sample.AccAddress() @@ -252,7 +261,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { k.RemoveSystemContract(ctx) // can't update the bytecode of the wzeta contract - _, err := k.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( + _, err := msgServer.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( admin, connector, sample.EthAddress(), @@ -264,6 +273,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ UseEVMMock: true, }) + msgServer := keeper.NewMsgServerImpl(*k) mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) @@ -280,7 +290,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { mock.Anything, ).Return(&statedb.Account{}) - _, err := k.UpdateContractBytecode(ctx, &types.MsgUpdateContractBytecode{ + _, err := msgServer.UpdateContractBytecode(ctx, &types.MsgUpdateContractBytecode{ Creator: admin, ContractAddress: contract.Hex(), NewBytecodeAddress: "invalid", @@ -295,6 +305,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ UseEVMMock: true, }) + msgServer := keeper.NewMsgServerImpl(*k) mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) @@ -318,7 +329,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { newBytecodeAddr, ).Return(nil) - _, err := k.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( + _, err := msgServer.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( admin, contractAddr, newBytecodeAddr, @@ -332,6 +343,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ UseEVMMock: true, }) + msgServer := keeper.NewMsgServerImpl(*k) mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) @@ -362,7 +374,7 @@ func TestKeeper_UpdateContractBytecode(t *testing.T) { mock.Anything, ).Return(errors.New("can't set account")) - _, err := k.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( + _, err := msgServer.UpdateContractBytecode(ctx, types.NewMsgUpdateContractBytecode( admin, contractAddr, newBytecodeAddr, diff --git a/x/fungible/keeper/msg_server_update_system_contract.go b/x/fungible/keeper/msg_server_update_system_contract.go index f6de594ecf..365e09d4eb 100644 --- a/x/fungible/keeper/msg_server_update_system_contract.go +++ b/x/fungible/keeper/msg_server_update_system_contract.go @@ -14,7 +14,7 @@ import ( zetaObserverTypes "github.com/zeta-chain/zetacore/x/observer/types" ) -func (k Keeper) UpdateSystemContract(goCtx context.Context, msg *types.MsgUpdateSystemContract) (*types.MsgUpdateSystemContractResponse, error) { +func (k msgServer) UpdateSystemContract(goCtx context.Context, msg *types.MsgUpdateSystemContract) (*types.MsgUpdateSystemContractResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) if msg.Creator != k.observerKeeper.GetParams(ctx).GetAdminPolicyAccount(zetaObserverTypes.Policy_Type_group2) { return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Deploy can only be executed by the correct policy account") diff --git a/x/fungible/keeper/msg_server_update_system_contract_test.go b/x/fungible/keeper/msg_server_update_system_contract_test.go index ebd72cd0d5..b464da209c 100644 --- a/x/fungible/keeper/msg_server_update_system_contract_test.go +++ b/x/fungible/keeper/msg_server_update_system_contract_test.go @@ -20,6 +20,7 @@ import ( func TestKeeper_UpdateSystemContract(t *testing.T) { t.Run("can update the system contract", func(t *testing.T) { k, ctx, sdkk, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) @@ -53,7 +54,7 @@ func TestKeeper_UpdateSystemContract(t *testing.T) { require.NotEqual(t, oldSystemContract, newSystemContract) // can update the system contract - _, err = k.UpdateSystemContract(ctx, types.NewMsgUpdateSystemContract(admin, newSystemContract.Hex())) + _, err = msgServer.UpdateSystemContract(ctx, types.NewMsgUpdateSystemContract(admin, newSystemContract.Hex())) require.NoError(t, err) // can retrieve the system contract @@ -75,6 +76,7 @@ func TestKeeper_UpdateSystemContract(t *testing.T) { t.Run("should not update the system contract if not admin", func(t *testing.T) { k, ctx, sdkk, _ := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) // deploy a new system contracts @@ -84,13 +86,14 @@ func TestKeeper_UpdateSystemContract(t *testing.T) { require.NotEqual(t, oldSystemContract, newSystemContract) // should not update the system contract if not admin - _, err = k.UpdateSystemContract(ctx, types.NewMsgUpdateSystemContract(sample.AccAddress(), newSystemContract.Hex())) + _, err = msgServer.UpdateSystemContract(ctx, types.NewMsgUpdateSystemContract(sample.AccAddress(), newSystemContract.Hex())) require.Error(t, err) require.ErrorIs(t, err, sdkerrors.ErrUnauthorized) }) t.Run("should not update the system contract if invalid address", func(t *testing.T) { k, ctx, sdkk, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) @@ -102,7 +105,7 @@ func TestKeeper_UpdateSystemContract(t *testing.T) { require.NotEqual(t, oldSystemContract, newSystemContract) // should not update the system contract if invalid address - _, err = k.UpdateSystemContract(ctx, types.NewMsgUpdateSystemContract(admin, "invalid")) + _, err = msgServer.UpdateSystemContract(ctx, types.NewMsgUpdateSystemContract(admin, "invalid")) require.Error(t, err) require.ErrorIs(t, err, sdkerrors.ErrInvalidAddress) }) diff --git a/x/fungible/keeper/msg_server_update_zrc20_paused_status.go b/x/fungible/keeper/msg_server_update_zrc20_paused_status.go index 2c0b89a4d0..739dbb7a2f 100644 --- a/x/fungible/keeper/msg_server_update_zrc20_paused_status.go +++ b/x/fungible/keeper/msg_server_update_zrc20_paused_status.go @@ -13,7 +13,7 @@ import ( // UpdateZRC20PausedStatus updates the paused status of a ZRC20 // The list of ZRC20s are either paused or unpaused -func (k Keeper) UpdateZRC20PausedStatus( +func (k msgServer) UpdateZRC20PausedStatus( goCtx context.Context, msg *types.MsgUpdateZRC20PausedStatus, ) (*types.MsgUpdateZRC20PausedStatusResponse, error) { diff --git a/x/fungible/keeper/msg_server_update_zrc20_paused_status_test.go b/x/fungible/keeper/msg_server_update_zrc20_paused_status_test.go index 33f02d8745..2183cccf9c 100644 --- a/x/fungible/keeper/msg_server_update_zrc20_paused_status_test.go +++ b/x/fungible/keeper/msg_server_update_zrc20_paused_status_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" keepertest "github.com/zeta-chain/zetacore/testutil/keeper" "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/fungible/keeper" "github.com/zeta-chain/zetacore/x/fungible/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) @@ -14,6 +15,7 @@ import ( func TestKeeper_UpdateZRC20PausedStatus(t *testing.T) { t.Run("can update the paused status of zrc20", func(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) admin := sample.AccAddress() requireUnpaused := func(zrc20 string) { @@ -39,7 +41,7 @@ func TestKeeper_UpdateZRC20PausedStatus(t *testing.T) { setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group1) // can pause zrc20 - _, err := k.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( + _, err := msgServer.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( admin, []string{ zrc20A, @@ -55,7 +57,7 @@ func TestKeeper_UpdateZRC20PausedStatus(t *testing.T) { setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) // can unpause zrc20 - _, err = k.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( + _, err = msgServer.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( admin, []string{ zrc20A, @@ -70,7 +72,7 @@ func TestKeeper_UpdateZRC20PausedStatus(t *testing.T) { setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group1) // can pause already paused zrc20 - _, err = k.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( + _, err = msgServer.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( admin, []string{ zrc20B, @@ -85,7 +87,7 @@ func TestKeeper_UpdateZRC20PausedStatus(t *testing.T) { setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) // can unpause already unpaused zrc20 - _, err = k.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( + _, err = msgServer.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( admin, []string{ zrc20C, @@ -100,7 +102,7 @@ func TestKeeper_UpdateZRC20PausedStatus(t *testing.T) { setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group1) // can pause all zrc20 - _, err = k.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( + _, err = msgServer.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( admin, []string{ zrc20A, @@ -117,7 +119,7 @@ func TestKeeper_UpdateZRC20PausedStatus(t *testing.T) { setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) // can unpause all zrc20 - _, err = k.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( + _, err = msgServer.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( admin, []string{ zrc20A, @@ -134,20 +136,22 @@ func TestKeeper_UpdateZRC20PausedStatus(t *testing.T) { t.Run("should fail if invalid message", func(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group1) invalidMsg := types.NewMsgUpdateZRC20PausedStatus(admin, []string{}, types.UpdatePausedStatusAction_PAUSE) require.ErrorIs(t, invalidMsg.ValidateBasic(), sdkerrors.ErrInvalidRequest) - _, err := k.UpdateZRC20PausedStatus(ctx, invalidMsg) + _, err := msgServer.UpdateZRC20PausedStatus(ctx, invalidMsg) require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) }) t.Run("should fail if not authorized", func(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) - _, err := k.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( + _, err := msgServer.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( sample.AccAddress(), []string{sample.EthAddress().String()}, types.UpdatePausedStatusAction_PAUSE, @@ -156,7 +160,7 @@ func TestKeeper_UpdateZRC20PausedStatus(t *testing.T) { admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group1) - _, err = k.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( + _, err = msgServer.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( sample.AccAddress(), []string{sample.EthAddress().String()}, types.UpdatePausedStatusAction_UNPAUSE, @@ -167,6 +171,7 @@ func TestKeeper_UpdateZRC20PausedStatus(t *testing.T) { t.Run("should fail if zrc20 does not exist", func(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group1) @@ -174,7 +179,7 @@ func TestKeeper_UpdateZRC20PausedStatus(t *testing.T) { k.SetForeignCoins(ctx, sample.ForeignCoins(t, zrc20A)) k.SetForeignCoins(ctx, sample.ForeignCoins(t, zrc20B)) - _, err := k.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( + _, err := msgServer.UpdateZRC20PausedStatus(ctx, types.NewMsgUpdateZRC20PausedStatus( admin, []string{ zrc20A, diff --git a/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee.go b/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee.go index 2cdb6f30b0..3abb312276 100644 --- a/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee.go +++ b/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee.go @@ -12,7 +12,7 @@ import ( zetaObserverTypes "github.com/zeta-chain/zetacore/x/observer/types" ) -func (k Keeper) UpdateZRC20WithdrawFee(goCtx context.Context, msg *types.MsgUpdateZRC20WithdrawFee) (*types.MsgUpdateZRC20WithdrawFeeResponse, error) { +func (k msgServer) UpdateZRC20WithdrawFee(goCtx context.Context, msg *types.MsgUpdateZRC20WithdrawFee) (*types.MsgUpdateZRC20WithdrawFeeResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) // check signer permission diff --git a/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go b/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go index 9de490dc8b..108c70c664 100644 --- a/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go +++ b/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go @@ -14,6 +14,7 @@ import ( "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" keepertest "github.com/zeta-chain/zetacore/testutil/keeper" "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/fungible/keeper" "github.com/zeta-chain/zetacore/x/fungible/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) @@ -21,6 +22,7 @@ import ( func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { t.Run("can update the withdraw fee", func(t *testing.T) { k, ctx, sdkk, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) chainID := getValidChainID(t) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) @@ -38,7 +40,7 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { require.Zero(t, protocolFee.Uint64()) // can update the protocol fee and gas limit - _, err = k.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( + _, err = msgServer.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( admin, zrc20Addr.String(), math.NewUint(42), @@ -55,7 +57,7 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { require.Equal(t, uint64(42), gasLimit.Uint64()) // can update protocol fee only - _, err = k.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( + _, err = msgServer.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( admin, zrc20Addr.String(), math.NewUint(43), @@ -70,7 +72,7 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { require.Equal(t, uint64(42), gasLimit.Uint64()) // can update gas limit only - _, err = k.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( + _, err = msgServer.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( admin, zrc20Addr.String(), math.Uint{}, @@ -87,8 +89,9 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { t.Run("should fail if not authorized", func(t *testing.T) { k, ctx, _, _ := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) - _, err := k.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( + _, err := msgServer.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( sample.AccAddress(), sample.EthAddress().String(), math.NewUint(42), @@ -99,10 +102,11 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { t.Run("should fail if invalid zrc20 address", func(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) - _, err := k.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( + _, err := msgServer.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( admin, "invalid_address", math.NewUint(42), @@ -113,10 +117,11 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { t.Run("should fail if can't retrieve the foreign coin", func(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) admin := sample.AccAddress() setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) - _, err := k.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( + _, err := msgServer.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( admin, sample.EthAddress().String(), math.NewUint(42), @@ -127,6 +132,7 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { t.Run("should fail if can't query old fee", func(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) // setup @@ -136,7 +142,7 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { k.SetForeignCoins(ctx, sample.ForeignCoins(t, zrc20.String())) // the method shall fail since we only set the foreign coin manually in the store but didn't deploy the contract - _, err := k.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( + _, err := msgServer.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( admin, zrc20.String(), math.NewUint(42), @@ -147,6 +153,7 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { t.Run("should fail if contract call for setting new protocol fee fails", func(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{UseEVMMock: true}) + msgServer := keeper.NewMsgServerImpl(*k) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) @@ -196,7 +203,7 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { true, ).Return(&evmtypes.MsgEthereumTxResponse{}, errors.New("transaction failed")) - _, err = k.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( + _, err = msgServer.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( admin, zrc20Addr.String(), math.NewUint(42), @@ -210,6 +217,7 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { t.Run("should fail if contract call for setting new protocol fee fails", func(t *testing.T) { k, ctx, _, zk := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{UseEVMMock: true}) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + msgServer := keeper.NewMsgServerImpl(*k) mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) // setup @@ -258,7 +266,7 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { true, ).Return(&evmtypes.MsgEthereumTxResponse{}, errors.New("transaction failed")) - _, err = k.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( + _, err = msgServer.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( admin, zrc20Addr.String(), math.Uint{}, diff --git a/x/fungible/types/codec.go b/x/fungible/types/codec.go index 3c06f02110..47bbfee990 100644 --- a/x/fungible/types/codec.go +++ b/x/fungible/types/codec.go @@ -10,6 +10,10 @@ import ( func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgDeployFungibleCoinZRC20{}, "fungible/DeployFungibleCoinZRC20", nil) cdc.RegisterConcrete(&MsgRemoveForeignCoin{}, "fungible/RemoveForeignCoin", nil) + cdc.RegisterConcrete(&MsgUpdateSystemContract{}, "fungible/UpdateSystemContract", nil) + cdc.RegisterConcrete(&MsgUpdateZRC20WithdrawFee{}, "fungible/UpdateZRC20WithdrawFee", nil) + cdc.RegisterConcrete(&MsgUpdateContractBytecode{}, "fungible/UpdateContractBytecode", nil) + cdc.RegisterConcrete(&MsgUpdateZRC20PausedStatus{}, "fungible/UpdateZRC20PausedStatus", nil) cdc.RegisterConcrete(&MsgUpdateZRC20LiquidityCap{}, "fungible/UpdateZRC20LiquidityCap", nil) } @@ -17,6 +21,10 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgDeployFungibleCoinZRC20{}, &MsgRemoveForeignCoin{}, + &MsgUpdateSystemContract{}, + &MsgUpdateZRC20WithdrawFee{}, + &MsgUpdateContractBytecode{}, + &MsgUpdateZRC20PausedStatus{}, &MsgUpdateZRC20LiquidityCap{}, ) diff --git a/x/observer/types/codec.go b/x/observer/types/codec.go index 76e51df8af..3d30bbc3a7 100644 --- a/x/observer/types/codec.go +++ b/x/observer/types/codec.go @@ -8,16 +8,22 @@ import ( ) func RegisterCodec(cdc *codec.LegacyAmino) { - cdc.RegisterConcrete(&MsgUpdateCoreParams{}, "observer/UpdateClientParams", nil) + cdc.RegisterConcrete(&MsgAddObserver{}, "observer/AddObserver", nil) + cdc.RegisterConcrete(&MsgUpdateCoreParams{}, "observer/UpdateCoreParam", nil) + cdc.RegisterConcrete(&MsgAddBlameVote{}, "crosschain/AddBlameVote", nil) cdc.RegisterConcrete(&MsgUpdateCrosschainFlags{}, "crosschain/UpdateCrosschainFlags", nil) cdc.RegisterConcrete(&MsgUpdateKeygen{}, "crosschain/UpdateKeygen", nil) + cdc.RegisterConcrete(&MsgAddBlockHeader{}, "crosschain/AddBlockHeader", nil) } func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgAddObserver{}, &MsgUpdateCoreParams{}, + &MsgAddBlameVote{}, &MsgUpdateCrosschainFlags{}, &MsgUpdateKeygen{}, + &MsgAddBlockHeader{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)