diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd459bafef..6872086e09 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,7 +78,7 @@ jobs: run: rm -rf * smoke-test: - runs-on: ["zeta-runners"] # 20 minutes + runs-on: ["zeta-runners"] # 25 minutes timeout-minutes: 25 steps: - uses: actions/checkout@v3 diff --git a/contrib/localnet/orchestrator/smoketest/main.go b/contrib/localnet/orchestrator/smoketest/main.go index 95ee48389e..9dd12669e0 100644 --- a/contrib/localnet/orchestrator/smoketest/main.go +++ b/contrib/localnet/orchestrator/smoketest/main.go @@ -312,6 +312,9 @@ func LocalSmokeTest(_ *cobra.Command, _ []string) { smokeTest.TestUpdateBytecode() smokeTest.CheckZRC20ReserveAndSupply() + smokeTest.TestDepositEtherLiquidityCap() + smokeTest.CheckZRC20ReserveAndSupply() + // add your dev test here smokeTest.TestMyTest() diff --git a/contrib/localnet/orchestrator/smoketest/test_deposit_eth.go b/contrib/localnet/orchestrator/smoketest/test_deposit_eth.go index cf3e03b4c1..904d1858e4 100644 --- a/contrib/localnet/orchestrator/smoketest/test_deposit_eth.go +++ b/contrib/localnet/orchestrator/smoketest/test_deposit_eth.go @@ -9,16 +9,17 @@ import ( "math/big" "time" - "github.com/zeta-chain/zetacore/common/ethereum" - observertypes "github.com/zeta-chain/zetacore/x/observer/types" - + "cosmossdk.io/math" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcommon "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" zrc20 "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" "github.com/zeta-chain/zetacore/common" + "github.com/zeta-chain/zetacore/common/ethereum" "github.com/zeta-chain/zetacore/x/crosschain/types" + fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" "github.com/zeta-chain/zetacore/zetaclient" ) @@ -285,6 +286,109 @@ func (sm *SmokeTest) TestDepositAndCallRefund() { }() } +// TestDepositEtherLiquidityCap tests depositing Ethers in a context where a liquidity cap is set +func (sm *SmokeTest) TestDepositEtherLiquidityCap() { + startTime := time.Now() + defer func() { + fmt.Printf("test finishes in %s\n", time.Since(startTime)) + }() + LoudPrintf("Deposit Ethers into ZEVM with a liquidity cap\n") + + supply, err := sm.ETHZRC20.TotalSupply(&bind.CallOpts{}) + if err != nil { + panic(err) + } + + // Set a liquidity cap slightly above the current supply + fmt.Println("Setting a liquidity cap") + liquidityCap := math.NewUintFromBigInt(supply).Add(math.NewUint(1e16)) + msg := fungibletypes.NewMsgUpdateZRC20LiquidityCap( + FungibleAdminAddress, + sm.ETHZRC20Addr.Hex(), + liquidityCap, + ) + res, err := sm.zetaTxServer.BroadcastTx(FungibleAdminName, msg) + if err != nil { + panic(err) + } + fmt.Printf("set liquidity cap tx hash: %s\n", res.TxHash) + + fmt.Println("Depositing more than liquidity cap should make cctx reverted") + signedTx, err := sm.SendEther(TSSAddress, big.NewInt(1e17), nil) + if err != nil { + panic(err) + } + receipt := MustWaitForTxReceipt(sm.goerliClient, signedTx) + if receipt.Status == 0 { + panic("deposit eth tx failed") + } + cctx := WaitCctxMinedByInTxHash(signedTx.Hash().Hex(), sm.cctxClient) + if cctx.CctxStatus.Status != types.CctxStatus_Reverted { + panic(fmt.Sprintf("expected cctx status to be Reverted; got %s", cctx.CctxStatus.Status)) + } + fmt.Println("CCTX has been reverted") + + fmt.Println("Depositing less than liquidity cap should still succeed") + initialBal, err := sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, DeployerAddress) + if err != nil { + panic(err) + } + signedTx, err = sm.SendEther(TSSAddress, big.NewInt(1e15), nil) + if err != nil { + panic(err) + } + receipt = MustWaitForTxReceipt(sm.goerliClient, signedTx) + if receipt.Status == 0 { + panic("deposit eth tx failed") + } + WaitCctxMinedByInTxHash(signedTx.Hash().Hex(), sm.cctxClient) + expectedBalance := big.NewInt(0).Add(initialBal, big.NewInt(1e15)) + + bal, err := sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, DeployerAddress) + if err != nil { + panic(err) + } + if bal.Cmp(expectedBalance) != 0 { + panic(fmt.Sprintf("expected balance to be %s; got %s", expectedBalance.String(), bal.String())) + } + fmt.Println("Deposit succeeded") + + fmt.Println("Removing the liquidity cap") + msg = fungibletypes.NewMsgUpdateZRC20LiquidityCap( + FungibleAdminAddress, + sm.ETHZRC20Addr.Hex(), + math.ZeroUint(), + ) + res, err = sm.zetaTxServer.BroadcastTx(FungibleAdminName, msg) + if err != nil { + panic(err) + } + fmt.Printf("remove liquidity cap tx hash: %s\n", res.TxHash) + initialBal, err = sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, DeployerAddress) + if err != nil { + panic(err) + } + signedTx, err = sm.SendEther(TSSAddress, big.NewInt(1e17), nil) + if err != nil { + panic(err) + } + receipt = MustWaitForTxReceipt(sm.goerliClient, signedTx) + if receipt.Status == 0 { + panic("deposit eth tx failed") + } + WaitCctxMinedByInTxHash(signedTx.Hash().Hex(), sm.cctxClient) + expectedBalance = big.NewInt(0).Add(initialBal, big.NewInt(1e17)) + + bal, err = sm.ETHZRC20.BalanceOf(&bind.CallOpts{}, DeployerAddress) + if err != nil { + panic(err) + } + if bal.Cmp(expectedBalance) != 0 { + panic(fmt.Sprintf("expected balance to be %s; got %s", expectedBalance.String(), bal.String())) + } + fmt.Println("New deposit succeeded") +} + func (sm *SmokeTest) SendEther(to ethcommon.Address, value *big.Int, data []byte) (*ethtypes.Transaction, error) { goerliClient := sm.goerliClient diff --git a/contrib/localnet/orchestrator/smoketest/test_erc20.go b/contrib/localnet/orchestrator/smoketest/test_erc20.go index d70b73cbf5..309916c3de 100644 --- a/contrib/localnet/orchestrator/smoketest/test_erc20.go +++ b/contrib/localnet/orchestrator/smoketest/test_erc20.go @@ -69,6 +69,9 @@ func (sm *SmokeTest) DepositERC20(amount *big.Int, msg []byte) ethcommon.Hash { panic(err) } receipt = MustWaitForTxReceipt(sm.goerliClient, tx) + if receipt.Status == 0 { + panic("deposit failed") + } fmt.Printf("Deposit receipt tx hash: %s, status %d\n", receipt.TxHash.Hex(), receipt.Status) for _, log := range receipt.Logs { event, err := sm.ERC20Custody.ParseDeposited(*log) @@ -83,7 +86,6 @@ func (sm *SmokeTest) DepositERC20(amount *big.Int, msg []byte) ethcommon.Hash { } fmt.Printf("gas limit %d\n", sm.zevmAuth.GasLimit) return tx.Hash() - //WaitCctxMinedByInTxHash(tx.Hash().Hex(), sm.cctxClient) } func (sm *SmokeTest) TestERC20Withdraw() { diff --git a/contrib/localnet/orchestrator/smoketest/test_stress.go b/contrib/localnet/orchestrator/smoketest/test_stress.go index bd03f5b1c7..02a424450d 100644 --- a/contrib/localnet/orchestrator/smoketest/test_stress.go +++ b/contrib/localnet/orchestrator/smoketest/test_stress.go @@ -5,6 +5,7 @@ package main import ( "context" + "errors" "fmt" "math/big" "os" @@ -18,7 +19,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/cobra" - "github.com/zeta-chain/zetacore/common" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" "github.com/zeta-chain/zetacore/x/crosschain/types" types2 "github.com/zeta-chain/zetacore/x/crosschain/types" fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" @@ -28,7 +29,6 @@ import ( const ( StatInterval = 5 - WithdrawInterval = 500 StressTestTimeout = 100 * time.Minute ) @@ -48,7 +48,8 @@ type stressArguments struct { zevmURL string deployerAddress string deployerPrivateKey string - local bool + network string + txnInterval int64 } var stressTestArgs = stressArguments{} @@ -60,7 +61,8 @@ func init() { StressCmd.Flags().StringVar(&stressTestArgs.zevmURL, "zevmURL", "http://zetacore0:8545", "--zevmURL http://zetacore0:8545") StressCmd.Flags().StringVar(&stressTestArgs.deployerAddress, "addr", "0xE5C5367B8224807Ac2207d350E60e1b6F27a7ecC", "--addr ") StressCmd.Flags().StringVar(&stressTestArgs.deployerPrivateKey, "privKey", "d87baf7bf6dc560a252596678c12e41f7d1682837f05b29d411bc3f78ae2c263", "--privKey ") - StressCmd.Flags().BoolVar(&stressTestArgs.local, "local", true, "--local") + StressCmd.Flags().StringVar(&stressTestArgs.network, "network", "PRIVNET", "--network PRIVNET") + StressCmd.Flags().Int64Var(&stressTestArgs.txnInterval, "tx-interval", 500, "--tx-interval [TIME_INTERVAL_MILLISECONDS]") DeployerAddress = ethcommon.HexToAddress(stressTestArgs.deployerAddress) } @@ -85,7 +87,7 @@ func StressTest(_ *cobra.Command, _ []string) { if err != nil { panic(err) } - fmt.Printf("Deployer address: %s, balance: %d Ether\n", DeployerAddress.Hex(), bal.Div(bal, big.NewInt(1e18))) + fmt.Printf("Deployer address: %s, balance: %d Wei\n", DeployerAddress.Hex(), bal) chainid, err := goerliClient.ChainID(context.Background()) deployerPrivkey, err := crypto.HexToECDSA(stressTestArgs.deployerPrivateKey) @@ -158,13 +160,27 @@ func StressTest(_ *cobra.Command, _ []string) { ) // If stress test is running on local docker environment - if stressTestArgs.local { + if stressTestArgs.network == "PRIVNET" { smokeTest.TestSetupZetaTokenAndConnectorAndZEVMContracts() smokeTest.TestDepositEtherIntoZRC20() smokeTest.TestSendZetaIn() + } else if stressTestArgs.network == "TESTNET" { + ethZRC20Addr, _ := smokeTest.SystemContract.GasCoinZRC20ByChainId(&bind.CallOpts{}, big.NewInt(5)) + smokeTest.ETHZRC20Addr = ethZRC20Addr + smokeTest.ETHZRC20, _ = zrc20.NewZRC20(smokeTest.ETHZRC20Addr, smokeTest.zevmClient) + } else { + err := errors.New("invalid network argument: " + stressTestArgs.network) + panic(err) + } + + // Check zrc20 balance of Deployer address + ethZRC20Balance, err := smokeTest.ETHZRC20.BalanceOf(nil, DeployerAddress) + if err != nil { + panic(err) } + fmt.Printf("eth zrc20 balance: %s Wei \n", ethZRC20Balance.String()) - //Pre-approve USDT withdraw on ZEVM + //Pre-approve ETH withdraw on ZEVM fmt.Printf("approving ETH ZRC20...\n") ethZRC20 := smokeTest.ETHZRC20 tx, err := ethZRC20.Approve(smokeTest.zevmAuth, smokeTest.ETHZRC20Addr, big.NewInt(1e18)) @@ -197,7 +213,7 @@ func StressTest(_ *cobra.Command, _ []string) { // WithdrawCCtx withdraw USDT from ZEVM to EVM func (sm *SmokeTest) WithdrawCCtx() { - ticker := time.NewTicker(time.Millisecond * WithdrawInterval) + ticker := time.NewTicker(time.Millisecond * time.Duration(stressTestArgs.txnInterval)) for { select { case <-ticker.C: @@ -212,13 +228,14 @@ func (sm *SmokeTest) EchoNetworkMetrics() { var numTicks = 0 var totalMinedTxns = uint64(0) var previousMinedTxns = uint64(0) + for { select { case <-ticker.C: numTicks++ // Get all pending outbound transactions cctxResp, err := sm.cctxClient.CctxAllPending(context.Background(), &types2.QueryAllCctxPendingRequest{ - ChainId: common.GoerliChain().ChainId, + ChainId: getChainID(), }) if err != nil { continue @@ -229,6 +246,8 @@ func (sm *SmokeTest) EchoNetworkMetrics() { }) if len(sends) > 0 { fmt.Printf("pending nonces %d to %d\n", sends[0].GetCurrentOutTxParam().OutboundTxTssNonce, sends[len(sends)-1].GetCurrentOutTxParam().OutboundTxTssNonce) + } else { + continue } // // Get all trackers @@ -274,3 +293,17 @@ func (sm *SmokeTest) WithdrawETHZRC20() { panic(err) } } + +// Get ETH based chain ID - Build flags are conflicting with current lib, need to do this manually +func getChainID() int64 { + switch stressTestArgs.network { + case "PRIVNET": + return 1337 + case "TESTNET": + return 5 + case "MAINNET": + return 1 + default: + return 1337 + } +} diff --git a/docs/openapi/openapi.swagger.yaml b/docs/openapi/openapi.swagger.yaml index cd342dc1f2..3c4345f108 100644 --- a/docs/openapi/openapi.swagger.yaml +++ b/docs/openapi/openapi.swagger.yaml @@ -50783,6 +50783,8 @@ definitions: format: uint64 paused: type: boolean + liquidity_cap: + type: string fungibleMsgDeployFungibleCoinZRC20Response: type: object properties: @@ -50798,6 +50800,8 @@ definitions: format: byte fungibleMsgUpdateSystemContractResponse: type: object + fungibleMsgUpdateZRC20LiquidityCapResponse: + type: object fungibleMsgUpdateZRC20PausedStatusResponse: type: object fungibleMsgUpdateZRC20WithdrawFeeResponse: diff --git a/docs/spec/fungible/messages.md b/docs/spec/fungible/messages.md index 9f86674b5b..3977d2212c 100644 --- a/docs/spec/fungible/messages.md +++ b/docs/spec/fungible/messages.md @@ -56,16 +56,6 @@ message MsgUpdateSystemContract { } ``` -## MsgUpdateZRC20WithdrawFee - -```proto -message MsgUpdateZRC20WithdrawFee { - string creator = 1; - string zrc20_address = 2; - string new_withdraw_fee = 6; -} -``` - ## MsgUpdateContractBytecode UpdateContractBytecode updates the bytecode of a contract from the bytecode of an existing contract @@ -81,6 +71,16 @@ message MsgUpdateContractBytecode { } ``` +## MsgUpdateZRC20WithdrawFee + +```proto +message MsgUpdateZRC20WithdrawFee { + string creator = 1; + string zrc20_address = 2; + string new_withdraw_fee = 6; +} +``` + ## MsgUpdateZRC20PausedStatus UpdateZRC20PausedStatus updates the paused status of a ZRC20 @@ -94,3 +94,15 @@ message MsgUpdateZRC20PausedStatus { } ``` +## MsgUpdateZRC20LiquidityCap + +UpdateZRC20LiquidityCap updates the liquidity cap for a ZRC20 token. + +```proto +message MsgUpdateZRC20LiquidityCap { + string creator = 1; + string zrc20_address = 2; + string liquidity_cap = 3; +} +``` + diff --git a/proto/fungible/foreign_coins.proto b/proto/fungible/foreign_coins.proto index 73447d6c92..81d52f0220 100644 --- a/proto/fungible/foreign_coins.proto +++ b/proto/fungible/foreign_coins.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package zetachain.zetacore.fungible; import "common/common.proto"; +import "gogoproto/gogo.proto"; option go_package = "github.com/zeta-chain/zetacore/x/fungible/types"; @@ -16,4 +17,8 @@ message ForeignCoins { common.CoinType coin_type = 8; uint64 gas_limit = 9; bool paused = 10; + string liquidity_cap = 11 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Uint", + (gogoproto.nullable) = false + ]; } diff --git a/proto/fungible/tx.proto b/proto/fungible/tx.proto index bd7a67794a..aa5161a592 100644 --- a/proto/fungible/tx.proto +++ b/proto/fungible/tx.proto @@ -11,9 +11,10 @@ service Msg { rpc DeployFungibleCoinZRC20(MsgDeployFungibleCoinZRC20) returns (MsgDeployFungibleCoinZRC20Response); rpc RemoveForeignCoin(MsgRemoveForeignCoin) returns (MsgRemoveForeignCoinResponse); rpc UpdateSystemContract(MsgUpdateSystemContract) returns (MsgUpdateSystemContractResponse); - rpc UpdateZRC20WithdrawFee(MsgUpdateZRC20WithdrawFee) returns (MsgUpdateZRC20WithdrawFeeResponse); rpc UpdateContractBytecode(MsgUpdateContractBytecode) returns (MsgUpdateContractBytecodeResponse); + rpc UpdateZRC20WithdrawFee(MsgUpdateZRC20WithdrawFee) returns (MsgUpdateZRC20WithdrawFeeResponse); rpc UpdateZRC20PausedStatus(MsgUpdateZRC20PausedStatus) returns (MsgUpdateZRC20PausedStatusResponse); + rpc UpdateZRC20LiquidityCap(MsgUpdateZRC20LiquidityCap) returns (MsgUpdateZRC20LiquidityCapResponse); } message MsgUpdateZRC20WithdrawFee { @@ -78,3 +79,14 @@ message MsgUpdateZRC20PausedStatus { } message MsgUpdateZRC20PausedStatusResponse {} + +message MsgUpdateZRC20LiquidityCap { + string creator = 1; + string zrc20_address = 2; + string liquidity_cap = 3 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Uint", + (gogoproto.nullable) = false + ]; +} + +message MsgUpdateZRC20LiquidityCapResponse {} diff --git a/testutil/nullify/nullify.go b/testutil/nullify/nullify.go index b073edc1b6..5812c1b3c5 100644 --- a/testutil/nullify/nullify.go +++ b/testutil/nullify/nullify.go @@ -5,12 +5,14 @@ import ( "reflect" "unsafe" + "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" ) var ( coinType = reflect.TypeOf(sdk.Coin{}) coinsType = reflect.TypeOf(sdk.Coins{}) + uintType = reflect.TypeOf(math.Uint{}) ) // Fill analyze all struct fields and slices with @@ -46,6 +48,10 @@ func Fill(x interface{}) interface{} { coins := reflect.New(coinsType).Interface() s := reflect.ValueOf(coins).Elem() f.Set(s) + case uintType: + mathUint := reflect.New(uintType).Interface() + s := reflect.ValueOf(mathUint).Elem() + f.Set(s) default: //#nosec G103 objPt := reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())).Interface() diff --git a/x/crosschain/keeper/evm_deposit.go b/x/crosschain/keeper/evm_deposit.go index 09fcd1efc0..14ab9e676e 100644 --- a/x/crosschain/keeper/evm_deposit.go +++ b/x/crosschain/keeper/evm_deposit.go @@ -4,6 +4,8 @@ import ( "encoding/hex" "fmt" + fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" + sdk "github.com/cosmos/cosmos-sdk/types" ethcommon "github.com/ethereum/go-ethereum/common" evmtypes "github.com/evmos/ethermint/x/evm/types" @@ -14,9 +16,10 @@ import ( "github.com/zeta-chain/zetacore/x/crosschain/types" ) +// HandleEVMDeposit handles a deposit from an inbound tx // returns (isContractReverted, err) // (true, non-nil) means CallEVM() reverted -func (k msgServer) HandleEVMDeposit(ctx sdk.Context, cctx *types.CrossChainTx, msg types.MsgVoteOnObservedInboundTx, senderChain *common.Chain) (bool, error) { +func (k Keeper) HandleEVMDeposit(ctx sdk.Context, cctx *types.CrossChainTx, msg types.MsgVoteOnObservedInboundTx, senderChain *common.Chain) (bool, error) { to := ethcommon.HexToAddress(msg.Receiver) var ethTxHash ethcommon.Hash if len(ctx.TxBytes()) > 0 { @@ -61,9 +64,12 @@ func (k msgServer) HandleEVMDeposit(ctx sdk.Context, cctx *types.CrossChainTx, m ) if err != nil { isContractReverted := false - if evmTxResponse != nil && evmTxResponse.Failed() { + + // consider the contract as reverted if foreign coin liquidity cap is reached + if (evmTxResponse != nil && evmTxResponse.Failed()) || errors.Is(err, fungibletypes.ErrForeignCoinCapReached) { isContractReverted = true } + return isContractReverted, err } @@ -71,26 +77,28 @@ func (k msgServer) HandleEVMDeposit(ctx sdk.Context, cctx *types.CrossChainTx, m // a withdrawal event in the logs could generate cctxs for outbound transactions. if !evmTxResponse.Failed() && contractCall { logs := evmtypes.LogsToEthereum(evmTxResponse.Logs) - ctx = ctx.WithValue("inCctxIndex", cctx.Index) - txOrigin := msg.TxOrigin - if txOrigin == "" { - txOrigin = msg.Sender - } + if len(logs) > 0 { + ctx = ctx.WithValue("inCctxIndex", cctx.Index) + txOrigin := msg.TxOrigin + if txOrigin == "" { + txOrigin = msg.Sender + } - err = k.ProcessLogs(ctx, logs, to, txOrigin) - if err != nil { - // ProcessLogs should not error; error indicates exception, should abort - return false, errors.Wrap(types.ErrCannotProcessWithdrawal, err.Error()) + err = k.ProcessLogs(ctx, logs, to, txOrigin) + if err != nil { + // ProcessLogs should not error; error indicates exception, should abort + return false, errors.Wrap(types.ErrCannotProcessWithdrawal, err.Error()) + } + ctx.EventManager().EmitEvent( + sdk.NewEvent(sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + sdk.NewAttribute("action", "DepositZRC20AndCallContract"), + sdk.NewAttribute("contract", to.String()), + sdk.NewAttribute("data", hex.EncodeToString(data)), + sdk.NewAttribute("cctxIndex", cctx.Index), + ), + ) } - ctx.EventManager().EmitEvent( - sdk.NewEvent(sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - sdk.NewAttribute("action", "DepositZRC20AndCallContract"), - sdk.NewAttribute("contract", to.String()), - sdk.NewAttribute("data", hex.EncodeToString(data)), - sdk.NewAttribute("cctxIndex", cctx.Index), - ), - ) } } return false, nil diff --git a/x/crosschain/keeper/evm_deposit_test.go b/x/crosschain/keeper/evm_deposit_test.go new file mode 100644 index 0000000000..f5ada00f5b --- /dev/null +++ b/x/crosschain/keeper/evm_deposit_test.go @@ -0,0 +1,265 @@ +package keeper_test + +import ( + "errors" + "math/big" + "testing" + + "cosmossdk.io/math" + evmtypes "github.com/evmos/ethermint/x/evm/types" + "github.com/stretchr/testify/mock" + "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/types" + fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" +) + +func TestMsgServer_HandleEVMDeposit(t *testing.T) { + t.Run("can process Zeta deposit calling fungible method", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + }) + + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + + // expect DepositCoinZeta to be called + fungibleMock.On("DepositCoinZeta", ctx, receiver, amount).Return(nil) + + // call HandleEVMDeposit + reverted, err := k.HandleEVMDeposit( + ctx, + sample.CrossChainTx(t, "foo"), + types.MsgVoteOnObservedInboundTx{ + Receiver: receiver.String(), + Amount: math.NewUintFromBigInt(amount), + CoinType: common.CoinType_Zeta, + }, + nil, + ) + require.NoError(t, err) + require.False(t, reverted) + fungibleMock.AssertExpectations(t) + }) + + t.Run("should return error with non-reverted if deposit Zeta fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + }) + + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + + // expect DepositCoinZeta to be called + errDeposit := errors.New("deposit failed") + fungibleMock.On("DepositCoinZeta", ctx, receiver, amount).Return(errDeposit) + + // call HandleEVMDeposit + reverted, err := k.HandleEVMDeposit( + ctx, + sample.CrossChainTx(t, "foo"), + types.MsgVoteOnObservedInboundTx{ + Receiver: receiver.String(), + Amount: math.NewUintFromBigInt(amount), + CoinType: common.CoinType_Zeta, + }, + nil, + ) + require.ErrorIs(t, err, errDeposit) + require.False(t, reverted) + fungibleMock.AssertExpectations(t) + }) + + t.Run("can process ERC20 deposit calling fungible method", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + }) + + senderChain := getValidEthChain(t) + + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + + // expect DepositCoinZeta to be called + // ZRC20DepositAndCallContract(ctx, from, to, msg.Amount.BigInt(), senderChain, msg.Message, contract, data, msg.CoinType, msg.Asset) + fungibleMock.On( + "ZRC20DepositAndCallContract", + ctx, + mock.Anything, + receiver, + amount, + senderChain, + mock.Anything, + mock.Anything, + mock.Anything, + common.CoinType_ERC20, + mock.Anything, + ).Return(&evmtypes.MsgEthereumTxResponse{}, nil) + + // call HandleEVMDeposit + reverted, err := k.HandleEVMDeposit( + ctx, + sample.CrossChainTx(t, "foo"), + types.MsgVoteOnObservedInboundTx{ + Sender: sample.EthAddress().String(), + Receiver: receiver.String(), + Amount: math.NewUintFromBigInt(amount), + CoinType: common.CoinType_ERC20, + Message: "", + Asset: "", + }, + senderChain, + ) + require.NoError(t, err) + require.False(t, reverted) + fungibleMock.AssertExpectations(t) + }) + + t.Run("should return error with non-reverted if deposit ERC20 fails with tx non-failed", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + }) + + senderChain := getValidEthChain(t) + + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + + // expect DepositCoinZeta to be called + // ZRC20DepositAndCallContract(ctx, from, to, msg.Amount.BigInt(), senderChain, msg.Message, contract, data, msg.CoinType, msg.Asset) + errDeposit := errors.New("deposit failed") + fungibleMock.On( + "ZRC20DepositAndCallContract", + ctx, + mock.Anything, + receiver, + amount, + senderChain, + mock.Anything, + mock.Anything, + mock.Anything, + common.CoinType_ERC20, + mock.Anything, + ).Return(&evmtypes.MsgEthereumTxResponse{}, errDeposit) + + // call HandleEVMDeposit + reverted, err := k.HandleEVMDeposit( + ctx, + sample.CrossChainTx(t, "foo"), + types.MsgVoteOnObservedInboundTx{ + Sender: sample.EthAddress().String(), + Receiver: receiver.String(), + Amount: math.NewUintFromBigInt(amount), + CoinType: common.CoinType_ERC20, + Message: "", + Asset: "", + }, + senderChain, + ) + require.ErrorIs(t, err, errDeposit) + require.False(t, reverted) + fungibleMock.AssertExpectations(t) + }) + + t.Run("should return error with reverted if deposit ERC20 fails with tx failed", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + }) + + senderChain := getValidEthChain(t) + + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + + // expect DepositCoinZeta to be called + // ZRC20DepositAndCallContract(ctx, from, to, msg.Amount.BigInt(), senderChain, msg.Message, contract, data, msg.CoinType, msg.Asset) + errDeposit := errors.New("deposit failed") + fungibleMock.On( + "ZRC20DepositAndCallContract", + ctx, + mock.Anything, + receiver, + amount, + senderChain, + mock.Anything, + mock.Anything, + mock.Anything, + common.CoinType_ERC20, + mock.Anything, + ).Return(&evmtypes.MsgEthereumTxResponse{VmError: "reverted"}, errDeposit) + + // call HandleEVMDeposit + reverted, err := k.HandleEVMDeposit( + ctx, + sample.CrossChainTx(t, "foo"), + types.MsgVoteOnObservedInboundTx{ + Sender: sample.EthAddress().String(), + Receiver: receiver.String(), + Amount: math.NewUintFromBigInt(amount), + CoinType: common.CoinType_ERC20, + Message: "", + Asset: "", + }, + senderChain, + ) + require.ErrorIs(t, err, errDeposit) + require.True(t, reverted) + fungibleMock.AssertExpectations(t) + }) + + t.Run("should return error with reverted if deposit ERC20 fails with liquidity cap reached", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + }) + + senderChain := getValidEthChain(t) + + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + + // expect DepositCoinZeta to be called + // ZRC20DepositAndCallContract(ctx, from, to, msg.Amount.BigInt(), senderChain, msg.Message, contract, data, msg.CoinType, msg.Asset) + fungibleMock.On( + "ZRC20DepositAndCallContract", + ctx, + mock.Anything, + receiver, + amount, + senderChain, + mock.Anything, + mock.Anything, + mock.Anything, + common.CoinType_ERC20, + mock.Anything, + ).Return(&evmtypes.MsgEthereumTxResponse{}, fungibletypes.ErrForeignCoinCapReached) + + // call HandleEVMDeposit + reverted, err := k.HandleEVMDeposit( + ctx, + sample.CrossChainTx(t, "foo"), + types.MsgVoteOnObservedInboundTx{ + Sender: sample.EthAddress().String(), + Receiver: receiver.String(), + Amount: math.NewUintFromBigInt(amount), + CoinType: common.CoinType_ERC20, + Message: "", + Asset: "", + }, + senderChain, + ) + require.ErrorIs(t, err, fungibletypes.ErrForeignCoinCapReached) + require.True(t, reverted) + fungibleMock.AssertExpectations(t) + }) + + // TODO: add test cases for testing logs process + // https://github.com/zeta-chain/node/issues/1207 +} diff --git a/x/crosschain/keeper/gas_payment_test.go b/x/crosschain/keeper/gas_payment_test.go index e917df3ea3..f76d878607 100644 --- a/x/crosschain/keeper/gas_payment_test.go +++ b/x/crosschain/keeper/gas_payment_test.go @@ -22,14 +22,19 @@ import ( observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) -// get a valid chain id independently of the build flag +// get a valid eth chain id independently of the build flag func getValidEthChainID(t *testing.T) int64 { + return getValidEthChain(t).ChainId +} + +// get a valid eth chain independently of the build flag +func getValidEthChain(t *testing.T) *zetacommon.Chain { list := zetacommon.DefaultChainsList() require.True(t, len(list) > 1) require.NotNil(t, list[1]) require.False(t, zetacommon.IsBitcoinChain(list[1].ChainId)) - return list[1].ChainId + return list[1] } // assert that a contract has been deployed by checking stored code is non-empty. diff --git a/x/fungible/client/cli/tx.go b/x/fungible/client/cli/tx.go index 4f17f8372f..9b347fad35 100644 --- a/x/fungible/client/cli/tx.go +++ b/x/fungible/client/cli/tx.go @@ -5,8 +5,6 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/spf13/cobra" - - // "github.com/cosmos/cosmos-sdk/client/flags" "github.com/zeta-chain/zetacore/x/fungible/types" ) @@ -23,6 +21,7 @@ func GetTxCmd() *cobra.Command { cmd.AddCommand( CmdDeployFungibleCoinZRC4(), CmdRemoveForeignCoin(), + CmdUpdateZRC20LiquidityCap(), ) return cmd diff --git a/x/fungible/client/cli/tx_update_zrc20_liquidity_cap.go b/x/fungible/client/cli/tx_update_zrc20_liquidity_cap.go new file mode 100644 index 0000000000..8bec27e035 --- /dev/null +++ b/x/fungible/client/cli/tx_update_zrc20_liquidity_cap.go @@ -0,0 +1,42 @@ +package cli + +import ( + "fmt" + + "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/spf13/cobra" + "github.com/zeta-chain/zetacore/x/fungible/types" +) + +func CmdUpdateZRC20LiquidityCap() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-zrc20-liquidity-cap [zrc20] [liquidity-cap]", + Short: "Broadcast message UpdateZRC20LiquidityCap", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) (err error) { + newCap := math.NewUintFromString(args[1]) + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + fmt.Printf("CLI address: %s\n", clientCtx.GetFromAddress().String()) + msg := types.NewMsgUpdateZRC20LiquidityCap( + clientCtx.GetFromAddress().String(), + args[0], + newCap, + ) + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/fungible/keeper/deposits.go b/x/fungible/keeper/deposits.go index c788a2a1aa..138a894bdc 100644 --- a/x/fungible/keeper/deposits.go +++ b/x/fungible/keeper/deposits.go @@ -8,15 +8,17 @@ import ( evmtypes "github.com/evmos/ethermint/x/evm/types" "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/systemcontract.sol" "github.com/zeta-chain/zetacore/common" - "github.com/zeta-chain/zetacore/x/crosschain/types" - fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" + "github.com/zeta-chain/zetacore/x/fungible/types" ) +// DepositCoinZeta immediately mints ZETA to the EVM account func (k Keeper) DepositCoinZeta(ctx sdk.Context, to eth.Address, amount *big.Int) error { zetaToAddress := sdk.AccAddress(to.Bytes()) return k.MintZetaToEVMAccount(ctx, zetaToAddress, amount) } +// ZRC20DepositAndCallContract deposits ZRC20 to the EVM account and calls the contract func (k Keeper) ZRC20DepositAndCallContract( ctx sdk.Context, from []byte, @@ -27,21 +29,36 @@ func (k Keeper) ZRC20DepositAndCallContract( coinType common.CoinType, asset string, ) (*evmtypes.MsgEthereumTxResponse, bool, error) { - var Zrc20Contract eth.Address - var coin fungibletypes.ForeignCoins + var ZRC20Contract eth.Address + var coin types.ForeignCoins var found bool + + // get foreign coin if coinType == common.CoinType_Gas { coin, found = k.GetGasCoinForForeignCoin(ctx, senderChain.ChainId) if !found { - return nil, false, types.ErrGasCoinNotFound + return nil, false, crosschaintypes.ErrGasCoinNotFound } } else { coin, found = k.GetForeignCoinFromAsset(ctx, asset, senderChain.ChainId) if !found { - return nil, false, types.ErrForeignCoinNotFound + return nil, false, crosschaintypes.ErrForeignCoinNotFound + } + } + ZRC20Contract = eth.HexToAddress(coin.Zrc20ContractAddress) + + // check foreign coins cap if it has a cap + if !coin.LiquidityCap.IsNil() && !coin.LiquidityCap.IsZero() { + liquidityCap := coin.LiquidityCap.BigInt() + totalSupply, err := k.TotalSupplyZRC4(ctx, ZRC20Contract) + if err != nil { + return nil, false, err + } + newSupply := new(big.Int).Add(totalSupply, amount) + if newSupply.Cmp(liquidityCap) > 0 { + return nil, false, types.ErrForeignCoinCapReached } } - Zrc20Contract = eth.HexToAddress(coin.Zrc20ContractAddress) // check if the receiver is a contract // if it is, then the hook onCrossChainCall() will be called @@ -53,9 +70,9 @@ func (k Keeper) ZRC20DepositAndCallContract( Sender: eth.Address{}, ChainID: big.NewInt(senderChain.ChainId), } - res, err := k.DepositZRC20AndCallContract(ctx, context, Zrc20Contract, to, amount, data) + res, err := k.DepositZRC20AndCallContract(ctx, context, ZRC20Contract, to, amount, data) return res, true, err } - res, err := k.DepositZRC20(ctx, Zrc20Contract, to, amount) + res, err := k.DepositZRC20(ctx, ZRC20Contract, to, amount) return res, false, err } diff --git a/x/fungible/keeper/deposits_test.go b/x/fungible/keeper/deposits_test.go new file mode 100644 index 0000000000..5a241d6dfc --- /dev/null +++ b/x/fungible/keeper/deposits_test.go @@ -0,0 +1,232 @@ +package keeper_test + +import ( + "math/big" + "testing" + + "cosmossdk.io/math" + + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/common" + testkeeper "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/testutil/sample" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" + "github.com/zeta-chain/zetacore/x/fungible/types" +) + +func TestKeeper_ZRC20DepositAndCallContract(t *testing.T) { + t.Run("can deposit gas coin for transfers", func(t *testing.T) { + // setup gas coin + k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainList := common.DefaultChainsList() + chain := chainList[0] + + // deploy the system contracts + deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) + zrc20 := setupGasCoin(t, ctx, k, sdkk.EvmKeeper, chain.ChainId, "foobar", "foobar") + + // deposit + to := sample.EthAddress() + _, err := k.ZRC20DepositAndCallContract( + ctx, + sample.EthAddress().Bytes(), + to, + big.NewInt(42), + chain, + "", + sample.EthAddress(), + []byte{}, + common.CoinType_Gas, + sample.EthAddress().String(), + ) + require.NoError(t, err) + + balance, err := k.BalanceOfZRC4(ctx, zrc20, to) + require.NoError(t, err) + require.Equal(t, big.NewInt(42), balance) + }) + + t.Run("can deposit non-gas coin for transfers", func(t *testing.T) { + k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainList := common.DefaultChainsList() + chain := chainList[0] + assetAddress := sample.EthAddress().String() + + // deploy the system contracts + deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) + zrc20 := deployZRC20(t, ctx, k, sdkk.EvmKeeper, chain.ChainId, "foobar", assetAddress, "foobar") + + // deposit + to := sample.EthAddress() + _, err := k.ZRC20DepositAndCallContract( + ctx, + sample.EthAddress().Bytes(), + to, + big.NewInt(42), + chain, + "", + sample.EthAddress(), + []byte{}, + common.CoinType_ERC20, + assetAddress, + ) + require.NoError(t, err) + + balance, err := k.BalanceOfZRC4(ctx, zrc20, to) + require.NoError(t, err) + require.Equal(t, big.NewInt(42), balance) + }) + + t.Run("can deposit coin for transfers with liquidity cap not reached", func(t *testing.T) { + // setup gas coin + k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainList := common.DefaultChainsList() + chain := chainList[0] + + // deploy the system contracts + deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) + zrc20 := setupGasCoin(t, ctx, k, sdkk.EvmKeeper, chain.ChainId, "foobar", "foobar") + + // there is an initial total supply minted during gas pool setup + initialTotalSupply, err := k.TotalSupplyZRC4(ctx, zrc20) + require.NoError(t, err) + + // set a liquidity cap + coin, found := k.GetForeignCoins(ctx, zrc20.String()) + require.True(t, found) + coin.LiquidityCap = math.NewUint(initialTotalSupply.Uint64() + 1000) + k.SetForeignCoins(ctx, coin) + + // increase total supply + _, err = k.DepositZRC20(ctx, zrc20, sample.EthAddress(), big.NewInt(500)) + require.NoError(t, err) + + // deposit + to := sample.EthAddress() + _, err = k.ZRC20DepositAndCallContract( + ctx, + sample.EthAddress().Bytes(), + to, + big.NewInt(500), + chain, + "", + sample.EthAddress(), + []byte{}, + common.CoinType_Gas, + sample.EthAddress().String(), + ) + require.NoError(t, err) + + balance, err := k.BalanceOfZRC4(ctx, zrc20, to) + require.NoError(t, err) + require.Equal(t, big.NewInt(500), balance) + }) + + t.Run("should fail if liquidity cap reached", func(t *testing.T) { + // setup gas coin + k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainList := common.DefaultChainsList() + chain := chainList[0] + + // deploy the system contracts + deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) + zrc20 := setupGasCoin(t, ctx, k, sdkk.EvmKeeper, chain.ChainId, "foobar", "foobar") + + // there is an initial total supply minted during gas pool setup + initialTotalSupply, err := k.TotalSupplyZRC4(ctx, zrc20) + require.NoError(t, err) + + // set a liquidity cap + coin, found := k.GetForeignCoins(ctx, zrc20.String()) + require.True(t, found) + coin.LiquidityCap = math.NewUint(initialTotalSupply.Uint64() + 1000) + k.SetForeignCoins(ctx, coin) + + // increase total supply + _, err = k.DepositZRC20(ctx, zrc20, sample.EthAddress(), big.NewInt(500)) + require.NoError(t, err) + + // deposit (500 + 501 > 1000) + to := sample.EthAddress() + _, err = k.ZRC20DepositAndCallContract( + ctx, + sample.EthAddress().Bytes(), + to, + big.NewInt(501), + chain, + "", + sample.EthAddress(), + []byte{}, + common.CoinType_Gas, + sample.EthAddress().String(), + ) + require.ErrorIs(t, err, types.ErrForeignCoinCapReached) + }) + + t.Run("should fail if gas coin not found", func(t *testing.T) { + // setup gas coin + k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainList := common.DefaultChainsList() + chain := chainList[0] + + // deploy the system contracts + deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) + + // deposit + to := sample.EthAddress() + _, err := k.ZRC20DepositAndCallContract( + ctx, + sample.EthAddress().Bytes(), + to, + big.NewInt(42), + chain, + "", + sample.EthAddress(), + []byte{}, + common.CoinType_Gas, + sample.EthAddress().String(), + ) + require.ErrorIs(t, err, crosschaintypes.ErrGasCoinNotFound) + }) + + t.Run("should fail if zrc20 not found", func(t *testing.T) { + k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainList := common.DefaultChainsList() + chain := chainList[0] + assetAddress := sample.EthAddress().String() + + // deploy the system contracts + deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) + + // deposit + to := sample.EthAddress() + _, err := k.ZRC20DepositAndCallContract( + ctx, + sample.EthAddress().Bytes(), + to, + big.NewInt(42), + chain, + "", + sample.EthAddress(), + []byte{}, + common.CoinType_ERC20, + assetAddress, + ) + require.ErrorIs(t, err, crosschaintypes.ErrForeignCoinNotFound) + }) + + // TODO: add test cases checking DepositZRC20AndCallContract + // https://github.com/zeta-chain/node/issues/1206 +} diff --git a/x/fungible/keeper/gas_coin_and_pool_test.go b/x/fungible/keeper/gas_coin_and_pool_test.go index 0bff359dad..c2fb61e960 100644 --- a/x/fungible/keeper/gas_coin_and_pool_test.go +++ b/x/fungible/keeper/gas_coin_and_pool_test.go @@ -36,6 +36,31 @@ func setupGasCoin( return addr } +func deployZRC20( + t *testing.T, + ctx sdk.Context, + k *fungiblekeeper.Keeper, + evmk *evmkeeper.Keeper, + chainID int64, + assetName string, + assetAddress string, + symbol string, +) (zrc20 common.Address) { + addr, err := k.DeployZRC20Contract( + ctx, + assetName, + symbol, + 8, + chainID, + 0, + assetAddress, + big.NewInt(21_000), + ) + require.NoError(t, err) + assertContractDeployment(t, evmk, ctx, addr) + return addr +} + func TestKeeper_SetupChainGasCoinAndPool(t *testing.T) { t.Run("can setup a new chain gas coin", func(t *testing.T) { k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) diff --git a/x/fungible/keeper/msg_server_udpate_zrc20_liquidity_cap.go b/x/fungible/keeper/msg_server_udpate_zrc20_liquidity_cap.go new file mode 100644 index 0000000000..5d0bbaeefa --- /dev/null +++ b/x/fungible/keeper/msg_server_udpate_zrc20_liquidity_cap.go @@ -0,0 +1,33 @@ +package keeper + +import ( + "context" + + cosmoserrors "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/zeta-chain/zetacore/x/fungible/types" + zetaObserverTypes "github.com/zeta-chain/zetacore/x/observer/types" +) + +// UpdateZRC20LiquidityCap updates the liquidity cap for a ZRC20 token. +func (k msgServer) UpdateZRC20LiquidityCap(goCtx context.Context, msg *types.MsgUpdateZRC20LiquidityCap) (*types.MsgUpdateZRC20LiquidityCapResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // check authorization + if msg.Creator != k.observerKeeper.GetParams(ctx).GetAdminPolicyAccount(zetaObserverTypes.Policy_Type_group2) { + return nil, cosmoserrors.Wrap(sdkerrors.ErrUnauthorized, "update can only be executed by group 2 policy group") + } + + // fetch the foreign coin + coin, found := k.GetForeignCoins(ctx, msg.Zrc20Address) + if !found { + return nil, types.ErrForeignCoinNotFound + } + + // update the liquidity cap + coin.LiquidityCap = msg.LiquidityCap + k.SetForeignCoins(ctx, coin) + + return &types.MsgUpdateZRC20LiquidityCapResponse{}, nil +} diff --git a/x/fungible/keeper/msg_server_udpate_zrc20_liquidity_cap_test.go b/x/fungible/keeper/msg_server_udpate_zrc20_liquidity_cap_test.go new file mode 100644 index 0000000000..ea51fabc14 --- /dev/null +++ b/x/fungible/keeper/msg_server_udpate_zrc20_liquidity_cap_test.go @@ -0,0 +1,115 @@ +package keeper_test + +import ( + "testing" + + "cosmossdk.io/math" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "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" +) + +func TestMsgServer_UpdateZRC20LiquidityCap(t *testing.T) { + t.Run("can update the liquidity cap of zrc20", func(t *testing.T) { + k, ctx, _, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + admin := sample.AccAddress() + coinAddress := sample.EthAddress().String() + + foreignCoin := sample.ForeignCoins(t, coinAddress) + foreignCoin.LiquidityCap = math.Uint{} + k.SetForeignCoins(ctx, foreignCoin) + + setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) + + // can update liquidity cap + _, err := msgServer.UpdateZRC20LiquidityCap(ctx, types.NewMsgUpdateZRC20LiquidityCap( + admin, + coinAddress, + math.NewUint(42), + )) + require.NoError(t, err) + + coin, found := k.GetForeignCoins(ctx, coinAddress) + require.True(t, found) + require.True(t, coin.LiquidityCap.Equal(math.NewUint(42)), "invalid liquidity cap", coin.LiquidityCap.String()) + + // can update liquidity cap again + _, err = msgServer.UpdateZRC20LiquidityCap(ctx, types.NewMsgUpdateZRC20LiquidityCap( + admin, + coinAddress, + math.NewUint(4200000), + )) + require.NoError(t, err) + + coin, found = k.GetForeignCoins(ctx, coinAddress) + require.True(t, found) + require.True(t, coin.LiquidityCap.Equal(math.NewUint(4200000)), "invalid liquidity cap", coin.LiquidityCap.String()) + + // can set liquidity cap to 0 + _, err = msgServer.UpdateZRC20LiquidityCap(ctx, types.NewMsgUpdateZRC20LiquidityCap( + admin, + coinAddress, + math.NewUint(0), + )) + require.NoError(t, err) + + coin, found = k.GetForeignCoins(ctx, coinAddress) + require.True(t, found) + require.True(t, coin.LiquidityCap.Equal(math.ZeroUint()), "invalid liquidity cap", coin.LiquidityCap.String()) + + // can set liquidity cap to nil + _, err = msgServer.UpdateZRC20LiquidityCap(ctx, types.NewMsgUpdateZRC20LiquidityCap( + admin, + coinAddress, + math.Uint{}, + )) + require.NoError(t, err) + + coin, found = k.GetForeignCoins(ctx, coinAddress) + require.True(t, found) + require.True(t, coin.LiquidityCap.Equal(math.ZeroUint()), "invalid liquidity cap", coin.LiquidityCap.String()) + }) + + t.Run("should fail if not admin", func(t *testing.T) { + k, ctx, _, zk := keepertest.FungibleKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + admin := sample.AccAddress() + coinAddress := sample.EthAddress().String() + + foreignCoin := sample.ForeignCoins(t, coinAddress) + foreignCoin.LiquidityCap = math.Uint{} + k.SetForeignCoins(ctx, foreignCoin) + + setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group1) + + _, err := msgServer.UpdateZRC20LiquidityCap(ctx, types.NewMsgUpdateZRC20LiquidityCap( + sample.AccAddress(), + coinAddress, + math.NewUint(42), + )) + require.Error(t, err) + require.ErrorIs(t, err, sdkerrors.ErrUnauthorized) + }) + + 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() + coinAddress := sample.EthAddress().String() + + setAdminPolicies(ctx, zk, admin, observertypes.Policy_Type_group2) + + _, err := msgServer.UpdateZRC20LiquidityCap(ctx, types.NewMsgUpdateZRC20LiquidityCap( + admin, + coinAddress, + math.NewUint(42), + )) + require.Error(t, err) + require.ErrorIs(t, err, types.ErrForeignCoinNotFound) + }) +} diff --git a/x/fungible/types/codec.go b/x/fungible/types/codec.go index 2f8689e4c2..3c06f02110 100644 --- a/x/fungible/types/codec.go +++ b/x/fungible/types/codec.go @@ -10,12 +10,14 @@ import ( func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgDeployFungibleCoinZRC20{}, "fungible/DeployFungibleCoinZRC20", nil) cdc.RegisterConcrete(&MsgRemoveForeignCoin{}, "fungible/RemoveForeignCoin", nil) + cdc.RegisterConcrete(&MsgUpdateZRC20LiquidityCap{}, "fungible/UpdateZRC20LiquidityCap", nil) } func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgDeployFungibleCoinZRC20{}, &MsgRemoveForeignCoin{}, + &MsgUpdateZRC20LiquidityCap{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/fungible/types/errors.go b/x/fungible/types/errors.go index 5b63632114..262fca0b68 100644 --- a/x/fungible/types/errors.go +++ b/x/fungible/types/errors.go @@ -31,4 +31,5 @@ var ( ErrInvalidContract = sdkerrors.Register(ModuleName, 1120, "invalid contract") ErrPausedZRC20 = sdkerrors.Register(ModuleName, 1121, "ZRC20 is paused") ErrForeignCoinNotFound = sdkerrors.Register(ModuleName, 1122, "foreign coin not found") + ErrForeignCoinCapReached = sdkerrors.Register(ModuleName, 1123, "foreign coin cap reached") ) diff --git a/x/fungible/types/foreign_coins.pb.go b/x/fungible/types/foreign_coins.pb.go index 59546724b7..dd834ae48d 100644 --- a/x/fungible/types/foreign_coins.pb.go +++ b/x/fungible/types/foreign_coins.pb.go @@ -9,6 +9,8 @@ import ( math "math" math_bits "math/bits" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/gogo/protobuf/proto" common "github.com/zeta-chain/zetacore/common" ) @@ -26,15 +28,16 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type ForeignCoins struct { // string index = 1; - Zrc20ContractAddress string `protobuf:"bytes,2,opt,name=zrc20_contract_address,json=zrc20ContractAddress,proto3" json:"zrc20_contract_address,omitempty"` - Asset string `protobuf:"bytes,3,opt,name=asset,proto3" json:"asset,omitempty"` - ForeignChainId int64 `protobuf:"varint,4,opt,name=foreign_chain_id,json=foreignChainId,proto3" json:"foreign_chain_id,omitempty"` - Decimals uint32 `protobuf:"varint,5,opt,name=decimals,proto3" json:"decimals,omitempty"` - Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` - Symbol string `protobuf:"bytes,7,opt,name=symbol,proto3" json:"symbol,omitempty"` - CoinType common.CoinType `protobuf:"varint,8,opt,name=coin_type,json=coinType,proto3,enum=common.CoinType" json:"coin_type,omitempty"` - GasLimit uint64 `protobuf:"varint,9,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"` - Paused bool `protobuf:"varint,10,opt,name=paused,proto3" json:"paused,omitempty"` + Zrc20ContractAddress string `protobuf:"bytes,2,opt,name=zrc20_contract_address,json=zrc20ContractAddress,proto3" json:"zrc20_contract_address,omitempty"` + Asset string `protobuf:"bytes,3,opt,name=asset,proto3" json:"asset,omitempty"` + ForeignChainId int64 `protobuf:"varint,4,opt,name=foreign_chain_id,json=foreignChainId,proto3" json:"foreign_chain_id,omitempty"` + Decimals uint32 `protobuf:"varint,5,opt,name=decimals,proto3" json:"decimals,omitempty"` + Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` + Symbol string `protobuf:"bytes,7,opt,name=symbol,proto3" json:"symbol,omitempty"` + CoinType common.CoinType `protobuf:"varint,8,opt,name=coin_type,json=coinType,proto3,enum=common.CoinType" json:"coin_type,omitempty"` + GasLimit uint64 `protobuf:"varint,9,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"` + Paused bool `protobuf:"varint,10,opt,name=paused,proto3" json:"paused,omitempty"` + LiquidityCap github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,11,opt,name=liquidity_cap,json=liquidityCap,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"liquidity_cap"` } func (m *ForeignCoins) Reset() { *m = ForeignCoins{} } @@ -140,29 +143,33 @@ func init() { func init() { proto.RegisterFile("fungible/foreign_coins.proto", fileDescriptor_5285bb476cecbbf8) } var fileDescriptor_5285bb476cecbbf8 = []byte{ - // 352 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x3c, 0x51, 0x4d, 0x6a, 0xeb, 0x30, - 0x10, 0x8e, 0xf2, 0xf7, 0x6c, 0xf1, 0x5e, 0x08, 0x7a, 0x21, 0x88, 0xa4, 0x18, 0xd3, 0x95, 0x37, - 0xb1, 0x4b, 0xda, 0x0b, 0xb4, 0x81, 0x42, 0xa0, 0x2b, 0xd3, 0x55, 0x37, 0x46, 0x96, 0x15, 0x47, - 0x60, 0x4b, 0xc6, 0x52, 0xa0, 0xc9, 0x29, 0x7a, 0x94, 0x1e, 0xa3, 0xcb, 0x2c, 0xbb, 0x2c, 0xc9, - 0x45, 0x8a, 0x64, 0x27, 0x2b, 0xcd, 0x37, 0xa3, 0x99, 0xf9, 0xbe, 0xf9, 0xe0, 0xcd, 0x66, 0x27, - 0x72, 0x9e, 0x16, 0x2c, 0xda, 0xc8, 0x9a, 0xf1, 0x5c, 0x24, 0x54, 0x72, 0xa1, 0xc2, 0xaa, 0x96, - 0x5a, 0xa2, 0xf9, 0x81, 0x69, 0x42, 0xb7, 0x84, 0x8b, 0xd0, 0x46, 0xb2, 0x66, 0xe1, 0xa5, 0x61, - 0xf6, 0x9f, 0xca, 0xb2, 0x94, 0x22, 0x6a, 0x9e, 0xa6, 0xe3, 0xf6, 0xb3, 0x0b, 0xff, 0x3e, 0x37, - 0x93, 0x56, 0x66, 0x10, 0x7a, 0x80, 0xd3, 0x43, 0x4d, 0x97, 0x77, 0x09, 0x95, 0x42, 0xd7, 0x84, - 0xea, 0x84, 0x64, 0x59, 0xcd, 0x94, 0xc2, 0x5d, 0x1f, 0x04, 0x6e, 0x3c, 0xb1, 0xd5, 0x55, 0x5b, - 0x7c, 0x6c, 0x6a, 0x68, 0x02, 0x07, 0x44, 0x29, 0xa6, 0x71, 0xcf, 0x7e, 0x6a, 0x00, 0x0a, 0xe0, - 0xf8, 0xca, 0xd2, 0x90, 0x4a, 0x78, 0x86, 0xfb, 0x3e, 0x08, 0x7a, 0xf1, 0xa8, 0xcd, 0xaf, 0x4c, - 0x7a, 0x9d, 0xa1, 0x19, 0x74, 0x32, 0x46, 0x79, 0x49, 0x0a, 0x85, 0x07, 0x3e, 0x08, 0xfe, 0xc5, - 0x57, 0x8c, 0x10, 0xec, 0x0b, 0x52, 0x32, 0x3c, 0xb4, 0xa3, 0x6d, 0x8c, 0xa6, 0x70, 0xa8, 0xf6, - 0x65, 0x2a, 0x0b, 0xfc, 0xc7, 0x66, 0x5b, 0x84, 0x16, 0xd0, 0x35, 0xf7, 0x48, 0xf4, 0xbe, 0x62, - 0xd8, 0xf1, 0x41, 0x30, 0x5a, 0x8e, 0xc3, 0x56, 0xb0, 0xd1, 0xf7, 0xba, 0xaf, 0x58, 0xec, 0xd0, - 0x36, 0x42, 0x73, 0xe8, 0xe6, 0x44, 0x25, 0x05, 0x2f, 0xb9, 0xc6, 0xae, 0x0f, 0x82, 0x7e, 0xec, - 0xe4, 0x44, 0xbd, 0x18, 0x6c, 0x76, 0x54, 0x64, 0xa7, 0x58, 0x86, 0xa1, 0x0f, 0x02, 0x27, 0x6e, - 0xd1, 0xd3, 0xfa, 0xeb, 0xe4, 0x81, 0xe3, 0xc9, 0x03, 0x3f, 0x27, 0x0f, 0x7c, 0x9c, 0xbd, 0xce, - 0xf1, 0xec, 0x75, 0xbe, 0xcf, 0x5e, 0xe7, 0x2d, 0xca, 0xb9, 0xde, 0xee, 0x52, 0xb3, 0x30, 0x32, - 0xf7, 0x5f, 0x58, 0xd5, 0xd1, 0xc5, 0x8a, 0xe8, 0x3d, 0xba, 0xba, 0x67, 0x08, 0xaa, 0x74, 0x68, - 0x4d, 0xb8, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xe9, 0xed, 0x99, 0xa3, 0xd6, 0x01, 0x00, 0x00, + // 416 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x52, 0xc1, 0x6e, 0xd4, 0x30, + 0x14, 0x5c, 0xb3, 0xdb, 0x25, 0x6b, 0xda, 0xaa, 0x32, 0xab, 0xca, 0xda, 0xa2, 0x34, 0xe2, 0x42, + 0x2e, 0x1b, 0xa3, 0xc2, 0x0f, 0xd0, 0x48, 0x48, 0x95, 0x38, 0x45, 0xe5, 0xc2, 0x25, 0x72, 0x6c, + 0x37, 0xb5, 0x48, 0xec, 0x10, 0x3b, 0x12, 0xe9, 0x07, 0x70, 0xe6, 0xb3, 0x7a, 0xec, 0x11, 0x71, + 0xa8, 0xd0, 0xee, 0x8f, 0x20, 0x3b, 0x69, 0xd4, 0x93, 0x67, 0xe6, 0xc5, 0xf3, 0x26, 0xef, 0x19, + 0xbe, 0xb9, 0xe9, 0x54, 0x29, 0x8b, 0x4a, 0x90, 0x1b, 0xdd, 0x0a, 0x59, 0xaa, 0x9c, 0x69, 0xa9, + 0x4c, 0xd2, 0xb4, 0xda, 0x6a, 0x74, 0x76, 0x27, 0x2c, 0x65, 0xb7, 0x54, 0xaa, 0xc4, 0x23, 0xdd, + 0x8a, 0xe4, 0xe9, 0xc2, 0xe6, 0x35, 0xd3, 0x75, 0xad, 0x15, 0x19, 0x8e, 0xe1, 0xc6, 0x66, 0x5d, + 0xea, 0x52, 0x7b, 0x48, 0x1c, 0x1a, 0xd4, 0xb7, 0xbf, 0xe6, 0xf0, 0xf0, 0xf3, 0xe0, 0x9f, 0x3a, + 0x7b, 0xf4, 0x11, 0x9e, 0xde, 0xb5, 0xec, 0xe2, 0x7d, 0xce, 0xb4, 0xb2, 0x2d, 0x65, 0x36, 0xa7, + 0x9c, 0xb7, 0xc2, 0x18, 0xfc, 0x22, 0x02, 0xf1, 0x2a, 0x5b, 0xfb, 0x6a, 0x3a, 0x16, 0x3f, 0x0d, + 0x35, 0xb4, 0x86, 0x07, 0xd4, 0x18, 0x61, 0xf1, 0xdc, 0x7f, 0x34, 0x10, 0x14, 0xc3, 0x93, 0x29, + 0xbb, 0x8b, 0x9a, 0x4b, 0x8e, 0x17, 0x11, 0x88, 0xe7, 0xd9, 0xf1, 0xa8, 0xa7, 0x4e, 0xbe, 0xe2, + 0x68, 0x03, 0x03, 0x2e, 0x98, 0xac, 0x69, 0x65, 0xf0, 0x41, 0x04, 0xe2, 0xa3, 0x6c, 0xe2, 0x08, + 0xc1, 0x85, 0xa2, 0xb5, 0xc0, 0x4b, 0x6f, 0xed, 0x31, 0x3a, 0x85, 0x4b, 0xd3, 0xd7, 0x85, 0xae, + 0xf0, 0x4b, 0xaf, 0x8e, 0x0c, 0x6d, 0xe1, 0xca, 0x4d, 0x29, 0xb7, 0x7d, 0x23, 0x70, 0x10, 0x81, + 0xf8, 0xf8, 0xe2, 0x24, 0x19, 0xc7, 0xe0, 0xfe, 0xef, 0xba, 0x6f, 0x44, 0x16, 0xb0, 0x11, 0xa1, + 0x33, 0xb8, 0x2a, 0xa9, 0xc9, 0x2b, 0x59, 0x4b, 0x8b, 0x57, 0x11, 0x88, 0x17, 0x59, 0x50, 0x52, + 0xf3, 0xc5, 0x71, 0xd7, 0xa3, 0xa1, 0x9d, 0x11, 0x1c, 0xc3, 0x08, 0xc4, 0x41, 0x36, 0x32, 0x74, + 0x0d, 0x8f, 0x2a, 0xf9, 0xa3, 0x93, 0x5c, 0xda, 0x3e, 0x67, 0xb4, 0xc1, 0xaf, 0x5c, 0x84, 0x4b, + 0x72, 0xff, 0x78, 0x3e, 0xfb, 0xfb, 0x78, 0xfe, 0xae, 0x94, 0xf6, 0xb6, 0x2b, 0x5c, 0x57, 0xc2, + 0xb4, 0xa9, 0xb5, 0x19, 0x8f, 0xad, 0xe1, 0xdf, 0x89, 0x0b, 0x66, 0x92, 0xaf, 0x52, 0xd9, 0xec, + 0x70, 0x72, 0x49, 0x69, 0x73, 0x79, 0x75, 0xbf, 0x0b, 0xc1, 0xc3, 0x2e, 0x04, 0xff, 0x76, 0x21, + 0xf8, 0xbd, 0x0f, 0x67, 0x0f, 0xfb, 0x70, 0xf6, 0x67, 0x1f, 0xce, 0xbe, 0x91, 0x67, 0x86, 0x6e, + 0xd7, 0x5b, 0x3f, 0x4b, 0xf2, 0xb4, 0x76, 0xf2, 0x93, 0x4c, 0x2f, 0xc5, 0xbb, 0x17, 0x4b, 0xbf, + 0xda, 0x0f, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x1b, 0xf5, 0xe7, 0x49, 0x42, 0x02, 0x00, 0x00, } func (m *ForeignCoins) Marshal() (dAtA []byte, err error) { @@ -185,6 +192,16 @@ func (m *ForeignCoins) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.LiquidityCap.Size() + i -= size + if _, err := m.LiquidityCap.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintForeignCoins(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a if m.Paused { i-- if m.Paused { @@ -294,6 +311,8 @@ func (m *ForeignCoins) Size() (n int) { if m.Paused { n += 2 } + l = m.LiquidityCap.Size() + n += 1 + l + sovForeignCoins(uint64(l)) return n } @@ -556,6 +575,40 @@ func (m *ForeignCoins) Unmarshal(dAtA []byte) error { } } m.Paused = bool(v != 0) + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LiquidityCap", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowForeignCoins + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthForeignCoins + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthForeignCoins + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LiquidityCap.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipForeignCoins(dAtA[iNdEx:]) diff --git a/x/fungible/types/message_update_zrc20_liquidity_cap.go b/x/fungible/types/message_update_zrc20_liquidity_cap.go new file mode 100644 index 0000000000..45bda0e1f5 --- /dev/null +++ b/x/fungible/types/message_update_zrc20_liquidity_cap.go @@ -0,0 +1,54 @@ +package types + +import ( + cosmoserrors "cosmossdk.io/errors" + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + ethcommon "github.com/ethereum/go-ethereum/common" +) + +const TypeMsgUpdateZRC20LiquidityCap = "update_zrc20_liquidity_cap" + +var _ sdk.Msg = &MsgUpdateZRC20LiquidityCap{} + +func NewMsgUpdateZRC20LiquidityCap(creator string, zrc20 string, liquidityCap math.Uint) *MsgUpdateZRC20LiquidityCap { + return &MsgUpdateZRC20LiquidityCap{ + Creator: creator, + Zrc20Address: zrc20, + LiquidityCap: liquidityCap, + } +} + +func (msg *MsgUpdateZRC20LiquidityCap) Route() string { + return RouterKey +} + +func (msg *MsgUpdateZRC20LiquidityCap) Type() string { + return TypeMsgUpdateSystemContract +} + +func (msg *MsgUpdateZRC20LiquidityCap) GetSigners() []sdk.AccAddress { + creator, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + panic(err) + } + return []sdk.AccAddress{creator} +} + +func (msg *MsgUpdateZRC20LiquidityCap) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg *MsgUpdateZRC20LiquidityCap) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + return cosmoserrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) + } + if !ethcommon.IsHexAddress(msg.Zrc20Address) { + return cosmoserrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid contract address (%s)", msg.Zrc20Address) + } + + return nil +} diff --git a/x/fungible/types/message_update_zrc20_liquidity_cap_test.go b/x/fungible/types/message_update_zrc20_liquidity_cap_test.go new file mode 100644 index 0000000000..d59198ce39 --- /dev/null +++ b/x/fungible/types/message_update_zrc20_liquidity_cap_test.go @@ -0,0 +1,70 @@ +package types_test + +import ( + "testing" + + "cosmossdk.io/math" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/fungible/types" +) + +func TestNewMsgUpdateZRC20LiquidityCap_ValidateBasics(t *testing.T) { + tests := []struct { + name string + msg types.MsgUpdateZRC20LiquidityCap + err error + }{ + { + name: "valid message", + msg: types.MsgUpdateZRC20LiquidityCap{ + Creator: sample.AccAddress(), + Zrc20Address: sample.EthAddress().String(), + LiquidityCap: math.NewUint(1000), + }, + }, + { + name: "valid message with liquidity cap 0", + msg: types.MsgUpdateZRC20LiquidityCap{ + Creator: sample.AccAddress(), + Zrc20Address: sample.EthAddress().String(), + LiquidityCap: math.ZeroUint(), + }, + }, + { + name: "valid message with liquidity cap nil", + msg: types.MsgUpdateZRC20LiquidityCap{ + Creator: sample.AccAddress(), + Zrc20Address: sample.EthAddress().String(), + }, + }, + { + name: "invalid address", + msg: types.MsgUpdateZRC20LiquidityCap{ + Creator: "invalid_address", + Zrc20Address: sample.EthAddress().String(), + }, + err: sdkerrors.ErrInvalidAddress, + }, + { + name: "invalid contract address", + msg: types.MsgUpdateZRC20LiquidityCap{ + Creator: sample.AccAddress(), + Zrc20Address: "invalid_address", + }, + err: sdkerrors.ErrInvalidAddress, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.msg.ValidateBasic() + if tt.err != nil { + require.ErrorIs(t, err, tt.err) + return + } + require.NoError(t, err) + }) + } +} diff --git a/x/fungible/types/tx.pb.go b/x/fungible/types/tx.pb.go index 62cb8d4ac8..41271cd126 100644 --- a/x/fungible/types/tx.pb.go +++ b/x/fungible/types/tx.pb.go @@ -665,6 +665,95 @@ func (m *MsgUpdateZRC20PausedStatusResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgUpdateZRC20PausedStatusResponse proto.InternalMessageInfo +type MsgUpdateZRC20LiquidityCap struct { + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + Zrc20Address string `protobuf:"bytes,2,opt,name=zrc20_address,json=zrc20Address,proto3" json:"zrc20_address,omitempty"` + LiquidityCap github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,3,opt,name=liquidity_cap,json=liquidityCap,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"liquidity_cap"` +} + +func (m *MsgUpdateZRC20LiquidityCap) Reset() { *m = MsgUpdateZRC20LiquidityCap{} } +func (m *MsgUpdateZRC20LiquidityCap) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateZRC20LiquidityCap) ProtoMessage() {} +func (*MsgUpdateZRC20LiquidityCap) Descriptor() ([]byte, []int) { + return fileDescriptor_197fdedece277fa0, []int{12} +} +func (m *MsgUpdateZRC20LiquidityCap) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateZRC20LiquidityCap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateZRC20LiquidityCap.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgUpdateZRC20LiquidityCap) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateZRC20LiquidityCap.Merge(m, src) +} +func (m *MsgUpdateZRC20LiquidityCap) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateZRC20LiquidityCap) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateZRC20LiquidityCap.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateZRC20LiquidityCap proto.InternalMessageInfo + +func (m *MsgUpdateZRC20LiquidityCap) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *MsgUpdateZRC20LiquidityCap) GetZrc20Address() string { + if m != nil { + return m.Zrc20Address + } + return "" +} + +type MsgUpdateZRC20LiquidityCapResponse struct { +} + +func (m *MsgUpdateZRC20LiquidityCapResponse) Reset() { *m = MsgUpdateZRC20LiquidityCapResponse{} } +func (m *MsgUpdateZRC20LiquidityCapResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateZRC20LiquidityCapResponse) ProtoMessage() {} +func (*MsgUpdateZRC20LiquidityCapResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_197fdedece277fa0, []int{13} +} +func (m *MsgUpdateZRC20LiquidityCapResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateZRC20LiquidityCapResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateZRC20LiquidityCapResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgUpdateZRC20LiquidityCapResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateZRC20LiquidityCapResponse.Merge(m, src) +} +func (m *MsgUpdateZRC20LiquidityCapResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateZRC20LiquidityCapResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateZRC20LiquidityCapResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateZRC20LiquidityCapResponse proto.InternalMessageInfo + func init() { proto.RegisterEnum("zetachain.zetacore.fungible.UpdatePausedStatusAction", UpdatePausedStatusAction_name, UpdatePausedStatusAction_value) proto.RegisterType((*MsgUpdateZRC20WithdrawFee)(nil), "zetachain.zetacore.fungible.MsgUpdateZRC20WithdrawFee") @@ -679,65 +768,71 @@ func init() { proto.RegisterType((*MsgUpdateContractBytecodeResponse)(nil), "zetachain.zetacore.fungible.MsgUpdateContractBytecodeResponse") proto.RegisterType((*MsgUpdateZRC20PausedStatus)(nil), "zetachain.zetacore.fungible.MsgUpdateZRC20PausedStatus") proto.RegisterType((*MsgUpdateZRC20PausedStatusResponse)(nil), "zetachain.zetacore.fungible.MsgUpdateZRC20PausedStatusResponse") + proto.RegisterType((*MsgUpdateZRC20LiquidityCap)(nil), "zetachain.zetacore.fungible.MsgUpdateZRC20LiquidityCap") + proto.RegisterType((*MsgUpdateZRC20LiquidityCapResponse)(nil), "zetachain.zetacore.fungible.MsgUpdateZRC20LiquidityCapResponse") } func init() { proto.RegisterFile("fungible/tx.proto", fileDescriptor_197fdedece277fa0) } var fileDescriptor_197fdedece277fa0 = []byte{ - // 843 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcd, 0x6e, 0xdb, 0x46, - 0x10, 0x16, 0xad, 0x58, 0xb6, 0xa6, 0x89, 0x2c, 0x6f, 0x85, 0x84, 0xa5, 0x0b, 0xd9, 0x61, 0x0a, - 0x44, 0x0d, 0x60, 0xd2, 0x55, 0x7f, 0x82, 0x02, 0x6d, 0x0a, 0x5b, 0x89, 0xd1, 0x00, 0x55, 0x1b, - 0xd0, 0x15, 0x8a, 0xe6, 0x42, 0xac, 0xc8, 0x35, 0x45, 0x54, 0xdc, 0x15, 0xb8, 0xab, 0x2a, 0xca, - 0xad, 0xd7, 0x9c, 0x82, 0xf6, 0x3d, 0x7a, 0xeb, 0x3b, 0xe4, 0x98, 0x63, 0xd1, 0x43, 0x50, 0xd8, - 0x97, 0x3e, 0x46, 0xc1, 0xe5, 0x4f, 0x28, 0x59, 0x94, 0x1c, 0x9f, 0xb8, 0xb3, 0x9a, 0xf9, 0xf6, - 0x9b, 0x99, 0x6f, 0x56, 0x0b, 0xdb, 0xa7, 0x63, 0xea, 0xf9, 0xfd, 0x21, 0x31, 0xc5, 0x33, 0x63, - 0x14, 0x32, 0xc1, 0xd0, 0xce, 0x73, 0x22, 0xb0, 0x33, 0xc0, 0x3e, 0x35, 0xe4, 0x8a, 0x85, 0xc4, - 0x48, 0xbd, 0xb4, 0xf7, 0x1d, 0x16, 0x04, 0x8c, 0x9a, 0xf1, 0x27, 0x8e, 0xd0, 0x1a, 0x1e, 0xf3, - 0x98, 0x5c, 0x9a, 0xd1, 0x2a, 0xde, 0xd5, 0xff, 0x52, 0xe0, 0x83, 0x2e, 0xf7, 0x7a, 0x23, 0x17, - 0x0b, 0xf2, 0xd4, 0xea, 0xb4, 0x0f, 0x7e, 0xf2, 0xc5, 0xc0, 0x0d, 0xf1, 0xe4, 0x98, 0x10, 0xa4, - 0xc2, 0x86, 0x13, 0x12, 0x2c, 0x58, 0xa8, 0x2a, 0x7b, 0x4a, 0xab, 0x6a, 0xa5, 0x26, 0xba, 0x03, - 0x37, 0x9e, 0x87, 0x4e, 0xfb, 0xc0, 0xc6, 0xae, 0x1b, 0x12, 0xce, 0xd5, 0x35, 0xf9, 0xfb, 0x75, - 0xb9, 0x79, 0x18, 0xef, 0xa1, 0x9f, 0xa1, 0x4e, 0xc9, 0xc4, 0x9e, 0x24, 0x88, 0xf6, 0x29, 0x21, - 0x6a, 0x25, 0xf2, 0x3b, 0x32, 0x5f, 0xbd, 0xd9, 0x2d, 0xfd, 0xf3, 0x66, 0xf7, 0xae, 0xe7, 0x8b, - 0xc1, 0xb8, 0x6f, 0x38, 0x2c, 0x30, 0x1d, 0xc6, 0x03, 0xc6, 0x93, 0xcf, 0x3e, 0x77, 0x7f, 0x31, - 0xc5, 0x74, 0x44, 0xb8, 0xd1, 0xf3, 0xa9, 0xb0, 0x6a, 0x94, 0x4c, 0x72, 0xcc, 0xf4, 0x3b, 0x70, - 0xbb, 0x90, 0xb6, 0x45, 0xf8, 0x88, 0x51, 0x4e, 0xf4, 0x10, 0x6e, 0x65, 0x4e, 0x27, 0x53, 0x2e, - 0x48, 0xd0, 0x61, 0x54, 0x84, 0xd8, 0x11, 0x4b, 0x32, 0xfb, 0x1a, 0x76, 0x22, 0xd2, 0x5c, 0xfa, - 0xdb, 0x4e, 0x12, 0x30, 0x97, 0xa7, 0x4a, 0xc9, 0x64, 0x16, 0x31, 0xc9, 0x59, 0xbf, 0x0d, 0xbb, - 0x05, 0x67, 0x66, 0xb4, 0x5e, 0xac, 0x81, 0xd6, 0xe5, 0xde, 0x43, 0x32, 0x1a, 0xb2, 0xe9, 0x71, - 0xd2, 0xb4, 0x0e, 0xf3, 0xa9, 0x4c, 0x64, 0x09, 0xb5, 0x06, 0xac, 0x3f, 0x8a, 0x5c, 0x12, 0x12, - 0xb1, 0x81, 0x5a, 0x50, 0x3f, 0x65, 0x21, 0xf1, 0x3d, 0x6a, 0x4b, 0x41, 0xd8, 0xbe, 0xab, 0x96, - 0xf7, 0x94, 0x56, 0xd9, 0xaa, 0x25, 0xfb, 0x9d, 0x68, 0xfb, 0xb1, 0x8b, 0x34, 0xd8, 0x74, 0x89, - 0xe3, 0x07, 0x78, 0xc8, 0xd5, 0x6b, 0x7b, 0x4a, 0xeb, 0x86, 0x95, 0xd9, 0x08, 0xc1, 0x35, 0x8a, - 0x03, 0xa2, 0xae, 0x4b, 0x68, 0xb9, 0x46, 0x37, 0xa1, 0xc2, 0xa7, 0x41, 0x9f, 0x0d, 0xe3, 0xae, - 0x59, 0x89, 0x85, 0xf6, 0xa1, 0xea, 0x30, 0x9f, 0xda, 0x51, 0x7f, 0xd4, 0x8d, 0x3d, 0xa5, 0x55, - 0x6b, 0xd7, 0x8d, 0x44, 0x6c, 0x51, 0x1e, 0x3f, 0x4e, 0x47, 0xc4, 0xda, 0x74, 0x92, 0x15, 0xda, - 0x81, 0xaa, 0x87, 0xb9, 0x3d, 0xf4, 0x03, 0x5f, 0xa8, 0x9b, 0x92, 0xd9, 0xa6, 0x87, 0xf9, 0x77, - 0x91, 0xad, 0x3f, 0x00, 0xbd, 0xb8, 0x16, 0x69, 0xc9, 0xa2, 0x9a, 0xa4, 0x0d, 0x48, 0x6a, 0x92, - 0x98, 0xfa, 0x43, 0x68, 0x74, 0xb9, 0x67, 0x91, 0x80, 0xfd, 0x4a, 0x8e, 0x93, 0x74, 0x99, 0x4f, - 0x97, 0x54, 0x31, 0xcd, 0x74, 0xed, 0x6d, 0xa6, 0x7a, 0x13, 0x3e, 0x5c, 0x84, 0x92, 0xb5, 0xec, - 0xf7, 0xfc, 0x98, 0xa4, 0x0d, 0x3d, 0x9a, 0x0a, 0xe2, 0x30, 0x77, 0xd9, 0x98, 0x7c, 0x0c, 0xf5, - 0x02, 0x05, 0x6d, 0x39, 0xb3, 0xc2, 0x41, 0x07, 0xd0, 0x88, 0x74, 0xd7, 0x4f, 0x40, 0x33, 0xf7, - 0xb2, 0x74, 0x47, 0x94, 0x4c, 0xd2, 0xf3, 0x52, 0xa9, 0xfd, 0x90, 0x9b, 0x81, 0x79, 0x4e, 0x59, - 0xe5, 0xee, 0xc1, 0xf6, 0x0c, 0xec, 0x00, 0xf3, 0x81, 0x64, 0x79, 0xdd, 0xda, 0xca, 0x61, 0x7e, - 0x8b, 0xf9, 0x40, 0xff, 0x53, 0x91, 0xc2, 0xcc, 0x4d, 0xd5, 0x13, 0x3c, 0xe6, 0xc4, 0x3d, 0x11, - 0x58, 0x8c, 0xf9, 0x92, 0x34, 0xef, 0xc2, 0xd6, 0xcc, 0x6d, 0x40, 0xa2, 0x2c, 0xcb, 0xad, 0xaa, - 0x55, 0xcb, 0xdf, 0x07, 0x84, 0xa3, 0x2e, 0x54, 0xb0, 0x23, 0x7c, 0x46, 0x65, 0x5a, 0xb5, 0xf6, - 0xe7, 0xc6, 0x92, 0x7b, 0xcc, 0x88, 0x89, 0xe4, 0x39, 0x1c, 0xca, 0x60, 0x2b, 0x01, 0xd1, 0x3f, - 0x92, 0xe2, 0x29, 0xe0, 0x9b, 0x96, 0xe0, 0x5e, 0x1b, 0xd4, 0x22, 0x24, 0x54, 0x85, 0xf5, 0x27, - 0x87, 0xbd, 0x93, 0x47, 0xf5, 0x12, 0x7a, 0x0f, 0x36, 0x7a, 0xdf, 0xc7, 0x86, 0xd2, 0xfe, 0xaf, - 0x02, 0xe5, 0x2e, 0xf7, 0xd0, 0x1f, 0x0a, 0xdc, 0x2a, 0x1a, 0xd4, 0xfb, 0x4b, 0xc9, 0x17, 0xab, - 0x5a, 0xfb, 0xe6, 0x8a, 0x81, 0x59, 0x53, 0x7f, 0x53, 0x60, 0xfb, 0xa2, 0xe4, 0x3f, 0x59, 0x05, - 0x7b, 0x21, 0x44, 0xfb, 0xf2, 0x9d, 0x43, 0x32, 0x0e, 0x2f, 0x14, 0x68, 0x2c, 0xbc, 0x5a, 0x3f, - 0x5b, 0x85, 0xb9, 0x28, 0x4a, 0xfb, 0xea, 0x2a, 0x51, 0x19, 0x99, 0x97, 0x0a, 0xdc, 0x2c, 0xf8, - 0x0f, 0xfb, 0xe2, 0x72, 0xc0, 0xf3, 0x71, 0xda, 0x83, 0xab, 0xc5, 0x2d, 0xa0, 0x74, 0xe1, 0xbe, - 0xb8, 0x24, 0xa5, 0xf9, 0xb8, 0xcb, 0x52, 0x2a, 0xbc, 0x0b, 0x22, 0x31, 0x17, 0x0d, 0xf7, 0xfd, - 0x77, 0x48, 0x37, 0x1f, 0xb8, 0x5a, 0xcc, 0x2b, 0xc6, 0xf3, 0xe8, 0xf1, 0xab, 0xb3, 0xa6, 0xf2, - 0xfa, 0xac, 0xa9, 0xfc, 0x7b, 0xd6, 0x54, 0x5e, 0x9e, 0x37, 0x4b, 0xaf, 0xcf, 0x9b, 0xa5, 0xbf, - 0xcf, 0x9b, 0xa5, 0xa7, 0x66, 0xee, 0x75, 0x10, 0x41, 0xef, 0xcb, 0x53, 0xcc, 0xf4, 0x14, 0xf3, - 0x99, 0xf9, 0xf6, 0x61, 0x14, 0x3d, 0x15, 0xfa, 0x15, 0xf9, 0xa8, 0xf9, 0xf4, 0xff, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x16, 0xf6, 0xee, 0xe7, 0x31, 0x09, 0x00, 0x00, + // 899 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0x4b, 0x6f, 0xdb, 0x46, + 0x10, 0x16, 0xad, 0xf8, 0xa1, 0xa9, 0x2d, 0xcb, 0x5b, 0x21, 0x61, 0xe5, 0x42, 0x76, 0x98, 0x02, + 0x51, 0x03, 0x58, 0x74, 0xd5, 0x47, 0x50, 0xa0, 0x4d, 0x61, 0x2b, 0x31, 0x1a, 0x20, 0x6a, 0x03, + 0x3a, 0x46, 0xd1, 0x5c, 0x88, 0x15, 0xb9, 0xa6, 0x16, 0x15, 0xb9, 0x2c, 0x77, 0x55, 0x45, 0xb9, + 0xf5, 0x9a, 0x53, 0xd0, 0xfe, 0x8f, 0x02, 0x3d, 0xf4, 0x3f, 0xe4, 0x98, 0x63, 0xd1, 0x43, 0x50, + 0xd8, 0xff, 0xa3, 0x28, 0xb8, 0x7c, 0x84, 0x7a, 0x50, 0xb6, 0x9c, 0x93, 0x76, 0x56, 0x33, 0xdf, + 0x7e, 0xdf, 0xcc, 0xec, 0x70, 0x61, 0xeb, 0x74, 0xe0, 0x39, 0xb4, 0xdb, 0x27, 0xba, 0x78, 0xd6, + 0xf4, 0x03, 0x26, 0x18, 0xda, 0x7e, 0x4e, 0x04, 0xb6, 0x7a, 0x98, 0x7a, 0x4d, 0xb9, 0x62, 0x01, + 0x69, 0x26, 0x5e, 0xb5, 0xf7, 0x2d, 0xe6, 0xba, 0xcc, 0xd3, 0xa3, 0x9f, 0x28, 0xa2, 0x56, 0x75, + 0x98, 0xc3, 0xe4, 0x52, 0x0f, 0x57, 0xd1, 0xae, 0xf6, 0x97, 0x02, 0x1f, 0x74, 0xb8, 0x73, 0xe2, + 0xdb, 0x58, 0x90, 0xa7, 0x46, 0xbb, 0xb5, 0xff, 0x03, 0x15, 0x3d, 0x3b, 0xc0, 0xc3, 0x23, 0x42, + 0x90, 0x0a, 0xab, 0x56, 0x40, 0xb0, 0x60, 0x81, 0xaa, 0xec, 0x2a, 0x8d, 0x92, 0x91, 0x98, 0xe8, + 0x16, 0x6c, 0x3c, 0x0f, 0xac, 0xd6, 0xbe, 0x89, 0x6d, 0x3b, 0x20, 0x9c, 0xab, 0x4b, 0xf2, 0xff, + 0x75, 0xb9, 0x79, 0x10, 0xed, 0xa1, 0x1f, 0xa1, 0xe2, 0x91, 0xa1, 0x39, 0x8c, 0x11, 0xcd, 0x53, + 0x42, 0xd4, 0x95, 0xd0, 0xef, 0x50, 0x7f, 0xf5, 0x66, 0xa7, 0xf0, 0xcf, 0x9b, 0x9d, 0xdb, 0x0e, + 0x15, 0xbd, 0x41, 0xb7, 0x69, 0x31, 0x57, 0xb7, 0x18, 0x77, 0x19, 0x8f, 0x7f, 0xf6, 0xb8, 0xfd, + 0x93, 0x2e, 0x46, 0x3e, 0xe1, 0xcd, 0x13, 0xea, 0x09, 0xa3, 0xec, 0x91, 0x61, 0x86, 0x99, 0x76, + 0x0b, 0x6e, 0xe6, 0xd2, 0x36, 0x08, 0xf7, 0x99, 0xc7, 0x89, 0x16, 0xc0, 0x8d, 0xd4, 0xe9, 0x78, + 0xc4, 0x05, 0x71, 0xdb, 0xcc, 0x13, 0x01, 0xb6, 0xc4, 0x1c, 0x65, 0x5f, 0xc3, 0x76, 0x48, 0x9a, + 0x4b, 0x7f, 0xd3, 0x8a, 0x03, 0x26, 0x74, 0xaa, 0x1e, 0x19, 0x8e, 0x23, 0xc6, 0x9a, 0xb5, 0x9b, + 0xb0, 0x93, 0x73, 0x66, 0x4a, 0xeb, 0xc5, 0x12, 0xd4, 0x3a, 0xdc, 0xb9, 0x4f, 0xfc, 0x3e, 0x1b, + 0x1d, 0xc5, 0x45, 0x6b, 0x33, 0xea, 0x49, 0x21, 0x73, 0xa8, 0x55, 0x61, 0xf9, 0x41, 0xe8, 0x12, + 0x93, 0x88, 0x0c, 0xd4, 0x80, 0xca, 0x29, 0x0b, 0x08, 0x75, 0x3c, 0x53, 0x36, 0x84, 0x49, 0x6d, + 0xb5, 0xb8, 0xab, 0x34, 0x8a, 0x46, 0x39, 0xde, 0x6f, 0x87, 0xdb, 0x0f, 0x6d, 0x54, 0x83, 0x35, + 0x9b, 0x58, 0xd4, 0xc5, 0x7d, 0xae, 0x5e, 0xdb, 0x55, 0x1a, 0x1b, 0x46, 0x6a, 0x23, 0x04, 0xd7, + 0x3c, 0xec, 0x12, 0x75, 0x59, 0x42, 0xcb, 0x35, 0xba, 0x0e, 0x2b, 0x7c, 0xe4, 0x76, 0x59, 0x3f, + 0xaa, 0x9a, 0x11, 0x5b, 0x68, 0x0f, 0x4a, 0x16, 0xa3, 0x9e, 0x19, 0xd6, 0x47, 0x5d, 0xdd, 0x55, + 0x1a, 0xe5, 0x56, 0xa5, 0x19, 0x37, 0x5b, 0xa8, 0xe3, 0xc9, 0xc8, 0x27, 0xc6, 0x9a, 0x15, 0xaf, + 0xd0, 0x36, 0x94, 0x1c, 0xcc, 0xcd, 0x3e, 0x75, 0xa9, 0x50, 0xd7, 0x24, 0xb3, 0x35, 0x07, 0xf3, + 0x47, 0xa1, 0xad, 0xdd, 0x03, 0x2d, 0x3f, 0x17, 0x49, 0xca, 0xc2, 0x9c, 0x24, 0x05, 0x88, 0x73, + 0x12, 0x9b, 0xda, 0x7d, 0xa8, 0x76, 0xb8, 0x63, 0x10, 0x97, 0xfd, 0x42, 0x8e, 0x62, 0xb9, 0x8c, + 0x7a, 0x73, 0xb2, 0x98, 0x28, 0x5d, 0x7a, 0xab, 0x54, 0xab, 0xc3, 0x87, 0xb3, 0x50, 0xd2, 0x92, + 0xfd, 0x96, 0xbd, 0x26, 0x49, 0x41, 0x0f, 0x47, 0x82, 0x58, 0xcc, 0x9e, 0x77, 0x4d, 0x3e, 0x86, + 0x4a, 0x4e, 0x07, 0x6d, 0x5a, 0xe3, 0x8d, 0x83, 0xf6, 0xa1, 0x1a, 0xf6, 0x5d, 0x37, 0x06, 0x4d, + 0xdd, 0x8b, 0xd2, 0x1d, 0x79, 0x64, 0x98, 0x9c, 0x97, 0xb4, 0xda, 0xf7, 0x99, 0x3b, 0x30, 0xc9, + 0x29, 0xcd, 0xdc, 0x1d, 0xd8, 0x1a, 0x83, 0xed, 0x61, 0xde, 0x93, 0x2c, 0xd7, 0x8d, 0xcd, 0x0c, + 0xe6, 0xb7, 0x98, 0xf7, 0xb4, 0x3f, 0x14, 0xd9, 0x98, 0x99, 0x5b, 0xf5, 0x18, 0x0f, 0x38, 0xb1, + 0x8f, 0x05, 0x16, 0x03, 0x3e, 0x47, 0xe6, 0x6d, 0xd8, 0x1c, 0x9b, 0x06, 0x24, 0x54, 0x59, 0x6c, + 0x94, 0x8c, 0x72, 0x76, 0x1e, 0x10, 0x8e, 0x3a, 0xb0, 0x82, 0x2d, 0x41, 0x99, 0x27, 0x65, 0x95, + 0x5b, 0x9f, 0x37, 0xe7, 0xcc, 0xb1, 0x66, 0x44, 0x24, 0xcb, 0xe1, 0x40, 0x06, 0x1b, 0x31, 0x88, + 0xf6, 0x91, 0x6c, 0x9e, 0x1c, 0xbe, 0x69, 0xf1, 0xfe, 0x9c, 0x92, 0xf5, 0x88, 0xfe, 0x3c, 0xa0, + 0x36, 0x15, 0xa3, 0x36, 0xf6, 0xdf, 0x75, 0xc8, 0x3d, 0x81, 0x8d, 0x7e, 0x02, 0x67, 0x5a, 0xd8, + 0x8f, 0x0a, 0xb6, 0xf8, 0x84, 0x5b, 0xef, 0x67, 0x48, 0x4d, 0x2b, 0xcb, 0x52, 0x4e, 0x94, 0xdd, + 0x69, 0x81, 0x9a, 0x97, 0x23, 0x54, 0x82, 0xe5, 0xc7, 0x07, 0x27, 0xc7, 0x0f, 0x2a, 0x05, 0xf4, + 0x1e, 0xac, 0x9e, 0x7c, 0x17, 0x19, 0x4a, 0xeb, 0xbf, 0x55, 0x28, 0x76, 0xb8, 0x83, 0x7e, 0x57, + 0xe0, 0x46, 0xde, 0x08, 0xba, 0x3b, 0xb7, 0x2c, 0xf9, 0xf7, 0xb5, 0xf6, 0xcd, 0x15, 0x03, 0xd3, + 0x76, 0xfd, 0x55, 0x81, 0xad, 0xe9, 0xcb, 0xfc, 0xc9, 0x45, 0xb0, 0x53, 0x21, 0xb5, 0x2f, 0x17, + 0x0e, 0x49, 0x39, 0xbc, 0x50, 0xa0, 0x3a, 0xf3, 0xa3, 0xf1, 0xd9, 0x45, 0x98, 0xb3, 0xa2, 0x6a, + 0x5f, 0x5d, 0x25, 0x2a, 0x25, 0xf3, 0x52, 0x81, 0xeb, 0x39, 0x63, 0xe7, 0x8b, 0xcb, 0x01, 0x4f, + 0xc6, 0xd5, 0xee, 0x5d, 0x2d, 0x6e, 0x06, 0xa5, 0xa9, 0x07, 0xc3, 0x25, 0x29, 0x4d, 0xc6, 0x5d, + 0x96, 0x52, 0xde, 0x97, 0x5e, 0x36, 0x73, 0xde, 0xd8, 0xba, 0xbb, 0x00, 0x76, 0x36, 0xf0, 0xe2, + 0x66, 0xbe, 0x60, 0xf0, 0x4c, 0xb2, 0x1a, 0x9b, 0x3a, 0x8b, 0xb0, 0xca, 0x06, 0x2e, 0xc4, 0x6a, + 0xd6, 0xd0, 0x38, 0x7c, 0xf8, 0xea, 0xac, 0xae, 0xbc, 0x3e, 0xab, 0x2b, 0xff, 0x9e, 0xd5, 0x95, + 0x97, 0xe7, 0xf5, 0xc2, 0xeb, 0xf3, 0x7a, 0xe1, 0xef, 0xf3, 0x7a, 0xe1, 0xa9, 0x9e, 0x99, 0x55, + 0x21, 0xf4, 0x9e, 0x3c, 0x45, 0x4f, 0x4e, 0xd1, 0x9f, 0xe9, 0x6f, 0x1f, 0xa2, 0xe1, 0xe0, 0xea, + 0xae, 0xc8, 0x47, 0xe4, 0xa7, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0x62, 0x38, 0xf4, 0x5f, 0xa1, + 0x0a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -755,9 +850,10 @@ type MsgClient interface { DeployFungibleCoinZRC20(ctx context.Context, in *MsgDeployFungibleCoinZRC20, opts ...grpc.CallOption) (*MsgDeployFungibleCoinZRC20Response, error) RemoveForeignCoin(ctx context.Context, in *MsgRemoveForeignCoin, opts ...grpc.CallOption) (*MsgRemoveForeignCoinResponse, error) UpdateSystemContract(ctx context.Context, in *MsgUpdateSystemContract, opts ...grpc.CallOption) (*MsgUpdateSystemContractResponse, error) - UpdateZRC20WithdrawFee(ctx context.Context, in *MsgUpdateZRC20WithdrawFee, opts ...grpc.CallOption) (*MsgUpdateZRC20WithdrawFeeResponse, error) UpdateContractBytecode(ctx context.Context, in *MsgUpdateContractBytecode, opts ...grpc.CallOption) (*MsgUpdateContractBytecodeResponse, error) + UpdateZRC20WithdrawFee(ctx context.Context, in *MsgUpdateZRC20WithdrawFee, opts ...grpc.CallOption) (*MsgUpdateZRC20WithdrawFeeResponse, error) UpdateZRC20PausedStatus(ctx context.Context, in *MsgUpdateZRC20PausedStatus, opts ...grpc.CallOption) (*MsgUpdateZRC20PausedStatusResponse, error) + UpdateZRC20LiquidityCap(ctx context.Context, in *MsgUpdateZRC20LiquidityCap, opts ...grpc.CallOption) (*MsgUpdateZRC20LiquidityCapResponse, error) } type msgClient struct { @@ -795,18 +891,18 @@ func (c *msgClient) UpdateSystemContract(ctx context.Context, in *MsgUpdateSyste return out, nil } -func (c *msgClient) UpdateZRC20WithdrawFee(ctx context.Context, in *MsgUpdateZRC20WithdrawFee, opts ...grpc.CallOption) (*MsgUpdateZRC20WithdrawFeeResponse, error) { - out := new(MsgUpdateZRC20WithdrawFeeResponse) - err := c.cc.Invoke(ctx, "/zetachain.zetacore.fungible.Msg/UpdateZRC20WithdrawFee", in, out, opts...) +func (c *msgClient) UpdateContractBytecode(ctx context.Context, in *MsgUpdateContractBytecode, opts ...grpc.CallOption) (*MsgUpdateContractBytecodeResponse, error) { + out := new(MsgUpdateContractBytecodeResponse) + err := c.cc.Invoke(ctx, "/zetachain.zetacore.fungible.Msg/UpdateContractBytecode", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *msgClient) UpdateContractBytecode(ctx context.Context, in *MsgUpdateContractBytecode, opts ...grpc.CallOption) (*MsgUpdateContractBytecodeResponse, error) { - out := new(MsgUpdateContractBytecodeResponse) - err := c.cc.Invoke(ctx, "/zetachain.zetacore.fungible.Msg/UpdateContractBytecode", in, out, opts...) +func (c *msgClient) UpdateZRC20WithdrawFee(ctx context.Context, in *MsgUpdateZRC20WithdrawFee, opts ...grpc.CallOption) (*MsgUpdateZRC20WithdrawFeeResponse, error) { + out := new(MsgUpdateZRC20WithdrawFeeResponse) + err := c.cc.Invoke(ctx, "/zetachain.zetacore.fungible.Msg/UpdateZRC20WithdrawFee", in, out, opts...) if err != nil { return nil, err } @@ -822,14 +918,24 @@ func (c *msgClient) UpdateZRC20PausedStatus(ctx context.Context, in *MsgUpdateZR return out, nil } +func (c *msgClient) UpdateZRC20LiquidityCap(ctx context.Context, in *MsgUpdateZRC20LiquidityCap, opts ...grpc.CallOption) (*MsgUpdateZRC20LiquidityCapResponse, error) { + out := new(MsgUpdateZRC20LiquidityCapResponse) + err := c.cc.Invoke(ctx, "/zetachain.zetacore.fungible.Msg/UpdateZRC20LiquidityCap", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { DeployFungibleCoinZRC20(context.Context, *MsgDeployFungibleCoinZRC20) (*MsgDeployFungibleCoinZRC20Response, error) RemoveForeignCoin(context.Context, *MsgRemoveForeignCoin) (*MsgRemoveForeignCoinResponse, error) UpdateSystemContract(context.Context, *MsgUpdateSystemContract) (*MsgUpdateSystemContractResponse, error) - UpdateZRC20WithdrawFee(context.Context, *MsgUpdateZRC20WithdrawFee) (*MsgUpdateZRC20WithdrawFeeResponse, error) UpdateContractBytecode(context.Context, *MsgUpdateContractBytecode) (*MsgUpdateContractBytecodeResponse, error) + UpdateZRC20WithdrawFee(context.Context, *MsgUpdateZRC20WithdrawFee) (*MsgUpdateZRC20WithdrawFeeResponse, error) UpdateZRC20PausedStatus(context.Context, *MsgUpdateZRC20PausedStatus) (*MsgUpdateZRC20PausedStatusResponse, error) + UpdateZRC20LiquidityCap(context.Context, *MsgUpdateZRC20LiquidityCap) (*MsgUpdateZRC20LiquidityCapResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -845,15 +951,18 @@ func (*UnimplementedMsgServer) RemoveForeignCoin(ctx context.Context, req *MsgRe func (*UnimplementedMsgServer) UpdateSystemContract(ctx context.Context, req *MsgUpdateSystemContract) (*MsgUpdateSystemContractResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateSystemContract not implemented") } -func (*UnimplementedMsgServer) UpdateZRC20WithdrawFee(ctx context.Context, req *MsgUpdateZRC20WithdrawFee) (*MsgUpdateZRC20WithdrawFeeResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateZRC20WithdrawFee not implemented") -} func (*UnimplementedMsgServer) UpdateContractBytecode(ctx context.Context, req *MsgUpdateContractBytecode) (*MsgUpdateContractBytecodeResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateContractBytecode not implemented") } +func (*UnimplementedMsgServer) UpdateZRC20WithdrawFee(ctx context.Context, req *MsgUpdateZRC20WithdrawFee) (*MsgUpdateZRC20WithdrawFeeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateZRC20WithdrawFee not implemented") +} func (*UnimplementedMsgServer) UpdateZRC20PausedStatus(ctx context.Context, req *MsgUpdateZRC20PausedStatus) (*MsgUpdateZRC20PausedStatusResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateZRC20PausedStatus not implemented") } +func (*UnimplementedMsgServer) UpdateZRC20LiquidityCap(ctx context.Context, req *MsgUpdateZRC20LiquidityCap) (*MsgUpdateZRC20LiquidityCapResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateZRC20LiquidityCap not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -913,38 +1022,38 @@ func _Msg_UpdateSystemContract_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } -func _Msg_UpdateZRC20WithdrawFee_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgUpdateZRC20WithdrawFee) +func _Msg_UpdateContractBytecode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateContractBytecode) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MsgServer).UpdateZRC20WithdrawFee(ctx, in) + return srv.(MsgServer).UpdateContractBytecode(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/zetachain.zetacore.fungible.Msg/UpdateZRC20WithdrawFee", + FullMethod: "/zetachain.zetacore.fungible.Msg/UpdateContractBytecode", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).UpdateZRC20WithdrawFee(ctx, req.(*MsgUpdateZRC20WithdrawFee)) + return srv.(MsgServer).UpdateContractBytecode(ctx, req.(*MsgUpdateContractBytecode)) } return interceptor(ctx, in, info, handler) } -func _Msg_UpdateContractBytecode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgUpdateContractBytecode) +func _Msg_UpdateZRC20WithdrawFee_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateZRC20WithdrawFee) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MsgServer).UpdateContractBytecode(ctx, in) + return srv.(MsgServer).UpdateZRC20WithdrawFee(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/zetachain.zetacore.fungible.Msg/UpdateContractBytecode", + FullMethod: "/zetachain.zetacore.fungible.Msg/UpdateZRC20WithdrawFee", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).UpdateContractBytecode(ctx, req.(*MsgUpdateContractBytecode)) + return srv.(MsgServer).UpdateZRC20WithdrawFee(ctx, req.(*MsgUpdateZRC20WithdrawFee)) } return interceptor(ctx, in, info, handler) } @@ -967,6 +1076,24 @@ func _Msg_UpdateZRC20PausedStatus_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _Msg_UpdateZRC20LiquidityCap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateZRC20LiquidityCap) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateZRC20LiquidityCap(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zetachain.zetacore.fungible.Msg/UpdateZRC20LiquidityCap", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateZRC20LiquidityCap(ctx, req.(*MsgUpdateZRC20LiquidityCap)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "zetachain.zetacore.fungible.Msg", HandlerType: (*MsgServer)(nil), @@ -983,18 +1110,22 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "UpdateSystemContract", Handler: _Msg_UpdateSystemContract_Handler, }, - { - MethodName: "UpdateZRC20WithdrawFee", - Handler: _Msg_UpdateZRC20WithdrawFee_Handler, - }, { MethodName: "UpdateContractBytecode", Handler: _Msg_UpdateContractBytecode_Handler, }, + { + MethodName: "UpdateZRC20WithdrawFee", + Handler: _Msg_UpdateZRC20WithdrawFee_Handler, + }, { MethodName: "UpdateZRC20PausedStatus", Handler: _Msg_UpdateZRC20PausedStatus_Handler, }, + { + MethodName: "UpdateZRC20LiquidityCap", + Handler: _Msg_UpdateZRC20LiquidityCap_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "fungible/tx.proto", @@ -1432,6 +1563,76 @@ func (m *MsgUpdateZRC20PausedStatusResponse) MarshalToSizedBuffer(dAtA []byte) ( return len(dAtA) - i, nil } +func (m *MsgUpdateZRC20LiquidityCap) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgUpdateZRC20LiquidityCap) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateZRC20LiquidityCap) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.LiquidityCap.Size() + i -= size + if _, err := m.LiquidityCap.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Zrc20Address) > 0 { + i -= len(m.Zrc20Address) + copy(dAtA[i:], m.Zrc20Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Zrc20Address))) + i-- + dAtA[i] = 0x12 + } + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintTx(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateZRC20LiquidityCapResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgUpdateZRC20LiquidityCapResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateZRC20LiquidityCapResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -1638,6 +1839,34 @@ func (m *MsgUpdateZRC20PausedStatusResponse) Size() (n int) { return n } +func (m *MsgUpdateZRC20LiquidityCap) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Zrc20Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.LiquidityCap.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateZRC20LiquidityCapResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -2919,6 +3148,204 @@ func (m *MsgUpdateZRC20PausedStatusResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgUpdateZRC20LiquidityCap) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateZRC20LiquidityCap: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateZRC20LiquidityCap: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Zrc20Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Zrc20Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LiquidityCap", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LiquidityCap.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateZRC20LiquidityCapResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateZRC20LiquidityCapResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateZRC20LiquidityCapResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0