diff --git a/docs/openapi/openapi.swagger.yaml b/docs/openapi/openapi.swagger.yaml index e658cefb3b..8e2cb02f21 100644 --- a/docs/openapi/openapi.swagger.yaml +++ b/docs/openapi/openapi.swagger.yaml @@ -53657,11 +53657,6 @@ definitions: items: type: object $ref: '#/definitions/crosschainOutboundTxParams' - event_index: - type: string - format: uint64 - coin_type: - $ref: '#/definitions/commonCoinType' crosschainGasPrice: type: object properties: @@ -53720,6 +53715,8 @@ definitions: tx_origin: type: string title: this address is the EOA that signs the inbound tx + coin_type: + $ref: '#/definitions/commonCoinType' asset: type: string title: for ERC20 coin type, the asset is an address of the ERC20 contract @@ -53810,6 +53807,8 @@ definitions: receiver_chainId: type: string format: int64 + coin_type: + $ref: '#/definitions/commonCoinType' amount: type: string outbound_tx_tss_nonce: diff --git a/proto/crosschain/cross_chain_tx.proto b/proto/crosschain/cross_chain_tx.proto index 3f6557594e..166803f6b8 100644 --- a/proto/crosschain/cross_chain_tx.proto +++ b/proto/crosschain/cross_chain_tx.proto @@ -27,6 +27,7 @@ message InboundTxParams { string sender = 1; // this address is the immediate contract/EOA that calls the Connector.send() int64 sender_chain_id = 2; string tx_origin = 3; // this address is the EOA that signs the inbound tx + common.CoinType coin_type = 4; string asset = 5; // for ERC20 coin type, the asset is an address of the ERC20 contract string amount = 6 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Uint", @@ -50,6 +51,7 @@ message ZetaAccounting { message OutboundTxParams { string receiver = 1; int64 receiver_chainId = 2; + common.CoinType coin_type = 3; string amount = 4 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Uint", (gogoproto.nullable) = false @@ -91,6 +93,4 @@ message CrossChainTx { Status cctx_status = 8; InboundTxParams inbound_tx_params = 9; repeated OutboundTxParams outbound_tx_params = 10; - uint64 event_index = 11; - common.CoinType coin_type = 12; } diff --git a/proto/crosschain/cross_chain_tx_v14.proto b/proto/crosschain/cross_chain_tx_v14.proto deleted file mode 100644 index 255ddb3d42..0000000000 --- a/proto/crosschain/cross_chain_tx_v14.proto +++ /dev/null @@ -1,65 +0,0 @@ -syntax = "proto3"; -package zetachain.zetacore.crosschain; - -import "common/common.proto"; -import "crosschain/cross_chain_tx.proto"; -import "gogoproto/gogo.proto"; - -option go_package = "github.com/zeta-chain/zetacore/x/crosschain/types"; - -message InboundTxParamsV14 { - string sender = 1; // this address is the immediate contract/EOA that calls the Connector.send() - int64 sender_chain_id = 2; - string tx_origin = 3; // this address is the EOA that signs the inbound tx - common.CoinType coin_type = 4; - string asset = 5; // for ERC20 coin type, the asset is an address of the ERC20 contract - string amount = 6 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Uint", - (gogoproto.nullable) = false - ]; - string inbound_tx_observed_hash = 7; - uint64 inbound_tx_observed_external_height = 8; - string inbound_tx_ballot_index = 9; - uint64 inbound_tx_finalized_zeta_height = 10; - TxFinalizationStatus tx_finalization_status = 11; -} - -message OutboundTxParamsV14 { - string receiver = 1; - int64 receiver_chainId = 2; - common.CoinType coin_type = 3; - string amount = 4 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Uint", - (gogoproto.nullable) = false - ]; - uint64 outbound_tx_tss_nonce = 5; - uint64 outbound_tx_gas_limit = 6; - string outbound_tx_gas_price = 7; - // the above are commands for zetaclients - // the following fields are used when the outbound tx is mined - string outbound_tx_hash = 8; - string outbound_tx_ballot_index = 9; - uint64 outbound_tx_observed_external_height = 10; - uint64 outbound_tx_gas_used = 20; - string outbound_tx_effective_gas_price = 21 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", - (gogoproto.nullable) = false - ]; - uint64 outbound_tx_effective_gas_limit = 22; - string tss_pubkey = 11; - TxFinalizationStatus tx_finalization_status = 12; -} - -message CrossChainTxV14 { - string creator = 1; - string index = 2; - string zeta_fees = 5 [ - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Uint", - (gogoproto.nullable) = false, - (gogoproto.moretags) = "yaml:\"zeta_fees\"" - ]; - string relayed_message = 6; // Not used by protocol , just relayed across - Status cctx_status = 8; - InboundTxParamsV14 inbound_tx_params = 9; - repeated OutboundTxParamsV14 outbound_tx_params = 10; -} diff --git a/testutil/sample/crosschain.go b/testutil/sample/crosschain.go index e705f6cddb..8daa3001c2 100644 --- a/testutil/sample/crosschain.go +++ b/testutil/sample/crosschain.go @@ -48,6 +48,7 @@ func InboundTxParams(r *rand.Rand) *types.InboundTxParams { InboundTxObservedExternalHeight: r.Uint64(), InboundTxBallotIndex: StringRandom(r, 32), InboundTxFinalizedZetaHeight: r.Uint64(), + CoinType: common.CoinType(r.Intn(100)), } } @@ -78,6 +79,7 @@ func OutboundTxParams(r *rand.Rand) *types.OutboundTxParams { OutboundTxObservedExternalHeight: r.Uint64(), OutboundTxGasUsed: r.Uint64(), OutboundTxEffectiveGasPrice: math.NewInt(r.Int63()), + CoinType: common.CoinType(r.Intn(100)), } } @@ -117,13 +119,11 @@ func CrossChainTx(t *testing.T, index string) *types.CrossChainTx { return &types.CrossChainTx{ Creator: AccAddress(), Index: GetCctxIndexFromString(index), - CoinType: common.CoinType(r.Intn(100)), ZetaFees: math.NewUint(uint64(r.Int63())), RelayedMessage: StringRandom(r, 32), CctxStatus: Status(t, index), InboundTxParams: InboundTxParams(r), OutboundTxParams: []*types.OutboundTxParams{OutboundTxParams(r), OutboundTxParams(r)}, - EventIndex: r.Uint64(), } } diff --git a/testutil/sample/crosschain_legacy.go b/testutil/sample/crosschain_legacy.go deleted file mode 100644 index f32f7caa58..0000000000 --- a/testutil/sample/crosschain_legacy.go +++ /dev/null @@ -1,56 +0,0 @@ -package sample - -import ( - "math/rand" - "testing" - - "cosmossdk.io/math" - "github.com/zeta-chain/zetacore/common" - "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -func CrossChainTxV14(t *testing.T, index string) *types.CrossChainTxV14 { - r := newRandFromStringSeed(t, index) - cointType := common.CoinType(r.Intn(100)) - return &types.CrossChainTxV14{ - Creator: AccAddress(), - Index: GetCctxIndexFromString(index), - ZetaFees: math.NewUint(uint64(r.Int63())), - RelayedMessage: StringRandom(r, 32), - CctxStatus: Status(t, index), - InboundTxParams: InboundTxParamsV14(r, cointType), - OutboundTxParams: []*types.OutboundTxParamsV14{OutboundTxParamsV14(r, cointType), OutboundTxParamsV14(r, cointType)}, - } -} - -func InboundTxParamsV14(r *rand.Rand, coinType common.CoinType) *types.InboundTxParamsV14 { - return &types.InboundTxParamsV14{ - Sender: EthAddress().String(), - SenderChainId: r.Int63(), - TxOrigin: EthAddress().String(), - Asset: StringRandom(r, 32), - Amount: math.NewUint(uint64(r.Int63())), - InboundTxObservedHash: StringRandom(r, 32), - InboundTxObservedExternalHeight: r.Uint64(), - InboundTxBallotIndex: StringRandom(r, 32), - InboundTxFinalizedZetaHeight: r.Uint64(), - CoinType: coinType, - } -} - -func OutboundTxParamsV14(r *rand.Rand, coinType common.CoinType) *types.OutboundTxParamsV14 { - return &types.OutboundTxParamsV14{ - Receiver: EthAddress().String(), - ReceiverChainId: r.Int63(), - Amount: math.NewUint(uint64(r.Int63())), - OutboundTxTssNonce: r.Uint64(), - OutboundTxGasLimit: r.Uint64(), - OutboundTxGasPrice: math.NewUint(uint64(r.Int63())).String(), - OutboundTxHash: StringRandom(r, 32), - OutboundTxBallotIndex: StringRandom(r, 32), - OutboundTxObservedExternalHeight: r.Uint64(), - OutboundTxGasUsed: r.Uint64(), - OutboundTxEffectiveGasPrice: math.NewInt(r.Int63()), - CoinType: coinType, - } -} diff --git a/typescript/crosschain/cross_chain_tx_pb.d.ts b/typescript/crosschain/cross_chain_tx_pb.d.ts index a370b8a079..0157548d54 100644 --- a/typescript/crosschain/cross_chain_tx_pb.d.ts +++ b/typescript/crosschain/cross_chain_tx_pb.d.ts @@ -103,6 +103,11 @@ export declare class InboundTxParams extends Message { */ txOrigin: string; + /** + * @generated from field: common.CoinType coin_type = 4; + */ + coinType: CoinType; + /** * for ERC20 coin type, the asset is an address of the ERC20 contract * @@ -195,6 +200,11 @@ export declare class OutboundTxParams extends Message { */ receiverChainId: bigint; + /** + * @generated from field: common.CoinType coin_type = 3; + */ + coinType: CoinType; + /** * @generated from field: string amount = 4; */ @@ -353,16 +363,6 @@ export declare class CrossChainTx extends Message { */ outboundTxParams: OutboundTxParams[]; - /** - * @generated from field: uint64 event_index = 11; - */ - eventIndex: bigint; - - /** - * @generated from field: common.CoinType coin_type = 12; - */ - coinType: CoinType; - constructor(data?: PartialMessage); static readonly runtime: typeof proto3; diff --git a/typescript/crosschain/cross_chain_tx_v14_pb.d.ts b/typescript/crosschain/cross_chain_tx_v14_pb.d.ts deleted file mode 100644 index 7f47395c89..0000000000 --- a/typescript/crosschain/cross_chain_tx_v14_pb.d.ts +++ /dev/null @@ -1,243 +0,0 @@ -// @generated by protoc-gen-es v1.3.0 with parameter "target=dts" -// @generated from file crosschain/cross_chain_tx_v14.proto (package zetachain.zetacore.crosschain, syntax proto3) -/* eslint-disable */ -// @ts-nocheck - -import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; -import { Message, proto3 } from "@bufbuild/protobuf"; -import type { CoinType } from "../common/common_pb.js"; -import type { Status, TxFinalizationStatus } from "./cross_chain_tx_pb.js"; - -/** - * @generated from message zetachain.zetacore.crosschain.InboundTxParamsV14 - */ -export declare class InboundTxParamsV14 extends Message { - /** - * this address is the immediate contract/EOA that calls the Connector.send() - * - * @generated from field: string sender = 1; - */ - sender: string; - - /** - * @generated from field: int64 sender_chain_id = 2; - */ - senderChainId: bigint; - - /** - * this address is the EOA that signs the inbound tx - * - * @generated from field: string tx_origin = 3; - */ - txOrigin: string; - - /** - * @generated from field: common.CoinType coin_type = 4; - */ - coinType: CoinType; - - /** - * for ERC20 coin type, the asset is an address of the ERC20 contract - * - * @generated from field: string asset = 5; - */ - asset: string; - - /** - * @generated from field: string amount = 6; - */ - amount: string; - - /** - * @generated from field: string inbound_tx_observed_hash = 7; - */ - inboundTxObservedHash: string; - - /** - * @generated from field: uint64 inbound_tx_observed_external_height = 8; - */ - inboundTxObservedExternalHeight: bigint; - - /** - * @generated from field: string inbound_tx_ballot_index = 9; - */ - inboundTxBallotIndex: string; - - /** - * @generated from field: uint64 inbound_tx_finalized_zeta_height = 10; - */ - inboundTxFinalizedZetaHeight: bigint; - - /** - * @generated from field: zetachain.zetacore.crosschain.TxFinalizationStatus tx_finalization_status = 11; - */ - txFinalizationStatus: TxFinalizationStatus; - - constructor(data?: PartialMessage); - - static readonly runtime: typeof proto3; - static readonly typeName = "zetachain.zetacore.crosschain.InboundTxParamsV14"; - static readonly fields: FieldList; - - static fromBinary(bytes: Uint8Array, options?: Partial): InboundTxParamsV14; - - static fromJson(jsonValue: JsonValue, options?: Partial): InboundTxParamsV14; - - static fromJsonString(jsonString: string, options?: Partial): InboundTxParamsV14; - - static equals(a: InboundTxParamsV14 | PlainMessage | undefined, b: InboundTxParamsV14 | PlainMessage | undefined): boolean; -} - -/** - * @generated from message zetachain.zetacore.crosschain.OutboundTxParamsV14 - */ -export declare class OutboundTxParamsV14 extends Message { - /** - * @generated from field: string receiver = 1; - */ - receiver: string; - - /** - * @generated from field: int64 receiver_chainId = 2; - */ - receiverChainId: bigint; - - /** - * @generated from field: common.CoinType coin_type = 3; - */ - coinType: CoinType; - - /** - * @generated from field: string amount = 4; - */ - amount: string; - - /** - * @generated from field: uint64 outbound_tx_tss_nonce = 5; - */ - outboundTxTssNonce: bigint; - - /** - * @generated from field: uint64 outbound_tx_gas_limit = 6; - */ - outboundTxGasLimit: bigint; - - /** - * @generated from field: string outbound_tx_gas_price = 7; - */ - outboundTxGasPrice: string; - - /** - * the above are commands for zetaclients - * the following fields are used when the outbound tx is mined - * - * @generated from field: string outbound_tx_hash = 8; - */ - outboundTxHash: string; - - /** - * @generated from field: string outbound_tx_ballot_index = 9; - */ - outboundTxBallotIndex: string; - - /** - * @generated from field: uint64 outbound_tx_observed_external_height = 10; - */ - outboundTxObservedExternalHeight: bigint; - - /** - * @generated from field: uint64 outbound_tx_gas_used = 20; - */ - outboundTxGasUsed: bigint; - - /** - * @generated from field: string outbound_tx_effective_gas_price = 21; - */ - outboundTxEffectiveGasPrice: string; - - /** - * @generated from field: uint64 outbound_tx_effective_gas_limit = 22; - */ - outboundTxEffectiveGasLimit: bigint; - - /** - * @generated from field: string tss_pubkey = 11; - */ - tssPubkey: string; - - /** - * @generated from field: zetachain.zetacore.crosschain.TxFinalizationStatus tx_finalization_status = 12; - */ - txFinalizationStatus: TxFinalizationStatus; - - constructor(data?: PartialMessage); - - static readonly runtime: typeof proto3; - static readonly typeName = "zetachain.zetacore.crosschain.OutboundTxParamsV14"; - static readonly fields: FieldList; - - static fromBinary(bytes: Uint8Array, options?: Partial): OutboundTxParamsV14; - - static fromJson(jsonValue: JsonValue, options?: Partial): OutboundTxParamsV14; - - static fromJsonString(jsonString: string, options?: Partial): OutboundTxParamsV14; - - static equals(a: OutboundTxParamsV14 | PlainMessage | undefined, b: OutboundTxParamsV14 | PlainMessage | undefined): boolean; -} - -/** - * @generated from message zetachain.zetacore.crosschain.CrossChainTxV14 - */ -export declare class CrossChainTxV14 extends Message { - /** - * @generated from field: string creator = 1; - */ - creator: string; - - /** - * @generated from field: string index = 2; - */ - index: string; - - /** - * @generated from field: string zeta_fees = 5; - */ - zetaFees: string; - - /** - * Not used by protocol , just relayed across - * - * @generated from field: string relayed_message = 6; - */ - relayedMessage: string; - - /** - * @generated from field: zetachain.zetacore.crosschain.Status cctx_status = 8; - */ - cctxStatus?: Status; - - /** - * @generated from field: zetachain.zetacore.crosschain.InboundTxParamsV14 inbound_tx_params = 9; - */ - inboundTxParams?: InboundTxParamsV14; - - /** - * @generated from field: repeated zetachain.zetacore.crosschain.OutboundTxParamsV14 outbound_tx_params = 10; - */ - outboundTxParams: OutboundTxParamsV14[]; - - constructor(data?: PartialMessage); - - static readonly runtime: typeof proto3; - static readonly typeName = "zetachain.zetacore.crosschain.CrossChainTxV14"; - static readonly fields: FieldList; - - static fromBinary(bytes: Uint8Array, options?: Partial): CrossChainTxV14; - - static fromJson(jsonValue: JsonValue, options?: Partial): CrossChainTxV14; - - static fromJsonString(jsonString: string, options?: Partial): CrossChainTxV14; - - static equals(a: CrossChainTxV14 | PlainMessage | undefined, b: CrossChainTxV14 | PlainMessage | undefined): boolean; -} - diff --git a/typescript/crosschain/index.d.ts b/typescript/crosschain/index.d.ts index f5fb4873df..4c073541bc 100644 --- a/typescript/crosschain/index.d.ts +++ b/typescript/crosschain/index.d.ts @@ -1,5 +1,4 @@ export * from "./cross_chain_tx_pb"; -export * from "./cross_chain_tx_v14_pb"; export * from "./events_pb"; export * from "./gas_price_pb"; export * from "./genesis_pb"; diff --git a/x/crosschain/keeper/cctx.go b/x/crosschain/keeper/cctx.go index 7411d787fd..29fda96f00 100644 --- a/x/crosschain/keeper/cctx.go +++ b/x/crosschain/keeper/cctx.go @@ -47,7 +47,7 @@ func (k Keeper) SetCctxAndNonceToCctxAndInTxHashToCctx(ctx sdk.Context, cctx typ Tss: tss.TssPubkey, }) } - if cctx.CctxStatus.Status == types.CctxStatus_Aborted && cctx.CoinType == common.CoinType_Zeta { + if cctx.CctxStatus.Status == types.CctxStatus_Aborted && cctx.InboundTxParams.CoinType == common.CoinType_Zeta { k.AddZetaAbortedAmount(ctx, GetAbortedAmount(cctx)) } } diff --git a/x/crosschain/keeper/cctx_test.go b/x/crosschain/keeper/cctx_test.go index bf98fc1d30..5e057cb833 100644 --- a/x/crosschain/keeper/cctx_test.go +++ b/x/crosschain/keeper/cctx_test.go @@ -51,6 +51,7 @@ func createNCctx(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.CrossCha InboundTxObservedHash: fmt.Sprintf("%d", i), InboundTxObservedExternalHeight: uint64(i), InboundTxFinalizedZetaHeight: uint64(i), + CoinType: common.CoinType_Zeta, } items[i].OutboundTxParams = []*types.OutboundTxParams{{ Receiver: fmt.Sprintf("%d", i), @@ -61,6 +62,7 @@ func createNCctx(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.CrossCha OutboundTxGasPrice: fmt.Sprintf("%d", i), OutboundTxBallotIndex: fmt.Sprintf("%d", i), OutboundTxObservedExternalHeight: uint64(i), + CoinType: common.CoinType_Zeta, }} items[i].CctxStatus = &types.Status{ Status: types.CctxStatus_PendingInbound, @@ -71,7 +73,7 @@ func createNCctx(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.CrossCha items[i].ZetaFees = math.OneUint() items[i].Index = fmt.Sprintf("%d", i) - items[i].CoinType = common.CoinType_Zeta + keeper.SetCctxAndNonceToCctxAndInTxHashToCctx(ctx, items[i]) } return items diff --git a/x/crosschain/keeper/cctx_utils.go b/x/crosschain/keeper/cctx_utils.go index 381b7a9b7e..190574dcfb 100644 --- a/x/crosschain/keeper/cctx_utils.go +++ b/x/crosschain/keeper/cctx_utils.go @@ -15,73 +15,6 @@ import ( zetaObserverTypes "github.com/zeta-chain/zetacore/x/observer/types" ) -func (k Keeper) GetInbound(ctx sdk.Context, msg *types.MsgVoteOnObservedInboundTx) types.CrossChainTx { - - // get the latest TSS to set the TSS public key in the CCTX - tssPub := "" - tss, tssFound := k.zetaObserverKeeper.GetTSS(ctx) - if tssFound { - tssPub = tss.TssPubkey - } - return CreateNewCCTX(ctx, msg, msg.Digest(), tssPub, types.CctxStatus_PendingInbound, msg.SenderChainId, msg.ReceiverChain) -} - -func CreateNewCCTX( - ctx sdk.Context, - msg *types.MsgVoteOnObservedInboundTx, - index string, - tssPubkey string, - s types.CctxStatus, - senderChainID, - receiverChainID int64, -) types.CrossChainTx { - if msg.TxOrigin == "" { - msg.TxOrigin = msg.Sender - } - inboundParams := &types.InboundTxParams{ - Sender: msg.Sender, - SenderChainId: senderChainID, - TxOrigin: msg.TxOrigin, - Asset: msg.Asset, - Amount: msg.Amount, - InboundTxObservedHash: msg.InTxHash, - InboundTxObservedExternalHeight: msg.InBlockHeight, - InboundTxFinalizedZetaHeight: 0, - InboundTxBallotIndex: index, - } - - outBoundParams := &types.OutboundTxParams{ - Receiver: msg.Receiver, - ReceiverChainId: receiverChainID, - OutboundTxHash: "", - OutboundTxTssNonce: 0, - OutboundTxGasLimit: msg.GasLimit, - OutboundTxGasPrice: "", - OutboundTxBallotIndex: "", - OutboundTxObservedExternalHeight: 0, - Amount: sdkmath.ZeroUint(), - TssPubkey: tssPubkey, - } - status := &types.Status{ - Status: s, - StatusMessage: "", - LastUpdateTimestamp: ctx.BlockHeader().Time.Unix(), - IsAbortRefunded: false, - } - newCctx := types.CrossChainTx{ - Creator: msg.Creator, - Index: index, - ZetaFees: sdkmath.ZeroUint(), - RelayedMessage: msg.Message, - CctxStatus: status, - InboundTxParams: inboundParams, - OutboundTxParams: []*types.OutboundTxParams{outBoundParams}, - EventIndex: msg.EventIndex, - CoinType: msg.CoinType, - } - return newCctx -} - // UpdateNonce sets the CCTX outbound nonce to the next nonce, and updates the nonce of blockchain state. // It also updates the PendingNonces that is used to track the unfulfilled outbound txs. func (k Keeper) UpdateNonce(ctx sdk.Context, receiveChainID int64, cctx *types.CrossChainTx) error { @@ -126,7 +59,7 @@ func (k Keeper) GetRevertGasLimit(ctx sdk.Context, cctx *types.CrossChainTx) (ui return 0, nil } - if cctx.CoinType == common.CoinType_Gas { + if cctx.InboundTxParams.CoinType == common.CoinType_Gas { // get the gas limit of the gas token fc, found := k.fungibleKeeper.GetGasCoinForForeignCoin(ctx, cctx.InboundTxParams.SenderChainId) if !found { @@ -137,7 +70,7 @@ func (k Keeper) GetRevertGasLimit(ctx sdk.Context, cctx *types.CrossChainTx) (ui return 0, errors.Wrap(fungibletypes.ErrContractCall, err.Error()) } return gasLimit.Uint64(), nil - } else if cctx.CoinType == common.CoinType_ERC20 { + } else if cctx.InboundTxParams.CoinType == common.CoinType_ERC20 { // get the gas limit of the associated asset fc, found := k.fungibleKeeper.GetForeignCoinFromAsset(ctx, cctx.InboundTxParams.Asset, cctx.InboundTxParams.SenderChainId) if !found { @@ -172,129 +105,3 @@ func GetAbortedAmount(cctx types.CrossChainTx) sdkmath.Uint { return sdkmath.ZeroUint() } - -// ProcessInbound processes the inbound CCTX. -// It does a conditional dispatch to ProcessZEVMDeposit or ProcessCrosschainMsgPassing based on the receiver chain. -func (k Keeper) ProcessInbound(ctx sdk.Context, cctx *types.CrossChainTx) { - if common.IsZetaChain(cctx.GetCurrentOutTxParam().ReceiverChainId) { - k.ProcessZEVMDeposit(ctx, cctx) - } else { - k.ProcessCrosschainMsgPassing(ctx, cctx) - } -} - -// ProcessZEVMDeposit processes the EVM deposit CCTX. A deposit is a cctx which has Zetachain as the receiver chain. -// If the deposit is successful, the CCTX status is changed to OutboundMined. -// If the deposit returns an internal error i.e if HandleEVMDeposit() returns an error, but isContractReverted is false, the CCTX status is changed to Aborted. -// If the deposit is reverted, the function tries to create a revert cctx with status PendingRevert. -// If the creation of revert tx also fails it changes the status to Aborted. -// Note : Aborted CCTXs are not refunded in this function. The refund is done using a separate refunding mechanism. -// We do not return an error from this function , as all changes need to be persisted to the state. -// Instead we use a temporary context to make changes and then commit the context on for the happy path ,i.e cctx is set to OutboundMined. -func (k Keeper) ProcessZEVMDeposit(ctx sdk.Context, cctx *types.CrossChainTx) { - tmpCtx, commit := ctx.CacheContext() - isContractReverted, err := k.HandleEVMDeposit(tmpCtx, cctx) - - if err != nil && !isContractReverted { // exceptional case; internal error; should abort CCTX - cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, err.Error()) - return - } else if err != nil && isContractReverted { // contract call reverted; should refund - revertMessage := err.Error() - senderChain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, cctx.InboundTxParams.SenderChainId) - if senderChain == nil { - cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, "invalid sender chain") - return - } - - gasLimit, err := k.GetRevertGasLimit(ctx, cctx) - if err != nil { - cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, fmt.Sprintf("can't get revert tx gas limit,%s", err.Error())) - return - } - if gasLimit == 0 { - // use same gas limit of outbound as a fallback -- should not happen - gasLimit = cctx.GetCurrentOutTxParam().OutboundTxGasLimit - } - - // create new OutboundTxParams for the revert - revertTxParams := &types.OutboundTxParams{ - Receiver: cctx.InboundTxParams.Sender, - ReceiverChainId: cctx.InboundTxParams.SenderChainId, - Amount: cctx.InboundTxParams.Amount, - OutboundTxGasLimit: gasLimit, - } - cctx.OutboundTxParams = append(cctx.OutboundTxParams, revertTxParams) - - // we create a new cached context, and we don't commit the previous one with EVM deposit - tmpCtxRevert, commitRevert := ctx.CacheContext() - err = func() error { - err := k.PayGasAndUpdateCctx( - tmpCtxRevert, - senderChain.ChainId, - cctx, - cctx.InboundTxParams.Amount, - false, - ) - if err != nil { - return err - } - // Update nonce using senderchain id as this is a revert tx and would go back to the original sender - return k.UpdateNonce(tmpCtxRevert, senderChain.ChainId, cctx) - }() - if err != nil { - cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, fmt.Sprintf("deposit revert message: %s err : %s", revertMessage, err.Error())) - return - } - commitRevert() - cctx.CctxStatus.ChangeStatus(types.CctxStatus_PendingRevert, revertMessage) - return - } - // successful HandleEVMDeposit; - commit() - cctx.CctxStatus.ChangeStatus(types.CctxStatus_OutboundMined, "Remote omnichain contract call completed") - return -} - -// ProcessCrosschainMsgPassing processes the CCTX for crosschain message passing. A crosschain message passing is a cctx which has a non-Zetachain as the receiver chain. -// If the crosschain message passing is successful, the CCTX status is changed to PendingOutbound. -// If the crosschain message passing returns an error, the CCTX status is changed to Aborted. -// We do not return an error from this function , as all changes need to be persisted to the state. -// Instead we use a temporary context to make changes and then commit the context on for the happy path ,i.e cctx is set to PendingOutbound. -func (k Keeper) ProcessCrosschainMsgPassing(ctx sdk.Context, cctx *types.CrossChainTx) { - tmpCtx, commit := ctx.CacheContext() - outboundReceiverChainID := cctx.GetCurrentOutTxParam().ReceiverChainId - err := func() error { - err := k.PayGasAndUpdateCctx( - tmpCtx, - outboundReceiverChainID, - cctx, - cctx.InboundTxParams.Amount, - false, - ) - if err != nil { - return err - } - return k.UpdateNonce(tmpCtx, outboundReceiverChainID, cctx) - }() - if err != nil { - // do not commit anything here as the CCTX should be aborted - cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, err.Error()) - return - } - commit() - cctx.CctxStatus.ChangeStatus(types.CctxStatus_PendingOutbound, "") - return -} - -func (k Keeper) SaveInbound(ctx sdk.Context, cctx *types.CrossChainTx) { - EmitEventInboundFinalized(ctx, cctx) - k.AddFinalizedInbound(ctx, - cctx.GetInboundTxParams().InboundTxObservedHash, - cctx.GetInboundTxParams().SenderChainId, - cctx.EventIndex) - // #nosec G701 always positive - cctx.InboundTxParams.InboundTxFinalizedZetaHeight = uint64(ctx.BlockHeight()) - cctx.InboundTxParams.TxFinalizationStatus = types.TxFinalizationStatus_Executed - k.RemoveInTxTrackerIfExists(ctx, cctx.InboundTxParams.SenderChainId, cctx.InboundTxParams.InboundTxObservedHash) - k.SetCctxAndNonceToCctxAndInTxHashToCctx(ctx, *cctx) -} diff --git a/x/crosschain/keeper/cctx_utils_outbound.go b/x/crosschain/keeper/cctx_utils_outbound.go deleted file mode 100644 index 7ba5e291ee..0000000000 --- a/x/crosschain/keeper/cctx_utils_outbound.go +++ /dev/null @@ -1,249 +0,0 @@ -package keeper - -import ( - "fmt" - "math/big" - - cosmoserrors "cosmossdk.io/errors" - "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/zeta-chain/zetacore/common" - "github.com/zeta-chain/zetacore/x/crosschain/types" - observertypes "github.com/zeta-chain/zetacore/x/observer/types" -) - -// SetRevertOutboundValues does the following things in one function: -// 1. create a new OutboundTxParams for the revert -// 2. append the new OutboundTxParams to the current OutboundTxParams -// 3. update the TxFinalizationStatus of the current OutboundTxParams to Executed. -func SetRevertOutboundValues(cctx *types.CrossChainTx, gasLimit uint64) { - revertTxParams := &types.OutboundTxParams{ - Receiver: cctx.InboundTxParams.Sender, - ReceiverChainId: cctx.InboundTxParams.SenderChainId, - Amount: cctx.InboundTxParams.Amount, - OutboundTxGasLimit: gasLimit, - TssPubkey: cctx.GetCurrentOutTxParam().TssPubkey, - } - // The original outbound has been finalized, the new outbound is pending - cctx.GetCurrentOutTxParam().TxFinalizationStatus = types.TxFinalizationStatus_Executed - cctx.OutboundTxParams = append(cctx.OutboundTxParams, revertTxParams) -} - -// SetOutboundValues sets the required values for the outbound transaction -// Note: It expects the cctx to already have been created, -// it updates the cctx based on the MsgVoteOnObservedOutboundTx message which is signed and broadcasted by the observer -func SetOutboundValues(ctx sdk.Context, cctx *types.CrossChainTx, msg types.MsgVoteOnObservedOutboundTx, ballotStatus observertypes.BallotStatus) error { - if ballotStatus != observertypes.BallotStatus_BallotFinalized_FailureObservation { - if !msg.ValueReceived.Equal(cctx.GetCurrentOutTxParam().Amount) { - ctx.Logger().Error(fmt.Sprintf("VoteOnObservedOutboundTx: Mint mismatch: %s value received vs %s cctx amount", - msg.ValueReceived, - cctx.GetCurrentOutTxParam().Amount)) - return cosmoserrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("ValueReceived %s does not match sent value %s", msg.ValueReceived, cctx.GetCurrentOutTxParam().Amount)) - } - } - // Update CCTX values - cctx.GetCurrentOutTxParam().OutboundTxHash = msg.ObservedOutTxHash - cctx.GetCurrentOutTxParam().OutboundTxGasUsed = msg.ObservedOutTxGasUsed - cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasPrice = msg.ObservedOutTxEffectiveGasPrice - cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasLimit = msg.ObservedOutTxEffectiveGasLimit - cctx.GetCurrentOutTxParam().OutboundTxObservedExternalHeight = msg.ObservedOutTxBlockHeight - cctx.CctxStatus.LastUpdateTimestamp = ctx.BlockHeader().Time.Unix() - - return nil -} - -// FundStabilityPool funds the stability pool with the remaining fees of an outbound tx -// The funds are sent to the gas stability pool associated with the receiver chain -func (k Keeper) FundStabilityPool(ctx sdk.Context, cctx *types.CrossChainTx) { - // Fund the gas stability pool with the remaining funds - if err := k.FundGasStabilityPoolFromRemainingFees(ctx, *cctx.GetCurrentOutTxParam(), cctx.GetCurrentOutTxParam().ReceiverChainId); err != nil { - ctx.Logger().Error(fmt.Sprintf("VoteOnObservedOutboundTx: CCTX: %s Can't fund the gas stability pool with remaining fees %s", cctx.Index, err.Error())) - } -} - -// FundGasStabilityPoolFromRemainingFees funds the gas stability pool with the remaining fees of an outbound tx -func (k Keeper) FundGasStabilityPoolFromRemainingFees(ctx sdk.Context, outboundTxParams types.OutboundTxParams, chainID int64) error { - gasUsed := outboundTxParams.OutboundTxGasUsed - gasLimit := outboundTxParams.OutboundTxEffectiveGasLimit - gasPrice := math.NewUintFromBigInt(outboundTxParams.OutboundTxEffectiveGasPrice.BigInt()) - - if gasLimit == gasUsed { - return nil - } - - // We skip gas stability pool funding if one of the params is zero - if gasLimit > 0 && gasUsed > 0 && !gasPrice.IsZero() { - if gasLimit > gasUsed { - remainingGas := gasLimit - gasUsed - remainingFees := math.NewUint(remainingGas).Mul(gasPrice).BigInt() - - // We fund the stability pool with a portion of the remaining fees - remainingFees = percentOf(remainingFees, RemainingFeesToStabilityPoolPercent) - // Fund the gas stability pool - if err := k.fungibleKeeper.FundGasStabilityPool(ctx, chainID, remainingFees); err != nil { - return err - } - } else { - return fmt.Errorf("VoteOnObservedOutboundTx: The gas limit %d is less than the gas used %d", gasLimit, gasUsed) - } - } - return nil -} - -// percentOf returns the percentage of a number -func percentOf(n *big.Int, percent int64) *big.Int { - n = n.Mul(n, big.NewInt(percent)) - n = n.Div(n, big.NewInt(100)) - return n -} - -// ProcessSuccessfulOutbound processes a successful outbound transaction. It does the following things in one function: -// 1. Change the status of the CCTX from PendingRevert to Reverted or from PendingOutbound to OutboundMined -// 2. Set the finalization status of the current outbound tx to executed -// 3. Emit an event for the successful outbound transaction -func (k Keeper) ProcessSuccessfulOutbound(ctx sdk.Context, cctx *types.CrossChainTx, valueReceived string) { - oldStatus := cctx.CctxStatus.Status - switch oldStatus { - case types.CctxStatus_PendingRevert: - cctx.CctxStatus.ChangeStatus(types.CctxStatus_Reverted, "") - case types.CctxStatus_PendingOutbound: - cctx.CctxStatus.ChangeStatus(types.CctxStatus_OutboundMined, "") - default: - return - } - cctx.GetCurrentOutTxParam().TxFinalizationStatus = types.TxFinalizationStatus_Executed - newStatus := cctx.CctxStatus.Status.String() - EmitOutboundSuccess(ctx, valueReceived, oldStatus.String(), newStatus, *cctx) -} - -// ProcessFailedOutbound processes a failed outbound transaction. It does the following things in one function: -// 1. For Admin Tx or a withdrawal from Zeta chain, it aborts the CCTX -// 2. For other CCTX, it creates a revert tx if the outbound tx is pending. If the status is pending revert, it aborts the CCTX -// 3. Emit an event for the failed outbound transaction -// 4. Set the finalization status of the current outbound tx to executed. If a revert tx is is created, the finalization status is not set, it would get set when the revert is processed via a subsequent transaction -func (k Keeper) ProcessFailedOutbound(ctx sdk.Context, cctx *types.CrossChainTx, valueReceived string) error { - oldStatus := cctx.CctxStatus.Status - if cctx.CoinType == common.CoinType_Cmd || common.IsZetaChain(cctx.InboundTxParams.SenderChainId) { - // if the cctx is of coin type cmd or the sender chain is zeta chain, then we do not revert, the cctx is aborted - cctx.GetCurrentOutTxParam().TxFinalizationStatus = types.TxFinalizationStatus_Executed - cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, "") - } else { - switch oldStatus { - case types.CctxStatus_PendingOutbound: - - gasLimit, err := k.GetRevertGasLimit(ctx, cctx) - if err != nil { - return cosmoserrors.Wrap(err, "GetRevertGasLimit") - } - if gasLimit == 0 { - // use same gas limit of outbound as a fallback -- should not happen - gasLimit = cctx.OutboundTxParams[0].OutboundTxGasLimit - } - - // create new OutboundTxParams for the revert - SetRevertOutboundValues(cctx, gasLimit) - - err = k.PayGasAndUpdateCctx( - ctx, - cctx.InboundTxParams.SenderChainId, - cctx, - cctx.OutboundTxParams[0].Amount, - false, - ) - if err != nil { - return err - } - err = k.UpdateNonce(ctx, cctx.InboundTxParams.SenderChainId, cctx) - if err != nil { - return err - } - // Not setting the finalization status here, the required changes have been mad while creating the revert tx - cctx.CctxStatus.ChangeStatus(types.CctxStatus_PendingRevert, "Outbound failed, start revert") - case types.CctxStatus_PendingRevert: - cctx.GetCurrentOutTxParam().TxFinalizationStatus = types.TxFinalizationStatus_Executed - cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, "Outbound failed: revert failed; abort TX") - } - } - newStatus := cctx.CctxStatus.Status.String() - EmitOutboundFailure(ctx, valueReceived, oldStatus.String(), newStatus, *cctx) - return nil -} - -// ProcessOutbound processes the finalization of an outbound transaction based on the ballot status -// The state is committed only if the individual steps are successful -func (k Keeper) ProcessOutbound(ctx sdk.Context, cctx *types.CrossChainTx, ballotStatus observertypes.BallotStatus, valueReceived string) error { - tmpCtx, commit := ctx.CacheContext() - err := func() error { - switch ballotStatus { - case observertypes.BallotStatus_BallotFinalized_SuccessObservation: - k.ProcessSuccessfulOutbound(tmpCtx, cctx, valueReceived) - case observertypes.BallotStatus_BallotFinalized_FailureObservation: - err := k.ProcessFailedOutbound(tmpCtx, cctx, valueReceived) - if err != nil { - return err - } - } - return nil - }() - if err != nil { - return err - } - commit() - return nil -} - -// SaveFailedOutBound saves a failed outbound transaction. -// It does the following things in one function: -// 1. Change the status of the CCTX to Aborted -// 2. Save the outbound -func (k Keeper) SaveFailedOutBound(ctx sdk.Context, cctx *types.CrossChainTx, errMessage string, ballotIndex string) { - cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, errMessage) - ctx.Logger().Error(errMessage) - - k.SaveOutbound(ctx, cctx, ballotIndex) -} - -// SaveSuccessfulOutBound saves a successful outbound transaction. -func (k Keeper) SaveSuccessfulOutBound(ctx sdk.Context, cctx *types.CrossChainTx, ballotIndex string) { - k.SaveOutbound(ctx, cctx, ballotIndex) -} - -// SaveOutbound saves the outbound transaction.It does the following things in one function: -// 1. Set the ballot index for the outbound vote to the cctx -// 2. Remove the nonce from the pending nonces -// 3. Remove the outbound tx tracker -// 4. Set the cctx and nonce to cctx and inTxHash to cctx -func (k Keeper) SaveOutbound(ctx sdk.Context, cctx *types.CrossChainTx, ballotIndex string) { - receiverChain := cctx.GetCurrentOutTxParam().ReceiverChainId - tssPubkey := cctx.GetCurrentOutTxParam().TssPubkey - outTxTssNonce := cctx.GetCurrentOutTxParam().OutboundTxTssNonce - - cctx.GetCurrentOutTxParam().OutboundTxBallotIndex = ballotIndex - // #nosec G701 always in range - k.GetObserverKeeper().RemoveFromPendingNonces(ctx, tssPubkey, receiverChain, int64(outTxTssNonce)) - k.RemoveOutTxTracker(ctx, receiverChain, outTxTssNonce) - ctx.Logger().Info(fmt.Sprintf("Remove tracker %s: , Block Height : %d ", getOutTrackerIndex(receiverChain, outTxTssNonce), ctx.BlockHeight())) - // This should set nonce to cctx only if a new revert is created. - k.SetCctxAndNonceToCctxAndInTxHashToCctx(ctx, *cctx) -} - -func (k Keeper) ValidateOutboundMessage(ctx sdk.Context, msg types.MsgVoteOnObservedOutboundTx) (types.CrossChainTx, error) { - // check if CCTX exists and if the nonce matches - cctx, found := k.GetCrossChainTx(ctx, msg.CctxHash) - if !found { - return types.CrossChainTx{}, cosmoserrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("CCTX %s does not exist", msg.CctxHash)) - } - if cctx.GetCurrentOutTxParam().OutboundTxTssNonce != msg.OutTxTssNonce { - return types.CrossChainTx{}, cosmoserrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("OutTxTssNonce %d does not match CCTX OutTxTssNonce %d", msg.OutTxTssNonce, cctx.GetCurrentOutTxParam().OutboundTxTssNonce)) - } - // do not process an outbound vote if TSS is not found - _, found = k.zetaObserverKeeper.GetTSS(ctx) - if !found { - return types.CrossChainTx{}, types.ErrCannotFindTSSKeys - } - if cctx.GetCurrentOutTxParam().ReceiverChainId != msg.OutTxChain { - return types.CrossChainTx{}, cosmoserrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("OutTxChain %d does not match CCTX OutTxChain %d", msg.OutTxChain, cctx.GetCurrentOutTxParam().ReceiverChainId)) - } - return cctx, nil -} diff --git a/x/crosschain/keeper/cctx_utils_outbound_test.go b/x/crosschain/keeper/cctx_utils_outbound_test.go deleted file mode 100644 index 78636c18c9..0000000000 --- a/x/crosschain/keeper/cctx_utils_outbound_test.go +++ /dev/null @@ -1,490 +0,0 @@ -package keeper_test - -import ( - "fmt" - "math/big" - "testing" - - sdkmath "cosmossdk.io/math" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "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/keeper" - "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" -) - -func TestKeeper_GetOutbound(t *testing.T) { - t.Run("successfully get outbound tx", func(t *testing.T) { - _, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - hash := sample.Hash().String() - - err := keeper.SetOutboundValues(ctx, cctx, types.MsgVoteOnObservedOutboundTx{ - ValueReceived: cctx.GetCurrentOutTxParam().Amount, - ObservedOutTxHash: hash, - ObservedOutTxBlockHeight: 10, - ObservedOutTxGasUsed: 100, - ObservedOutTxEffectiveGasPrice: sdkmath.NewInt(100), - ObservedOutTxEffectiveGasLimit: 20, - }, observertypes.BallotStatus_BallotFinalized_SuccessObservation) - require.NoError(t, err) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxHash, hash) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxGasUsed, uint64(100)) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasPrice, sdkmath.NewInt(100)) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasLimit, uint64(20)) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxObservedExternalHeight, uint64(10)) - require.Equal(t, cctx.CctxStatus.LastUpdateTimestamp, ctx.BlockHeader().Time.Unix()) - }) - - t.Run("successfully get outbound tx for failed ballot without amount check", func(t *testing.T) { - _, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - hash := sample.Hash().String() - - err := keeper.SetOutboundValues(ctx, cctx, types.MsgVoteOnObservedOutboundTx{ - ObservedOutTxHash: hash, - ObservedOutTxBlockHeight: 10, - ObservedOutTxGasUsed: 100, - ObservedOutTxEffectiveGasPrice: sdkmath.NewInt(100), - ObservedOutTxEffectiveGasLimit: 20, - }, observertypes.BallotStatus_BallotFinalized_FailureObservation) - require.NoError(t, err) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxHash, hash) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxGasUsed, uint64(100)) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasPrice, sdkmath.NewInt(100)) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasLimit, uint64(20)) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxObservedExternalHeight, uint64(10)) - require.Equal(t, cctx.CctxStatus.LastUpdateTimestamp, ctx.BlockHeader().Time.Unix()) - }) - - t.Run("failed to get outbound tx if amount does not match value received", func(t *testing.T) { - _, ctx, _, _ := keepertest.CrosschainKeeper(t) - - cctx := sample.CrossChainTx(t, "test") - hash := sample.Hash().String() - - err := keeper.SetOutboundValues(ctx, cctx, types.MsgVoteOnObservedOutboundTx{ - ValueReceived: sdkmath.NewUint(100), - ObservedOutTxHash: hash, - ObservedOutTxBlockHeight: 10, - ObservedOutTxGasUsed: 100, - ObservedOutTxEffectiveGasPrice: sdkmath.NewInt(100), - ObservedOutTxEffectiveGasLimit: 20, - }, observertypes.BallotStatus_BallotFinalized_SuccessObservation) - require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) - }) -} - -func TestKeeper_ProcessSuccessfulOutbound(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - // transition to reverted if pending revert - cctx.CctxStatus.Status = types.CctxStatus_PendingRevert - k.ProcessSuccessfulOutbound(ctx, cctx, sample.String()) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Reverted) - // transition to outbound mined if pending outbound - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - k.ProcessSuccessfulOutbound(ctx, cctx, sample.String()) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_OutboundMined) - // do nothing if it's in any other state - k.ProcessSuccessfulOutbound(ctx, cctx, sample.String()) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_OutboundMined) -} - -func TestKeeper_ProcessFailedOutbound(t *testing.T) { - t.Run("successfully process failed outbound set to aborted for type cmd", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - cctx.CoinType = common.CoinType_Cmd - err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) - require.NoError(t, err) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Aborted) - require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_Executed) - }) - - t.Run("successfully process failed outbound set to aborted for withdraw tx", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - cctx.InboundTxParams.SenderChainId = common.ZetaChainMainnet().ChainId - err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) - require.NoError(t, err) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Aborted) - require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_Executed) - }) - - t.Run("successfully process failed outbound set to pending revert", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - observerMock := keepertest.GetCrosschainObserverMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - asset := "" - - // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) - - // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) - - // mock successful UpdateNonce - _ = keepertest.MockUpdateNonce(observerMock, *senderChain) - - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) - // Remove the first outbound tx param to make the scenario realistic - oldParams := cctx.OutboundTxParams - cctx.OutboundTxParams = make([]*types.OutboundTxParams, 1) - cctx.OutboundTxParams[0] = oldParams[1] - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) - require.NoError(t, err) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingRevert) - require.Equal(t, types.TxFinalizationStatus_NotFinalized, cctx.GetCurrentOutTxParam().TxFinalizationStatus) - require.Equal(t, types.TxFinalizationStatus_Executed, cctx.OutboundTxParams[0].TxFinalizationStatus) - - }) - - t.Run("unable to process revert when update nonce fails", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - observerMock := keepertest.GetCrosschainObserverMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - asset := "" - - // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) - - // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) - - // mock failed UpdateNonce - observerMock.On("GetChainNonces", mock.Anything, senderChain.ChainName.String()). - Return(observertypes.ChainNonces{}, false) - - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) - require.ErrorIs(t, err, types.ErrCannotFindReceiverNonce) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingOutbound) - }) - - t.Run("unable to process revert when PayGasAndUpdateCctx fails", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - observerMock := keepertest.GetCrosschainObserverMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - asset := "" - - // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) - - // mock successful PayGasAndUpdateCctx - observerMock.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). - Return(nil).Once() - - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) - require.ErrorIs(t, err, observertypes.ErrSupportedChains) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingOutbound) - }) - - t.Run("unable to process revert when GetRevertGasLimit fails", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - asset := "" - - // mock failed GetRevertGasLimit for ERC20 - fungibleMock.On("GetForeignCoinFromAsset", mock.Anything, asset, senderChain.ChainId). - Return(fungibletypes.ForeignCoins{ - Zrc20ContractAddress: sample.EthAddress().String(), - }, false).Once() - - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) - require.ErrorIs(t, err, types.ErrForeignCoinNotFound) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingOutbound) - }) -} - -func TestKeeper_ProcessOutbound(t *testing.T) { - t.Run("successfully process outbound with ballot finalized to success", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_SuccessObservation, sample.String()) - require.NoError(t, err) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_OutboundMined) - }) - - t.Run("successfully process outbound with ballot finalized to failed and old status is Pending Revert", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - cctx.CctxStatus.Status = types.CctxStatus_PendingRevert - err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_FailureObservation, sample.String()) - require.NoError(t, err) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Aborted) - require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_Executed) - }) - - t.Run("successfully process outbound with ballot finalized to failed and coin-type is CMD", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - cctx.CoinType = common.CoinType_Cmd - err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_FailureObservation, sample.String()) - require.NoError(t, err) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Aborted) - require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_Executed) - }) - - t.Run("do not process outbound on error, no new outbound created", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - asset := "" - - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - oldOutTxParamsLen := len(cctx.OutboundTxParams) - // mock failed GetRevertGasLimit for ERC20 - fungibleMock.On("GetForeignCoinFromAsset", mock.Anything, asset, senderChain.ChainId). - Return(fungibletypes.ForeignCoins{ - Zrc20ContractAddress: sample.EthAddress().String(), - }, false).Once() - - err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_FailureObservation, sample.String()) - require.ErrorIs(t, err, types.ErrForeignCoinNotFound) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingOutbound) - // New outbound not added and the old outbound is not finalized - require.Len(t, cctx.OutboundTxParams, oldOutTxParamsLen) - require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_NotFinalized) - }) - - t.Run("successfully revert a outbound and create a new revert tx", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - observerMock := keepertest.GetCrosschainObserverMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - asset := "" - - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - oldOutTxParamsLen := len(cctx.OutboundTxParams) - // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) - - // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) - - // mock successful UpdateNonce - _ = keepertest.MockUpdateNonce(observerMock, *senderChain) - - err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_FailureObservation, sample.String()) - require.NoError(t, err) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingRevert) - // New outbound added for revert and the old outbound is finalized - require.Len(t, cctx.OutboundTxParams, oldOutTxParamsLen+1) - require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_NotFinalized) - require.Equal(t, cctx.OutboundTxParams[oldOutTxParamsLen-1].TxFinalizationStatus, types.TxFinalizationStatus_Executed) - }) -} - -func TestKeeper_SaveFailedOutBound(t *testing.T) { - t.Run("successfully save failed outbound", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - k.SetOutTxTracker(ctx, types.OutTxTracker{ - Index: "", - ChainId: cctx.GetCurrentOutTxParam().ReceiverChainId, - Nonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, - HashList: nil, - }) - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - k.SaveFailedOutBound(ctx, cctx, sample.String(), sample.ZetaIndex(t)) - require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Aborted) - _, found := k.GetOutTxTracker(ctx, cctx.GetCurrentOutTxParam().ReceiverChainId, cctx.GetCurrentOutTxParam().OutboundTxTssNonce) - require.False(t, found) - }) -} - -func TestKeeper_SaveSuccessfulOutBound(t *testing.T) { - t.Run("successfully save successful outbound", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - k.SetOutTxTracker(ctx, types.OutTxTracker{ - Index: "", - ChainId: cctx.GetCurrentOutTxParam().ReceiverChainId, - Nonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, - HashList: nil, - }) - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - k.SaveSuccessfulOutBound(ctx, cctx, sample.String()) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxBallotIndex, sample.String()) - _, found := k.GetOutTxTracker(ctx, cctx.GetCurrentOutTxParam().ReceiverChainId, cctx.GetCurrentOutTxParam().OutboundTxTssNonce) - require.False(t, found) - }) -} - -func TestKeeper_SaveOutbound(t *testing.T) { - t.Run("successfully save outbound", func(t *testing.T) { - k, ctx, _, zk := keepertest.CrosschainKeeper(t) - - // setup state for crosschain and observer modules - cctx := sample.CrossChainTx(t, "test") - cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound - ballotIndex := sample.String() - k.SetOutTxTracker(ctx, types.OutTxTracker{ - Index: "", - ChainId: cctx.GetCurrentOutTxParam().ReceiverChainId, - Nonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, - HashList: nil, - }) - - zk.ObserverKeeper.SetPendingNonces(ctx, observertypes.PendingNonces{ - NonceLow: int64(cctx.GetCurrentOutTxParam().OutboundTxTssNonce) - 1, - NonceHigh: int64(cctx.GetCurrentOutTxParam().OutboundTxTssNonce) + 1, - ChainId: cctx.GetCurrentOutTxParam().ReceiverChainId, - Tss: cctx.GetCurrentOutTxParam().TssPubkey, - }) - zk.ObserverKeeper.SetTSS(ctx, observertypes.TSS{ - TssPubkey: cctx.GetCurrentOutTxParam().TssPubkey, - }) - - // Save outbound and assert all values are successfully saved - k.SaveOutbound(ctx, cctx, ballotIndex) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxBallotIndex, ballotIndex) - _, found := k.GetOutTxTracker(ctx, cctx.GetCurrentOutTxParam().ReceiverChainId, cctx.GetCurrentOutTxParam().OutboundTxTssNonce) - require.False(t, found) - pn, found := zk.ObserverKeeper.GetPendingNonces(ctx, cctx.GetCurrentOutTxParam().TssPubkey, cctx.GetCurrentOutTxParam().ReceiverChainId) - require.True(t, found) - require.Equal(t, pn.NonceLow, int64(cctx.GetCurrentOutTxParam().OutboundTxTssNonce)+1) - require.Equal(t, pn.NonceHigh, int64(cctx.GetCurrentOutTxParam().OutboundTxTssNonce)+1) - _, found = k.GetInTxHashToCctx(ctx, cctx.InboundTxParams.InboundTxObservedHash) - require.True(t, found) - _, found = zk.ObserverKeeper.GetNonceToCctx(ctx, cctx.GetCurrentOutTxParam().TssPubkey, cctx.GetCurrentOutTxParam().ReceiverChainId, int64(cctx.GetCurrentOutTxParam().OutboundTxTssNonce)) - require.True(t, found) - }) -} - -func Test_SetRevertOutboundValues(t *testing.T) { - cctx := sample.CrossChainTx(t, "test") - cctx.OutboundTxParams = cctx.OutboundTxParams[:1] - keeper.SetRevertOutboundValues(cctx, 100) - require.Len(t, cctx.OutboundTxParams, 2) - require.Equal(t, cctx.GetCurrentOutTxParam().Receiver, cctx.InboundTxParams.Sender) - require.Equal(t, cctx.GetCurrentOutTxParam().ReceiverChainId, cctx.InboundTxParams.SenderChainId) - require.Equal(t, cctx.GetCurrentOutTxParam().Amount, cctx.InboundTxParams.Amount) - require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxGasLimit, uint64(100)) - require.Equal(t, cctx.GetCurrentOutTxParam().TssPubkey, cctx.OutboundTxParams[0].TssPubkey) - require.Equal(t, types.TxFinalizationStatus_Executed, cctx.OutboundTxParams[0].TxFinalizationStatus) -} - -func TestKeeper_ValidateOutboundMessage(t *testing.T) { - t.Run("successfully validate outbound message", func(t *testing.T) { - k, ctx, _, zk := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - k.SetCrossChainTx(ctx, *cctx) - zk.ObserverKeeper.SetTSS(ctx, sample.Tss()) - _, err := k.ValidateOutboundMessage(ctx, types.MsgVoteOnObservedOutboundTx{ - CctxHash: cctx.Index, - OutTxTssNonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, - OutTxChain: cctx.GetCurrentOutTxParam().ReceiverChainId, - }) - require.NoError(t, err) - }) - - t.Run("failed to validate outbound message if cctx not found", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - msg := types.MsgVoteOnObservedOutboundTx{ - CctxHash: sample.String(), - OutTxTssNonce: 1, - } - _, err := k.ValidateOutboundMessage(ctx, msg) - require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) - require.ErrorContains(t, err, fmt.Sprintf("CCTX %s does not exist", msg.CctxHash)) - }) - - t.Run("failed to validate outbound message if nonce does not match", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - k.SetCrossChainTx(ctx, *cctx) - msg := types.MsgVoteOnObservedOutboundTx{ - CctxHash: cctx.Index, - OutTxTssNonce: 2, - } - _, err := k.ValidateOutboundMessage(ctx, msg) - require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) - require.ErrorContains(t, err, fmt.Sprintf("OutTxTssNonce %d does not match CCTX OutTxTssNonce %d", msg.OutTxTssNonce, cctx.GetCurrentOutTxParam().OutboundTxTssNonce)) - }) - - t.Run("failed to validate outbound message if tss not found", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - k.SetCrossChainTx(ctx, *cctx) - _, err := k.ValidateOutboundMessage(ctx, types.MsgVoteOnObservedOutboundTx{ - CctxHash: cctx.Index, - OutTxTssNonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, - }) - require.ErrorIs(t, err, types.ErrCannotFindTSSKeys) - }) - - t.Run("failed to validate outbound message if chain does not match", func(t *testing.T) { - k, ctx, _, zk := keepertest.CrosschainKeeper(t) - cctx := sample.CrossChainTx(t, "test") - k.SetCrossChainTx(ctx, *cctx) - zk.ObserverKeeper.SetTSS(ctx, sample.Tss()) - _, err := k.ValidateOutboundMessage(ctx, types.MsgVoteOnObservedOutboundTx{ - CctxHash: cctx.Index, - OutTxTssNonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, - OutTxChain: 2, - }) - require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) - require.ErrorContains(t, err, fmt.Sprintf("OutTxChain %d does not match CCTX OutTxChain %d", 2, cctx.GetCurrentOutTxParam().ReceiverChainId)) - }) -} diff --git a/x/crosschain/keeper/cctx_utils_test.go b/x/crosschain/keeper/cctx_utils_test.go index f0255214a8..00bf4db518 100644 --- a/x/crosschain/keeper/cctx_utils_test.go +++ b/x/crosschain/keeper/cctx_utils_test.go @@ -6,8 +6,6 @@ import ( "testing" sdkmath "cosmossdk.io/math" - ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/common" keepertest "github.com/zeta-chain/zetacore/testutil/keeper" @@ -15,7 +13,6 @@ import ( crosschainkeeper "github.com/zeta-chain/zetacore/x/crosschain/keeper" "github.com/zeta-chain/zetacore/x/crosschain/types" fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" - observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) func TestGetRevertGasLimit(t *testing.T) { @@ -31,7 +28,10 @@ func TestGetRevertGasLimit(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) gasLimit, err := k.GetRevertGasLimit(ctx, &types.CrossChainTx{ - CoinType: common.CoinType_Zeta}) + InboundTxParams: &types.InboundTxParams{ + CoinType: common.CoinType_Zeta, + }, + }) require.NoError(t, err) require.Equal(t, uint64(0), gasLimit) }) @@ -48,9 +48,10 @@ func TestGetRevertGasLimit(t *testing.T) { require.NoError(t, err) gasLimit, err := k.GetRevertGasLimit(ctx, &types.CrossChainTx{ - CoinType: common.CoinType_Gas, + InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, + CoinType: common.CoinType_Gas, }}) require.NoError(t, err) require.Equal(t, uint64(42), gasLimit) @@ -78,10 +79,11 @@ func TestGetRevertGasLimit(t *testing.T) { require.NoError(t, err) gasLimit, err := k.GetRevertGasLimit(ctx, &types.CrossChainTx{ - CoinType: common.CoinType_ERC20, + InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Asset: asset, + CoinType: common.CoinType_ERC20, }}) require.NoError(t, err) require.Equal(t, uint64(42), gasLimit) @@ -91,9 +93,10 @@ func TestGetRevertGasLimit(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) _, err := k.GetRevertGasLimit(ctx, &types.CrossChainTx{ - CoinType: common.CoinType_Gas, + InboundTxParams: &types.InboundTxParams{ SenderChainId: 999999, + CoinType: common.CoinType_Gas, }}) require.ErrorIs(t, err, types.ErrForeignCoinNotFound) }) @@ -112,9 +115,10 @@ func TestGetRevertGasLimit(t *testing.T) { // no contract deployed therefore will fail _, err := k.GetRevertGasLimit(ctx, &types.CrossChainTx{ - CoinType: common.CoinType_Gas, + InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, + CoinType: common.CoinType_Gas, }}) require.ErrorIs(t, err, fungibletypes.ErrContractCall) }) @@ -123,9 +127,10 @@ func TestGetRevertGasLimit(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) _, err := k.GetRevertGasLimit(ctx, &types.CrossChainTx{ - CoinType: common.CoinType_ERC20, + InboundTxParams: &types.InboundTxParams{ SenderChainId: 999999, + CoinType: common.CoinType_ERC20, }}) require.ErrorIs(t, err, types.ErrForeignCoinNotFound) }) @@ -146,10 +151,10 @@ func TestGetRevertGasLimit(t *testing.T) { // no contract deployed therefore will fail _, err := k.GetRevertGasLimit(ctx, &types.CrossChainTx{ - CoinType: common.CoinType_ERC20, InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Asset: asset, + CoinType: common.CoinType_ERC20, }}) require.ErrorIs(t, err, fungibletypes.ErrContractCall) }) @@ -194,365 +199,6 @@ func TestGetAbortedAmount(t *testing.T) { }) } -func TestKeeper_ProcessZEVMDeposit(t *testing.T) { - t.Run("process zevm deposit successfully", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - - // expect DepositCoinZeta to be called - fungibleMock.On("DepositCoinZeta", mock.Anything, receiver, amount). - Return(nil) - - // call ProcessZEVMDeposit - cctx := sample.CrossChainTx(t, "test") - cctx.CctxStatus = &types.Status{Status: types.CctxStatus_PendingInbound} - cctx.GetCurrentOutTxParam().Receiver = receiver.String() - cctx.GetInboundTxParams().Amount = sdkmath.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_Zeta - cctx.GetInboundTxParams().SenderChainId = 0 - k.ProcessZEVMDeposit(ctx, cctx) - require.Equal(t, types.CctxStatus_OutboundMined, cctx.CctxStatus.Status) - }) - - t.Run("unable to process zevm deposit HandleEVMDeposit returns err without reverting", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - - // mock unsuccessful HandleEVMDeposit which does not revert - fungibleMock.On("DepositCoinZeta", mock.Anything, receiver, amount). - Return(fmt.Errorf("deposit error"), false) - - // call ProcessZEVMDeposit - cctx := sample.CrossChainTx(t, "test") - cctx.CctxStatus = &types.Status{Status: types.CctxStatus_PendingInbound} - cctx.GetCurrentOutTxParam().Receiver = receiver.String() - cctx.GetInboundTxParams().Amount = sdkmath.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_Zeta - cctx.GetInboundTxParams().SenderChainId = 0 - k.ProcessZEVMDeposit(ctx, cctx) - require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) - require.Equal(t, "deposit error", cctx.CctxStatus.StatusMessage) - }) - - t.Run("unable to process zevm deposit HandleEVMDeposit reverts fails at GetSupportedChainFromChainID", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - observerMock := keepertest.GetCrosschainObserverMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - errDeposit := fmt.Errorf("deposit failed") - - // Setup expected calls - // mock unsuccessful HandleEVMDeposit which reverts , i.e returns err and isContractReverted = true - keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) - - // mock unsuccessful GetSupportedChainFromChainID - observerMock.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). - Return(nil) - - // call ProcessZEVMDeposit - cctx := GetERC20Cctx(t, receiver, *senderChain, "", amount) - k.ProcessZEVMDeposit(ctx, cctx) - require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) - require.Equal(t, "invalid sender chain", cctx.CctxStatus.StatusMessage) - }) - - t.Run("unable to process zevm deposit HandleEVMDeposit revert fails at and GetRevertGasLimit", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - observerMock := keepertest.GetCrosschainObserverMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - asset := "" - errDeposit := fmt.Errorf("deposit failed") - - // Setup expected calls - keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) - - // Mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) - - // mock unsuccessful GetRevertGasLimit for ERC20 - fungibleMock.On("GetForeignCoinFromAsset", mock.Anything, asset, senderChain.ChainId). - Return(fungibletypes.ForeignCoins{}, false) - - // call ProcessZEVMDeposit - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) - k.ProcessZEVMDeposit(ctx, cctx) - require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) - require.Equal(t, fmt.Sprintf("can't get revert tx gas limit,%s", types.ErrForeignCoinNotFound), cctx.CctxStatus.StatusMessage) - }) - - t.Run("unable to process zevm deposit HandleEVMDeposit revert fails at PayGasInERC20AndUpdateCctx", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - asset := "" - - // Setup expected calls - errDeposit := fmt.Errorf("deposit failed") - keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) - - observerMock := keepertest.GetCrosschainObserverMock(t, k) - - // Mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) - - // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) - - // mock unsuccessful PayGasInERC20AndUpdateCctx - observerMock.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). - Return(nil).Once() - - // call ProcessZEVMDeposit - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) - k.ProcessZEVMDeposit(ctx, cctx) - require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) - require.Equal(t, fmt.Sprintf("deposit revert message: %s err : %s", errDeposit, observertypes.ErrSupportedChains), cctx.CctxStatus.StatusMessage) - }) - - t.Run("unable to process zevm deposit HandleEVMDeposit reverts fails at UpdateNonce", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - observerMock := keepertest.GetCrosschainObserverMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - asset := "" - errDeposit := fmt.Errorf("deposit failed") - - // Setup expected calls - // mock unsuccessful HandleEVMDeposit which reverts , i.e returns err and isContractReverted = true - keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) - - // Mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) - - // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) - - // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) - - // Mock unsuccessful UpdateNonce - observerMock.On("GetChainNonces", mock.Anything, senderChain.ChainName.String()). - Return(observertypes.ChainNonces{}, false) - - // call ProcessZEVMDeposit - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) - k.ProcessZEVMDeposit(ctx, cctx) - require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) - require.Contains(t, cctx.CctxStatus.StatusMessage, "cannot find receiver chain nonce") - }) - - t.Run("unable to process zevm deposit HandleEVMDeposit revert successfully", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - observerMock := keepertest.GetCrosschainObserverMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - asset := "" - errDeposit := fmt.Errorf("deposit failed") - - // Setup expected calls - // mock unsuccessful HandleEVMDeposit which reverts , i.e returns err and isContractReverted = true - keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) - - // Mock successful GetSupportedChainFromChainID - keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) - - // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) - - // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) - // mock successful UpdateNonce - updatedNonce := keepertest.MockUpdateNonce(observerMock, *senderChain) - - // call ProcessZEVMDeposit - cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) - k.ProcessZEVMDeposit(ctx, cctx) - require.Equal(t, types.CctxStatus_PendingRevert, cctx.CctxStatus.Status) - require.Equal(t, errDeposit.Error(), cctx.CctxStatus.StatusMessage) - require.Equal(t, updatedNonce, cctx.GetCurrentOutTxParam().OutboundTxTssNonce) - }) -} - -func TestKeeper_ProcessCrosschainMsgPassing(t *testing.T) { - t.Run("process crosschain msg passing successfully", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - observerMock := keepertest.GetCrosschainObserverMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - receiverChain := getValidEthChain(t) - - // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *receiverChain, "") - - // mock successful UpdateNonce - updatedNonce := keepertest.MockUpdateNonce(observerMock, *receiverChain) - - // call ProcessCrosschainMsgPassing - cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) - k.ProcessCrosschainMsgPassing(ctx, cctx) - require.Equal(t, types.CctxStatus_PendingOutbound, cctx.CctxStatus.Status) - require.Equal(t, updatedNonce, cctx.GetCurrentOutTxParam().OutboundTxTssNonce) - }) - - t.Run("unable to process crosschain msg passing PayGasAndUpdateCctx fails", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - observerMock := keepertest.GetCrosschainObserverMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - receiverChain := getValidEthChain(t) - - // mock unsuccessful PayGasAndUpdateCctx - observerMock.On("GetSupportedChainFromChainID", mock.Anything, receiverChain.ChainId). - Return(nil).Once() - - // call ProcessCrosschainMsgPassing - cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) - k.ProcessCrosschainMsgPassing(ctx, cctx) - require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) - require.Equal(t, observertypes.ErrSupportedChains.Error(), cctx.CctxStatus.StatusMessage) - }) - - t.Run("unable to process crosschain msg passing UpdateNonce fails", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ - UseFungibleMock: true, - UseObserverMock: true, - }) - - // Setup mock data - fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) - observerMock := keepertest.GetCrosschainObserverMock(t, k) - receiver := sample.EthAddress() - amount := big.NewInt(42) - receiverChain := getValidEthChain(t) - - // mock successful PayGasAndUpdateCctx - keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *receiverChain, "") - - // mock unsuccessful UpdateNonce - observerMock.On("GetChainNonces", mock.Anything, receiverChain.ChainName.String()). - Return(observertypes.ChainNonces{}, false) - - // call ProcessCrosschainMsgPassing - cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) - k.ProcessCrosschainMsgPassing(ctx, cctx) - require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) - require.Contains(t, cctx.CctxStatus.StatusMessage, "cannot find receiver chain nonce") - }) -} - -func TestKeeper_GetInbound(t *testing.T) { - t.Run("should return a cctx with correct values", func(t *testing.T) { - k, ctx, _, zk := keepertest.CrosschainKeeper(t) - senderChain := getValidEthChain(t) - sender := sample.EthAddress() - receiverChain := getValidEthChain(t) - receiver := sample.EthAddress() - creator := sample.AccAddress() - amount := sdkmath.NewUint(42) - message := "test" - intxBlockHeight := uint64(420) - intxHash := sample.Hash() - gasLimit := uint64(100) - asset := "test-asset" - eventIndex := uint64(1) - cointType := common.CoinType_ERC20 - tss := sample.Tss() - msg := types.MsgVoteOnObservedInboundTx{ - Creator: creator, - Sender: sender.String(), - SenderChainId: senderChain.ChainId, - Receiver: receiver.String(), - ReceiverChain: receiverChain.ChainId, - Amount: amount, - Message: message, - InTxHash: intxHash.String(), - InBlockHeight: intxBlockHeight, - GasLimit: gasLimit, - CoinType: cointType, - TxOrigin: sender.String(), - Asset: asset, - EventIndex: eventIndex, - } - zk.ObserverKeeper.SetTSS(ctx, tss) - cctx := k.GetInbound(ctx, &msg) - require.Equal(t, receiver.String(), cctx.GetCurrentOutTxParam().Receiver) - require.Equal(t, receiverChain.ChainId, cctx.GetCurrentOutTxParam().ReceiverChainId) - require.Equal(t, sender.String(), cctx.GetInboundTxParams().Sender) - require.Equal(t, senderChain.ChainId, cctx.GetInboundTxParams().SenderChainId) - require.Equal(t, amount, cctx.GetInboundTxParams().Amount) - require.Equal(t, message, cctx.RelayedMessage) - require.Equal(t, intxHash.String(), cctx.GetInboundTxParams().InboundTxObservedHash) - require.Equal(t, intxBlockHeight, cctx.GetInboundTxParams().InboundTxObservedExternalHeight) - require.Equal(t, gasLimit, cctx.GetCurrentOutTxParam().OutboundTxGasLimit) - require.Equal(t, asset, cctx.GetInboundTxParams().Asset) - require.Equal(t, eventIndex, cctx.EventIndex) - require.Equal(t, cointType, cctx.CoinType) - require.Equal(t, uint64(0), cctx.GetCurrentOutTxParam().OutboundTxTssNonce) - require.Equal(t, sdkmath.ZeroUint(), cctx.GetCurrentOutTxParam().Amount) - require.Equal(t, types.CctxStatus_PendingInbound, cctx.CctxStatus.Status) - require.Equal(t, false, cctx.CctxStatus.IsAbortRefunded) - }) -} - func Test_IsPending(t *testing.T) { tt := []struct { status types.CctxStatus @@ -571,57 +217,3 @@ func Test_IsPending(t *testing.T) { }) } } - -func TestKeeper_SaveInbound(t *testing.T) { - t.Run("should save the cctx", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - cctx := GetERC20Cctx(t, receiver, *senderChain, "", amount) - k.SaveInbound(ctx, cctx) - require.Equal(t, types.TxFinalizationStatus_Executed, cctx.InboundTxParams.TxFinalizationStatus) - require.True(t, k.IsFinalizedInbound(ctx, cctx.GetInboundTxParams().InboundTxObservedHash, cctx.GetInboundTxParams().SenderChainId, cctx.EventIndex)) - _, found := k.GetCrossChainTx(ctx, cctx.Index) - require.True(t, found) - }) - - t.Run("should save the cctx and remove tracker", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - receiver := sample.EthAddress() - amount := big.NewInt(42) - senderChain := getValidEthChain(t) - cctx := GetERC20Cctx(t, receiver, *senderChain, "", amount) - hash := sample.Hash() - cctx.InboundTxParams.InboundTxObservedHash = hash.String() - k.SetInTxTracker(ctx, types.InTxTracker{ - ChainId: senderChain.ChainId, - TxHash: hash.String(), - CoinType: 0, - }) - k.SaveInbound(ctx, cctx) - require.Equal(t, types.TxFinalizationStatus_Executed, cctx.InboundTxParams.TxFinalizationStatus) - require.True(t, k.IsFinalizedInbound(ctx, cctx.GetInboundTxParams().InboundTxObservedHash, cctx.GetInboundTxParams().SenderChainId, cctx.EventIndex)) - _, found := k.GetCrossChainTx(ctx, cctx.Index) - require.True(t, found) - _, found = k.GetInTxTracker(ctx, senderChain.ChainId, hash.String()) - require.False(t, found) - }) -} - -func GetERC20Cctx(t *testing.T, receiver ethcommon.Address, senderChain common.Chain, asset string, amount *big.Int) *types.CrossChainTx { - cctx := sample.CrossChainTx(t, "test") - cctx.CctxStatus = &types.Status{Status: types.CctxStatus_PendingInbound} - cctx.GetCurrentOutTxParam().Receiver = receiver.String() - cctx.GetInboundTxParams().Amount = sdkmath.NewUintFromBigInt(amount) - cctx.GetInboundTxParams().SenderChainId = senderChain.ChainId - cctx.GetCurrentOutTxParam().ReceiverChainId = senderChain.ChainId - cctx.CoinType = common.CoinType_ERC20 - cctx.RelayedMessage = "" - cctx.GetInboundTxParams().Asset = asset - cctx.GetInboundTxParams().Sender = sample.EthAddress().String() - cctx.GetCurrentOutTxParam().OutboundTxTssNonce = 42 - cctx.GetCurrentOutTxParam().OutboundTxGasUsed = 100 - cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasLimit = 100 - return cctx -} diff --git a/x/crosschain/keeper/evm_deposit.go b/x/crosschain/keeper/evm_deposit.go index b65974d419..ed528a4268 100644 --- a/x/crosschain/keeper/evm_deposit.go +++ b/x/crosschain/keeper/evm_deposit.go @@ -24,7 +24,7 @@ func (k Keeper) HandleEVMDeposit(ctx sdk.Context, cctx *types.CrossChainTx) (boo inboundAmount := cctx.GetInboundTxParams().Amount.BigInt() inboundSender := cctx.GetInboundTxParams().Sender inboundSenderChainID := cctx.GetInboundTxParams().SenderChainId - inboundCoinType := cctx.CoinType + inboundCoinType := cctx.InboundTxParams.CoinType if len(ctx.TxBytes()) > 0 { // add event for tendermint transaction hash format hash := tmbytes.HexBytes(tmtypes.Tx(ctx.TxBytes()).Hash()) diff --git a/x/crosschain/keeper/evm_deposit_test.go b/x/crosschain/keeper/evm_deposit_test.go index 26bc2d1039..b3daede09a 100644 --- a/x/crosschain/keeper/evm_deposit_test.go +++ b/x/crosschain/keeper/evm_deposit_test.go @@ -34,7 +34,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = receiver.String() cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_Zeta + cctx.GetInboundTxParams().CoinType = common.CoinType_Zeta cctx.GetInboundTxParams().SenderChainId = 0 reverted, err := k.HandleEVMDeposit( ctx, @@ -63,7 +63,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = receiver.String() cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_Zeta + cctx.GetInboundTxParams().CoinType = common.CoinType_Zeta cctx.GetInboundTxParams().SenderChainId = 0 reverted, err := k.HandleEVMDeposit( ctx, @@ -103,7 +103,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = receiver.String() cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_ERC20 + cctx.GetInboundTxParams().CoinType = common.CoinType_ERC20 cctx.GetInboundTxParams().Sender = sample.EthAddress().String() cctx.GetInboundTxParams().SenderChainId = senderChain cctx.RelayedMessage = "" @@ -147,7 +147,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = receiver.String() cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_ERC20 + cctx.GetInboundTxParams().CoinType = common.CoinType_ERC20 cctx.GetInboundTxParams().Sender = sample.EthAddress().String() cctx.GetInboundTxParams().SenderChainId = senderChain cctx.RelayedMessage = "" @@ -191,7 +191,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = receiver.String() cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_ERC20 + cctx.InboundTxParams.CoinType = common.CoinType_ERC20 cctx.GetInboundTxParams().Sender = sample.EthAddress().String() cctx.GetInboundTxParams().SenderChainId = senderChain cctx.RelayedMessage = "" @@ -234,7 +234,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = receiver.String() cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_ERC20 + cctx.GetInboundTxParams().CoinType = common.CoinType_ERC20 cctx.GetInboundTxParams().Sender = sample.EthAddress().String() cctx.GetInboundTxParams().SenderChainId = senderChain cctx.RelayedMessage = "" @@ -277,7 +277,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = receiver.String() cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_ERC20 + cctx.GetInboundTxParams().CoinType = common.CoinType_ERC20 cctx.GetInboundTxParams().Sender = sample.EthAddress().String() cctx.GetInboundTxParams().SenderChainId = senderChain cctx.RelayedMessage = "" @@ -318,7 +318,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = receiver.String() cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_ERC20 + cctx.GetInboundTxParams().CoinType = common.CoinType_ERC20 cctx.GetInboundTxParams().Sender = sample.EthAddress().String() cctx.GetInboundTxParams().SenderChainId = senderChain cctx.RelayedMessage = "" @@ -341,7 +341,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = sample.EthAddress().String() cctx.GetInboundTxParams().Amount = math.NewUint(42) - cctx.CoinType = common.CoinType_Gas + cctx.GetInboundTxParams().CoinType = common.CoinType_Gas cctx.GetInboundTxParams().Sender = sample.EthAddress().String() cctx.GetInboundTxParams().SenderChainId = senderChain cctx.RelayedMessage = "not_hex" @@ -381,7 +381,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = sample.EthAddress().String() cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_ERC20 + cctx.GetInboundTxParams().CoinType = common.CoinType_ERC20 cctx.GetInboundTxParams().Sender = sample.EthAddress().String() cctx.GetInboundTxParams().SenderChainId = senderChain cctx.RelayedMessage = receiver.Hex()[2:] + "DEADBEEF" @@ -423,7 +423,7 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) { cctx := sample.CrossChainTx(t, "foo") cctx.GetCurrentOutTxParam().Receiver = receiver.String() cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount) - cctx.CoinType = common.CoinType_ERC20 + cctx.GetInboundTxParams().CoinType = common.CoinType_ERC20 cctx.GetInboundTxParams().Sender = sample.EthAddress().String() cctx.GetInboundTxParams().SenderChainId = senderChain cctx.RelayedMessage = "DEADBEEF" diff --git a/x/crosschain/keeper/gas_payment.go b/x/crosschain/keeper/gas_payment.go index a7d99dea3d..a085e9cc7d 100644 --- a/x/crosschain/keeper/gas_payment.go +++ b/x/crosschain/keeper/gas_payment.go @@ -28,7 +28,7 @@ func (k Keeper) PayGasAndUpdateCctx( noEthereumTxEvent bool, ) error { // Dispatch to the correct function based on the coin type - switch cctx.CoinType { + switch cctx.InboundTxParams.CoinType { case common.CoinType_Zeta: return k.PayGasInZetaAndUpdateCctx(ctx, chainID, cctx, inputAmount, noEthereumTxEvent) case common.CoinType_Gas: @@ -37,7 +37,7 @@ func (k Keeper) PayGasAndUpdateCctx( return k.PayGasInERC20AndUpdateCctx(ctx, chainID, cctx, inputAmount, noEthereumTxEvent) default: // can't pay gas with coin type - return fmt.Errorf("can't pay gas with coin type %s", cctx.CoinType.String()) + return fmt.Errorf("can't pay gas with coin type %s", cctx.InboundTxParams.CoinType.String()) } } @@ -90,8 +90,8 @@ func (k Keeper) PayGasNativeAndUpdateCctx( inputAmount math.Uint, ) error { // preliminary checks - if cctx.CoinType != common.CoinType_Gas { - return cosmoserrors.Wrapf(types.ErrInvalidCoinType, "can't pay gas in native gas with %s", cctx.CoinType.String()) + if cctx.InboundTxParams.CoinType != common.CoinType_Gas { + return cosmoserrors.Wrapf(types.ErrInvalidCoinType, "can't pay gas in native gas with %s", cctx.InboundTxParams.CoinType.String()) } if chain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, chainID); chain == nil { return observertypes.ErrSupportedChains @@ -137,8 +137,8 @@ func (k Keeper) PayGasInERC20AndUpdateCctx( noEthereumTxEvent bool, ) error { // preliminary checks - if cctx.CoinType != common.CoinType_ERC20 { - return cosmoserrors.Wrapf(types.ErrInvalidCoinType, "can't pay gas in erc20 with %s", cctx.CoinType.String()) + if cctx.InboundTxParams.CoinType != common.CoinType_ERC20 { + return cosmoserrors.Wrapf(types.ErrInvalidCoinType, "can't pay gas in erc20 with %s", cctx.InboundTxParams.CoinType.String()) } if chain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, chainID); chain == nil { @@ -262,8 +262,8 @@ func (k Keeper) PayGasInZetaAndUpdateCctx( noEthereumTxEvent bool, ) error { // preliminary checks - if cctx.CoinType != common.CoinType_Zeta { - return cosmoserrors.Wrapf(types.ErrInvalidCoinType, "can't pay gas in zeta with %s", cctx.CoinType.String()) + if cctx.InboundTxParams.CoinType != common.CoinType_Zeta { + return cosmoserrors.Wrapf(types.ErrInvalidCoinType, "can't pay gas in zeta with %s", cctx.InboundTxParams.CoinType.String()) } if chain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, chainID); chain == nil { diff --git a/x/crosschain/keeper/gas_payment_test.go b/x/crosschain/keeper/gas_payment_test.go index e51c75566c..3de3f08a50 100644 --- a/x/crosschain/keeper/gas_payment_test.go +++ b/x/crosschain/keeper/gas_payment_test.go @@ -46,10 +46,13 @@ func TestKeeper_PayGasNativeAndUpdateCctx(t *testing.T) { // create a cctx reverted from zeta cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_Gas, + InboundTxParams: &types.InboundTxParams{ + CoinType: zetacommon.CoinType_Gas, + }, OutboundTxParams: []*types.OutboundTxParams{ { ReceiverChainId: zetacommon.ZetaPrivnetChain().ChainId, + CoinType: zetacommon.CoinType_Gas, }, { ReceiverChainId: chainID, @@ -70,7 +73,9 @@ func TestKeeper_PayGasNativeAndUpdateCctx(t *testing.T) { k, ctx, _, _ := testkeeper.CrosschainKeeper(t) chainID := getValidEthChainID(t) cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_Zeta, + InboundTxParams: &types.InboundTxParams{ + CoinType: zetacommon.CoinType_Zeta, + }, } err := k.PayGasNativeAndUpdateCctx(ctx, chainID, &cctx, math.NewUint(inputAmount)) require.ErrorIs(t, err, types.ErrInvalidCoinType) @@ -79,7 +84,9 @@ func TestKeeper_PayGasNativeAndUpdateCctx(t *testing.T) { t.Run("should fail if chain is not supported", func(t *testing.T) { k, ctx, _, _ := testkeeper.CrosschainKeeper(t) cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_Gas, + InboundTxParams: &types.InboundTxParams{ + CoinType: zetacommon.CoinType_Gas, + }, } err := k.PayGasNativeAndUpdateCctx(ctx, 999999, &cctx, math.NewUint(inputAmount)) require.ErrorIs(t, err, observertypes.ErrSupportedChains) @@ -97,7 +104,9 @@ func TestKeeper_PayGasNativeAndUpdateCctx(t *testing.T) { // create a cctx reverted from zeta cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_Gas, + InboundTxParams: &types.InboundTxParams{ + CoinType: zetacommon.CoinType_Gas, + }, OutboundTxParams: []*types.OutboundTxParams{ { ReceiverChainId: zetacommon.ZetaPrivnetChain().ChainId, @@ -132,10 +141,10 @@ func TestKeeper_PayGasNativeAndUpdateCctx(t *testing.T) { }) cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_Gas, InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sample.EthAddress().String(), + CoinType: zetacommon.CoinType_Gas, }, OutboundTxParams: []*types.OutboundTxParams{ { @@ -195,9 +204,10 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { // create a cctx reverted from zeta cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_ERC20, + InboundTxParams: &types.InboundTxParams{ - Asset: assetAddress, + Asset: assetAddress, + CoinType: zetacommon.CoinType_ERC20, }, OutboundTxParams: []*types.OutboundTxParams{ { @@ -227,7 +237,9 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { k, ctx, _, _ := testkeeper.CrosschainKeeper(t) chainID := getValidEthChainID(t) cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_Zeta, + InboundTxParams: &types.InboundTxParams{ + CoinType: zetacommon.CoinType_Zeta, + }, } err := k.PayGasInERC20AndUpdateCctx(ctx, chainID, &cctx, math.NewUint(inputAmount), false) require.ErrorIs(t, err, types.ErrInvalidCoinType) @@ -236,7 +248,9 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { t.Run("should fail if chain is not supported", func(t *testing.T) { k, ctx, _, _ := testkeeper.CrosschainKeeper(t) cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_ERC20, + InboundTxParams: &types.InboundTxParams{ + CoinType: zetacommon.CoinType_ERC20, + }, } err := k.PayGasInERC20AndUpdateCctx(ctx, 999999, &cctx, math.NewUint(inputAmount), false) require.ErrorIs(t, err, observertypes.ErrSupportedChains) @@ -254,7 +268,9 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { // create a cctx reverted from zeta cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_ERC20, + InboundTxParams: &types.InboundTxParams{ + CoinType: zetacommon.CoinType_ERC20, + }, OutboundTxParams: []*types.OutboundTxParams{ { ReceiverChainId: zetacommon.ZetaPrivnetChain().ChainId, @@ -293,9 +309,9 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { // create a cctx reverted from zeta cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_ERC20, InboundTxParams: &types.InboundTxParams{ - Asset: assetAddress, + Asset: assetAddress, + CoinType: zetacommon.CoinType_ERC20, }, OutboundTxParams: []*types.OutboundTxParams{ { @@ -345,9 +361,9 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { // create a cctx reverted from zeta cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_ERC20, InboundTxParams: &types.InboundTxParams{ - Asset: assetAddress, + Asset: assetAddress, + CoinType: zetacommon.CoinType_ERC20, }, OutboundTxParams: []*types.OutboundTxParams{ { @@ -403,9 +419,9 @@ func TestKeeper_PayGasInERC20AndUpdateCctx(t *testing.T) { // create a cctx reverted from zeta cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_ERC20, InboundTxParams: &types.InboundTxParams{ - Asset: assetAddress, + Asset: assetAddress, + CoinType: zetacommon.CoinType_ERC20, }, OutboundTxParams: []*types.OutboundTxParams{ { @@ -448,7 +464,9 @@ func TestKeeper_PayGasInZetaAndUpdateCctx(t *testing.T) { // create a cctx reverted from zeta cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_Zeta, + InboundTxParams: &types.InboundTxParams{ + CoinType: zetacommon.CoinType_Zeta, + }, OutboundTxParams: []*types.OutboundTxParams{ { ReceiverChainId: chainID, @@ -472,7 +490,9 @@ func TestKeeper_PayGasInZetaAndUpdateCctx(t *testing.T) { // can call with undefined zeta fees cctx = types.CrossChainTx{ - CoinType: zetacommon.CoinType_Zeta, + InboundTxParams: &types.InboundTxParams{ + CoinType: zetacommon.CoinType_Zeta, + }, OutboundTxParams: []*types.OutboundTxParams{ { ReceiverChainId: chainID, @@ -495,7 +515,9 @@ func TestKeeper_PayGasInZetaAndUpdateCctx(t *testing.T) { k, ctx, _, _ := testkeeper.CrosschainKeeper(t) chainID := getValidEthChainID(t) cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_Gas, + InboundTxParams: &types.InboundTxParams{ + CoinType: zetacommon.CoinType_Gas, + }, } err := k.PayGasInZetaAndUpdateCctx(ctx, chainID, &cctx, math.NewUint(100000), false) require.ErrorIs(t, err, types.ErrInvalidCoinType) @@ -504,7 +526,9 @@ func TestKeeper_PayGasInZetaAndUpdateCctx(t *testing.T) { t.Run("should fail if chain is not supported", func(t *testing.T) { k, ctx, _, _ := testkeeper.CrosschainKeeper(t) cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_Zeta, + InboundTxParams: &types.InboundTxParams{ + CoinType: zetacommon.CoinType_Zeta, + }, } err := k.PayGasInZetaAndUpdateCctx(ctx, 999999, &cctx, math.NewUint(100000), false) require.ErrorIs(t, err, observertypes.ErrSupportedChains) @@ -524,10 +548,10 @@ func TestKeeper_PayGasInZetaAndUpdateCctx(t *testing.T) { // create a cctx reverted from zeta cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_Zeta, InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sample.EthAddress().String(), + CoinType: zetacommon.CoinType_Zeta, }, OutboundTxParams: []*types.OutboundTxParams{ { @@ -558,10 +582,10 @@ func TestKeeper_PayGasInZetaAndUpdateCctx(t *testing.T) { // create a cctx reverted from zeta cctx := types.CrossChainTx{ - CoinType: zetacommon.CoinType_Zeta, InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sample.EthAddress().String(), + CoinType: zetacommon.CoinType_Zeta, }, OutboundTxParams: []*types.OutboundTxParams{ { diff --git a/x/crosschain/keeper/migrator.go b/x/crosschain/keeper/migrator.go index 51fe3a8f7d..4de64140c8 100644 --- a/x/crosschain/keeper/migrator.go +++ b/x/crosschain/keeper/migrator.go @@ -6,7 +6,6 @@ import ( v3 "github.com/zeta-chain/zetacore/x/crosschain/migrations/v3" v4 "github.com/zeta-chain/zetacore/x/crosschain/migrations/v4" v5 "github.com/zeta-chain/zetacore/x/crosschain/migrations/v5" - v6 "github.com/zeta-chain/zetacore/x/crosschain/migrations/v6" ) // Migrator is a struct for handling in-place store migrations. @@ -40,7 +39,3 @@ func (m Migrator) Migrate3to4(ctx sdk.Context) error { func (m Migrator) Migrate4to5(ctx sdk.Context) error { return v5.MigrateStore(ctx, m.crossChainKeeper, m.crossChainKeeper.zetaObserverKeeper) } - -func (m Migrator) Migrate5to6(ctx sdk.Context) error { - return v6.MigrateStore(ctx, m.crossChainKeeper) -} diff --git a/x/crosschain/keeper/msg_server_migrate_tss_funds.go b/x/crosschain/keeper/msg_server_migrate_tss_funds.go index afdb656331..3a76462b4f 100644 --- a/x/crosschain/keeper/msg_server_migrate_tss_funds.go +++ b/x/crosschain/keeper/msg_server_migrate_tss_funds.go @@ -78,9 +78,11 @@ func (k Keeper) MigrateTSSFundsForChain(ctx sdk.Context, chainID int64, amount s hash := crypto.Keccak256Hash([]byte(indexString)) index := hash.Hex() + + // TODO : Use the `CreateNewCctx` function to create the cctx + // https://github.com/zeta-chain/node/issues/1909 cctx := types.CrossChainTx{ Creator: "", - CoinType: common.CoinType_Cmd, Index: index, ZetaFees: sdkmath.Uint{}, RelayedMessage: fmt.Sprintf("%s:%s", common.CmdMigrateTssFunds, "Funds Migrator Admin Cmd"), @@ -99,6 +101,7 @@ func (k Keeper) MigrateTSSFundsForChain(ctx sdk.Context, chainID int64, amount s InboundTxObservedExternalHeight: 0, InboundTxBallotIndex: "", InboundTxFinalizedZetaHeight: 0, + CoinType: common.CoinType_Cmd, }, OutboundTxParams: []*types.OutboundTxParams{{ Receiver: "", @@ -114,6 +117,7 @@ func (k Keeper) MigrateTSSFundsForChain(ctx sdk.Context, chainID int64, amount s OutboundTxEffectiveGasPrice: sdkmath.Int{}, OutboundTxEffectiveGasLimit: 0, TssPubkey: currentTss.TssPubkey, + CoinType: common.CoinType_Cmd, }}} // Set the sender and receiver addresses for EVM chain if common.IsEVMChain(chainID) { diff --git a/x/crosschain/keeper/msg_server_refund_aborted_tx.go b/x/crosschain/keeper/msg_server_refund_aborted_tx.go index c79c6d81ff..fc651ec249 100644 --- a/x/crosschain/keeper/msg_server_refund_aborted_tx.go +++ b/x/crosschain/keeper/msg_server_refund_aborted_tx.go @@ -43,7 +43,7 @@ func (k msgServer) RefundAbortedCCTX(goCtx context.Context, msg *types.MsgRefund } // Check if aborted amount is available to maintain zeta accounting - if cctx.CoinType == common.CoinType_Zeta { + if cctx.InboundTxParams.CoinType == common.CoinType_Zeta { err := k.RemoveZetaAbortedAmount(ctx, GetAbortedAmount(cctx)) // if the zeta accounting is not found, it means the zeta accounting is not set yet and the refund should not be processed if errors.Is(err, types.ErrUnableToFindZetaAccounting) { diff --git a/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go b/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go index 3331bc1e6d..1c6f7da680 100644 --- a/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go +++ b/x/crosschain/keeper/msg_server_refund_aborted_tx_test.go @@ -55,7 +55,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Gas + cctx.InboundTxParams.CoinType = common.CoinType_Gas k.SetCrossChainTx(ctx, *cctx) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) zrc20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, cctx.InboundTxParams.SenderChainId, "foobar", "foobar") @@ -94,7 +94,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Zeta + cctx.InboundTxParams.CoinType = common.CoinType_Zeta k.SetCrossChainTx(ctx, *cctx) k.SetZetaAccounting(ctx, crosschaintypes.ZetaAccounting{AbortedZetaAmount: cctx.GetCurrentOutTxParam().Amount}) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -133,7 +133,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Zeta + cctx.InboundTxParams.CoinType = common.CoinType_Zeta cctx.OutboundTxParams = nil k.SetCrossChainTx(ctx, *cctx) k.SetZetaAccounting(ctx, crosschaintypes.ZetaAccounting{AbortedZetaAmount: cctx.GetCurrentOutTxParam().Amount}) @@ -173,7 +173,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Zeta + cctx.InboundTxParams.CoinType = common.CoinType_Zeta k.SetCrossChainTx(ctx, *cctx) k.SetZetaAccounting(ctx, crosschaintypes.ZetaAccounting{AbortedZetaAmount: cctx.InboundTxParams.Amount}) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -212,7 +212,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.Status = crosschaintypes.CctxStatus_Aborted cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_ERC20 + cctx.InboundTxParams.CoinType = common.CoinType_ERC20 cctx.InboundTxParams.Asset = asset k.SetCrossChainTx(ctx, *cctx) // deploy zrc20 @@ -262,7 +262,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Gas + cctx.InboundTxParams.CoinType = common.CoinType_Gas k.SetCrossChainTx(ctx, *cctx) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) zrc20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, cctx.InboundTxParams.SenderChainId, "foobar", "foobar") @@ -301,7 +301,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Zeta + cctx.InboundTxParams.CoinType = common.CoinType_Zeta k.SetCrossChainTx(ctx, *cctx) k.SetZetaAccounting(ctx, crosschaintypes.ZetaAccounting{AbortedZetaAmount: cctx.InboundTxParams.Amount}) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -332,7 +332,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Zeta + cctx.InboundTxParams.CoinType = common.CoinType_Zeta k.SetCrossChainTx(ctx, *cctx) k.SetZetaAccounting(ctx, crosschaintypes.ZetaAccounting{AbortedZetaAmount: cctx.InboundTxParams.Amount}) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -363,7 +363,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Gas + cctx.InboundTxParams.CoinType = common.CoinType_Gas k.SetCrossChainTx(ctx, *cctx) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -396,7 +396,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Gas + cctx.InboundTxParams.CoinType = common.CoinType_Gas deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) _, err := msgServer.RefundAbortedCCTX(ctx, &crosschaintypes.MsgRefundAbortedCCTX{ @@ -425,7 +425,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Gas + cctx.InboundTxParams.CoinType = common.CoinType_Gas k.SetCrossChainTx(ctx, *cctx) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) _ = setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, cctx.InboundTxParams.SenderChainId, "foobar", "foobar") @@ -456,7 +456,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Zeta + cctx.InboundTxParams.CoinType = common.CoinType_Zeta k.SetCrossChainTx(ctx, *cctx) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) @@ -486,7 +486,7 @@ func TestMsgServer_RefundAbortedCCTX(t *testing.T) { cctx.CctxStatus.IsAbortRefunded = false cctx.InboundTxParams.TxOrigin = cctx.InboundTxParams.Sender cctx.InboundTxParams.SenderChainId = chainID - cctx.CoinType = common.CoinType_Gas + cctx.InboundTxParams.CoinType = common.CoinType_Gas k.SetCrossChainTx(ctx, *cctx) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) _ = setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, cctx.InboundTxParams.SenderChainId, "foobar", "foobar") diff --git a/x/crosschain/keeper/msg_server_vote_inbound_tx.go b/x/crosschain/keeper/msg_server_vote_inbound_tx.go index b59b538517..6a78d66844 100644 --- a/x/crosschain/keeper/msg_server_vote_inbound_tx.go +++ b/x/crosschain/keeper/msg_server_vote_inbound_tx.go @@ -5,7 +5,9 @@ import ( "fmt" cosmoserrors "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/zeta-chain/zetacore/common" "github.com/zeta-chain/zetacore/x/crosschain/types" ) @@ -95,6 +97,201 @@ func (k msgServer) VoteOnObservedInboundTx(goCtx context.Context, msg *types.Msg return nil, err } k.ProcessInbound(ctx, &inboundCctx) - k.SaveInbound(ctx, &inboundCctx) + k.SaveInbound(ctx, &inboundCctx, msg.EventIndex) return &types.MsgVoteOnObservedInboundTxResponse{}, nil } + +// GetInbound returns a new CCTX from a given inbound message. +func (k Keeper) GetInbound(ctx sdk.Context, msg *types.MsgVoteOnObservedInboundTx) types.CrossChainTx { + + // get the latest TSS to set the TSS public key in the CCTX + tssPub := "" + tss, tssFound := k.zetaObserverKeeper.GetTSS(ctx) + if tssFound { + tssPub = tss.TssPubkey + } + return CreateNewCCTX(ctx, msg, msg.Digest(), tssPub, types.CctxStatus_PendingInbound, msg.SenderChainId, msg.ReceiverChain) +} + +// CreateNewCCTX creates a new CCTX with the given parameters. +func CreateNewCCTX( + ctx sdk.Context, + msg *types.MsgVoteOnObservedInboundTx, + index string, + tssPubkey string, + s types.CctxStatus, + senderChainID, + receiverChainID int64, +) types.CrossChainTx { + if msg.TxOrigin == "" { + msg.TxOrigin = msg.Sender + } + inboundParams := &types.InboundTxParams{ + Sender: msg.Sender, + SenderChainId: senderChainID, + TxOrigin: msg.TxOrigin, + Asset: msg.Asset, + Amount: msg.Amount, + InboundTxObservedHash: msg.InTxHash, + InboundTxObservedExternalHeight: msg.InBlockHeight, + InboundTxFinalizedZetaHeight: 0, + InboundTxBallotIndex: index, + CoinType: msg.CoinType, + } + + outBoundParams := &types.OutboundTxParams{ + Receiver: msg.Receiver, + ReceiverChainId: receiverChainID, + OutboundTxHash: "", + OutboundTxTssNonce: 0, + OutboundTxGasLimit: msg.GasLimit, + OutboundTxGasPrice: "", + OutboundTxBallotIndex: "", + OutboundTxObservedExternalHeight: 0, + Amount: sdkmath.ZeroUint(), + TssPubkey: tssPubkey, + CoinType: msg.CoinType, + } + status := &types.Status{ + Status: s, + StatusMessage: "", + LastUpdateTimestamp: ctx.BlockHeader().Time.Unix(), + IsAbortRefunded: false, + } + newCctx := types.CrossChainTx{ + Creator: msg.Creator, + Index: index, + ZetaFees: sdkmath.ZeroUint(), + RelayedMessage: msg.Message, + CctxStatus: status, + InboundTxParams: inboundParams, + OutboundTxParams: []*types.OutboundTxParams{outBoundParams}, + } + return newCctx +} + +// ProcessInbound processes the inbound CCTX. +// It does a conditional dispatch to ProcessZEVMDeposit or ProcessCrosschainMsgPassing based on the receiver chain. +func (k Keeper) ProcessInbound(ctx sdk.Context, cctx *types.CrossChainTx) { + if common.IsZetaChain(cctx.GetCurrentOutTxParam().ReceiverChainId) { + k.ProcessZEVMDeposit(ctx, cctx) + } else { + k.ProcessCrosschainMsgPassing(ctx, cctx) + } +} + +// ProcessZEVMDeposit processes the EVM deposit CCTX. A deposit is a cctx which has Zetachain as the receiver chain. +// If the deposit is successful, the CCTX status is changed to OutboundMined. +// If the deposit returns an internal error i.e if HandleEVMDeposit() returns an error, but isContractReverted is false, the CCTX status is changed to Aborted. +// If the deposit is reverted, the function tries to create a revert cctx with status PendingRevert. +// If the creation of revert tx also fails it changes the status to Aborted. +// Note : Aborted CCTXs are not refunded in this function. The refund is done using a separate refunding mechanism. +// We do not return an error from this function , as all changes need to be persisted to the state. +// Instead we use a temporary context to make changes and then commit the context on for the happy path ,i.e cctx is set to OutboundMined. +func (k Keeper) ProcessZEVMDeposit(ctx sdk.Context, cctx *types.CrossChainTx) { + tmpCtx, commit := ctx.CacheContext() + isContractReverted, err := k.HandleEVMDeposit(tmpCtx, cctx) + + if err != nil && !isContractReverted { // exceptional case; internal error; should abort CCTX + cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, err.Error()) + return + } else if err != nil && isContractReverted { // contract call reverted; should refund + revertMessage := err.Error() + senderChain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, cctx.InboundTxParams.SenderChainId) + if senderChain == nil { + cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, "invalid sender chain") + return + } + + gasLimit, err := k.GetRevertGasLimit(ctx, cctx) + if err != nil { + cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, fmt.Sprintf("can't get revert tx gas limit,%s", err.Error())) + return + } + if gasLimit == 0 { + // use same gas limit of outbound as a fallback -- should not happen + gasLimit = cctx.GetCurrentOutTxParam().OutboundTxGasLimit + } + + // create new OutboundTxParams for the revert + revertTxParams := &types.OutboundTxParams{ + Receiver: cctx.InboundTxParams.Sender, + ReceiverChainId: cctx.InboundTxParams.SenderChainId, + Amount: cctx.InboundTxParams.Amount, + OutboundTxGasLimit: gasLimit, + } + cctx.OutboundTxParams = append(cctx.OutboundTxParams, revertTxParams) + + // we create a new cached context, and we don't commit the previous one with EVM deposit + tmpCtxRevert, commitRevert := ctx.CacheContext() + err = func() error { + err := k.PayGasAndUpdateCctx( + tmpCtxRevert, + senderChain.ChainId, + cctx, + cctx.InboundTxParams.Amount, + false, + ) + if err != nil { + return err + } + // Update nonce using senderchain id as this is a revert tx and would go back to the original sender + return k.UpdateNonce(tmpCtxRevert, senderChain.ChainId, cctx) + }() + if err != nil { + cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, fmt.Sprintf("deposit revert message: %s err : %s", revertMessage, err.Error())) + return + } + commitRevert() + cctx.CctxStatus.ChangeStatus(types.CctxStatus_PendingRevert, revertMessage) + return + } + // successful HandleEVMDeposit; + commit() + cctx.CctxStatus.ChangeStatus(types.CctxStatus_OutboundMined, "Remote omnichain contract call completed") + return +} + +// ProcessCrosschainMsgPassing processes the CCTX for crosschain message passing. A crosschain message passing is a cctx which has a non-Zetachain as the receiver chain. +// If the crosschain message passing is successful, the CCTX status is changed to PendingOutbound. +// If the crosschain message passing returns an error, the CCTX status is changed to Aborted. +// We do not return an error from this function , as all changes need to be persisted to the state. +// Instead we use a temporary context to make changes and then commit the context on for the happy path ,i.e cctx is set to PendingOutbound. +func (k Keeper) ProcessCrosschainMsgPassing(ctx sdk.Context, cctx *types.CrossChainTx) { + tmpCtx, commit := ctx.CacheContext() + outboundReceiverChainID := cctx.GetCurrentOutTxParam().ReceiverChainId + err := func() error { + err := k.PayGasAndUpdateCctx( + tmpCtx, + outboundReceiverChainID, + cctx, + cctx.InboundTxParams.Amount, + false, + ) + if err != nil { + return err + } + return k.UpdateNonce(tmpCtx, outboundReceiverChainID, cctx) + }() + if err != nil { + // do not commit anything here as the CCTX should be aborted + cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, err.Error()) + return + } + commit() + cctx.CctxStatus.ChangeStatus(types.CctxStatus_PendingOutbound, "") + return +} + +func (k Keeper) SaveInbound(ctx sdk.Context, cctx *types.CrossChainTx, eventIndex uint64) { + EmitEventInboundFinalized(ctx, cctx) + k.AddFinalizedInbound(ctx, + cctx.GetInboundTxParams().InboundTxObservedHash, + cctx.GetInboundTxParams().SenderChainId, + eventIndex) + // #nosec G701 always positive + cctx.InboundTxParams.InboundTxFinalizedZetaHeight = uint64(ctx.BlockHeight()) + cctx.InboundTxParams.TxFinalizationStatus = types.TxFinalizationStatus_Executed + k.RemoveInTxTrackerIfExists(ctx, cctx.InboundTxParams.SenderChainId, cctx.InboundTxParams.InboundTxObservedHash) + k.SetCctxAndNonceToCctxAndInTxHashToCctx(ctx, *cctx) +} diff --git a/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go b/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go index 803de84576..3b27ebb1a0 100644 --- a/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go +++ b/x/crosschain/keeper/msg_server_vote_inbound_tx_test.go @@ -2,16 +2,21 @@ package keeper_test import ( "encoding/hex" + "fmt" + "math/big" "testing" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + ethcommon "github.com/ethereum/go-ethereum/common" + "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/keeper" "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" ) @@ -199,3 +204,437 @@ func TestStatus_ChangeStatus(t *testing.T) { }) } } + +func TestKeeper_ProcessZEVMDeposit(t *testing.T) { + t.Run("process zevm deposit successfully", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + + // expect DepositCoinZeta to be called + fungibleMock.On("DepositCoinZeta", mock.Anything, receiver, amount). + Return(nil) + + // call ProcessZEVMDeposit + cctx := sample.CrossChainTx(t, "test") + cctx.CctxStatus = &types.Status{Status: types.CctxStatus_PendingInbound} + cctx.GetCurrentOutTxParam().Receiver = receiver.String() + cctx.GetInboundTxParams().Amount = sdkmath.NewUintFromBigInt(amount) + cctx.InboundTxParams.CoinType = common.CoinType_Zeta + cctx.GetInboundTxParams().SenderChainId = 0 + k.ProcessZEVMDeposit(ctx, cctx) + require.Equal(t, types.CctxStatus_OutboundMined, cctx.CctxStatus.Status) + }) + + t.Run("unable to process zevm deposit HandleEVMDeposit returns err without reverting", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + + // mock unsuccessful HandleEVMDeposit which does not revert + fungibleMock.On("DepositCoinZeta", mock.Anything, receiver, amount). + Return(fmt.Errorf("deposit error"), false) + + // call ProcessZEVMDeposit + cctx := sample.CrossChainTx(t, "test") + cctx.CctxStatus = &types.Status{Status: types.CctxStatus_PendingInbound} + cctx.GetCurrentOutTxParam().Receiver = receiver.String() + cctx.GetInboundTxParams().Amount = sdkmath.NewUintFromBigInt(amount) + cctx.InboundTxParams.CoinType = common.CoinType_Zeta + cctx.GetInboundTxParams().SenderChainId = 0 + k.ProcessZEVMDeposit(ctx, cctx) + require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) + require.Equal(t, "deposit error", cctx.CctxStatus.StatusMessage) + }) + + t.Run("unable to process zevm deposit HandleEVMDeposit reverts fails at GetSupportedChainFromChainID", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + errDeposit := fmt.Errorf("deposit failed") + + // Setup expected calls + // mock unsuccessful HandleEVMDeposit which reverts , i.e returns err and isContractReverted = true + keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) + + // mock unsuccessful GetSupportedChainFromChainID + observerMock.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). + Return(nil) + + // call ProcessZEVMDeposit + cctx := GetERC20Cctx(t, receiver, *senderChain, "", amount) + k.ProcessZEVMDeposit(ctx, cctx) + require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) + require.Equal(t, "invalid sender chain", cctx.CctxStatus.StatusMessage) + }) + + t.Run("unable to process zevm deposit HandleEVMDeposit revert fails at and GetRevertGasLimit", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + errDeposit := fmt.Errorf("deposit failed") + + // Setup expected calls + keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) + + // Mock successful GetSupportedChainFromChainID + keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) + + // mock unsuccessful GetRevertGasLimit for ERC20 + fungibleMock.On("GetForeignCoinFromAsset", mock.Anything, asset, senderChain.ChainId). + Return(fungibletypes.ForeignCoins{}, false) + + // call ProcessZEVMDeposit + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + k.ProcessZEVMDeposit(ctx, cctx) + require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) + require.Equal(t, fmt.Sprintf("can't get revert tx gas limit,%s", types.ErrForeignCoinNotFound), cctx.CctxStatus.StatusMessage) + }) + + t.Run("unable to process zevm deposit HandleEVMDeposit revert fails at PayGasInERC20AndUpdateCctx", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + + // Setup expected calls + errDeposit := fmt.Errorf("deposit failed") + keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + + // Mock successful GetSupportedChainFromChainID + keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) + + // mock successful GetRevertGasLimit for ERC20 + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + + // mock unsuccessful PayGasInERC20AndUpdateCctx + observerMock.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). + Return(nil).Once() + + // call ProcessZEVMDeposit + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + k.ProcessZEVMDeposit(ctx, cctx) + require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) + require.Equal(t, fmt.Sprintf("deposit revert message: %s err : %s", errDeposit, observertypes.ErrSupportedChains), cctx.CctxStatus.StatusMessage) + }) + + t.Run("unable to process zevm deposit HandleEVMDeposit reverts fails at UpdateNonce", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + errDeposit := fmt.Errorf("deposit failed") + + // Setup expected calls + // mock unsuccessful HandleEVMDeposit which reverts , i.e returns err and isContractReverted = true + keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) + + // Mock successful GetSupportedChainFromChainID + keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) + + // mock successful GetRevertGasLimit for ERC20 + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + + // mock successful PayGasAndUpdateCctx + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) + + // Mock unsuccessful UpdateNonce + observerMock.On("GetChainNonces", mock.Anything, senderChain.ChainName.String()). + Return(observertypes.ChainNonces{}, false) + + // call ProcessZEVMDeposit + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + k.ProcessZEVMDeposit(ctx, cctx) + require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) + require.Contains(t, cctx.CctxStatus.StatusMessage, "cannot find receiver chain nonce") + }) + + t.Run("unable to process zevm deposit HandleEVMDeposit revert successfully", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + errDeposit := fmt.Errorf("deposit failed") + + // Setup expected calls + // mock unsuccessful HandleEVMDeposit which reverts , i.e returns err and isContractReverted = true + keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) + + // Mock successful GetSupportedChainFromChainID + keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) + + // mock successful GetRevertGasLimit for ERC20 + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + + // mock successful PayGasAndUpdateCctx + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) + // mock successful UpdateNonce + updatedNonce := keepertest.MockUpdateNonce(observerMock, *senderChain) + + // call ProcessZEVMDeposit + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + k.ProcessZEVMDeposit(ctx, cctx) + require.Equal(t, types.CctxStatus_PendingRevert, cctx.CctxStatus.Status) + require.Equal(t, errDeposit.Error(), cctx.CctxStatus.StatusMessage) + require.Equal(t, updatedNonce, cctx.GetCurrentOutTxParam().OutboundTxTssNonce) + }) +} + +func TestKeeper_ProcessCrosschainMsgPassing(t *testing.T) { + t.Run("process crosschain msg passing successfully", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + receiverChain := getValidEthChain(t) + + // mock successful PayGasAndUpdateCctx + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *receiverChain, "") + + // mock successful UpdateNonce + updatedNonce := keepertest.MockUpdateNonce(observerMock, *receiverChain) + + // call ProcessCrosschainMsgPassing + cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) + k.ProcessCrosschainMsgPassing(ctx, cctx) + require.Equal(t, types.CctxStatus_PendingOutbound, cctx.CctxStatus.Status) + require.Equal(t, updatedNonce, cctx.GetCurrentOutTxParam().OutboundTxTssNonce) + }) + + t.Run("unable to process crosschain msg passing PayGasAndUpdateCctx fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + receiverChain := getValidEthChain(t) + + // mock unsuccessful PayGasAndUpdateCctx + observerMock.On("GetSupportedChainFromChainID", mock.Anything, receiverChain.ChainId). + Return(nil).Once() + + // call ProcessCrosschainMsgPassing + cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) + k.ProcessCrosschainMsgPassing(ctx, cctx) + require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) + require.Equal(t, observertypes.ErrSupportedChains.Error(), cctx.CctxStatus.StatusMessage) + }) + + t.Run("unable to process crosschain msg passing UpdateNonce fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + receiverChain := getValidEthChain(t) + + // mock successful PayGasAndUpdateCctx + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *receiverChain, "") + + // mock unsuccessful UpdateNonce + observerMock.On("GetChainNonces", mock.Anything, receiverChain.ChainName.String()). + Return(observertypes.ChainNonces{}, false) + + // call ProcessCrosschainMsgPassing + cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) + k.ProcessCrosschainMsgPassing(ctx, cctx) + require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) + require.Contains(t, cctx.CctxStatus.StatusMessage, "cannot find receiver chain nonce") + }) +} + +func TestKeeper_GetInbound(t *testing.T) { + t.Run("should return a cctx with correct values", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + senderChain := getValidEthChain(t) + sender := sample.EthAddress() + receiverChain := getValidEthChain(t) + receiver := sample.EthAddress() + creator := sample.AccAddress() + amount := sdkmath.NewUint(42) + message := "test" + intxBlockHeight := uint64(420) + intxHash := sample.Hash() + gasLimit := uint64(100) + asset := "test-asset" + eventIndex := uint64(1) + cointType := common.CoinType_ERC20 + tss := sample.Tss() + msg := types.MsgVoteOnObservedInboundTx{ + Creator: creator, + Sender: sender.String(), + SenderChainId: senderChain.ChainId, + Receiver: receiver.String(), + ReceiverChain: receiverChain.ChainId, + Amount: amount, + Message: message, + InTxHash: intxHash.String(), + InBlockHeight: intxBlockHeight, + GasLimit: gasLimit, + CoinType: cointType, + TxOrigin: sender.String(), + Asset: asset, + EventIndex: eventIndex, + } + zk.ObserverKeeper.SetTSS(ctx, tss) + cctx := k.GetInbound(ctx, &msg) + require.Equal(t, receiver.String(), cctx.GetCurrentOutTxParam().Receiver) + require.Equal(t, receiverChain.ChainId, cctx.GetCurrentOutTxParam().ReceiverChainId) + require.Equal(t, sender.String(), cctx.GetInboundTxParams().Sender) + require.Equal(t, senderChain.ChainId, cctx.GetInboundTxParams().SenderChainId) + require.Equal(t, amount, cctx.GetInboundTxParams().Amount) + require.Equal(t, message, cctx.RelayedMessage) + require.Equal(t, intxHash.String(), cctx.GetInboundTxParams().InboundTxObservedHash) + require.Equal(t, intxBlockHeight, cctx.GetInboundTxParams().InboundTxObservedExternalHeight) + require.Equal(t, gasLimit, cctx.GetCurrentOutTxParam().OutboundTxGasLimit) + require.Equal(t, asset, cctx.GetInboundTxParams().Asset) + require.Equal(t, cointType, cctx.InboundTxParams.CoinType) + require.Equal(t, uint64(0), cctx.GetCurrentOutTxParam().OutboundTxTssNonce) + require.Equal(t, sdkmath.ZeroUint(), cctx.GetCurrentOutTxParam().Amount) + require.Equal(t, types.CctxStatus_PendingInbound, cctx.CctxStatus.Status) + require.Equal(t, false, cctx.CctxStatus.IsAbortRefunded) + }) +} + +func TestKeeper_SaveInbound(t *testing.T) { + t.Run("should save the cctx", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + cctx := GetERC20Cctx(t, receiver, *senderChain, "", amount) + eventIndex := sample.Uint64InRange(1, 100) + k.SaveInbound(ctx, cctx, eventIndex) + require.Equal(t, types.TxFinalizationStatus_Executed, cctx.InboundTxParams.TxFinalizationStatus) + require.True(t, k.IsFinalizedInbound(ctx, cctx.GetInboundTxParams().InboundTxObservedHash, cctx.GetInboundTxParams().SenderChainId, eventIndex)) + _, found := k.GetCrossChainTx(ctx, cctx.Index) + require.True(t, found) + }) + + t.Run("should save the cctx and remove tracker", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + cctx := GetERC20Cctx(t, receiver, *senderChain, "", amount) + hash := sample.Hash() + cctx.InboundTxParams.InboundTxObservedHash = hash.String() + k.SetInTxTracker(ctx, types.InTxTracker{ + ChainId: senderChain.ChainId, + TxHash: hash.String(), + CoinType: 0, + }) + eventIndex := sample.Uint64InRange(1, 100) + + k.SaveInbound(ctx, cctx, eventIndex) + require.Equal(t, types.TxFinalizationStatus_Executed, cctx.InboundTxParams.TxFinalizationStatus) + require.True(t, k.IsFinalizedInbound(ctx, cctx.GetInboundTxParams().InboundTxObservedHash, cctx.GetInboundTxParams().SenderChainId, eventIndex)) + _, found := k.GetCrossChainTx(ctx, cctx.Index) + require.True(t, found) + _, found = k.GetInTxTracker(ctx, senderChain.ChainId, hash.String()) + require.False(t, found) + }) +} + +// GetERC20Cctx returns a sample CrossChainTx with ERC20 params. This is used for testing Inbound and Outbound voting transactions +func GetERC20Cctx(t *testing.T, receiver ethcommon.Address, senderChain common.Chain, asset string, amount *big.Int) *types.CrossChainTx { + r := sample.Rand() + cctx := &types.CrossChainTx{ + Creator: sample.AccAddress(), + Index: sample.ZetaIndex(t), + ZetaFees: sample.UintInRange(0, 100), + RelayedMessage: "", + CctxStatus: &types.Status{Status: types.CctxStatus_PendingInbound}, + InboundTxParams: sample.InboundTxParams(r), + OutboundTxParams: []*types.OutboundTxParams{sample.OutboundTxParams(r)}, + } + + cctx.GetInboundTxParams().Amount = sdkmath.NewUintFromBigInt(amount) + cctx.GetInboundTxParams().SenderChainId = senderChain.ChainId + cctx.GetInboundTxParams().InboundTxObservedHash = sample.Hash().String() + cctx.GetInboundTxParams().InboundTxBallotIndex = sample.ZetaIndex(t) + + cctx.GetCurrentOutTxParam().ReceiverChainId = senderChain.ChainId + cctx.GetCurrentOutTxParam().Receiver = receiver.String() + cctx.GetCurrentOutTxParam().OutboundTxHash = sample.Hash().String() + cctx.GetCurrentOutTxParam().OutboundTxBallotIndex = sample.ZetaIndex(t) + + cctx.InboundTxParams.CoinType = common.CoinType_ERC20 + for _, outboundTxParam := range cctx.OutboundTxParams { + outboundTxParam.CoinType = common.CoinType_ERC20 + } + + cctx.GetInboundTxParams().Asset = asset + cctx.GetInboundTxParams().Sender = sample.EthAddress().String() + cctx.GetCurrentOutTxParam().OutboundTxTssNonce = 42 + cctx.GetCurrentOutTxParam().OutboundTxGasUsed = 100 + cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasLimit = 100 + return cctx +} diff --git a/x/crosschain/keeper/msg_server_vote_outbound_tx.go b/x/crosschain/keeper/msg_server_vote_outbound_tx.go index 1602d86b25..09c2cd2cfc 100644 --- a/x/crosschain/keeper/msg_server_vote_outbound_tx.go +++ b/x/crosschain/keeper/msg_server_vote_outbound_tx.go @@ -2,10 +2,17 @@ package keeper import ( "context" + "fmt" + "math/big" + cosmoserrors "cosmossdk.io/errors" + "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/zeta-chain/zetacore/common" "github.com/zeta-chain/zetacore/x/crosschain/types" observerkeeper "github.com/zeta-chain/zetacore/x/observer/keeper" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) // VoteOnObservedOutboundTx casts a vote on an outbound transaction observed on a connected chain (after @@ -98,3 +105,238 @@ func (k msgServer) VoteOnObservedOutboundTx(goCtx context.Context, msg *types.Ms k.SaveSuccessfulOutBound(ctx, &cctx, ballotIndex) return &types.MsgVoteOnObservedOutboundTxResponse{}, nil } + +// SetRevertOutboundValues does the following things in one function: +// 1. create a new OutboundTxParams for the revert +// 2. append the new OutboundTxParams to the current OutboundTxParams +// 3. update the TxFinalizationStatus of the current OutboundTxParams to Executed. +func SetRevertOutboundValues(cctx *types.CrossChainTx, gasLimit uint64) { + revertTxParams := &types.OutboundTxParams{ + Receiver: cctx.InboundTxParams.Sender, + ReceiverChainId: cctx.InboundTxParams.SenderChainId, + Amount: cctx.InboundTxParams.Amount, + OutboundTxGasLimit: gasLimit, + TssPubkey: cctx.GetCurrentOutTxParam().TssPubkey, + } + // The original outbound has been finalized, the new outbound is pending + cctx.GetCurrentOutTxParam().TxFinalizationStatus = types.TxFinalizationStatus_Executed + cctx.OutboundTxParams = append(cctx.OutboundTxParams, revertTxParams) +} + +// SetOutboundValues sets the required values for the outbound transaction +// Note: It expects the cctx to already have been created, +// it updates the cctx based on the MsgVoteOnObservedOutboundTx message which is signed and broadcasted by the observer +func SetOutboundValues(ctx sdk.Context, cctx *types.CrossChainTx, msg types.MsgVoteOnObservedOutboundTx, ballotStatus observertypes.BallotStatus) error { + if ballotStatus != observertypes.BallotStatus_BallotFinalized_FailureObservation { + if !msg.ValueReceived.Equal(cctx.GetCurrentOutTxParam().Amount) { + ctx.Logger().Error(fmt.Sprintf("VoteOnObservedOutboundTx: Mint mismatch: %s value received vs %s cctx amount", + msg.ValueReceived, + cctx.GetCurrentOutTxParam().Amount)) + return cosmoserrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("ValueReceived %s does not match sent value %s", msg.ValueReceived, cctx.GetCurrentOutTxParam().Amount)) + } + } + // Update CCTX values + cctx.GetCurrentOutTxParam().OutboundTxHash = msg.ObservedOutTxHash + cctx.GetCurrentOutTxParam().OutboundTxGasUsed = msg.ObservedOutTxGasUsed + cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasPrice = msg.ObservedOutTxEffectiveGasPrice + cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasLimit = msg.ObservedOutTxEffectiveGasLimit + cctx.GetCurrentOutTxParam().OutboundTxObservedExternalHeight = msg.ObservedOutTxBlockHeight + cctx.CctxStatus.LastUpdateTimestamp = ctx.BlockHeader().Time.Unix() + + return nil +} + +// FundStabilityPool funds the stability pool with the remaining fees of an outbound tx +// The funds are sent to the gas stability pool associated with the receiver chain +func (k Keeper) FundStabilityPool(ctx sdk.Context, cctx *types.CrossChainTx) { + // Fund the gas stability pool with the remaining funds + if err := k.FundGasStabilityPoolFromRemainingFees(ctx, *cctx.GetCurrentOutTxParam(), cctx.GetCurrentOutTxParam().ReceiverChainId); err != nil { + ctx.Logger().Error(fmt.Sprintf("VoteOnObservedOutboundTx: CCTX: %s Can't fund the gas stability pool with remaining fees %s", cctx.Index, err.Error())) + } +} + +// FundGasStabilityPoolFromRemainingFees funds the gas stability pool with the remaining fees of an outbound tx +func (k Keeper) FundGasStabilityPoolFromRemainingFees(ctx sdk.Context, outboundTxParams types.OutboundTxParams, chainID int64) error { + gasUsed := outboundTxParams.OutboundTxGasUsed + gasLimit := outboundTxParams.OutboundTxEffectiveGasLimit + gasPrice := math.NewUintFromBigInt(outboundTxParams.OutboundTxEffectiveGasPrice.BigInt()) + + if gasLimit == gasUsed { + return nil + } + + // We skip gas stability pool funding if one of the params is zero + if gasLimit > 0 && gasUsed > 0 && !gasPrice.IsZero() { + if gasLimit > gasUsed { + remainingGas := gasLimit - gasUsed + remainingFees := math.NewUint(remainingGas).Mul(gasPrice).BigInt() + + // We fund the stability pool with a portion of the remaining fees + remainingFees = percentOf(remainingFees, RemainingFeesToStabilityPoolPercent) + // Fund the gas stability pool + if err := k.fungibleKeeper.FundGasStabilityPool(ctx, chainID, remainingFees); err != nil { + return err + } + } else { + return fmt.Errorf("VoteOnObservedOutboundTx: The gas limit %d is less than the gas used %d", gasLimit, gasUsed) + } + } + return nil +} + +// percentOf returns the percentage of a number +func percentOf(n *big.Int, percent int64) *big.Int { + n = n.Mul(n, big.NewInt(percent)) + n = n.Div(n, big.NewInt(100)) + return n +} + +// ProcessSuccessfulOutbound processes a successful outbound transaction. It does the following things in one function: +// 1. Change the status of the CCTX from PendingRevert to Reverted or from PendingOutbound to OutboundMined +// 2. Set the finalization status of the current outbound tx to executed +// 3. Emit an event for the successful outbound transaction +func (k Keeper) ProcessSuccessfulOutbound(ctx sdk.Context, cctx *types.CrossChainTx, valueReceived string) { + oldStatus := cctx.CctxStatus.Status + switch oldStatus { + case types.CctxStatus_PendingRevert: + cctx.CctxStatus.ChangeStatus(types.CctxStatus_Reverted, "") + case types.CctxStatus_PendingOutbound: + cctx.CctxStatus.ChangeStatus(types.CctxStatus_OutboundMined, "") + default: + return + } + cctx.GetCurrentOutTxParam().TxFinalizationStatus = types.TxFinalizationStatus_Executed + newStatus := cctx.CctxStatus.Status.String() + EmitOutboundSuccess(ctx, valueReceived, oldStatus.String(), newStatus, *cctx) +} + +// ProcessFailedOutbound processes a failed outbound transaction. It does the following things in one function: +// 1. For Admin Tx or a withdrawal from Zeta chain, it aborts the CCTX +// 2. For other CCTX, it creates a revert tx if the outbound tx is pending. If the status is pending revert, it aborts the CCTX +// 3. Emit an event for the failed outbound transaction +// 4. Set the finalization status of the current outbound tx to executed. If a revert tx is is created, the finalization status is not set, it would get set when the revert is processed via a subsequent transaction +func (k Keeper) ProcessFailedOutbound(ctx sdk.Context, cctx *types.CrossChainTx, valueReceived string) error { + oldStatus := cctx.CctxStatus.Status + if cctx.InboundTxParams.CoinType == common.CoinType_Cmd || common.IsZetaChain(cctx.InboundTxParams.SenderChainId) { + // if the cctx is of coin type cmd or the sender chain is zeta chain, then we do not revert, the cctx is aborted + cctx.GetCurrentOutTxParam().TxFinalizationStatus = types.TxFinalizationStatus_Executed + cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, "") + } else { + switch oldStatus { + case types.CctxStatus_PendingOutbound: + + gasLimit, err := k.GetRevertGasLimit(ctx, cctx) + if err != nil { + return cosmoserrors.Wrap(err, "GetRevertGasLimit") + } + if gasLimit == 0 { + // use same gas limit of outbound as a fallback -- should not happen + gasLimit = cctx.OutboundTxParams[0].OutboundTxGasLimit + } + + // create new OutboundTxParams for the revert + SetRevertOutboundValues(cctx, gasLimit) + + err = k.PayGasAndUpdateCctx( + ctx, + cctx.InboundTxParams.SenderChainId, + cctx, + cctx.OutboundTxParams[0].Amount, + false, + ) + if err != nil { + return err + } + err = k.UpdateNonce(ctx, cctx.InboundTxParams.SenderChainId, cctx) + if err != nil { + return err + } + // Not setting the finalization status here, the required changes have been mad while creating the revert tx + cctx.CctxStatus.ChangeStatus(types.CctxStatus_PendingRevert, "Outbound failed, start revert") + case types.CctxStatus_PendingRevert: + cctx.GetCurrentOutTxParam().TxFinalizationStatus = types.TxFinalizationStatus_Executed + cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, "Outbound failed: revert failed; abort TX") + } + } + newStatus := cctx.CctxStatus.Status.String() + EmitOutboundFailure(ctx, valueReceived, oldStatus.String(), newStatus, *cctx) + return nil +} + +// ProcessOutbound processes the finalization of an outbound transaction based on the ballot status +// The state is committed only if the individual steps are successful +func (k Keeper) ProcessOutbound(ctx sdk.Context, cctx *types.CrossChainTx, ballotStatus observertypes.BallotStatus, valueReceived string) error { + tmpCtx, commit := ctx.CacheContext() + err := func() error { + switch ballotStatus { + case observertypes.BallotStatus_BallotFinalized_SuccessObservation: + k.ProcessSuccessfulOutbound(tmpCtx, cctx, valueReceived) + case observertypes.BallotStatus_BallotFinalized_FailureObservation: + err := k.ProcessFailedOutbound(tmpCtx, cctx, valueReceived) + if err != nil { + return err + } + } + return nil + }() + if err != nil { + return err + } + commit() + return nil +} + +// SaveFailedOutBound saves a failed outbound transaction. +// It does the following things in one function: +// 1. Change the status of the CCTX to Aborted +// 2. Save the outbound +func (k Keeper) SaveFailedOutBound(ctx sdk.Context, cctx *types.CrossChainTx, errMessage string, ballotIndex string) { + cctx.CctxStatus.ChangeStatus(types.CctxStatus_Aborted, errMessage) + ctx.Logger().Error(errMessage) + + k.SaveOutbound(ctx, cctx, ballotIndex) +} + +// SaveSuccessfulOutBound saves a successful outbound transaction. +func (k Keeper) SaveSuccessfulOutBound(ctx sdk.Context, cctx *types.CrossChainTx, ballotIndex string) { + k.SaveOutbound(ctx, cctx, ballotIndex) +} + +// SaveOutbound saves the outbound transaction.It does the following things in one function: +// 1. Set the ballot index for the outbound vote to the cctx +// 2. Remove the nonce from the pending nonces +// 3. Remove the outbound tx tracker +// 4. Set the cctx and nonce to cctx and inTxHash to cctx +func (k Keeper) SaveOutbound(ctx sdk.Context, cctx *types.CrossChainTx, ballotIndex string) { + receiverChain := cctx.GetCurrentOutTxParam().ReceiverChainId + tssPubkey := cctx.GetCurrentOutTxParam().TssPubkey + outTxTssNonce := cctx.GetCurrentOutTxParam().OutboundTxTssNonce + + cctx.GetCurrentOutTxParam().OutboundTxBallotIndex = ballotIndex + // #nosec G701 always in range + k.GetObserverKeeper().RemoveFromPendingNonces(ctx, tssPubkey, receiverChain, int64(outTxTssNonce)) + k.RemoveOutTxTracker(ctx, receiverChain, outTxTssNonce) + ctx.Logger().Info(fmt.Sprintf("Remove tracker %s: , Block Height : %d ", getOutTrackerIndex(receiverChain, outTxTssNonce), ctx.BlockHeight())) + // This should set nonce to cctx only if a new revert is created. + k.SetCctxAndNonceToCctxAndInTxHashToCctx(ctx, *cctx) +} + +func (k Keeper) ValidateOutboundMessage(ctx sdk.Context, msg types.MsgVoteOnObservedOutboundTx) (types.CrossChainTx, error) { + // check if CCTX exists and if the nonce matches + cctx, found := k.GetCrossChainTx(ctx, msg.CctxHash) + if !found { + return types.CrossChainTx{}, cosmoserrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("CCTX %s does not exist", msg.CctxHash)) + } + if cctx.GetCurrentOutTxParam().OutboundTxTssNonce != msg.OutTxTssNonce { + return types.CrossChainTx{}, cosmoserrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("OutTxTssNonce %d does not match CCTX OutTxTssNonce %d", msg.OutTxTssNonce, cctx.GetCurrentOutTxParam().OutboundTxTssNonce)) + } + // do not process an outbound vote if TSS is not found + _, found = k.zetaObserverKeeper.GetTSS(ctx) + if !found { + return types.CrossChainTx{}, types.ErrCannotFindTSSKeys + } + if cctx.GetCurrentOutTxParam().ReceiverChainId != msg.OutTxChain { + return types.CrossChainTx{}, cosmoserrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("OutTxChain %d does not match CCTX OutTxChain %d", msg.OutTxChain, cctx.GetCurrentOutTxParam().ReceiverChainId)) + } + return cctx, nil +} diff --git a/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go b/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go index 1875389328..1b35b832a6 100644 --- a/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go +++ b/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go @@ -2,11 +2,13 @@ package keeper_test import ( "errors" + "fmt" "math/big" "math/rand" "testing" "cosmossdk.io/math" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/common" @@ -159,7 +161,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { ObservedOutTxBlockHeight: 10, ObservedOutTxEffectiveGasPrice: math.NewInt(21), ObservedOutTxGasUsed: 21, - CoinType: cctx.CoinType, + CoinType: cctx.InboundTxParams.CoinType, }) require.NoError(t, err) c, found := k.GetCrossChainTx(ctx, cctx.Index) @@ -215,7 +217,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { ObservedOutTxBlockHeight: 10, ObservedOutTxEffectiveGasPrice: math.NewInt(21), ObservedOutTxGasUsed: 21, - CoinType: cctx.CoinType, + CoinType: cctx.InboundTxParams.CoinType, }) require.NoError(t, err) c, found := k.GetCrossChainTx(ctx, cctx.Index) @@ -275,7 +277,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { ObservedOutTxBlockHeight: 10, ObservedOutTxEffectiveGasPrice: math.NewInt(21), ObservedOutTxGasUsed: 21, - CoinType: cctx.CoinType, + CoinType: cctx.InboundTxParams.CoinType, }) require.NoError(t, err) c, found := k.GetCrossChainTx(ctx, cctx.Index) @@ -337,7 +339,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { ObservedOutTxBlockHeight: 10, ObservedOutTxEffectiveGasPrice: math.NewInt(21), ObservedOutTxGasUsed: 21, - CoinType: cctx.CoinType, + CoinType: cctx.InboundTxParams.CoinType, }) require.NoError(t, err) c, found := k.GetCrossChainTx(ctx, cctx.Index) @@ -381,7 +383,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { ObservedOutTxBlockHeight: 10, ObservedOutTxEffectiveGasPrice: math.NewInt(21), ObservedOutTxGasUsed: 21, - CoinType: cctx.CoinType, + CoinType: cctx.InboundTxParams.CoinType, } _, err = msgServer.VoteOnObservedOutboundTx(ctx, msg) require.NoError(t, err) @@ -427,7 +429,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { ObservedOutTxBlockHeight: 10, ObservedOutTxEffectiveGasPrice: math.NewInt(21), ObservedOutTxGasUsed: 21, - CoinType: cctx.CoinType, + CoinType: cctx.InboundTxParams.CoinType, } _, err = msgServer.VoteOnObservedOutboundTx(ctx, msg) require.ErrorIs(t, err, types.ErrCannotFindTSSKeys) @@ -438,3 +440,470 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { require.False(t, found) }) } + +func TestKeeper_GetOutbound(t *testing.T) { + t.Run("successfully get outbound tx", func(t *testing.T) { + _, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + hash := sample.Hash().String() + + err := keeper.SetOutboundValues(ctx, cctx, types.MsgVoteOnObservedOutboundTx{ + ValueReceived: cctx.GetCurrentOutTxParam().Amount, + ObservedOutTxHash: hash, + ObservedOutTxBlockHeight: 10, + ObservedOutTxGasUsed: 100, + ObservedOutTxEffectiveGasPrice: math.NewInt(100), + ObservedOutTxEffectiveGasLimit: 20, + }, observertypes.BallotStatus_BallotFinalized_SuccessObservation) + require.NoError(t, err) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxHash, hash) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxGasUsed, uint64(100)) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasPrice, math.NewInt(100)) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasLimit, uint64(20)) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxObservedExternalHeight, uint64(10)) + require.Equal(t, cctx.CctxStatus.LastUpdateTimestamp, ctx.BlockHeader().Time.Unix()) + }) + + t.Run("successfully get outbound tx for failed ballot without amount check", func(t *testing.T) { + _, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + hash := sample.Hash().String() + + err := keeper.SetOutboundValues(ctx, cctx, types.MsgVoteOnObservedOutboundTx{ + ObservedOutTxHash: hash, + ObservedOutTxBlockHeight: 10, + ObservedOutTxGasUsed: 100, + ObservedOutTxEffectiveGasPrice: math.NewInt(100), + ObservedOutTxEffectiveGasLimit: 20, + }, observertypes.BallotStatus_BallotFinalized_FailureObservation) + require.NoError(t, err) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxHash, hash) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxGasUsed, uint64(100)) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasPrice, math.NewInt(100)) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxEffectiveGasLimit, uint64(20)) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxObservedExternalHeight, uint64(10)) + require.Equal(t, cctx.CctxStatus.LastUpdateTimestamp, ctx.BlockHeader().Time.Unix()) + }) + + t.Run("failed to get outbound tx if amount does not match value received", func(t *testing.T) { + _, ctx, _, _ := keepertest.CrosschainKeeper(t) + + cctx := sample.CrossChainTx(t, "test") + hash := sample.Hash().String() + + err := keeper.SetOutboundValues(ctx, cctx, types.MsgVoteOnObservedOutboundTx{ + ValueReceived: math.NewUint(100), + ObservedOutTxHash: hash, + ObservedOutTxBlockHeight: 10, + ObservedOutTxGasUsed: 100, + ObservedOutTxEffectiveGasPrice: math.NewInt(100), + ObservedOutTxEffectiveGasLimit: 20, + }, observertypes.BallotStatus_BallotFinalized_SuccessObservation) + require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) + }) +} + +func TestKeeper_ProcessSuccessfulOutbound(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + // transition to reverted if pending revert + cctx.CctxStatus.Status = types.CctxStatus_PendingRevert + k.ProcessSuccessfulOutbound(ctx, cctx, sample.String()) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Reverted) + // transition to outbound mined if pending outbound + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + k.ProcessSuccessfulOutbound(ctx, cctx, sample.String()) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_OutboundMined) + // do nothing if it's in any other state + k.ProcessSuccessfulOutbound(ctx, cctx, sample.String()) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_OutboundMined) +} + +func TestKeeper_ProcessFailedOutbound(t *testing.T) { + t.Run("successfully process failed outbound set to aborted for type cmd", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + cctx.InboundTxParams.CoinType = common.CoinType_Cmd + err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) + require.NoError(t, err) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Aborted) + require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_Executed) + }) + + t.Run("successfully process failed outbound set to aborted for withdraw tx", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + cctx.InboundTxParams.SenderChainId = common.ZetaChainMainnet().ChainId + err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) + require.NoError(t, err) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Aborted) + require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_Executed) + }) + + t.Run("successfully process failed outbound set to pending revert", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + + // mock successful GetRevertGasLimit for ERC20 + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + + // mock successful PayGasAndUpdateCctx + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) + + // mock successful UpdateNonce + _ = keepertest.MockUpdateNonce(observerMock, *senderChain) + + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) + require.NoError(t, err) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingRevert) + require.Equal(t, types.TxFinalizationStatus_NotFinalized, cctx.GetCurrentOutTxParam().TxFinalizationStatus) + require.Equal(t, types.TxFinalizationStatus_Executed, cctx.OutboundTxParams[0].TxFinalizationStatus) + + }) + + t.Run("unable to process revert when update nonce fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + + // mock successful GetRevertGasLimit for ERC20 + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + + // mock successful PayGasAndUpdateCctx + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) + + // mock failed UpdateNonce + observerMock.On("GetChainNonces", mock.Anything, senderChain.ChainName.String()). + Return(observertypes.ChainNonces{}, false) + + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) + require.ErrorIs(t, err, types.ErrCannotFindReceiverNonce) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingOutbound) + }) + + t.Run("unable to process revert when PayGasAndUpdateCctx fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + + // mock successful GetRevertGasLimit for ERC20 + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + + // mock successful PayGasAndUpdateCctx + observerMock.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). + Return(nil).Once() + + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) + require.ErrorIs(t, err, observertypes.ErrSupportedChains) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingOutbound) + }) + + t.Run("unable to process revert when GetRevertGasLimit fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + + // mock failed GetRevertGasLimit for ERC20 + fungibleMock.On("GetForeignCoinFromAsset", mock.Anything, asset, senderChain.ChainId). + Return(fungibletypes.ForeignCoins{ + Zrc20ContractAddress: sample.EthAddress().String(), + }, false).Once() + + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) + require.ErrorIs(t, err, types.ErrForeignCoinNotFound) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingOutbound) + }) +} + +func TestKeeper_ProcessOutbound(t *testing.T) { + t.Run("successfully process outbound with ballot finalized to success", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_SuccessObservation, sample.String()) + require.NoError(t, err) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_OutboundMined) + }) + + t.Run("successfully process outbound with ballot finalized to failed and old status is Pending Revert", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + cctx.CctxStatus.Status = types.CctxStatus_PendingRevert + err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_FailureObservation, sample.String()) + require.NoError(t, err) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Aborted) + require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_Executed) + }) + + t.Run("successfully process outbound with ballot finalized to failed and coin-type is CMD", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + cctx.InboundTxParams.CoinType = common.CoinType_Cmd + err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_FailureObservation, sample.String()) + require.NoError(t, err) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Aborted) + require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_Executed) + }) + + t.Run("do not process outbound on error, no new outbound created", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + oldOutTxParamsLen := len(cctx.OutboundTxParams) + // mock failed GetRevertGasLimit for ERC20 + fungibleMock.On("GetForeignCoinFromAsset", mock.Anything, asset, senderChain.ChainId). + Return(fungibletypes.ForeignCoins{ + Zrc20ContractAddress: sample.EthAddress().String(), + }, false).Once() + + err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_FailureObservation, sample.String()) + require.ErrorIs(t, err, types.ErrForeignCoinNotFound) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingOutbound) + // New outbound not added and the old outbound is not finalized + require.Len(t, cctx.OutboundTxParams, oldOutTxParamsLen) + require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_NotFinalized) + }) + + t.Run("successfully revert a outbound and create a new revert tx", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + oldOutTxParamsLen := len(cctx.OutboundTxParams) + // mock successful GetRevertGasLimit for ERC20 + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + + // mock successful PayGasAndUpdateCctx + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) + + // mock successful UpdateNonce + _ = keepertest.MockUpdateNonce(observerMock, *senderChain) + + err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_FailureObservation, sample.String()) + require.NoError(t, err) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingRevert) + // New outbound added for revert and the old outbound is finalized + require.Len(t, cctx.OutboundTxParams, oldOutTxParamsLen+1) + require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_NotFinalized) + require.Equal(t, cctx.OutboundTxParams[oldOutTxParamsLen-1].TxFinalizationStatus, types.TxFinalizationStatus_Executed) + }) +} + +func TestKeeper_SaveFailedOutBound(t *testing.T) { + t.Run("successfully save failed outbound", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + k.SetOutTxTracker(ctx, types.OutTxTracker{ + Index: "", + ChainId: cctx.GetCurrentOutTxParam().ReceiverChainId, + Nonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, + HashList: nil, + }) + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + k.SaveFailedOutBound(ctx, cctx, sample.String(), sample.ZetaIndex(t)) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_Aborted) + _, found := k.GetOutTxTracker(ctx, cctx.GetCurrentOutTxParam().ReceiverChainId, cctx.GetCurrentOutTxParam().OutboundTxTssNonce) + require.False(t, found) + }) +} + +func TestKeeper_SaveSuccessfulOutBound(t *testing.T) { + t.Run("successfully save successful outbound", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + k.SetOutTxTracker(ctx, types.OutTxTracker{ + Index: "", + ChainId: cctx.GetCurrentOutTxParam().ReceiverChainId, + Nonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, + HashList: nil, + }) + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + k.SaveSuccessfulOutBound(ctx, cctx, sample.String()) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxBallotIndex, sample.String()) + _, found := k.GetOutTxTracker(ctx, cctx.GetCurrentOutTxParam().ReceiverChainId, cctx.GetCurrentOutTxParam().OutboundTxTssNonce) + require.False(t, found) + }) +} + +func TestKeeper_SaveOutbound(t *testing.T) { + t.Run("successfully save outbound", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + + // setup state for crosschain and observer modules + cctx := sample.CrossChainTx(t, "test") + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + ballotIndex := sample.String() + k.SetOutTxTracker(ctx, types.OutTxTracker{ + Index: "", + ChainId: cctx.GetCurrentOutTxParam().ReceiverChainId, + Nonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, + HashList: nil, + }) + + zk.ObserverKeeper.SetPendingNonces(ctx, observertypes.PendingNonces{ + NonceLow: int64(cctx.GetCurrentOutTxParam().OutboundTxTssNonce) - 1, + NonceHigh: int64(cctx.GetCurrentOutTxParam().OutboundTxTssNonce) + 1, + ChainId: cctx.GetCurrentOutTxParam().ReceiverChainId, + Tss: cctx.GetCurrentOutTxParam().TssPubkey, + }) + zk.ObserverKeeper.SetTSS(ctx, observertypes.TSS{ + TssPubkey: cctx.GetCurrentOutTxParam().TssPubkey, + }) + + // Save outbound and assert all values are successfully saved + k.SaveOutbound(ctx, cctx, ballotIndex) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxBallotIndex, ballotIndex) + _, found := k.GetOutTxTracker(ctx, cctx.GetCurrentOutTxParam().ReceiverChainId, cctx.GetCurrentOutTxParam().OutboundTxTssNonce) + require.False(t, found) + pn, found := zk.ObserverKeeper.GetPendingNonces(ctx, cctx.GetCurrentOutTxParam().TssPubkey, cctx.GetCurrentOutTxParam().ReceiverChainId) + require.True(t, found) + require.Equal(t, pn.NonceLow, int64(cctx.GetCurrentOutTxParam().OutboundTxTssNonce)+1) + require.Equal(t, pn.NonceHigh, int64(cctx.GetCurrentOutTxParam().OutboundTxTssNonce)+1) + _, found = k.GetInTxHashToCctx(ctx, cctx.InboundTxParams.InboundTxObservedHash) + require.True(t, found) + _, found = zk.ObserverKeeper.GetNonceToCctx(ctx, cctx.GetCurrentOutTxParam().TssPubkey, cctx.GetCurrentOutTxParam().ReceiverChainId, int64(cctx.GetCurrentOutTxParam().OutboundTxTssNonce)) + require.True(t, found) + }) +} + +func Test_SetRevertOutboundValues(t *testing.T) { + cctx := sample.CrossChainTx(t, "test") + cctx.OutboundTxParams = cctx.OutboundTxParams[:1] + keeper.SetRevertOutboundValues(cctx, 100) + require.Len(t, cctx.OutboundTxParams, 2) + require.Equal(t, cctx.GetCurrentOutTxParam().Receiver, cctx.InboundTxParams.Sender) + require.Equal(t, cctx.GetCurrentOutTxParam().ReceiverChainId, cctx.InboundTxParams.SenderChainId) + require.Equal(t, cctx.GetCurrentOutTxParam().Amount, cctx.InboundTxParams.Amount) + require.Equal(t, cctx.GetCurrentOutTxParam().OutboundTxGasLimit, uint64(100)) + require.Equal(t, cctx.GetCurrentOutTxParam().TssPubkey, cctx.OutboundTxParams[0].TssPubkey) + require.Equal(t, types.TxFinalizationStatus_Executed, cctx.OutboundTxParams[0].TxFinalizationStatus) +} + +func TestKeeper_ValidateOutboundMessage(t *testing.T) { + t.Run("successfully validate outbound message", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + k.SetCrossChainTx(ctx, *cctx) + zk.ObserverKeeper.SetTSS(ctx, sample.Tss()) + _, err := k.ValidateOutboundMessage(ctx, types.MsgVoteOnObservedOutboundTx{ + CctxHash: cctx.Index, + OutTxTssNonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, + OutTxChain: cctx.GetCurrentOutTxParam().ReceiverChainId, + }) + require.NoError(t, err) + }) + + t.Run("failed to validate outbound message if cctx not found", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + msg := types.MsgVoteOnObservedOutboundTx{ + CctxHash: sample.String(), + OutTxTssNonce: 1, + } + _, err := k.ValidateOutboundMessage(ctx, msg) + require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) + require.ErrorContains(t, err, fmt.Sprintf("CCTX %s does not exist", msg.CctxHash)) + }) + + t.Run("failed to validate outbound message if nonce does not match", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + k.SetCrossChainTx(ctx, *cctx) + msg := types.MsgVoteOnObservedOutboundTx{ + CctxHash: cctx.Index, + OutTxTssNonce: 2, + } + _, err := k.ValidateOutboundMessage(ctx, msg) + require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) + require.ErrorContains(t, err, fmt.Sprintf("OutTxTssNonce %d does not match CCTX OutTxTssNonce %d", msg.OutTxTssNonce, cctx.GetCurrentOutTxParam().OutboundTxTssNonce)) + }) + + t.Run("failed to validate outbound message if tss not found", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + k.SetCrossChainTx(ctx, *cctx) + _, err := k.ValidateOutboundMessage(ctx, types.MsgVoteOnObservedOutboundTx{ + CctxHash: cctx.Index, + OutTxTssNonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, + }) + require.ErrorIs(t, err, types.ErrCannotFindTSSKeys) + }) + + t.Run("failed to validate outbound message if chain does not match", func(t *testing.T) { + k, ctx, _, zk := keepertest.CrosschainKeeper(t) + cctx := sample.CrossChainTx(t, "test") + k.SetCrossChainTx(ctx, *cctx) + zk.ObserverKeeper.SetTSS(ctx, sample.Tss()) + _, err := k.ValidateOutboundMessage(ctx, types.MsgVoteOnObservedOutboundTx{ + CctxHash: cctx.Index, + OutTxTssNonce: cctx.GetCurrentOutTxParam().OutboundTxTssNonce, + OutTxChain: 2, + }) + require.ErrorIs(t, err, sdkerrors.ErrInvalidRequest) + require.ErrorContains(t, err, fmt.Sprintf("OutTxChain %d does not match CCTX OutTxChain %d", 2, cctx.GetCurrentOutTxParam().ReceiverChainId)) + }) +} diff --git a/x/crosschain/keeper/msg_server_whitelist_erc20.go b/x/crosschain/keeper/msg_server_whitelist_erc20.go index e690da980b..efd79e7f28 100644 --- a/x/crosschain/keeper/msg_server_whitelist_erc20.go +++ b/x/crosschain/keeper/msg_server_whitelist_erc20.go @@ -111,9 +111,10 @@ func (k msgServer) WhitelistERC20(goCtx context.Context, msg *types.MsgWhitelist index := hash.Hex() // create a cmd cctx to whitelist the erc20 on the external chain + // TODO : refactor this to use the `CreateNewCCTX` function instead. + //https://github.com/zeta-chain/node/issues/1909 cctx := types.CrossChainTx{ Creator: msg.Creator, - CoinType: common.CoinType_Cmd, Index: index, ZetaFees: sdk.NewUint(0), RelayedMessage: fmt.Sprintf("%s:%s", common.CmdWhitelistERC20, msg.Erc20Address), @@ -123,16 +124,16 @@ func (k msgServer) WhitelistERC20(goCtx context.Context, msg *types.MsgWhitelist LastUpdateTimestamp: 0, }, InboundTxParams: &types.InboundTxParams{ - Sender: "", - SenderChainId: 0, - TxOrigin: "", - + Sender: "", + SenderChainId: 0, + TxOrigin: "", Asset: "", Amount: math.Uint{}, InboundTxObservedHash: hash.String(), // all Upper case Cosmos TX HEX, with no 0x prefix InboundTxObservedExternalHeight: 0, InboundTxBallotIndex: "", InboundTxFinalizedZetaHeight: 0, + CoinType: common.CoinType_Cmd, }, OutboundTxParams: []*types.OutboundTxParams{ { @@ -146,6 +147,7 @@ func (k msgServer) WhitelistERC20(goCtx context.Context, msg *types.MsgWhitelist OutboundTxBallotIndex: "", OutboundTxObservedExternalHeight: 0, TssPubkey: tss.TssPubkey, + CoinType: common.CoinType_Cmd, }, }, } diff --git a/x/crosschain/keeper/refund.go b/x/crosschain/keeper/refund.go index b29de2097e..9d10b7ce13 100644 --- a/x/crosschain/keeper/refund.go +++ b/x/crosschain/keeper/refund.go @@ -12,7 +12,7 @@ import ( ) func (k Keeper) RefundAbortedAmountOnZetaChain(ctx sdk.Context, cctx types.CrossChainTx, refundAddress ethcommon.Address) error { - coinType := cctx.CoinType + coinType := cctx.InboundTxParams.CoinType switch coinType { case common.CoinType_Gas: return k.RefundAmountOnZetaChainGas(ctx, cctx, refundAddress) @@ -75,7 +75,7 @@ func (k Keeper) RefundAmountOnZetaChainZeta(ctx sdk.Context, cctx types.CrossCha func (k Keeper) RefundAmountOnZetaChainERC20(ctx sdk.Context, cctx types.CrossChainTx, refundAddress ethcommon.Address) error { refundAmount := GetAbortedAmount(cctx) // preliminary checks - if cctx.CoinType != common.CoinType_ERC20 { + if cctx.InboundTxParams.CoinType != common.CoinType_ERC20 { return errors.New("unsupported coin type for refund on ZetaChain") } if !common.IsEVMChain(cctx.InboundTxParams.SenderChainId) { diff --git a/x/crosschain/keeper/refund_test.go b/x/crosschain/keeper/refund_test.go index 55cb674574..bf18530fc0 100644 --- a/x/crosschain/keeper/refund_test.go +++ b/x/crosschain/keeper/refund_test.go @@ -25,12 +25,12 @@ func TestKeeper_RefundAmountOnZetaChainGas(t *testing.T) { zrc20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") err := k.RefundAmountOnZetaChainGas(ctx, types.CrossChainTx{ - CoinType: common.CoinType_Gas, InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sender.String(), TxOrigin: sender.String(), Amount: math.NewUint(20), + CoinType: common.CoinType_Gas, }, OutboundTxParams: []*types.OutboundTxParams{{ Amount: math.NewUint(42), @@ -52,12 +52,12 @@ func TestKeeper_RefundAmountOnZetaChainGas(t *testing.T) { zrc20 := setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") err := k.RefundAmountOnZetaChainGas(ctx, types.CrossChainTx{ - CoinType: common.CoinType_Gas, InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sender.String(), TxOrigin: sender.String(), Amount: math.NewUint(20), + CoinType: common.CoinType_Gas, }, }, sender, @@ -74,12 +74,12 @@ func TestKeeper_RefundAmountOnZetaChainGas(t *testing.T) { chainID := getValidEthChainID(t) deploySystemContracts(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper) err := k.RefundAmountOnZetaChainGas(ctx, types.CrossChainTx{ - CoinType: common.CoinType_Gas, InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sender.String(), TxOrigin: sender.String(), Amount: math.NewUint(20), + CoinType: common.CoinType_Gas, }, OutboundTxParams: []*types.OutboundTxParams{{ Amount: math.NewUint(42), @@ -99,12 +99,12 @@ func TestKeeper_RefundAmountOnZetaChainGas(t *testing.T) { _ = setupGasCoin(t, ctx, zk.FungibleKeeper, sdkk.EvmKeeper, chainID, "foobar", "foobar") err := k.RefundAmountOnZetaChainGas(ctx, types.CrossChainTx{ - CoinType: common.CoinType_Gas, InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sender.String(), TxOrigin: sender.String(), Amount: math.ZeroUint(), + CoinType: common.CoinType_Gas, }, OutboundTxParams: []*types.OutboundTxParams{{ Amount: math.ZeroUint(), @@ -125,12 +125,12 @@ func TestKeeper_RefundAmountOnZetaChainZeta(t *testing.T) { chainID := getValidEthChainID(t) err := k.RefundAmountOnZetaChainZeta(ctx, types.CrossChainTx{ - CoinType: common.CoinType_Gas, InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sender.String(), TxOrigin: sender.String(), Amount: math.NewUint(20), + CoinType: common.CoinType_Gas, }, OutboundTxParams: []*types.OutboundTxParams{{ Amount: math.NewUint(42), @@ -150,12 +150,12 @@ func TestKeeper_RefundAmountOnZetaChainZeta(t *testing.T) { chainID := getValidEthChainID(t) err := k.RefundAmountOnZetaChainZeta(ctx, types.CrossChainTx{ - CoinType: common.CoinType_Gas, InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sender.String(), TxOrigin: sender.String(), Amount: math.NewUint(20), + CoinType: common.CoinType_Gas, }, }, sender, @@ -171,12 +171,13 @@ func TestKeeper_RefundAmountOnZetaChainZeta(t *testing.T) { chainID := getValidEthChainID(t) err := k.RefundAmountOnZetaChainZeta(ctx, types.CrossChainTx{ - CoinType: common.CoinType_Gas, + InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sender.String(), TxOrigin: sender.String(), Amount: math.ZeroUint(), + CoinType: common.CoinType_Gas, }, OutboundTxParams: []*types.OutboundTxParams{{ Amount: math.ZeroUint(), @@ -210,12 +211,13 @@ func TestKeeper_RefundAmountOnZetaChainERC20(t *testing.T) { ) err := k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ - CoinType: common.CoinType_ERC20, + InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sender.String(), Asset: asset, Amount: math.NewUint(42), + CoinType: common.CoinType_ERC20, }, OutboundTxParams: []*types.OutboundTxParams{{ Amount: math.NewUint(42), @@ -232,12 +234,13 @@ func TestKeeper_RefundAmountOnZetaChainERC20(t *testing.T) { // can refund again err = k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ - CoinType: common.CoinType_ERC20, + InboundTxParams: &types.InboundTxParams{ SenderChainId: chainID, Sender: sender.String(), Asset: asset, Amount: math.NewUint(42), + CoinType: common.CoinType_ERC20, }}, sender, ) @@ -251,47 +254,55 @@ func TestKeeper_RefundAmountOnZetaChainERC20(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) err := k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ - CoinType: common.CoinType_Zeta, + InboundTxParams: &types.InboundTxParams{ - Amount: math.NewUint(42), + Amount: math.NewUint(42), + CoinType: common.CoinType_Zeta, }}, + sample.EthAddress(), ) require.ErrorContains(t, err, "unsupported coin type") err = k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ - CoinType: common.CoinType_Gas}, + InboundTxParams: &types.InboundTxParams{ + CoinType: common.CoinType_Gas, + }, + }, sample.EthAddress(), ) require.ErrorContains(t, err, "unsupported coin type") err = k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ - CoinType: common.CoinType_ERC20, + InboundTxParams: &types.InboundTxParams{ SenderChainId: 999999, Amount: math.NewUint(42), + CoinType: common.CoinType_ERC20, }}, sample.EthAddress(), ) require.ErrorContains(t, err, "only EVM chains are supported") err = k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ - CoinType: common.CoinType_ERC20, + InboundTxParams: &types.InboundTxParams{ SenderChainId: getValidEthChainID(t), Sender: sample.EthAddress().String(), Amount: math.Uint{}, + CoinType: common.CoinType_ERC20, }}, sample.EthAddress(), ) require.ErrorContains(t, err, "no amount to refund") err = k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ - CoinType: common.CoinType_ERC20, + InboundTxParams: &types.InboundTxParams{ SenderChainId: getValidEthChainID(t), Sender: sample.EthAddress().String(), Amount: math.ZeroUint(), + CoinType: common.CoinType_ERC20, }}, sample.EthAddress(), ) @@ -299,12 +310,13 @@ func TestKeeper_RefundAmountOnZetaChainERC20(t *testing.T) { // the foreign coin has not been set err = k.RefundAmountOnZetaChainERC20(ctx, types.CrossChainTx{ - CoinType: common.CoinType_ERC20, + InboundTxParams: &types.InboundTxParams{ SenderChainId: getValidEthChainID(t), Sender: sample.EthAddress().String(), Asset: sample.EthAddress().String(), Amount: math.NewUint(42), + CoinType: common.CoinType_ERC20, }}, sample.EthAddress(), ) diff --git a/x/crosschain/migrations/v4/migrate.go b/x/crosschain/migrations/v4/migrate.go index 5a421c9d55..6b9ee6ffb8 100644 --- a/x/crosschain/migrations/v4/migrate.go +++ b/x/crosschain/migrations/v4/migrate.go @@ -54,7 +54,7 @@ func SetZetaAccounting( for ; iterator.Valid(); iterator.Next() { var val types.CrossChainTx cdc.MustUnmarshal(iterator.Value(), &val) - if val.CctxStatus.Status == types.CctxStatus_Aborted && val.CoinType == common.CoinType_Zeta { + if val.CctxStatus.Status == types.CctxStatus_Aborted && val.InboundTxParams.CoinType == common.CoinType_Zeta { abortedAmountZeta = abortedAmountZeta.Add(val.GetCurrentOutTxParam().Amount) } } diff --git a/x/crosschain/migrations/v4/migrate_test.go b/x/crosschain/migrations/v4/migrate_test.go index 67113b9c0a..b2d88a1add 100644 --- a/x/crosschain/migrations/v4/migrate_test.go +++ b/x/crosschain/migrations/v4/migrate_test.go @@ -167,10 +167,13 @@ func SetRandomCctx(ctx sdk.Context, k keeper.Keeper) sdkmath.Uint { amount := sdkmath.NewUint(uint64(r.Uint32())) k.SetCrossChainTx(ctx, types.CrossChainTx{ Index: fmt.Sprintf("%d", i), - CoinType: common.CoinType_Zeta, CctxStatus: &types.Status{Status: types.CctxStatus_Aborted}, + InboundTxParams: &types.InboundTxParams{ + CoinType: common.CoinType_Zeta, + }, OutboundTxParams: []*types.OutboundTxParams{{ - Amount: amount, + Amount: amount, + CoinType: common.CoinType_Zeta, }}, }) totalZeta = totalZeta.Add(amount) diff --git a/x/crosschain/migrations/v5/migrate.go b/x/crosschain/migrations/v5/migrate.go index cc29a265e6..27ceba92cc 100644 --- a/x/crosschain/migrations/v5/migrate.go +++ b/x/crosschain/migrations/v5/migrate.go @@ -93,7 +93,7 @@ func SetZetaAccounting( for _, cctx := range ccctxList { if cctx.CctxStatus.Status == types.CctxStatus_Aborted { - switch cctx.CoinType { + switch cctx.InboundTxParams.CoinType { case common.CoinType_ERC20: { receiverChain := observerKeeper.GetSupportedChainFromChainID(ctx, cctx.GetCurrentOutTxParam().ReceiverChainId) diff --git a/x/crosschain/migrations/v5/migrate_test.go b/x/crosschain/migrations/v5/migrate_test.go index 884777d626..4c3e3a735e 100644 --- a/x/crosschain/migrations/v5/migrate_test.go +++ b/x/crosschain/migrations/v5/migrate_test.go @@ -24,7 +24,7 @@ func TestMigrateStore(t *testing.T) { v4ZetaAccountingAmount := math.ZeroUint() for _, cctx := range cctxList { k.SetCrossChainTx(ctx, cctx) - if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_Aborted || cctx.CoinType != common.CoinType_Zeta { + if cctx.CctxStatus.Status != crosschaintypes.CctxStatus_Aborted || cctx.InboundTxParams.CoinType != common.CoinType_Zeta { continue } v5ZetaAccountingAmount = v5ZetaAccountingAmount.Add(crosschainkeeper.GetAbortedAmount(cctx)) @@ -44,7 +44,7 @@ func TestMigrateStore(t *testing.T) { cctxListUpdated := k.GetAllCrossChainTx(ctx) // Check refund status of the cctx for _, cctx := range cctxListUpdated { - switch cctx.CoinType { + switch cctx.InboundTxParams.CoinType { case common.CoinType_ERC20: receiverChain := zk.ObserverKeeper.GetSupportedChainFromChainID(ctx, cctx.GetCurrentOutTxParam().ReceiverChainId) require.NotNil(t, receiverChain) @@ -180,37 +180,40 @@ func CrossChainTxList(count int) []crosschaintypes.CrossChainTx { amount := math.NewUint(uint64(r.Uint32())) cctxList[i] = crosschaintypes.CrossChainTx{ Index: fmt.Sprintf("%d", i), - CoinType: common.CoinType_Zeta, CctxStatus: &crosschaintypes.Status{Status: crosschaintypes.CctxStatus_Aborted}, InboundTxParams: &crosschaintypes.InboundTxParams{ - Amount: amount.Add(math.NewUint(uint64(r.Uint32()))), + Amount: amount.Add(math.NewUint(uint64(r.Uint32()))), + CoinType: common.CoinType_Zeta, }, OutboundTxParams: []*crosschaintypes.OutboundTxParams{{ - Amount: amount, + Amount: amount, + CoinType: common.CoinType_Zeta, }}, } for ; i < count; i++ { amount := math.NewUint(uint64(r.Uint32())) cctxList[i] = crosschaintypes.CrossChainTx{ Index: fmt.Sprintf("%d", i), - CoinType: common.CoinType_Zeta, CctxStatus: &crosschaintypes.Status{Status: crosschaintypes.CctxStatus_Aborted}, InboundTxParams: &crosschaintypes.InboundTxParams{ - Amount: amount, + Amount: amount, + CoinType: common.CoinType_Zeta, }, OutboundTxParams: []*crosschaintypes.OutboundTxParams{{ - Amount: math.ZeroUint(), + Amount: math.ZeroUint(), + CoinType: common.CoinType_Zeta, }}, } } for ; i < count+20; i++ { amount := math.NewUint(uint64(r.Uint32())) cctxList[i] = crosschaintypes.CrossChainTx{ - Index: fmt.Sprintf("%d", i), - CoinType: common.CoinType_ERC20, + Index: fmt.Sprintf("%d", i), + CctxStatus: &crosschaintypes.Status{Status: crosschaintypes.CctxStatus_Aborted}, InboundTxParams: &crosschaintypes.InboundTxParams{ - Amount: amount, + Amount: amount, + CoinType: common.CoinType_ERC20, }, OutboundTxParams: []*crosschaintypes.OutboundTxParams{{ Amount: math.ZeroUint(), @@ -222,10 +225,10 @@ func CrossChainTxList(count int) []crosschaintypes.CrossChainTx { amount := math.NewUint(uint64(r.Uint32())) cctxList[i] = crosschaintypes.CrossChainTx{ Index: fmt.Sprintf("%d", i), - CoinType: common.CoinType_ERC20, CctxStatus: &crosschaintypes.Status{Status: crosschaintypes.CctxStatus_Aborted}, InboundTxParams: &crosschaintypes.InboundTxParams{ - Amount: amount, + Amount: amount, + CoinType: common.CoinType_ERC20, }, OutboundTxParams: []*crosschaintypes.OutboundTxParams{{ Amount: math.ZeroUint(), @@ -237,10 +240,10 @@ func CrossChainTxList(count int) []crosschaintypes.CrossChainTx { amount := math.NewUint(uint64(r.Uint32())) cctxList[i] = crosschaintypes.CrossChainTx{ Index: fmt.Sprintf("%d", i), - CoinType: common.CoinType_Gas, CctxStatus: &crosschaintypes.Status{Status: crosschaintypes.CctxStatus_Aborted}, InboundTxParams: &crosschaintypes.InboundTxParams{ - Amount: amount, + Amount: amount, + CoinType: common.CoinType_Gas, }, OutboundTxParams: []*crosschaintypes.OutboundTxParams{{ Amount: amount, diff --git a/x/crosschain/migrations/v6/migrate.go b/x/crosschain/migrations/v6/migrate.go deleted file mode 100644 index fb00ff2574..0000000000 --- a/x/crosschain/migrations/v6/migrate.go +++ /dev/null @@ -1,93 +0,0 @@ -package v6 - -import ( - "fmt" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store/prefix" - storetypes "github.com/cosmos/cosmos-sdk/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -// crosschainKeeper is an interface to prevent cyclic dependency -type crosschainKeeper interface { - GetStoreKey() storetypes.StoreKey - GetCodec() codec.Codec - GetAllCrossChainTx(ctx sdk.Context) []types.CrossChainTx - - SetCrossChainTx(ctx sdk.Context, cctx types.CrossChainTx) - AddFinalizedInbound(ctx sdk.Context, inboundTxHash string, senderChainID int64, height uint64) - - SetZetaAccounting(ctx sdk.Context, accounting types.ZetaAccounting) -} - -// MigrateStore migrates the x/crosschain module state from the consensus version 4 to 5 -// It resets the aborted zeta amount to use the inbound tx amount instead in situations where the outbound cctx is never created. -func MigrateStore(ctx sdk.Context, crosschainKeeper crosschainKeeper) error { - tmpctx, commit := ctx.CacheContext() - cctxListV14 := GetV14CCTX(tmpctx, crosschainKeeper) - for _, cctx := range cctxListV14 { - OutBoundParamsV15 := make([]*types.OutboundTxParams, len(cctx.OutboundTxParams)) - for j, outBoundParams := range cctx.OutboundTxParams { - OutBoundParamsV15[j] = &types.OutboundTxParams{ - Receiver: outBoundParams.Receiver, - ReceiverChainId: outBoundParams.ReceiverChainId, - Amount: outBoundParams.Amount, - OutboundTxTssNonce: outBoundParams.OutboundTxTssNonce, - OutboundTxGasLimit: outBoundParams.OutboundTxGasLimit, - OutboundTxGasPrice: outBoundParams.OutboundTxGasPrice, - OutboundTxHash: outBoundParams.OutboundTxHash, - OutboundTxBallotIndex: outBoundParams.OutboundTxBallotIndex, - OutboundTxObservedExternalHeight: outBoundParams.OutboundTxObservedExternalHeight, - OutboundTxGasUsed: outBoundParams.OutboundTxGasUsed, - OutboundTxEffectiveGasPrice: outBoundParams.OutboundTxEffectiveGasPrice, - OutboundTxEffectiveGasLimit: outBoundParams.OutboundTxEffectiveGasLimit, - TssPubkey: outBoundParams.TssPubkey, - TxFinalizationStatus: outBoundParams.TxFinalizationStatus, - } - } - - cctxV15 := types.CrossChainTx{ - InboundTxParams: &types.InboundTxParams{ - Sender: cctx.InboundTxParams.Sender, - SenderChainId: cctx.InboundTxParams.SenderChainId, - TxOrigin: cctx.InboundTxParams.TxOrigin, - Asset: cctx.InboundTxParams.Asset, - Amount: cctx.InboundTxParams.Amount, - InboundTxObservedHash: cctx.InboundTxParams.InboundTxObservedHash, - InboundTxObservedExternalHeight: cctx.InboundTxParams.InboundTxObservedExternalHeight, - InboundTxBallotIndex: cctx.InboundTxParams.InboundTxBallotIndex, - InboundTxFinalizedZetaHeight: cctx.InboundTxParams.InboundTxFinalizedZetaHeight, - TxFinalizationStatus: cctx.InboundTxParams.TxFinalizationStatus, - }, - Index: cctx.Index, - Creator: cctx.Creator, - OutboundTxParams: OutBoundParamsV15, - CctxStatus: cctx.CctxStatus, - CoinType: cctx.InboundTxParams.CoinType, - ZetaFees: cctx.ZetaFees, - RelayedMessage: cctx.RelayedMessage, - EventIndex: 1, // We don't have this information in the old version - } - crosschainKeeper.SetCrossChainTx(tmpctx, cctxV15) - } - commit() - return nil -} - -func GetV14CCTX(ctx sdk.Context, crosschainKeeper crosschainKeeper) (list []types.CrossChainTxV14) { - p := types.KeyPrefix(fmt.Sprintf("%s", types.SendKey)) - store := prefix.NewStore(ctx.KVStore(crosschainKeeper.GetStoreKey()), p) - - iterator := sdk.KVStorePrefixIterator(store, []byte{}) - - defer iterator.Close() - - for ; iterator.Valid(); iterator.Next() { - var val types.CrossChainTxV14 - crosschainKeeper.GetCodec().MustUnmarshal(iterator.Value(), &val) - list = append(list, val) - } - return list -} diff --git a/x/crosschain/migrations/v6/migrate_test.go b/x/crosschain/migrations/v6/migrate_test.go deleted file mode 100644 index a6bb9eed8f..0000000000 --- a/x/crosschain/migrations/v6/migrate_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package v6_test - -import ( - "fmt" - "sort" - "testing" - - "github.com/cosmos/cosmos-sdk/store/prefix" - sdk "github.com/cosmos/cosmos-sdk/types" - "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/crosschain/keeper" - v6 "github.com/zeta-chain/zetacore/x/crosschain/migrations/v6" - "github.com/zeta-chain/zetacore/x/crosschain/types" -) - -func TestMigrateStore(t *testing.T) { - t.Run("successful migrate cctx from v14 to v15", func(t *testing.T) { - k, ctx, _, _ := keepertest.CrosschainKeeper(t) - v14cctxList := make([]*types.CrossChainTxV14, 10) - for i := 0; i < 10; i++ { - v14cctxList[i] = sample.CrossChainTxV14(t, fmt.Sprintf("%d-%s", i, "v14")) - SetCrossChainTxV14(ctx, *v14cctxList[i], k) - } - err := v6.MigrateStore(ctx, k) - require.NoError(t, err) - cctxListv15 := k.GetAllCrossChainTx(ctx) - require.Len(t, cctxListv15, 10) - sort.Slice(cctxListv15, func(i, j int) bool { - return cctxListv15[i].Index < cctxListv15[j].Index - }) - sort.Slice(v14cctxList, func(i, j int) bool { - return v14cctxList[i].Index < v14cctxList[j].Index - }) - for i := 0; i < 10; i++ { - require.Equal(t, v14cctxList[i].Index, cctxListv15[i].Index) - require.Equal(t, v14cctxList[i].Creator, cctxListv15[i].Creator) - require.Equal(t, v14cctxList[i].ZetaFees, cctxListv15[i].ZetaFees) - require.Equal(t, v14cctxList[i].RelayedMessage, cctxListv15[i].RelayedMessage) - require.Equal(t, v14cctxList[i].CctxStatus, cctxListv15[i].CctxStatus) - require.Equal(t, v14cctxList[i].InboundTxParams.Sender, cctxListv15[i].InboundTxParams.Sender) - require.Equal(t, v14cctxList[i].InboundTxParams.SenderChainId, cctxListv15[i].InboundTxParams.SenderChainId) - require.Equal(t, v14cctxList[i].InboundTxParams.TxOrigin, cctxListv15[i].InboundTxParams.TxOrigin) - require.Equal(t, v14cctxList[i].InboundTxParams.Asset, cctxListv15[i].InboundTxParams.Asset) - require.Equal(t, v14cctxList[i].InboundTxParams.Amount, cctxListv15[i].InboundTxParams.Amount) - require.Equal(t, v14cctxList[i].InboundTxParams.InboundTxObservedHash, cctxListv15[i].InboundTxParams.InboundTxObservedHash) - require.Equal(t, v14cctxList[i].InboundTxParams.InboundTxObservedExternalHeight, cctxListv15[i].InboundTxParams.InboundTxObservedExternalHeight) - require.Equal(t, v14cctxList[i].InboundTxParams.InboundTxBallotIndex, cctxListv15[i].InboundTxParams.InboundTxBallotIndex) - require.Equal(t, v14cctxList[i].InboundTxParams.InboundTxFinalizedZetaHeight, cctxListv15[i].InboundTxParams.InboundTxFinalizedZetaHeight) - require.Equal(t, v14cctxList[i].InboundTxParams.CoinType, cctxListv15[i].CoinType) - require.Len(t, v14cctxList[i].OutboundTxParams, len(cctxListv15[i].OutboundTxParams)) - for j := 0; j < len(cctxListv15[i].OutboundTxParams); j++ { - require.Equal(t, v14cctxList[i].OutboundTxParams[j].Receiver, cctxListv15[i].OutboundTxParams[j].Receiver) - require.Equal(t, v14cctxList[i].OutboundTxParams[j].ReceiverChainId, cctxListv15[i].OutboundTxParams[j].ReceiverChainId) - require.Equal(t, v14cctxList[i].OutboundTxParams[j].Amount, cctxListv15[i].OutboundTxParams[j].Amount) - require.Equal(t, v14cctxList[i].OutboundTxParams[j].OutboundTxTssNonce, cctxListv15[i].OutboundTxParams[j].OutboundTxTssNonce) - require.Equal(t, v14cctxList[i].OutboundTxParams[j].OutboundTxGasLimit, cctxListv15[i].OutboundTxParams[j].OutboundTxGasLimit) - require.Equal(t, v14cctxList[i].OutboundTxParams[j].OutboundTxGasPrice, cctxListv15[i].OutboundTxParams[j].OutboundTxGasPrice) - require.Equal(t, v14cctxList[i].OutboundTxParams[j].OutboundTxHash, cctxListv15[i].OutboundTxParams[j].OutboundTxHash) - require.Equal(t, v14cctxList[i].OutboundTxParams[j].OutboundTxBallotIndex, cctxListv15[i].OutboundTxParams[j].OutboundTxBallotIndex) - require.Equal(t, v14cctxList[i].OutboundTxParams[j].OutboundTxObservedExternalHeight, cctxListv15[i].OutboundTxParams[j].OutboundTxObservedExternalHeight) - require.Equal(t, v14cctxList[i].OutboundTxParams[j].OutboundTxGasUsed, cctxListv15[i].OutboundTxParams[j].OutboundTxGasUsed) - require.Equal(t, v14cctxList[i].OutboundTxParams[j].OutboundTxEffectiveGasPrice, cctxListv15[i].OutboundTxParams[j].OutboundTxEffectiveGasPrice) - require.Equal(t, v14cctxList[i].OutboundTxParams[j].CoinType, cctxListv15[i].CoinType) - } - } - }) -} - -func SetCrossChainTxV14(ctx sdk.Context, cctx types.CrossChainTxV14, k *keeper.Keeper) { - p := types.KeyPrefix(fmt.Sprintf("%s", types.SendKey)) - store := prefix.NewStore(ctx.KVStore(k.GetStoreKey()), p) - b := k.GetCodec().MustMarshal(&cctx) - store.Set(types.KeyPrefix(cctx.Index), b) -} diff --git a/x/crosschain/module.go b/x/crosschain/module.go index 197ecb2564..45d23053da 100644 --- a/x/crosschain/module.go +++ b/x/crosschain/module.go @@ -154,9 +154,6 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { if err := cfg.RegisterMigration(types.ModuleName, 4, m.Migrate4to5); err != nil { panic(err) } - if err := cfg.RegisterMigration(types.ModuleName, 5, m.Migrate5to6); err != nil { - panic(err) - } } @@ -185,7 +182,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 6 } +func (AppModule) ConsensusVersion() uint64 { return 5 } // BeginBlock executes all ABCI BeginBlock logic respective to the crosschain module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { diff --git a/x/crosschain/types/cctx_utils.go b/x/crosschain/types/cctx_utils.go index 695cb152f3..144acc379c 100644 --- a/x/crosschain/types/cctx_utils.go +++ b/x/crosschain/types/cctx_utils.go @@ -5,6 +5,7 @@ import ( "regexp" "strconv" + "cosmossdk.io/errors" "github.com/btcsuite/btcutil" sdk "github.com/cosmos/cosmos-sdk/types" ethcommon "github.com/ethereum/go-ethereum/common" @@ -106,12 +107,12 @@ func (m InboundTxParams) Validate() error { } err = ValidateHashForChain(m.InboundTxObservedHash, m.SenderChainId) if err != nil { - return err + return errors.Wrap(err, "invalid inbound tx observed hash") } if m.InboundTxBallotIndex != "" { err = ValidateZetaIndex(m.InboundTxBallotIndex) if err != nil { - return err + return errors.Wrap(err, "invalid inbound tx ballot index") } } return nil @@ -134,13 +135,13 @@ func (m OutboundTxParams) Validate() error { if m.OutboundTxBallotIndex != "" { err = ValidateZetaIndex(m.OutboundTxBallotIndex) if err != nil { - return err + return errors.Wrap(err, "invalid outbound tx ballot index") } } if m.OutboundTxHash != "" { err = ValidateHashForChain(m.OutboundTxHash, m.ReceiverChainId) if err != nil { - return err + return errors.Wrap(err, "invalid outbound tx hash") } } return nil diff --git a/x/crosschain/types/cross_chain_tx.pb.go b/x/crosschain/types/cross_chain_tx.pb.go index c0a76dba6a..94f34e6e46 100644 --- a/x/crosschain/types/cross_chain_tx.pb.go +++ b/x/crosschain/types/cross_chain_tx.pb.go @@ -95,6 +95,7 @@ type InboundTxParams struct { Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` SenderChainId int64 `protobuf:"varint,2,opt,name=sender_chain_id,json=senderChainId,proto3" json:"sender_chain_id,omitempty"` TxOrigin string `protobuf:"bytes,3,opt,name=tx_origin,json=txOrigin,proto3" json:"tx_origin,omitempty"` + CoinType common.CoinType `protobuf:"varint,4,opt,name=coin_type,json=coinType,proto3,enum=common.CoinType" json:"coin_type,omitempty"` Asset string `protobuf:"bytes,5,opt,name=asset,proto3" json:"asset,omitempty"` Amount github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,6,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"amount"` InboundTxObservedHash string `protobuf:"bytes,7,opt,name=inbound_tx_observed_hash,json=inboundTxObservedHash,proto3" json:"inbound_tx_observed_hash,omitempty"` @@ -158,6 +159,13 @@ func (m *InboundTxParams) GetTxOrigin() string { return "" } +func (m *InboundTxParams) GetCoinType() common.CoinType { + if m != nil { + return m.CoinType + } + return common.CoinType_Zeta +} + func (m *InboundTxParams) GetAsset() string { if m != nil { return m.Asset @@ -241,6 +249,7 @@ var xxx_messageInfo_ZetaAccounting proto.InternalMessageInfo type OutboundTxParams struct { Receiver string `protobuf:"bytes,1,opt,name=receiver,proto3" json:"receiver,omitempty"` ReceiverChainId int64 `protobuf:"varint,2,opt,name=receiver_chainId,json=receiverChainId,proto3" json:"receiver_chainId,omitempty"` + CoinType common.CoinType `protobuf:"varint,3,opt,name=coin_type,json=coinType,proto3,enum=common.CoinType" json:"coin_type,omitempty"` Amount github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,4,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"amount"` OutboundTxTssNonce uint64 `protobuf:"varint,5,opt,name=outbound_tx_tss_nonce,json=outboundTxTssNonce,proto3" json:"outbound_tx_tss_nonce,omitempty"` OutboundTxGasLimit uint64 `protobuf:"varint,6,opt,name=outbound_tx_gas_limit,json=outboundTxGasLimit,proto3" json:"outbound_tx_gas_limit,omitempty"` @@ -304,6 +313,13 @@ func (m *OutboundTxParams) GetReceiverChainId() int64 { return 0 } +func (m *OutboundTxParams) GetCoinType() common.CoinType { + if m != nil { + return m.CoinType + } + return common.CoinType_Zeta +} + func (m *OutboundTxParams) GetOutboundTxTssNonce() uint64 { if m != nil { return m.OutboundTxTssNonce @@ -450,8 +466,6 @@ type CrossChainTx struct { CctxStatus *Status `protobuf:"bytes,8,opt,name=cctx_status,json=cctxStatus,proto3" json:"cctx_status,omitempty"` InboundTxParams *InboundTxParams `protobuf:"bytes,9,opt,name=inbound_tx_params,json=inboundTxParams,proto3" json:"inbound_tx_params,omitempty"` OutboundTxParams []*OutboundTxParams `protobuf:"bytes,10,rep,name=outbound_tx_params,json=outboundTxParams,proto3" json:"outbound_tx_params,omitempty"` - EventIndex uint64 `protobuf:"varint,11,opt,name=event_index,json=eventIndex,proto3" json:"event_index,omitempty"` - CoinType common.CoinType `protobuf:"varint,12,opt,name=coin_type,json=coinType,proto3,enum=common.CoinType" json:"coin_type,omitempty"` } func (m *CrossChainTx) Reset() { *m = CrossChainTx{} } @@ -529,20 +543,6 @@ func (m *CrossChainTx) GetOutboundTxParams() []*OutboundTxParams { return nil } -func (m *CrossChainTx) GetEventIndex() uint64 { - if m != nil { - return m.EventIndex - } - return 0 -} - -func (m *CrossChainTx) GetCoinType() common.CoinType { - if m != nil { - return m.CoinType - } - return common.CoinType_Zeta -} - func init() { proto.RegisterEnum("zetachain.zetacore.crosschain.CctxStatus", CctxStatus_name, CctxStatus_value) proto.RegisterEnum("zetachain.zetacore.crosschain.TxFinalizationStatus", TxFinalizationStatus_name, TxFinalizationStatus_value) @@ -556,78 +556,77 @@ func init() { func init() { proto.RegisterFile("crosschain/cross_chain_tx.proto", fileDescriptor_af3a0ad055343c21) } var fileDescriptor_af3a0ad055343c21 = []byte{ - // 1132 bytes of a gzipped FileDescriptorProto + // 1120 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcd, 0x6e, 0x1b, 0x37, - 0x10, 0xd6, 0xc6, 0x8a, 0x22, 0x8d, 0x6c, 0x6b, 0x4d, 0xcb, 0xe9, 0xc2, 0x69, 0x24, 0x41, 0x6d, - 0x12, 0x25, 0x40, 0x24, 0xc4, 0x41, 0x11, 0xa0, 0x37, 0xdb, 0x8d, 0x13, 0x23, 0x89, 0x6d, 0x6c, - 0xed, 0x8b, 0x81, 0x62, 0x4b, 0xed, 0x8e, 0x25, 0x22, 0xd2, 0x52, 0x5d, 0x52, 0x86, 0x14, 0xf4, - 0x21, 0xfa, 0x00, 0x3d, 0xf6, 0xd0, 0xa7, 0xe8, 0x39, 0xb7, 0xe6, 0x58, 0xf4, 0x60, 0x14, 0x36, - 0xfa, 0x02, 0x7d, 0x82, 0x62, 0x49, 0xae, 0xb4, 0x56, 0xfd, 0xd3, 0xbf, 0xd3, 0x0e, 0x87, 0xfc, - 0x86, 0xb3, 0x9c, 0xef, 0x1b, 0x12, 0xaa, 0x7e, 0xc4, 0x85, 0xf0, 0xbb, 0x94, 0x85, 0x2d, 0x65, - 0x7a, 0xca, 0xf6, 0xe4, 0xa8, 0x39, 0x88, 0xb8, 0xe4, 0xe4, 0xee, 0x3b, 0x94, 0x54, 0xf9, 0x9a, - 0xca, 0xe2, 0x11, 0x36, 0xa7, 0x98, 0xd5, 0x65, 0x9f, 0xf7, 0xfb, 0x3c, 0x6c, 0xe9, 0x8f, 0xc6, - 0xac, 0x96, 0x3b, 0xbc, 0xc3, 0x95, 0xd9, 0x8a, 0x2d, 0xed, 0xad, 0xff, 0x94, 0x85, 0xd2, 0x76, - 0xd8, 0xe6, 0xc3, 0x30, 0xd8, 0x1f, 0xed, 0xd1, 0x88, 0xf6, 0x05, 0xb9, 0x0d, 0x39, 0x81, 0x61, - 0x80, 0x91, 0x63, 0xd5, 0xac, 0x46, 0xc1, 0x35, 0x23, 0x72, 0x1f, 0x4a, 0xda, 0x32, 0xe9, 0xb0, - 0xc0, 0xb9, 0x51, 0xb3, 0x1a, 0x73, 0xee, 0x82, 0x76, 0x6f, 0xc6, 0xde, 0xed, 0x80, 0xdc, 0x81, - 0x82, 0x1c, 0x79, 0x3c, 0x62, 0x1d, 0x16, 0x3a, 0x73, 0x2a, 0x44, 0x5e, 0x8e, 0x76, 0xd5, 0x98, - 0x94, 0xe1, 0x26, 0x15, 0x02, 0xa5, 0x73, 0x53, 0x4d, 0xe8, 0x01, 0x79, 0x01, 0x39, 0xda, 0xe7, - 0xc3, 0x50, 0x3a, 0xb9, 0xd8, 0xbd, 0xd1, 0x7a, 0x7f, 0x52, 0xcd, 0xfc, 0x7a, 0x52, 0x7d, 0xd0, - 0x61, 0xb2, 0x3b, 0x6c, 0x37, 0x7d, 0xde, 0x6f, 0xf9, 0x5c, 0xf4, 0xb9, 0x30, 0x9f, 0xc7, 0x22, - 0x78, 0xdb, 0x92, 0xe3, 0x01, 0x8a, 0xe6, 0x01, 0x0b, 0xa5, 0x6b, 0xe0, 0xe4, 0x19, 0x38, 0x4c, - 0xff, 0x8e, 0x17, 0xe7, 0xd0, 0x16, 0x18, 0x1d, 0x63, 0xe0, 0x75, 0xa9, 0xe8, 0x3a, 0xb7, 0xd4, - 0x8e, 0x2b, 0x2c, 0xf9, 0xdd, 0x5d, 0x33, 0xfb, 0x92, 0x8a, 0x2e, 0x79, 0x0d, 0x9f, 0x5c, 0x04, - 0xc4, 0x91, 0xc4, 0x28, 0xa4, 0x3d, 0xaf, 0x8b, 0xac, 0xd3, 0x95, 0x4e, 0xbe, 0x66, 0x35, 0xb2, - 0x6e, 0xf5, 0x2f, 0x31, 0x9e, 0x9b, 0x75, 0x2f, 0xd5, 0x32, 0xf2, 0x19, 0x7c, 0x94, 0x8a, 0xd6, - 0xa6, 0xbd, 0x1e, 0x97, 0x1e, 0x0b, 0x03, 0x1c, 0x39, 0x05, 0x95, 0x45, 0x79, 0x12, 0x61, 0x43, - 0x4d, 0x6e, 0xc7, 0x73, 0x64, 0x0b, 0x6a, 0x29, 0xd8, 0x11, 0x0b, 0x69, 0x8f, 0xbd, 0xc3, 0xc0, - 0x8b, 0x8b, 0x9c, 0x64, 0x00, 0x2a, 0x83, 0x8f, 0x27, 0xf8, 0xad, 0x64, 0xd5, 0x21, 0x4a, 0x6a, - 0xb6, 0x67, 0x70, 0x7b, 0x8a, 0xa7, 0x92, 0xf1, 0xd0, 0x13, 0x92, 0xca, 0xa1, 0x70, 0x8a, 0x35, - 0xab, 0xb1, 0xb8, 0xf6, 0xb4, 0x79, 0x25, 0x81, 0x9a, 0x93, 0xa8, 0x0a, 0xfb, 0xa5, 0x82, 0xba, - 0x65, 0x79, 0x81, 0xb7, 0xfe, 0x0d, 0x2c, 0xc6, 0x1b, 0xaf, 0xfb, 0x7e, 0x7c, 0xfe, 0x2c, 0xec, - 0x10, 0x0f, 0x96, 0x69, 0x9b, 0x47, 0x32, 0xc9, 0xdb, 0x14, 0xd6, 0xfa, 0x77, 0x85, 0x5d, 0x32, - 0xb1, 0xd4, 0x26, 0x2a, 0x52, 0xfd, 0xf7, 0x1c, 0xd8, 0xbb, 0x43, 0x79, 0x9e, 0xb4, 0xab, 0x90, - 0x8f, 0xd0, 0x47, 0x76, 0x3c, 0xa1, 0xed, 0x64, 0x4c, 0x1e, 0x82, 0x9d, 0xd8, 0x9a, 0xba, 0xdb, - 0x09, 0x73, 0x4b, 0x89, 0x3f, 0xe1, 0xee, 0x94, 0x88, 0xd9, 0xff, 0x46, 0xc4, 0x27, 0xb0, 0xc2, - 0x4d, 0x8e, 0x71, 0x2d, 0xa5, 0x10, 0x5e, 0xc8, 0x43, 0x1f, 0x15, 0xef, 0xb3, 0x2e, 0xe1, 0x93, - 0x1f, 0xd8, 0x17, 0x62, 0x27, 0x9e, 0x99, 0x85, 0x74, 0xa8, 0xf0, 0x7a, 0xac, 0xcf, 0xb4, 0x26, - 0xce, 0x41, 0x5e, 0x50, 0xf1, 0x3a, 0x9e, 0xb9, 0x08, 0x32, 0x88, 0x98, 0x8f, 0x86, 0xeb, 0xe7, - 0x21, 0x7b, 0xf1, 0x0c, 0x69, 0x80, 0x9d, 0x86, 0x28, 0x65, 0xe4, 0xd5, 0xea, 0xc5, 0xe9, 0x6a, - 0x25, 0x89, 0x67, 0xe0, 0xa4, 0x57, 0x5e, 0xc0, 0xe2, 0x95, 0x29, 0x22, 0x4d, 0xe3, 0x1d, 0xf8, - 0x34, 0x0d, 0xbc, 0x54, 0x4c, 0x9a, 0xca, 0xb5, 0x69, 0x90, 0x4b, 0xd4, 0xd4, 0x82, 0xf2, 0xec, - 0x5f, 0x0e, 0x05, 0x06, 0x4e, 0x59, 0xe1, 0x97, 0xce, 0xfd, 0xe4, 0x81, 0xc0, 0x80, 0x48, 0xa8, - 0xa6, 0x01, 0x78, 0x74, 0x84, 0xbe, 0x64, 0xc7, 0x98, 0x3a, 0xa0, 0x15, 0x55, 0xde, 0xa6, 0x29, - 0xef, 0xfd, 0xbf, 0x51, 0xde, 0xed, 0x50, 0xba, 0x77, 0xa6, 0x7b, 0x3d, 0x4f, 0x82, 0x4e, 0x4e, - 0xf6, 0x8b, 0xab, 0x76, 0xd5, 0x95, 0xbc, 0xad, 0x32, 0xbe, 0x24, 0x8a, 0x2e, 0xe9, 0x5d, 0x80, - 0x98, 0x2c, 0x83, 0x61, 0xfb, 0x2d, 0x8e, 0x95, 0x5e, 0x0b, 0x6e, 0x41, 0x0a, 0xb1, 0xa7, 0x1c, - 0x57, 0x48, 0x7b, 0xfe, 0xff, 0x96, 0xf6, 0xcf, 0x16, 0xe4, 0xb4, 0x49, 0xd6, 0x21, 0x67, 0x76, - 0xb1, 0xd4, 0x2e, 0x0f, 0xaf, 0xd9, 0x65, 0xd3, 0x97, 0x23, 0x13, 0xdb, 0x00, 0xc9, 0x3d, 0x58, - 0xd4, 0x96, 0xd7, 0x47, 0x21, 0x68, 0x07, 0x95, 0x04, 0x0b, 0xee, 0x82, 0xf6, 0xbe, 0xd1, 0x4e, - 0xf2, 0x04, 0xca, 0x3d, 0x2a, 0xe4, 0xc1, 0x20, 0xa0, 0x12, 0x3d, 0xc9, 0xfa, 0x28, 0x24, 0xed, - 0x0f, 0xd4, 0x3d, 0x32, 0xe7, 0x2e, 0x4f, 0xe7, 0xf6, 0x93, 0x29, 0xd2, 0x80, 0x12, 0x13, 0xeb, - 0x71, 0x9b, 0x70, 0xf1, 0x68, 0x18, 0x06, 0x18, 0x28, 0xf1, 0xe6, 0xdd, 0x59, 0x77, 0xfd, 0xfb, - 0x2c, 0xcc, 0x6f, 0xc6, 0x59, 0x2a, 0xb9, 0xef, 0x8f, 0x88, 0x03, 0xb7, 0xfc, 0x08, 0xa9, 0xe4, - 0x49, 0xd3, 0x48, 0x86, 0xf1, 0x3d, 0xa5, 0x99, 0xae, 0xb3, 0xd4, 0x03, 0xf2, 0x35, 0x14, 0x54, - 0x4f, 0x3b, 0x42, 0x14, 0xfa, 0x06, 0xdb, 0xd8, 0xfc, 0x87, 0x1d, 0xe2, 0x8f, 0x93, 0xaa, 0x3d, - 0xa6, 0xfd, 0xde, 0xe7, 0xf5, 0x49, 0xa4, 0xba, 0x9b, 0x8f, 0xed, 0x2d, 0x44, 0x41, 0x1e, 0x40, - 0x29, 0xc2, 0x1e, 0x1d, 0x63, 0x30, 0x39, 0xa7, 0x9c, 0x56, 0xa7, 0x71, 0x27, 0x07, 0xb5, 0x05, - 0x45, 0xdf, 0x97, 0xa3, 0xa4, 0xfa, 0xb1, 0x84, 0x8b, 0x6b, 0xf7, 0xae, 0xa9, 0x8b, 0xa9, 0x09, - 0xf8, 0x93, 0xfa, 0x90, 0x43, 0x58, 0x4a, 0xdd, 0x39, 0x03, 0xd5, 0x4d, 0x95, 0xbc, 0x8b, 0x6b, - 0xcd, 0x6b, 0xa2, 0xcd, 0x3c, 0x1c, 0xdc, 0x12, 0x9b, 0x79, 0x49, 0x7c, 0x05, 0x24, 0xad, 0x08, - 0x13, 0x1c, 0x6a, 0x73, 0x8d, 0xe2, 0x5a, 0xeb, 0x9a, 0xe0, 0xb3, 0x1d, 0xde, 0xb5, 0xf9, 0x6c, - 0xcf, 0xaf, 0x42, 0x11, 0x8f, 0x31, 0x4c, 0x7a, 0x52, 0x51, 0x89, 0x0b, 0x94, 0x4b, 0x37, 0xa2, - 0xc7, 0x50, 0xf0, 0x79, 0xfc, 0x70, 0x1a, 0x0f, 0xd0, 0xe8, 0xc3, 0x6e, 0x9a, 0x57, 0xd1, 0x26, - 0x67, 0xe1, 0xfe, 0x78, 0x80, 0x6e, 0xde, 0x37, 0xd6, 0xa3, 0x6f, 0x01, 0xa6, 0xc4, 0x25, 0x04, - 0x16, 0xf7, 0x30, 0x0c, 0x58, 0xd8, 0x31, 0xff, 0x69, 0x67, 0xc8, 0x32, 0x94, 0x8c, 0x2f, 0x49, - 0xcf, 0xb6, 0xc8, 0x12, 0x2c, 0x24, 0xa3, 0x37, 0x2c, 0xc4, 0xc0, 0x9e, 0x8b, 0x5d, 0x66, 0x9d, - 0x8b, 0xc7, 0x18, 0x49, 0x3b, 0x4b, 0xe6, 0x21, 0xaf, 0x6d, 0x0c, 0xec, 0x9b, 0xa4, 0x08, 0xb7, - 0xd6, 0xf5, 0xc5, 0x66, 0xe7, 0x56, 0xb3, 0x3f, 0xfe, 0x50, 0xb1, 0x1e, 0xbd, 0x82, 0xf2, 0x45, - 0xe2, 0x24, 0x36, 0xcc, 0xef, 0x70, 0x39, 0xb9, 0xe6, 0xed, 0x0c, 0x59, 0x80, 0xc2, 0x74, 0x68, - 0xc5, 0x91, 0x9f, 0x8f, 0xd0, 0x1f, 0xc6, 0xc1, 0x6e, 0xe8, 0x60, 0x1b, 0xaf, 0xde, 0x9f, 0x56, - 0xac, 0x0f, 0xa7, 0x15, 0xeb, 0xb7, 0xd3, 0x8a, 0xf5, 0xdd, 0x59, 0x25, 0xf3, 0xe1, 0xac, 0x92, - 0xf9, 0xe5, 0xac, 0x92, 0x39, 0x7c, 0x92, 0xe2, 0x69, 0x7c, 0xee, 0x8f, 0xf5, 0x3b, 0x33, 0x29, - 0x41, 0x6b, 0xd4, 0x4a, 0xbd, 0x3e, 0x15, 0x6d, 0xdb, 0x39, 0xf5, 0x56, 0x7c, 0xfa, 0x67, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xcf, 0x88, 0x02, 0x98, 0x0a, 0x00, 0x00, + 0x10, 0xd6, 0x46, 0x8a, 0x2c, 0x8d, 0x6c, 0x6b, 0x4d, 0xcb, 0xe9, 0xc2, 0x69, 0x24, 0x41, 0x6d, + 0x12, 0x25, 0x80, 0x25, 0xd8, 0x41, 0x11, 0xa0, 0x37, 0xdb, 0xb5, 0x13, 0x23, 0x89, 0x6d, 0x6c, + 0xed, 0x8b, 0x81, 0x62, 0x4b, 0xed, 0xd2, 0x12, 0x11, 0x69, 0xa9, 0x2e, 0x29, 0x43, 0x0e, 0xfa, + 0x10, 0x3d, 0xf4, 0x11, 0x7a, 0xe8, 0xa3, 0xe4, 0x50, 0xa0, 0x39, 0x16, 0x3d, 0x18, 0x85, 0x7d, + 0xee, 0xa5, 0x4f, 0x50, 0xf0, 0x67, 0x57, 0x6b, 0xd5, 0x3f, 0xfd, 0x3b, 0xed, 0x70, 0xc8, 0xef, + 0x9b, 0x21, 0xe7, 0x1b, 0x72, 0xa1, 0xe6, 0x47, 0x8c, 0x73, 0xbf, 0x87, 0x69, 0xd8, 0x56, 0xa6, + 0xa7, 0x6c, 0x4f, 0x8c, 0x5b, 0xc3, 0x88, 0x09, 0x86, 0x1e, 0xbc, 0x23, 0x02, 0x2b, 0x5f, 0x4b, + 0x59, 0x2c, 0x22, 0xad, 0x09, 0x66, 0x79, 0xd1, 0x67, 0x83, 0x01, 0x0b, 0xdb, 0xfa, 0xa3, 0x31, + 0xcb, 0x95, 0x2e, 0xeb, 0x32, 0x65, 0xb6, 0xa5, 0xa5, 0xbd, 0x8d, 0xdf, 0x73, 0x50, 0xde, 0x09, + 0x3b, 0x6c, 0x14, 0x06, 0x07, 0xe3, 0x7d, 0x1c, 0xe1, 0x01, 0x47, 0xf7, 0x20, 0xcf, 0x49, 0x18, + 0x90, 0xc8, 0xb1, 0xea, 0x56, 0xb3, 0xe8, 0x9a, 0x11, 0x7a, 0x04, 0x65, 0x6d, 0x99, 0x74, 0x68, + 0xe0, 0xdc, 0xa9, 0x5b, 0xcd, 0xac, 0x3b, 0xa7, 0xdd, 0x9b, 0xd2, 0xbb, 0x13, 0xa0, 0xfb, 0x50, + 0x14, 0x63, 0x8f, 0x45, 0xb4, 0x4b, 0x43, 0x27, 0xab, 0x28, 0x0a, 0x62, 0xbc, 0xa7, 0xc6, 0x68, + 0x05, 0x8a, 0x3e, 0x93, 0x7b, 0x39, 0x1d, 0x12, 0x27, 0x57, 0xb7, 0x9a, 0xf3, 0x6b, 0x76, 0xcb, + 0x24, 0xba, 0xc9, 0x68, 0x78, 0x70, 0x3a, 0x24, 0x6e, 0xc1, 0x37, 0x16, 0xaa, 0xc0, 0x5d, 0xcc, + 0x39, 0x11, 0xce, 0x5d, 0xc5, 0xa3, 0x07, 0xe8, 0x05, 0xe4, 0xf1, 0x80, 0x8d, 0x42, 0xe1, 0xe4, + 0xa5, 0x7b, 0xa3, 0xfd, 0xfe, 0xac, 0x96, 0xf9, 0xf5, 0xac, 0xf6, 0xb8, 0x4b, 0x45, 0x6f, 0xd4, + 0x91, 0x7c, 0x6d, 0x9f, 0xf1, 0x01, 0xe3, 0xe6, 0xb3, 0xc2, 0x83, 0xb7, 0x6d, 0x19, 0x92, 0xb7, + 0x0e, 0x69, 0x28, 0x5c, 0x03, 0x47, 0xcf, 0xc1, 0xa1, 0x7a, 0xf7, 0x9e, 0x4c, 0xb9, 0xc3, 0x49, + 0x74, 0x42, 0x02, 0xaf, 0x87, 0x79, 0xcf, 0x99, 0x51, 0x11, 0x97, 0x68, 0x7c, 0x3a, 0x7b, 0x66, + 0xf6, 0x25, 0xe6, 0x3d, 0xf4, 0x1a, 0x3e, 0xb9, 0x0a, 0x48, 0xc6, 0x82, 0x44, 0x21, 0xee, 0x7b, + 0x3d, 0x42, 0xbb, 0x3d, 0xe1, 0x14, 0xea, 0x56, 0x33, 0xe7, 0xd6, 0xfe, 0xc2, 0xb1, 0x65, 0xd6, + 0xbd, 0x54, 0xcb, 0xd0, 0x67, 0xf0, 0x51, 0x8a, 0xad, 0x83, 0xfb, 0x7d, 0x26, 0x3c, 0x1a, 0x06, + 0x64, 0xec, 0x14, 0x55, 0x16, 0x95, 0x84, 0x61, 0x43, 0x4d, 0xee, 0xc8, 0x39, 0xb4, 0x0d, 0xf5, + 0x14, 0xec, 0x98, 0x86, 0xb8, 0x4f, 0xdf, 0x91, 0xc0, 0x93, 0x9a, 0x88, 0x33, 0x00, 0x95, 0xc1, + 0xc7, 0x09, 0x7e, 0x3b, 0x5e, 0x75, 0x44, 0x04, 0x36, 0xe1, 0x29, 0xdc, 0x9b, 0xe0, 0xb1, 0xa0, + 0x2c, 0xf4, 0xb8, 0xc0, 0x62, 0xc4, 0x9d, 0x92, 0x2a, 0xd0, 0xb3, 0xd6, 0x8d, 0x7a, 0x6b, 0x25, + 0xac, 0x0a, 0xfb, 0xa5, 0x82, 0xba, 0x15, 0x71, 0x85, 0xb7, 0xf1, 0x0d, 0xcc, 0xcb, 0xc0, 0xeb, + 0xbe, 0x2f, 0xcf, 0x9f, 0x86, 0x5d, 0xe4, 0xc1, 0x22, 0xee, 0xb0, 0x48, 0xc4, 0x79, 0x9b, 0xc2, + 0x5a, 0xff, 0xae, 0xb0, 0x0b, 0x86, 0x4b, 0x05, 0x51, 0x4c, 0x8d, 0xef, 0x67, 0xc0, 0xde, 0x1b, + 0x89, 0xcb, 0x1a, 0x5f, 0x86, 0x42, 0x44, 0x7c, 0x42, 0x4f, 0x12, 0x95, 0x27, 0x63, 0xf4, 0x04, + 0xec, 0xd8, 0xd6, 0x4a, 0xdf, 0x89, 0x85, 0x5e, 0x8e, 0xfd, 0xb1, 0xd4, 0x2f, 0xa9, 0x39, 0x7b, + 0xab, 0x9a, 0x27, 0xba, 0xcd, 0xfd, 0x37, 0xdd, 0xae, 0xc2, 0x12, 0x33, 0x5b, 0x92, 0xa5, 0x17, + 0x9c, 0x7b, 0x21, 0x0b, 0x7d, 0xa2, 0xda, 0x24, 0xe7, 0x22, 0x96, 0xec, 0xf7, 0x80, 0xf3, 0x5d, + 0x39, 0x33, 0x0d, 0xe9, 0x62, 0xee, 0xf5, 0xe9, 0x80, 0xea, 0x16, 0xba, 0x04, 0x79, 0x81, 0xf9, + 0x6b, 0x39, 0x73, 0x15, 0x64, 0x18, 0x51, 0x9f, 0x98, 0xd6, 0xb8, 0x0c, 0xd9, 0x97, 0x33, 0xa8, + 0x09, 0x76, 0x1a, 0xa2, 0x1a, 0xa9, 0xa0, 0x56, 0xcf, 0x4f, 0x56, 0xab, 0x0e, 0x7a, 0x0e, 0x4e, + 0x7a, 0xe5, 0x15, 0xa2, 0x5f, 0x9a, 0x20, 0xd2, 0xaa, 0xdf, 0x85, 0x4f, 0xd3, 0xc0, 0x6b, 0x7b, + 0x4f, 0x2b, 0xbf, 0x3e, 0x21, 0xb9, 0xa6, 0xf9, 0xda, 0x50, 0x99, 0xde, 0xe5, 0x88, 0x93, 0xc0, + 0xa9, 0x28, 0xfc, 0xc2, 0xa5, 0x4d, 0x1e, 0x72, 0x12, 0x20, 0x01, 0xb5, 0x34, 0x80, 0x1c, 0x1f, + 0x13, 0x5f, 0xd0, 0x13, 0x92, 0x3a, 0xa0, 0x25, 0x55, 0xde, 0x96, 0x29, 0xef, 0xa3, 0xbf, 0x51, + 0xde, 0x9d, 0x50, 0xb8, 0xf7, 0x27, 0xb1, 0xb6, 0x62, 0xd2, 0xe4, 0x64, 0xbf, 0xb8, 0x29, 0xaa, + 0xae, 0xe4, 0x3d, 0x95, 0xf1, 0x35, 0x2c, 0xba, 0xa4, 0x0f, 0x00, 0xa4, 0x58, 0x86, 0xa3, 0xce, + 0x5b, 0x72, 0xaa, 0xda, 0xbb, 0xe8, 0x16, 0x05, 0xe7, 0xfb, 0xca, 0x71, 0xc3, 0x4d, 0x30, 0xfb, + 0x7f, 0xdf, 0x04, 0x3f, 0x5b, 0x90, 0xd7, 0x26, 0x5a, 0x87, 0xbc, 0x89, 0x62, 0xa9, 0x28, 0x4f, + 0x6e, 0x89, 0xb2, 0xe9, 0x8b, 0xb1, 0xe1, 0x36, 0x40, 0xf4, 0x10, 0xe6, 0xb5, 0xe5, 0x0d, 0x08, + 0xe7, 0xb8, 0x4b, 0x54, 0xc7, 0x16, 0xdd, 0x39, 0xed, 0x7d, 0xa3, 0x9d, 0x68, 0x15, 0x2a, 0x7d, + 0xcc, 0xc5, 0xe1, 0x30, 0xc0, 0x82, 0x78, 0x82, 0x0e, 0x08, 0x17, 0x78, 0x30, 0x54, 0xad, 0x9b, + 0x75, 0x17, 0x27, 0x73, 0x07, 0xf1, 0x14, 0x6a, 0x42, 0x99, 0xf2, 0x75, 0x79, 0xab, 0xb8, 0xe4, + 0x78, 0x14, 0x06, 0x24, 0x50, 0xcd, 0x5b, 0x70, 0xa7, 0xdd, 0x8d, 0x9f, 0xb2, 0x30, 0xbb, 0x29, + 0xb3, 0x54, 0xb7, 0xc3, 0xc1, 0x18, 0x39, 0x30, 0xe3, 0x47, 0x04, 0x0b, 0x16, 0xdf, 0x31, 0xf1, + 0x50, 0x3e, 0x6b, 0x5a, 0xe9, 0x3a, 0x4b, 0x3d, 0x40, 0x5f, 0x43, 0x51, 0x5d, 0x81, 0xc7, 0x84, + 0x70, 0xfd, 0xe0, 0x6d, 0x6c, 0xfe, 0xc3, 0x1b, 0xe2, 0x8f, 0xb3, 0x9a, 0x7d, 0x8a, 0x07, 0xfd, + 0xcf, 0x1b, 0x09, 0x53, 0xc3, 0x2d, 0x48, 0x7b, 0x9b, 0x10, 0x8e, 0x1e, 0x43, 0x39, 0x22, 0x7d, + 0x7c, 0x4a, 0x82, 0xe4, 0x9c, 0xf2, 0xba, 0x3b, 0x8d, 0x3b, 0x3e, 0xa8, 0x6d, 0x28, 0xf9, 0xbe, + 0x18, 0xc7, 0xd5, 0x97, 0x2d, 0x5c, 0x5a, 0x7b, 0x78, 0x4b, 0x5d, 0x4c, 0x4d, 0xc0, 0x4f, 0xea, + 0x83, 0x8e, 0x60, 0x21, 0xf5, 0x44, 0x0d, 0xd5, 0xe5, 0xab, 0xda, 0xbb, 0xb4, 0xd6, 0xba, 0x85, + 0x6d, 0xea, 0xb7, 0xc4, 0x2d, 0xd3, 0xa9, 0xff, 0x94, 0xaf, 0x00, 0xa5, 0x3b, 0xc2, 0x90, 0x43, + 0x3d, 0xdb, 0x2c, 0xad, 0xb5, 0x6f, 0x21, 0x9f, 0x7e, 0x10, 0x5c, 0x9b, 0x4d, 0x79, 0x9e, 0x7e, + 0x0b, 0x30, 0x11, 0x1a, 0x42, 0x30, 0xbf, 0x4f, 0xc2, 0x80, 0x86, 0x5d, 0x93, 0x97, 0x9d, 0x41, + 0x8b, 0x50, 0x36, 0xbe, 0x98, 0xce, 0xb6, 0xd0, 0x02, 0xcc, 0xc5, 0xa3, 0x37, 0x34, 0x24, 0x81, + 0x9d, 0x95, 0x2e, 0xb3, 0xce, 0x25, 0x27, 0x24, 0x12, 0x76, 0x0e, 0xcd, 0x42, 0x41, 0xdb, 0x24, + 0xb0, 0xef, 0xa2, 0x12, 0xcc, 0xac, 0xeb, 0x77, 0xcb, 0xce, 0x2f, 0xe7, 0x7e, 0xfc, 0xa1, 0x6a, + 0x3d, 0x7d, 0x05, 0x95, 0xab, 0x9a, 0x09, 0xd9, 0x30, 0xbb, 0xcb, 0x44, 0xf2, 0x8a, 0xdb, 0x19, + 0x34, 0x07, 0xc5, 0xc9, 0xd0, 0x92, 0xcc, 0x5b, 0x63, 0xe2, 0x8f, 0x24, 0xd9, 0x1d, 0x4d, 0xb6, + 0xf1, 0xea, 0xfd, 0x79, 0xd5, 0xfa, 0x70, 0x5e, 0xb5, 0x7e, 0x3b, 0xaf, 0x5a, 0xdf, 0x5d, 0x54, + 0x33, 0x1f, 0x2e, 0xaa, 0x99, 0x5f, 0x2e, 0xaa, 0x99, 0xa3, 0xd5, 0x94, 0xae, 0xe4, 0x39, 0xad, + 0xe8, 0xbf, 0xce, 0xf8, 0xc8, 0xda, 0xe3, 0x76, 0xea, 0x5f, 0x54, 0xc9, 0xac, 0x93, 0x57, 0x7f, + 0x8e, 0xcf, 0xfe, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x13, 0xc7, 0x24, 0x8d, 0xa6, 0x0a, 0x00, 0x00, } func (m *InboundTxParams) Marshal() (dAtA []byte, err error) { @@ -696,6 +695,11 @@ func (m *InboundTxParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x2a } + if m.CoinType != 0 { + i = encodeVarintCrossChainTx(dAtA, i, uint64(m.CoinType)) + i-- + dAtA[i] = 0x20 + } if len(m.TxOrigin) > 0 { i -= len(m.TxOrigin) copy(dAtA[i:], m.TxOrigin) @@ -855,6 +859,11 @@ func (m *OutboundTxParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { } i-- dAtA[i] = 0x22 + if m.CoinType != 0 { + i = encodeVarintCrossChainTx(dAtA, i, uint64(m.CoinType)) + i-- + dAtA[i] = 0x18 + } if m.ReceiverChainId != 0 { i = encodeVarintCrossChainTx(dAtA, i, uint64(m.ReceiverChainId)) i-- @@ -940,16 +949,6 @@ func (m *CrossChainTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.CoinType != 0 { - i = encodeVarintCrossChainTx(dAtA, i, uint64(m.CoinType)) - i-- - dAtA[i] = 0x60 - } - if m.EventIndex != 0 { - i = encodeVarintCrossChainTx(dAtA, i, uint64(m.EventIndex)) - i-- - dAtA[i] = 0x58 - } if len(m.OutboundTxParams) > 0 { for iNdEx := len(m.OutboundTxParams) - 1; iNdEx >= 0; iNdEx-- { { @@ -1050,6 +1049,9 @@ func (m *InboundTxParams) Size() (n int) { if l > 0 { n += 1 + l + sovCrossChainTx(uint64(l)) } + if m.CoinType != 0 { + n += 1 + sovCrossChainTx(uint64(m.CoinType)) + } l = len(m.Asset) if l > 0 { n += 1 + l + sovCrossChainTx(uint64(l)) @@ -1100,6 +1102,9 @@ func (m *OutboundTxParams) Size() (n int) { if m.ReceiverChainId != 0 { n += 1 + sovCrossChainTx(uint64(m.ReceiverChainId)) } + if m.CoinType != 0 { + n += 1 + sovCrossChainTx(uint64(m.CoinType)) + } l = m.Amount.Size() n += 1 + l + sovCrossChainTx(uint64(l)) if m.OutboundTxTssNonce != 0 { @@ -1197,12 +1202,6 @@ func (m *CrossChainTx) Size() (n int) { n += 1 + l + sovCrossChainTx(uint64(l)) } } - if m.EventIndex != 0 { - n += 1 + sovCrossChainTx(uint64(m.EventIndex)) - } - if m.CoinType != 0 { - n += 1 + sovCrossChainTx(uint64(m.CoinType)) - } return n } @@ -1324,6 +1323,25 @@ func (m *InboundTxParams) Unmarshal(dAtA []byte) error { } m.TxOrigin = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CoinType", wireType) + } + m.CoinType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCrossChainTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CoinType |= common.CoinType(b&0x7F) << shift + if b < 0x80 { + break + } + } case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Asset", wireType) @@ -1696,6 +1714,25 @@ func (m *OutboundTxParams) Unmarshal(dAtA []byte) error { break } } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CoinType", wireType) + } + m.CoinType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCrossChainTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CoinType |= common.CoinType(b&0x7F) << shift + if b < 0x80 { + break + } + } case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) @@ -2432,44 +2469,6 @@ func (m *CrossChainTx) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 11: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field EventIndex", wireType) - } - m.EventIndex = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.EventIndex |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 12: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field CoinType", wireType) - } - m.CoinType = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.CoinType |= common.CoinType(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skipCrossChainTx(dAtA[iNdEx:]) diff --git a/x/crosschain/types/cross_chain_tx_v14.pb.go b/x/crosschain/types/cross_chain_tx_v14.pb.go deleted file mode 100644 index be51a85fd0..0000000000 --- a/x/crosschain/types/cross_chain_tx_v14.pb.go +++ /dev/null @@ -1,2051 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: crosschain/cross_chain_tx_v14.proto - -package types - -import ( - fmt "fmt" - io "io" - 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" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package - -type InboundTxParamsV14 struct { - Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` - SenderChainId int64 `protobuf:"varint,2,opt,name=sender_chain_id,json=senderChainId,proto3" json:"sender_chain_id,omitempty"` - TxOrigin string `protobuf:"bytes,3,opt,name=tx_origin,json=txOrigin,proto3" json:"tx_origin,omitempty"` - CoinType common.CoinType `protobuf:"varint,4,opt,name=coin_type,json=coinType,proto3,enum=common.CoinType" json:"coin_type,omitempty"` - Asset string `protobuf:"bytes,5,opt,name=asset,proto3" json:"asset,omitempty"` - Amount github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,6,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"amount"` - InboundTxObservedHash string `protobuf:"bytes,7,opt,name=inbound_tx_observed_hash,json=inboundTxObservedHash,proto3" json:"inbound_tx_observed_hash,omitempty"` - InboundTxObservedExternalHeight uint64 `protobuf:"varint,8,opt,name=inbound_tx_observed_external_height,json=inboundTxObservedExternalHeight,proto3" json:"inbound_tx_observed_external_height,omitempty"` - InboundTxBallotIndex string `protobuf:"bytes,9,opt,name=inbound_tx_ballot_index,json=inboundTxBallotIndex,proto3" json:"inbound_tx_ballot_index,omitempty"` - InboundTxFinalizedZetaHeight uint64 `protobuf:"varint,10,opt,name=inbound_tx_finalized_zeta_height,json=inboundTxFinalizedZetaHeight,proto3" json:"inbound_tx_finalized_zeta_height,omitempty"` - TxFinalizationStatus TxFinalizationStatus `protobuf:"varint,11,opt,name=tx_finalization_status,json=txFinalizationStatus,proto3,enum=zetachain.zetacore.crosschain.TxFinalizationStatus" json:"tx_finalization_status,omitempty"` -} - -func (m *InboundTxParamsV14) Reset() { *m = InboundTxParamsV14{} } -func (m *InboundTxParamsV14) String() string { return proto.CompactTextString(m) } -func (*InboundTxParamsV14) ProtoMessage() {} -func (*InboundTxParamsV14) Descriptor() ([]byte, []int) { - return fileDescriptor_9a400eff2bb43434, []int{0} -} -func (m *InboundTxParamsV14) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *InboundTxParamsV14) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_InboundTxParamsV14.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 *InboundTxParamsV14) XXX_Merge(src proto.Message) { - xxx_messageInfo_InboundTxParamsV14.Merge(m, src) -} -func (m *InboundTxParamsV14) XXX_Size() int { - return m.Size() -} -func (m *InboundTxParamsV14) XXX_DiscardUnknown() { - xxx_messageInfo_InboundTxParamsV14.DiscardUnknown(m) -} - -var xxx_messageInfo_InboundTxParamsV14 proto.InternalMessageInfo - -func (m *InboundTxParamsV14) GetSender() string { - if m != nil { - return m.Sender - } - return "" -} - -func (m *InboundTxParamsV14) GetSenderChainId() int64 { - if m != nil { - return m.SenderChainId - } - return 0 -} - -func (m *InboundTxParamsV14) GetTxOrigin() string { - if m != nil { - return m.TxOrigin - } - return "" -} - -func (m *InboundTxParamsV14) GetCoinType() common.CoinType { - if m != nil { - return m.CoinType - } - return common.CoinType_Zeta -} - -func (m *InboundTxParamsV14) GetAsset() string { - if m != nil { - return m.Asset - } - return "" -} - -func (m *InboundTxParamsV14) GetInboundTxObservedHash() string { - if m != nil { - return m.InboundTxObservedHash - } - return "" -} - -func (m *InboundTxParamsV14) GetInboundTxObservedExternalHeight() uint64 { - if m != nil { - return m.InboundTxObservedExternalHeight - } - return 0 -} - -func (m *InboundTxParamsV14) GetInboundTxBallotIndex() string { - if m != nil { - return m.InboundTxBallotIndex - } - return "" -} - -func (m *InboundTxParamsV14) GetInboundTxFinalizedZetaHeight() uint64 { - if m != nil { - return m.InboundTxFinalizedZetaHeight - } - return 0 -} - -func (m *InboundTxParamsV14) GetTxFinalizationStatus() TxFinalizationStatus { - if m != nil { - return m.TxFinalizationStatus - } - return TxFinalizationStatus_NotFinalized -} - -type OutboundTxParamsV14 struct { - Receiver string `protobuf:"bytes,1,opt,name=receiver,proto3" json:"receiver,omitempty"` - ReceiverChainId int64 `protobuf:"varint,2,opt,name=receiver_chainId,json=receiverChainId,proto3" json:"receiver_chainId,omitempty"` - CoinType common.CoinType `protobuf:"varint,3,opt,name=coin_type,json=coinType,proto3,enum=common.CoinType" json:"coin_type,omitempty"` - Amount github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,4,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"amount"` - OutboundTxTssNonce uint64 `protobuf:"varint,5,opt,name=outbound_tx_tss_nonce,json=outboundTxTssNonce,proto3" json:"outbound_tx_tss_nonce,omitempty"` - OutboundTxGasLimit uint64 `protobuf:"varint,6,opt,name=outbound_tx_gas_limit,json=outboundTxGasLimit,proto3" json:"outbound_tx_gas_limit,omitempty"` - OutboundTxGasPrice string `protobuf:"bytes,7,opt,name=outbound_tx_gas_price,json=outboundTxGasPrice,proto3" json:"outbound_tx_gas_price,omitempty"` - // the above are commands for zetaclients - // the following fields are used when the outbound tx is mined - OutboundTxHash string `protobuf:"bytes,8,opt,name=outbound_tx_hash,json=outboundTxHash,proto3" json:"outbound_tx_hash,omitempty"` - OutboundTxBallotIndex string `protobuf:"bytes,9,opt,name=outbound_tx_ballot_index,json=outboundTxBallotIndex,proto3" json:"outbound_tx_ballot_index,omitempty"` - OutboundTxObservedExternalHeight uint64 `protobuf:"varint,10,opt,name=outbound_tx_observed_external_height,json=outboundTxObservedExternalHeight,proto3" json:"outbound_tx_observed_external_height,omitempty"` - OutboundTxGasUsed uint64 `protobuf:"varint,20,opt,name=outbound_tx_gas_used,json=outboundTxGasUsed,proto3" json:"outbound_tx_gas_used,omitempty"` - OutboundTxEffectiveGasPrice github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,21,opt,name=outbound_tx_effective_gas_price,json=outboundTxEffectiveGasPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"outbound_tx_effective_gas_price"` - OutboundTxEffectiveGasLimit uint64 `protobuf:"varint,22,opt,name=outbound_tx_effective_gas_limit,json=outboundTxEffectiveGasLimit,proto3" json:"outbound_tx_effective_gas_limit,omitempty"` - TssPubkey string `protobuf:"bytes,11,opt,name=tss_pubkey,json=tssPubkey,proto3" json:"tss_pubkey,omitempty"` - TxFinalizationStatus TxFinalizationStatus `protobuf:"varint,12,opt,name=tx_finalization_status,json=txFinalizationStatus,proto3,enum=zetachain.zetacore.crosschain.TxFinalizationStatus" json:"tx_finalization_status,omitempty"` -} - -func (m *OutboundTxParamsV14) Reset() { *m = OutboundTxParamsV14{} } -func (m *OutboundTxParamsV14) String() string { return proto.CompactTextString(m) } -func (*OutboundTxParamsV14) ProtoMessage() {} -func (*OutboundTxParamsV14) Descriptor() ([]byte, []int) { - return fileDescriptor_9a400eff2bb43434, []int{1} -} -func (m *OutboundTxParamsV14) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *OutboundTxParamsV14) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_OutboundTxParamsV14.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 *OutboundTxParamsV14) XXX_Merge(src proto.Message) { - xxx_messageInfo_OutboundTxParamsV14.Merge(m, src) -} -func (m *OutboundTxParamsV14) XXX_Size() int { - return m.Size() -} -func (m *OutboundTxParamsV14) XXX_DiscardUnknown() { - xxx_messageInfo_OutboundTxParamsV14.DiscardUnknown(m) -} - -var xxx_messageInfo_OutboundTxParamsV14 proto.InternalMessageInfo - -func (m *OutboundTxParamsV14) GetReceiver() string { - if m != nil { - return m.Receiver - } - return "" -} - -func (m *OutboundTxParamsV14) GetReceiverChainId() int64 { - if m != nil { - return m.ReceiverChainId - } - return 0 -} - -func (m *OutboundTxParamsV14) GetCoinType() common.CoinType { - if m != nil { - return m.CoinType - } - return common.CoinType_Zeta -} - -func (m *OutboundTxParamsV14) GetOutboundTxTssNonce() uint64 { - if m != nil { - return m.OutboundTxTssNonce - } - return 0 -} - -func (m *OutboundTxParamsV14) GetOutboundTxGasLimit() uint64 { - if m != nil { - return m.OutboundTxGasLimit - } - return 0 -} - -func (m *OutboundTxParamsV14) GetOutboundTxGasPrice() string { - if m != nil { - return m.OutboundTxGasPrice - } - return "" -} - -func (m *OutboundTxParamsV14) GetOutboundTxHash() string { - if m != nil { - return m.OutboundTxHash - } - return "" -} - -func (m *OutboundTxParamsV14) GetOutboundTxBallotIndex() string { - if m != nil { - return m.OutboundTxBallotIndex - } - return "" -} - -func (m *OutboundTxParamsV14) GetOutboundTxObservedExternalHeight() uint64 { - if m != nil { - return m.OutboundTxObservedExternalHeight - } - return 0 -} - -func (m *OutboundTxParamsV14) GetOutboundTxGasUsed() uint64 { - if m != nil { - return m.OutboundTxGasUsed - } - return 0 -} - -func (m *OutboundTxParamsV14) GetOutboundTxEffectiveGasLimit() uint64 { - if m != nil { - return m.OutboundTxEffectiveGasLimit - } - return 0 -} - -func (m *OutboundTxParamsV14) GetTssPubkey() string { - if m != nil { - return m.TssPubkey - } - return "" -} - -func (m *OutboundTxParamsV14) GetTxFinalizationStatus() TxFinalizationStatus { - if m != nil { - return m.TxFinalizationStatus - } - return TxFinalizationStatus_NotFinalized -} - -type CrossChainTxV14 struct { - Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` - Index string `protobuf:"bytes,2,opt,name=index,proto3" json:"index,omitempty"` - ZetaFees github_com_cosmos_cosmos_sdk_types.Uint `protobuf:"bytes,5,opt,name=zeta_fees,json=zetaFees,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Uint" json:"zeta_fees" yaml:"zeta_fees"` - RelayedMessage string `protobuf:"bytes,6,opt,name=relayed_message,json=relayedMessage,proto3" json:"relayed_message,omitempty"` - CctxStatus *Status `protobuf:"bytes,8,opt,name=cctx_status,json=cctxStatus,proto3" json:"cctx_status,omitempty"` - InboundTxParams *InboundTxParamsV14 `protobuf:"bytes,9,opt,name=inbound_tx_params,json=inboundTxParams,proto3" json:"inbound_tx_params,omitempty"` - OutboundTxParams []*OutboundTxParamsV14 `protobuf:"bytes,10,rep,name=outbound_tx_params,json=outboundTxParams,proto3" json:"outbound_tx_params,omitempty"` -} - -func (m *CrossChainTxV14) Reset() { *m = CrossChainTxV14{} } -func (m *CrossChainTxV14) String() string { return proto.CompactTextString(m) } -func (*CrossChainTxV14) ProtoMessage() {} -func (*CrossChainTxV14) Descriptor() ([]byte, []int) { - return fileDescriptor_9a400eff2bb43434, []int{2} -} -func (m *CrossChainTxV14) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *CrossChainTxV14) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_CrossChainTxV14.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 *CrossChainTxV14) XXX_Merge(src proto.Message) { - xxx_messageInfo_CrossChainTxV14.Merge(m, src) -} -func (m *CrossChainTxV14) XXX_Size() int { - return m.Size() -} -func (m *CrossChainTxV14) XXX_DiscardUnknown() { - xxx_messageInfo_CrossChainTxV14.DiscardUnknown(m) -} - -var xxx_messageInfo_CrossChainTxV14 proto.InternalMessageInfo - -func (m *CrossChainTxV14) GetCreator() string { - if m != nil { - return m.Creator - } - return "" -} - -func (m *CrossChainTxV14) GetIndex() string { - if m != nil { - return m.Index - } - return "" -} - -func (m *CrossChainTxV14) GetRelayedMessage() string { - if m != nil { - return m.RelayedMessage - } - return "" -} - -func (m *CrossChainTxV14) GetCctxStatus() *Status { - if m != nil { - return m.CctxStatus - } - return nil -} - -func (m *CrossChainTxV14) GetInboundTxParams() *InboundTxParamsV14 { - if m != nil { - return m.InboundTxParams - } - return nil -} - -func (m *CrossChainTxV14) GetOutboundTxParams() []*OutboundTxParamsV14 { - if m != nil { - return m.OutboundTxParams - } - return nil -} - -func init() { - proto.RegisterType((*InboundTxParamsV14)(nil), "zetachain.zetacore.crosschain.InboundTxParamsV14") - proto.RegisterType((*OutboundTxParamsV14)(nil), "zetachain.zetacore.crosschain.OutboundTxParamsV14") - proto.RegisterType((*CrossChainTxV14)(nil), "zetachain.zetacore.crosschain.CrossChainTxV14") -} - -func init() { - proto.RegisterFile("crosschain/cross_chain_tx_v14.proto", fileDescriptor_9a400eff2bb43434) -} - -var fileDescriptor_9a400eff2bb43434 = []byte{ - // 913 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x51, 0x6f, 0x1a, 0x47, - 0x10, 0x36, 0x81, 0xd8, 0x30, 0xb4, 0x86, 0x6c, 0xb0, 0x7b, 0x72, 0x1a, 0x40, 0x4e, 0x9b, 0xd0, - 0x07, 0x73, 0x82, 0xa4, 0x8a, 0xd4, 0x47, 0xbb, 0x71, 0x82, 0x9a, 0xc6, 0xd6, 0xd5, 0xe9, 0x43, - 0xa4, 0xea, 0xb2, 0xdc, 0x8d, 0x61, 0x15, 0xb8, 0x45, 0xb7, 0x8b, 0x75, 0xe4, 0x57, 0xf4, 0xad, - 0x7f, 0x29, 0x8f, 0x79, 0xa9, 0x54, 0xf5, 0xc1, 0xaa, 0xec, 0x3f, 0x50, 0xf5, 0x17, 0x54, 0xbb, - 0x7b, 0x77, 0x1c, 0x36, 0xb6, 0x5b, 0xb5, 0x4f, 0xcc, 0xce, 0xce, 0xf7, 0xed, 0xee, 0xcc, 0x37, - 0xc3, 0xc1, 0x03, 0x2f, 0xe4, 0x42, 0x78, 0x43, 0xca, 0x02, 0x5b, 0x9b, 0xae, 0xb6, 0x5d, 0x19, - 0xb9, 0x27, 0x9d, 0x27, 0xed, 0x49, 0xc8, 0x25, 0x27, 0xf7, 0xdf, 0xa3, 0xa4, 0xda, 0xdf, 0xd6, - 0x16, 0x0f, 0xb1, 0x3d, 0xc7, 0x6d, 0xdd, 0xf5, 0xf8, 0x78, 0xcc, 0x03, 0xdb, 0xfc, 0x18, 0xcc, - 0x56, 0xe3, 0x4a, 0xe2, 0x38, 0xa0, 0x36, 0xe0, 0x03, 0xae, 0x4d, 0x5b, 0x59, 0xc6, 0xbb, 0xfd, - 0x67, 0x01, 0x48, 0x2f, 0xe8, 0xf3, 0x69, 0xe0, 0x1f, 0x45, 0x87, 0x34, 0xa4, 0x63, 0xf1, 0x63, - 0xe7, 0x09, 0xd9, 0x84, 0x55, 0x81, 0x81, 0x8f, 0xa1, 0x95, 0x6b, 0xe6, 0x5a, 0x25, 0x27, 0x5e, - 0x91, 0x87, 0x50, 0x31, 0x56, 0xcc, 0xce, 0x7c, 0xeb, 0x56, 0x33, 0xd7, 0xca, 0x3b, 0x9f, 0x1a, - 0xf7, 0x9e, 0xf2, 0xf6, 0x7c, 0x72, 0x0f, 0x4a, 0x32, 0x72, 0x79, 0xc8, 0x06, 0x2c, 0xb0, 0xf2, - 0x9a, 0xa2, 0x28, 0xa3, 0x03, 0xbd, 0x26, 0x3b, 0x50, 0xf2, 0xb8, 0xba, 0xda, 0x6c, 0x82, 0x56, - 0xa1, 0x99, 0x6b, 0xad, 0x77, 0xab, 0xed, 0xf8, 0x31, 0x7b, 0x9c, 0x05, 0x47, 0xb3, 0x09, 0x3a, - 0x45, 0x2f, 0xb6, 0x48, 0x0d, 0x6e, 0x53, 0x21, 0x50, 0x5a, 0xb7, 0x35, 0x8f, 0x59, 0x90, 0xe7, - 0xb0, 0x4a, 0xc7, 0x7c, 0x1a, 0x48, 0x6b, 0x55, 0xb9, 0x77, 0xed, 0x0f, 0xa7, 0x8d, 0x95, 0xdf, - 0x4f, 0x1b, 0x8f, 0x06, 0x4c, 0x0e, 0xa7, 0x7d, 0xc5, 0x67, 0x7b, 0x5c, 0x8c, 0xb9, 0x88, 0x7f, - 0x76, 0x84, 0xff, 0xce, 0x56, 0x47, 0x8a, 0xf6, 0x6b, 0x16, 0x48, 0x27, 0x86, 0x93, 0xa7, 0x60, - 0x31, 0x93, 0x00, 0x55, 0x04, 0xde, 0x17, 0x18, 0x9e, 0xa0, 0xef, 0x0e, 0xa9, 0x18, 0x5a, 0x6b, - 0xfa, 0xc4, 0x0d, 0x96, 0x24, 0xe8, 0x20, 0xde, 0x7d, 0x41, 0xc5, 0x90, 0xbc, 0x84, 0x07, 0xcb, - 0x80, 0x18, 0x49, 0x0c, 0x03, 0x3a, 0x72, 0x87, 0xc8, 0x06, 0x43, 0x69, 0x15, 0x9b, 0xb9, 0x56, - 0xc1, 0x69, 0x5c, 0xe2, 0x78, 0x16, 0xc7, 0xbd, 0xd0, 0x61, 0xe4, 0x6b, 0xf8, 0x2c, 0xc3, 0xd6, - 0xa7, 0xa3, 0x11, 0x97, 0x2e, 0x0b, 0x7c, 0x8c, 0xac, 0x92, 0xbe, 0x45, 0x2d, 0x65, 0xd8, 0xd5, - 0x9b, 0x3d, 0xb5, 0x47, 0xf6, 0xa1, 0x99, 0x81, 0x1d, 0xb3, 0x80, 0x8e, 0xd8, 0x7b, 0xf4, 0x5d, - 0xa5, 0x9b, 0xe4, 0x06, 0xa0, 0x6f, 0xf0, 0x79, 0x8a, 0xdf, 0x4f, 0xa2, 0xde, 0xa0, 0xa4, 0xf1, - 0xf1, 0x0c, 0x36, 0xe7, 0x78, 0x2a, 0x19, 0x0f, 0x5c, 0x21, 0xa9, 0x9c, 0x0a, 0xab, 0xac, 0x0b, - 0xf4, 0xb8, 0x7d, 0xad, 0x26, 0xdb, 0x29, 0xab, 0xc6, 0xfe, 0xa0, 0xa1, 0x4e, 0x4d, 0x2e, 0xf1, - 0x6e, 0xff, 0xb2, 0x06, 0x77, 0x0f, 0xa6, 0xf2, 0x92, 0xe6, 0xb6, 0xa0, 0x18, 0xa2, 0x87, 0xec, - 0x24, 0x55, 0x5d, 0xba, 0x26, 0x5f, 0x41, 0x35, 0xb1, 0x8d, 0xf2, 0x7a, 0x89, 0xf0, 0x2a, 0x89, - 0x3f, 0x91, 0xde, 0x82, 0xba, 0xf2, 0x37, 0xaa, 0x6b, 0xae, 0xa3, 0xc2, 0x7f, 0xd3, 0x51, 0x07, - 0x36, 0x78, 0xfc, 0x2a, 0x55, 0x0a, 0x29, 0x84, 0x1b, 0xf0, 0xc0, 0x43, 0x2d, 0xdb, 0x82, 0x43, - 0x78, 0xfa, 0xe4, 0x23, 0x21, 0x5e, 0xa9, 0x9d, 0x8b, 0x90, 0x01, 0x15, 0xee, 0x88, 0x8d, 0x99, - 0x91, 0xf4, 0x02, 0xe4, 0x39, 0x15, 0x2f, 0xd5, 0xce, 0x32, 0xc8, 0x24, 0x64, 0x1e, 0xc6, 0x52, - 0x5d, 0x84, 0x1c, 0xaa, 0x1d, 0xd2, 0x82, 0x6a, 0x16, 0xa2, 0x85, 0x5d, 0xd4, 0xd1, 0xeb, 0xf3, - 0x68, 0xad, 0xe8, 0xa7, 0x60, 0x65, 0x23, 0x97, 0x88, 0x70, 0x63, 0x8e, 0xc8, 0xaa, 0xf0, 0x15, - 0x7c, 0x91, 0x05, 0x5e, 0xd9, 0x0b, 0x46, 0x89, 0xcd, 0x39, 0xc9, 0x15, 0xcd, 0x60, 0x43, 0xed, - 0xe2, 0x2b, 0xa7, 0x02, 0x7d, 0xab, 0xa6, 0xf1, 0x77, 0x16, 0x1e, 0xf9, 0x5a, 0xa0, 0x4f, 0x24, - 0x34, 0xb2, 0x00, 0x3c, 0x3e, 0x46, 0x4f, 0xb2, 0x13, 0xcc, 0x24, 0x68, 0x43, 0x97, 0xb7, 0x1d, - 0x97, 0xf7, 0xe1, 0x3f, 0x28, 0x6f, 0x2f, 0x90, 0xce, 0xbd, 0xf9, 0x59, 0xcf, 0x12, 0xd2, 0x34, - 0xb3, 0xdf, 0x5e, 0x77, 0xaa, 0xa9, 0xe4, 0xa6, 0xbe, 0xf1, 0x15, 0x2c, 0xa6, 0xa4, 0xf7, 0x01, - 0x94, 0x58, 0x26, 0xd3, 0xfe, 0x3b, 0x9c, 0xe9, 0x76, 0x2b, 0x39, 0x25, 0x29, 0xc4, 0xa1, 0x76, - 0x5c, 0xd3, 0x99, 0x9f, 0xfc, 0xdf, 0x9d, 0xf9, 0x6b, 0x1e, 0x2a, 0x7b, 0x0a, 0xa9, 0x7b, 0xe9, - 0x28, 0x52, 0x5d, 0x69, 0xc1, 0x9a, 0x17, 0x22, 0x95, 0x3c, 0x69, 0xca, 0x64, 0xa9, 0xe6, 0xb2, - 0x91, 0xc6, 0x2d, 0x33, 0x97, 0xf5, 0x82, 0xbc, 0x85, 0x92, 0x9e, 0x3d, 0xc7, 0x88, 0xc2, 0x4c, - 0xec, 0xdd, 0xbd, 0x7f, 0xd9, 0x52, 0x7f, 0x9d, 0x36, 0xaa, 0x33, 0x3a, 0x1e, 0x7d, 0xb3, 0x9d, - 0x32, 0x6d, 0x3b, 0x45, 0x65, 0xef, 0x23, 0x0a, 0xf2, 0x08, 0x2a, 0x21, 0x8e, 0xe8, 0x0c, 0x7d, - 0x77, 0x8c, 0x42, 0xd0, 0x01, 0x9a, 0xbf, 0x00, 0x67, 0x3d, 0x76, 0x7f, 0x6f, 0xbc, 0x64, 0x1f, - 0xca, 0x9e, 0x27, 0xa3, 0x24, 0x5d, 0x4a, 0xf3, 0xe5, 0xee, 0x97, 0x37, 0xa4, 0x2b, 0x4e, 0x10, - 0x28, 0xa4, 0xb1, 0xc9, 0x4f, 0x70, 0x27, 0x33, 0x63, 0x27, 0x7a, 0x60, 0xe9, 0x7e, 0x28, 0x77, - 0x3b, 0x37, 0xb0, 0x5d, 0xfe, 0x6b, 0x75, 0x2a, 0x6c, 0xd1, 0x47, 0xde, 0x02, 0xc9, 0xaa, 0x28, - 0xe6, 0x87, 0x66, 0xbe, 0x55, 0xee, 0x76, 0x6f, 0xe0, 0x5f, 0x32, 0x47, 0x9d, 0x2a, 0xbf, 0xe0, - 0xdc, 0xfd, 0xee, 0xc3, 0x59, 0x3d, 0xf7, 0xf1, 0xac, 0x9e, 0xfb, 0xe3, 0xac, 0x9e, 0xfb, 0xf9, - 0xbc, 0xbe, 0xf2, 0xf1, 0xbc, 0xbe, 0xf2, 0xdb, 0x79, 0x7d, 0xe5, 0x4d, 0x27, 0x53, 0x12, 0xc5, - 0xbf, 0x63, 0x3e, 0x20, 0x92, 0xa3, 0xec, 0xc8, 0xce, 0x7c, 0x56, 0xe8, 0x0a, 0xf5, 0x57, 0xf5, - 0x87, 0xc3, 0xe3, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x77, 0x00, 0xe1, 0x29, 0xca, 0x08, 0x00, - 0x00, -} - -func (m *InboundTxParamsV14) 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 *InboundTxParamsV14) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *InboundTxParamsV14) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.TxFinalizationStatus != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.TxFinalizationStatus)) - i-- - dAtA[i] = 0x58 - } - if m.InboundTxFinalizedZetaHeight != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.InboundTxFinalizedZetaHeight)) - i-- - dAtA[i] = 0x50 - } - if len(m.InboundTxBallotIndex) > 0 { - i -= len(m.InboundTxBallotIndex) - copy(dAtA[i:], m.InboundTxBallotIndex) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.InboundTxBallotIndex))) - i-- - dAtA[i] = 0x4a - } - if m.InboundTxObservedExternalHeight != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.InboundTxObservedExternalHeight)) - i-- - dAtA[i] = 0x40 - } - if len(m.InboundTxObservedHash) > 0 { - i -= len(m.InboundTxObservedHash) - copy(dAtA[i:], m.InboundTxObservedHash) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.InboundTxObservedHash))) - i-- - dAtA[i] = 0x3a - } - { - size := m.Amount.Size() - i -= size - if _, err := m.Amount.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x32 - if len(m.Asset) > 0 { - i -= len(m.Asset) - copy(dAtA[i:], m.Asset) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.Asset))) - i-- - dAtA[i] = 0x2a - } - if m.CoinType != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.CoinType)) - i-- - dAtA[i] = 0x20 - } - if len(m.TxOrigin) > 0 { - i -= len(m.TxOrigin) - copy(dAtA[i:], m.TxOrigin) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.TxOrigin))) - i-- - dAtA[i] = 0x1a - } - if m.SenderChainId != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.SenderChainId)) - i-- - dAtA[i] = 0x10 - } - if len(m.Sender) > 0 { - i -= len(m.Sender) - copy(dAtA[i:], m.Sender) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.Sender))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *OutboundTxParamsV14) 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 *OutboundTxParamsV14) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *OutboundTxParamsV14) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.OutboundTxEffectiveGasLimit != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.OutboundTxEffectiveGasLimit)) - i-- - dAtA[i] = 0x1 - i-- - dAtA[i] = 0xb0 - } - { - size := m.OutboundTxEffectiveGasPrice.Size() - i -= size - if _, err := m.OutboundTxEffectiveGasPrice.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1 - i-- - dAtA[i] = 0xaa - if m.OutboundTxGasUsed != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.OutboundTxGasUsed)) - i-- - dAtA[i] = 0x1 - i-- - dAtA[i] = 0xa0 - } - if m.TxFinalizationStatus != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.TxFinalizationStatus)) - i-- - dAtA[i] = 0x60 - } - if len(m.TssPubkey) > 0 { - i -= len(m.TssPubkey) - copy(dAtA[i:], m.TssPubkey) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.TssPubkey))) - i-- - dAtA[i] = 0x5a - } - if m.OutboundTxObservedExternalHeight != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.OutboundTxObservedExternalHeight)) - i-- - dAtA[i] = 0x50 - } - if len(m.OutboundTxBallotIndex) > 0 { - i -= len(m.OutboundTxBallotIndex) - copy(dAtA[i:], m.OutboundTxBallotIndex) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.OutboundTxBallotIndex))) - i-- - dAtA[i] = 0x4a - } - if len(m.OutboundTxHash) > 0 { - i -= len(m.OutboundTxHash) - copy(dAtA[i:], m.OutboundTxHash) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.OutboundTxHash))) - i-- - dAtA[i] = 0x42 - } - if len(m.OutboundTxGasPrice) > 0 { - i -= len(m.OutboundTxGasPrice) - copy(dAtA[i:], m.OutboundTxGasPrice) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.OutboundTxGasPrice))) - i-- - dAtA[i] = 0x3a - } - if m.OutboundTxGasLimit != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.OutboundTxGasLimit)) - i-- - dAtA[i] = 0x30 - } - if m.OutboundTxTssNonce != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.OutboundTxTssNonce)) - i-- - dAtA[i] = 0x28 - } - { - size := m.Amount.Size() - i -= size - if _, err := m.Amount.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - if m.CoinType != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.CoinType)) - i-- - dAtA[i] = 0x18 - } - if m.ReceiverChainId != 0 { - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(m.ReceiverChainId)) - i-- - dAtA[i] = 0x10 - } - if len(m.Receiver) > 0 { - i -= len(m.Receiver) - copy(dAtA[i:], m.Receiver) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.Receiver))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *CrossChainTxV14) 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 *CrossChainTxV14) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *CrossChainTxV14) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.OutboundTxParams) > 0 { - for iNdEx := len(m.OutboundTxParams) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.OutboundTxParams[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x52 - } - } - if m.InboundTxParams != nil { - { - size, err := m.InboundTxParams.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x4a - } - if m.CctxStatus != nil { - { - size, err := m.CctxStatus.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x42 - } - if len(m.RelayedMessage) > 0 { - i -= len(m.RelayedMessage) - copy(dAtA[i:], m.RelayedMessage) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.RelayedMessage))) - i-- - dAtA[i] = 0x32 - } - { - size := m.ZetaFees.Size() - i -= size - if _, err := m.ZetaFees.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x2a - if len(m.Index) > 0 { - i -= len(m.Index) - copy(dAtA[i:], m.Index) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.Index))) - i-- - dAtA[i] = 0x12 - } - if len(m.Creator) > 0 { - i -= len(m.Creator) - copy(dAtA[i:], m.Creator) - i = encodeVarintCrossChainTxV14(dAtA, i, uint64(len(m.Creator))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func encodeVarintCrossChainTxV14(dAtA []byte, offset int, v uint64) int { - offset -= sovCrossChainTxV14(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *InboundTxParamsV14) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Sender) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - if m.SenderChainId != 0 { - n += 1 + sovCrossChainTxV14(uint64(m.SenderChainId)) - } - l = len(m.TxOrigin) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - if m.CoinType != 0 { - n += 1 + sovCrossChainTxV14(uint64(m.CoinType)) - } - l = len(m.Asset) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - l = m.Amount.Size() - n += 1 + l + sovCrossChainTxV14(uint64(l)) - l = len(m.InboundTxObservedHash) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - if m.InboundTxObservedExternalHeight != 0 { - n += 1 + sovCrossChainTxV14(uint64(m.InboundTxObservedExternalHeight)) - } - l = len(m.InboundTxBallotIndex) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - if m.InboundTxFinalizedZetaHeight != 0 { - n += 1 + sovCrossChainTxV14(uint64(m.InboundTxFinalizedZetaHeight)) - } - if m.TxFinalizationStatus != 0 { - n += 1 + sovCrossChainTxV14(uint64(m.TxFinalizationStatus)) - } - return n -} - -func (m *OutboundTxParamsV14) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Receiver) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - if m.ReceiverChainId != 0 { - n += 1 + sovCrossChainTxV14(uint64(m.ReceiverChainId)) - } - if m.CoinType != 0 { - n += 1 + sovCrossChainTxV14(uint64(m.CoinType)) - } - l = m.Amount.Size() - n += 1 + l + sovCrossChainTxV14(uint64(l)) - if m.OutboundTxTssNonce != 0 { - n += 1 + sovCrossChainTxV14(uint64(m.OutboundTxTssNonce)) - } - if m.OutboundTxGasLimit != 0 { - n += 1 + sovCrossChainTxV14(uint64(m.OutboundTxGasLimit)) - } - l = len(m.OutboundTxGasPrice) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - l = len(m.OutboundTxHash) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - l = len(m.OutboundTxBallotIndex) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - if m.OutboundTxObservedExternalHeight != 0 { - n += 1 + sovCrossChainTxV14(uint64(m.OutboundTxObservedExternalHeight)) - } - l = len(m.TssPubkey) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - if m.TxFinalizationStatus != 0 { - n += 1 + sovCrossChainTxV14(uint64(m.TxFinalizationStatus)) - } - if m.OutboundTxGasUsed != 0 { - n += 2 + sovCrossChainTxV14(uint64(m.OutboundTxGasUsed)) - } - l = m.OutboundTxEffectiveGasPrice.Size() - n += 2 + l + sovCrossChainTxV14(uint64(l)) - if m.OutboundTxEffectiveGasLimit != 0 { - n += 2 + sovCrossChainTxV14(uint64(m.OutboundTxEffectiveGasLimit)) - } - return n -} - -func (m *CrossChainTxV14) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Creator) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - l = len(m.Index) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - l = m.ZetaFees.Size() - n += 1 + l + sovCrossChainTxV14(uint64(l)) - l = len(m.RelayedMessage) - if l > 0 { - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - if m.CctxStatus != nil { - l = m.CctxStatus.Size() - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - if m.InboundTxParams != nil { - l = m.InboundTxParams.Size() - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - if len(m.OutboundTxParams) > 0 { - for _, e := range m.OutboundTxParams { - l = e.Size() - n += 1 + l + sovCrossChainTxV14(uint64(l)) - } - } - return n -} - -func sovCrossChainTxV14(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozCrossChainTxV14(x uint64) (n int) { - return sovCrossChainTxV14(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *InboundTxParamsV14) 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 ErrIntOverflowCrossChainTxV14 - } - 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: InboundTxParamsV14: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: InboundTxParamsV14: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Sender = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field SenderChainId", wireType) - } - m.SenderChainId = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.SenderChainId |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TxOrigin", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.TxOrigin = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field CoinType", wireType) - } - m.CoinType = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.CoinType |= common.CoinType(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Asset", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Asset = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field InboundTxObservedHash", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.InboundTxObservedHash = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 8: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field InboundTxObservedExternalHeight", wireType) - } - m.InboundTxObservedExternalHeight = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.InboundTxObservedExternalHeight |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 9: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field InboundTxBallotIndex", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.InboundTxBallotIndex = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 10: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field InboundTxFinalizedZetaHeight", wireType) - } - m.InboundTxFinalizedZetaHeight = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.InboundTxFinalizedZetaHeight |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 11: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TxFinalizationStatus", wireType) - } - m.TxFinalizationStatus = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.TxFinalizationStatus |= TxFinalizationStatus(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipCrossChainTxV14(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *OutboundTxParamsV14) 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 ErrIntOverflowCrossChainTxV14 - } - 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: OutboundTxParamsV14: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: OutboundTxParamsV14: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Receiver = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ReceiverChainId", wireType) - } - m.ReceiverChainId = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.ReceiverChainId |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field CoinType", wireType) - } - m.CoinType = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.CoinType |= common.CoinType(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field OutboundTxTssNonce", wireType) - } - m.OutboundTxTssNonce = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.OutboundTxTssNonce |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field OutboundTxGasLimit", wireType) - } - m.OutboundTxGasLimit = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.OutboundTxGasLimit |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OutboundTxGasPrice", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.OutboundTxGasPrice = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OutboundTxHash", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.OutboundTxHash = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 9: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OutboundTxBallotIndex", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.OutboundTxBallotIndex = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 10: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field OutboundTxObservedExternalHeight", wireType) - } - m.OutboundTxObservedExternalHeight = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.OutboundTxObservedExternalHeight |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 11: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TssPubkey", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.TssPubkey = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 12: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TxFinalizationStatus", wireType) - } - m.TxFinalizationStatus = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.TxFinalizationStatus |= TxFinalizationStatus(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 20: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field OutboundTxGasUsed", wireType) - } - m.OutboundTxGasUsed = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.OutboundTxGasUsed |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 21: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OutboundTxEffectiveGasPrice", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.OutboundTxEffectiveGasPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 22: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field OutboundTxEffectiveGasLimit", wireType) - } - m.OutboundTxEffectiveGasLimit = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.OutboundTxEffectiveGasLimit |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipCrossChainTxV14(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *CrossChainTxV14) 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 ErrIntOverflowCrossChainTxV14 - } - 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: CrossChainTxV14: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: CrossChainTxV14: 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 ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - 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 Index", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Index = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ZetaFees", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.ZetaFees.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RelayedMessage", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - 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 ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.RelayedMessage = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CctxStatus", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.CctxStatus == nil { - m.CctxStatus = &Status{} - } - if err := m.CctxStatus.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 9: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field InboundTxParams", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.InboundTxParams == nil { - m.InboundTxParams = &InboundTxParamsV14{} - } - if err := m.InboundTxParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 10: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OutboundTxParams", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.OutboundTxParams = append(m.OutboundTxParams, &OutboundTxParamsV14{}) - if err := m.OutboundTxParams[len(m.OutboundTxParams)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipCrossChainTxV14(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthCrossChainTxV14 - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipCrossChainTxV14(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - depth := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - case 1: - iNdEx += 8 - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowCrossChainTxV14 - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthCrossChainTxV14 - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupCrossChainTxV14 - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthCrossChainTxV14 - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthCrossChainTxV14 = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowCrossChainTxV14 = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupCrossChainTxV14 = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/crosschain/types/errors.go b/x/crosschain/types/errors.go index 62720aaf66..bfdef64cc2 100644 --- a/x/crosschain/types/errors.go +++ b/x/crosschain/types/errors.go @@ -41,4 +41,6 @@ var ( ErrUnableProcessRefund = errorsmod.Register(ModuleName, 1148, "unable to process refund") ErrUnableToFindZetaAccounting = errorsmod.Register(ModuleName, 1149, "unable to find zeta accounting") ErrInsufficientZetaAmount = errorsmod.Register(ModuleName, 1150, "insufficient zeta amount") + + ErrInvalidCCTXIndex = errorsmod.Register(ModuleName, 1151, "invalid cctx index") ) diff --git a/zetaclient/bitcoin/bitcoin_signer.go b/zetaclient/bitcoin/bitcoin_signer.go index f250805a8f..90b6b48d3e 100644 --- a/zetaclient/bitcoin/bitcoin_signer.go +++ b/zetaclient/bitcoin/bitcoin_signer.go @@ -259,7 +259,8 @@ func (signer *BTCSigner) TryProcessOutTx( Logger() params := cctx.GetCurrentOutTxParam() - if cctx.CoinType == common.CoinType_Zeta || cctx.CoinType == common.CoinType_ERC20 { + coinType := cctx.InboundTxParams.CoinType + if coinType == common.CoinType_Zeta || coinType == common.CoinType_ERC20 { logger.Error().Msgf("BTC TryProcessOutTx: can only send BTC to a BTC network") return } diff --git a/zetaclient/evm/evm_client.go b/zetaclient/evm/evm_client.go index 443510f545..1580464245 100644 --- a/zetaclient/evm/evm_client.go +++ b/zetaclient/evm/evm_client.go @@ -314,7 +314,7 @@ func (ob *ChainClient) Stop() { // If isConfirmed, it also post to ZetaCore func (ob *ChainClient) IsSendOutTxProcessed(cctx *crosschaintypes.CrossChainTx, logger zerolog.Logger) (bool, bool, error) { sendHash := cctx.Index - cointype := cctx.CoinType + cointype := cctx.InboundTxParams.CoinType nonce := cctx.GetCurrentOutTxParam().OutboundTxTssNonce // skip if outtx is not confirmed diff --git a/zetaclient/evm/evm_signer.go b/zetaclient/evm/evm_signer.go index 474864c246..f77bc343f9 100644 --- a/zetaclient/evm/evm_signer.go +++ b/zetaclient/evm/evm_signer.go @@ -324,13 +324,13 @@ func (signer *Signer) TryProcessOutTx( // compliance check goes first if clientcommon.IsCctxRestricted(cctx) { clientcommon.PrintComplianceLog(logger, signer.logger.Compliance, - true, evmClient.chain.ChainId, cctx.Index, cctx.InboundTxParams.Sender, txData.to.Hex(), cctx.CoinType.String()) + true, evmClient.chain.ChainId, cctx.Index, cctx.InboundTxParams.Sender, txData.to.Hex(), cctx.InboundTxParams.CoinType.String()) tx, err = signer.SignCancelTx(txData.nonce, txData.gasPrice, height) // cancel the tx if err != nil { logger.Warn().Err(err).Msg(SignerErrorMsg(cctx)) return } - } else if cctx.CoinType == common.CoinType_Cmd { // admin command + } else if cctx.InboundTxParams.CoinType == common.CoinType_Cmd { // admin command to := ethcommon.HexToAddress(cctx.GetCurrentOutTxParam().Receiver) if to == (ethcommon.Address{}) { logger.Error().Msgf("invalid receiver %s", cctx.GetCurrentOutTxParam().Receiver) @@ -353,7 +353,7 @@ func (signer *Signer) TryProcessOutTx( return } } else if IsSenderZetaChain(cctx, zetaBridge, &crossChainflags) { - switch cctx.CoinType { + switch cctx.InboundTxParams.CoinType { case common.CoinType_Gas: logger.Info().Msgf("SignWithdrawTx: %d => %s, nonce %d, gasPrice %d", cctx.InboundTxParams.SenderChainId, toChain, cctx.GetCurrentOutTxParam().OutboundTxTssNonce, txData.gasPrice) tx, err = signer.SignWithdrawTx(txData) @@ -369,7 +369,7 @@ func (signer *Signer) TryProcessOutTx( return } } else if cctx.CctxStatus.Status == types.CctxStatus_PendingRevert && cctx.OutboundTxParams[0].ReceiverChainId == zetaBridge.ZetaChain().ChainId { - switch cctx.CoinType { + switch cctx.InboundTxParams.CoinType { case common.CoinType_Gas: logger.Info().Msgf("SignWithdrawTx: %d => %s, nonce %d, gasPrice %d", cctx.InboundTxParams.SenderChainId, toChain, cctx.GetCurrentOutTxParam().OutboundTxTssNonce, txData.gasPrice) tx, err = signer.SignWithdrawTx(txData) diff --git a/zetaclient/evm/outbound_transaction_data.go b/zetaclient/evm/outbound_transaction_data.go index 544d8c0503..b595dd42c5 100644 --- a/zetaclient/evm/outbound_transaction_data.go +++ b/zetaclient/evm/outbound_transaction_data.go @@ -169,7 +169,7 @@ func NewOutBoundTransactionData( } // Base64 decode message - if cctx.CoinType != common.CoinType_Cmd { + if cctx.InboundTxParams.CoinType != common.CoinType_Cmd { txData.message, err = base64.StdEncoding.DecodeString(cctx.RelayedMessage) if err != nil { logger.Err(err).Msgf("decode CCTX.Message %s error", cctx.RelayedMessage) diff --git a/zetaclient/supplychecker/zeta_supply_checker.go b/zetaclient/supplychecker/zeta_supply_checker.go index d69cb28c54..0206b27f21 100644 --- a/zetaclient/supplychecker/zeta_supply_checker.go +++ b/zetaclient/supplychecker/zeta_supply_checker.go @@ -246,7 +246,7 @@ func (zs *ZetaSupplyChecker) GetPendingCCTXInTransit(receivingChains []common.Ch } nonceToCctxMap := make(map[uint64]*types.CrossChainTx) for _, c := range cctx { - if c.CoinType == common.CoinType_Zeta { + if c.InboundTxParams.CoinType == common.CoinType_Zeta { nonceToCctxMap[c.GetCurrentOutTxParam().OutboundTxTssNonce] = c } }