From 9406c27480dcc40eb5d5513ab83307eaec2b9c5c Mon Sep 17 00:00:00 2001 From: Tanmay Date: Sun, 18 Feb 2024 13:22:58 -0500 Subject: [PATCH] refactor: fix invalid zrc20withdraw (#1766) --- changelog.md | 3 +- common/address.go | 3 + common/address_test.go | 35 ++++++-- common/chain.go | 4 +- x/crosschain/keeper/evm_hooks.go | 110 +++++++++++++++++--------- x/crosschain/keeper/evm_hooks_test.go | 96 ++++++++++++++++++++++ x/crosschain/types/errors.go | 2 + x/fungible/keeper/evm.go | 1 - x/observer/types/errors.go | 2 + 9 files changed, 206 insertions(+), 50 deletions(-) create mode 100644 x/crosschain/keeper/evm_hooks_test.go diff --git a/changelog.md b/changelog.md index ec047c11d4..3651fded47 100644 --- a/changelog.md +++ b/changelog.md @@ -17,7 +17,7 @@ *[1728] (https://github.com/zeta-chain/node/pull/1728) - allow aborted transactions to be refunded by minting tokens to zEvm. ### Refactor - +* [1766](https://github.com/zeta-chain/node/pull/1766) - Refactors the `PostTxProcessing` EVM hook functionality to deal with invalid withdraw events * [1630](https://github.com/zeta-chain/node/pull/1630) added password prompts for hotkey and tss keyshare in zetaclient Starting zetaclient now requires two passwords to be input; one for the hotkey and another for the tss key-share. * [1760](https://github.com/zeta-chain/node/pull/1760) - Make staking keeper private in crosschain module @@ -35,6 +35,7 @@ * [1721](https://github.com/zeta-chain/node/issues/1721) - zetaclient should provide bitcoin_chain_id when querying TSS address * [1744](https://github.com/zeta-chain/node/pull/1744) - added cmd to encrypt tss keyshare file, allowing empty tss password for backward compatibility. + ### Tests * [1584](https://github.com/zeta-chain/node/pull/1584) - allow to run E2E tests on any networks diff --git a/common/address.go b/common/address.go index 77b4234fed..c79a4c5c9f 100644 --- a/common/address.go +++ b/common/address.go @@ -72,6 +72,9 @@ func DecodeBtcAddress(inputAddress string, chainID int64) (address btcutil.Addre return nil, fmt.Errorf("chain params not found") } address, err = btcutil.DecodeAddress(inputAddress, chainParams) + if err != nil { + return nil, fmt.Errorf("decode address failed: %s , for input address %s", err.Error(), inputAddress) + } ok := address.IsForNet(chainParams) if !ok { return nil, fmt.Errorf("address is not for network %s", chainParams.Name) diff --git a/common/address_test.go b/common/address_test.go index af386c3bdc..d39945935c 100644 --- a/common/address_test.go +++ b/common/address_test.go @@ -23,20 +23,41 @@ func TestAddress(t *testing.T) { func TestDecodeBtcAddress(t *testing.T) { t.Run("invalid string", func(t *testing.T) { - _, err := DecodeBtcAddress("�U�ڷ���i߭����꿚�l", 18332) + _, err := DecodeBtcAddress("�U�ڷ���i߭����꿚�l", BtcTestNetChain().ChainId) require.ErrorContains(t, err, "runtime error: index out of range") }) t.Run("invalid chain", func(t *testing.T) { _, err := DecodeBtcAddress("14CEjTd5ci3228J45GdnGeUKLSSeCWUQxK", 0) - require.ErrorContains(t, err, "is not a Bitcoin chain") + require.ErrorContains(t, err, "is not a bitcoin chain") }) - t.Run("nil pointer dereference", func(t *testing.T) { - _, err := DecodeBtcAddress("tb1qy9pqmk2pd9sv63g27jt8r657wy0d9uee4x2dt2", 18332) - require.ErrorContains(t, err, "runtime error: invalid memory address or nil pointer dereference") + t.Run("invalid checksum", func(t *testing.T) { + _, err := DecodeBtcAddress("tb1qy9pqmk2pd9sv63g27jt8r657wy0d9uee4x2dt2", BtcTestNetChain().ChainId) + require.ErrorContains(t, err, "invalid checksum") }) - t.Run("valid address", func(t *testing.T) { - _, err := DecodeBtcAddress("bcrt1qy9pqmk2pd9sv63g27jt8r657wy0d9uee4x2dt2", 18444) + t.Run("valid legacy main-net address address incorrect params TestNet", func(t *testing.T) { + _, err := DecodeBtcAddress("1EYVvXLusCxtVuEwoYvWRyN5EZTXwPVvo3", BtcTestNetChain().ChainId) + require.ErrorContains(t, err, "decode address failed") + }) + t.Run("valid legacy main-net address address incorrect params RegTestNet", func(t *testing.T) { + _, err := DecodeBtcAddress("1EYVvXLusCxtVuEwoYvWRyN5EZTXwPVvo3", BtcRegtestChain().ChainId) + require.ErrorContains(t, err, "decode address failed") + }) + + t.Run("valid legacy main-net address address correct params", func(t *testing.T) { + _, err := DecodeBtcAddress("1EYVvXLusCxtVuEwoYvWRyN5EZTXwPVvo3", BtcMainnetChain().ChainId) + require.NoError(t, err) + }) + t.Run("valid legacy testnet address with correct params", func(t *testing.T) { + _, err := DecodeBtcAddress("n2TCLD16i8SNjwPCcgGBkTEeG6CQAcYTN1", BtcTestNetChain().ChainId) require.NoError(t, err) }) + t.Run("non legacy valid address with incorrect params", func(t *testing.T) { + _, err := DecodeBtcAddress("bcrt1qy9pqmk2pd9sv63g27jt8r657wy0d9uee4x2dt2", BtcMainnetChain().ChainId) + require.ErrorContains(t, err, "address is not for network mainnet") + }) + t.Run("non legacy valid address with correct params", func(t *testing.T) { + _, err := DecodeBtcAddress("bcrt1qy9pqmk2pd9sv63g27jt8r657wy0d9uee4x2dt2", BtcRegtestChain().ChainId) + require.NoError(t, err) + }) } diff --git a/common/chain.go b/common/chain.go index d048a251b1..5254f150f6 100644 --- a/common/chain.go +++ b/common/chain.go @@ -191,7 +191,7 @@ func GetBTCChainParams(chainID int64) (*chaincfg.Params, error) { case 8332: return &chaincfg.MainNetParams, nil default: - return nil, fmt.Errorf("error chainID %d is not a Bitcoin chain", chainID) + return nil, fmt.Errorf("error chainID %d is not a bitcoin chain", chainID) } } @@ -204,7 +204,7 @@ func GetBTCChainIDFromChainParams(params *chaincfg.Params) (int64, error) { case chaincfg.MainNetParams.Name: return 8332, nil default: - return 0, fmt.Errorf("error chain %s is not a Bitcoin chain", params.Name) + return 0, fmt.Errorf("error chain %s is not a bitcoin chain", params.Name) } } diff --git a/x/crosschain/keeper/evm_hooks.go b/x/crosschain/keeper/evm_hooks.go index 5b896473a8..998da57672 100644 --- a/x/crosschain/keeper/evm_hooks.go +++ b/x/crosschain/keeper/evm_hooks.go @@ -20,7 +20,7 @@ import ( "github.com/zeta-chain/zetacore/common" "github.com/zeta-chain/zetacore/x/crosschain/types" fungibletypes "github.com/zeta-chain/zetacore/x/fungible/types" - zetaObserverTypes "github.com/zeta-chain/zetacore/x/observer/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" ) var _ evmtypes.EvmHooks = Hooks{} @@ -55,6 +55,11 @@ func (k Keeper) PostTxProcessing( // ProcessLogs post-processes logs emitted by a zEVM contract; if the log contains Withdrawal event // from registered ZRC20 contract, new CCTX will be created to trigger and track outbound // transaction. +// Returning error from process logs does the following: +// - revert the whole tx. +// - clear the logs +// TODO: implement unit tests +// https://github.com/zeta-chain/node/issues/1759 func (k Keeper) ProcessLogs(ctx sdk.Context, logs []*ethtypes.Log, emittingContract ethcommon.Address, txOrigin string) error { system, found := k.fungibleKeeper.GetSystemContract(ctx) if !found { @@ -66,15 +71,52 @@ func (k Keeper) ProcessLogs(ctx sdk.Context, logs []*ethtypes.Log, emittingContr } for _, log := range logs { - eventWithdrawal, err := k.ParseZRC20WithdrawalEvent(ctx, *log) - if err == nil { - if err := k.ProcessZRC20WithdrawalEvent(ctx, eventWithdrawal, emittingContract, txOrigin); err != nil { + eventZrc20Withdrawal, errZrc20 := ParseZRC20WithdrawalEvent(*log) + eventZetaSent, errZetaSent := ParseZetaSentEvent(*log, connectorZEVMAddr) + if errZrc20 != nil && errZetaSent != nil { + // This log does not contain any of the two events + continue + } + if eventZrc20Withdrawal != nil && eventZetaSent != nil { + // This log contains both events, this is not possible + ctx.Logger().Error(fmt.Sprintf("ProcessLogs: log contains both ZRC20Withdrawal and ZetaSent events, %s , %s", log.Topics, log.Data)) + continue + } + + // We have found either eventZrc20Withdrawal or eventZetaSent + // These cannot be processed without TSS keys, return an error if TSS is not found + tss, found := k.zetaObserverKeeper.GetTSS(ctx) + if !found { + return errorsmod.Wrap(types.ErrCannotFindTSSKeys, "Cannot process logs without TSS keys") + } + + // Do not process withdrawal events if inbound is disabled + if !k.zetaObserverKeeper.IsInboundEnabled(ctx) { + return observertypes.ErrInboundDisabled + } + + // if eventZrc20Withdrawal is not nil we will try to validate it and see if it can be processed + if eventZrc20Withdrawal != nil { + // Check if the contract is a registered ZRC20 contract. If its not a registered ZRC20 contract, we can discard this event as it is not relevant + coin, foundCoin := k.fungibleKeeper.GetForeignCoins(ctx, eventZrc20Withdrawal.Raw.Address.Hex()) + if !foundCoin { + ctx.Logger().Info(fmt.Sprintf("cannot find foreign coin with contract address %s", eventZrc20Withdrawal.Raw.Address.Hex())) + continue + } + // If Validation fails, we will not process the event and return and error. This condition means that the event was correct, and emitted from a registered ZRC20 contract + // But the information entered by the user is incorrect. In this case we can return an error and roll back the transaction + if err := ValidateZrc20WithdrawEvent(eventZrc20Withdrawal, coin.ForeignChainId); err != nil { + return err + } + // If the event is valid, we will process it and create a new CCTX + // If the process fails, we will return an error and roll back the transaction + if err := k.ProcessZRC20WithdrawalEvent(ctx, eventZrc20Withdrawal, emittingContract, txOrigin, tss); err != nil { return err } } - eZeta, err := ParseZetaSentEvent(*log, connectorZEVMAddr) - if err == nil { - if err := k.ProcessZetaSentEvent(ctx, eZeta, emittingContract, txOrigin); err != nil { + // if eventZetaSent is not nil we will try to validate it and see if it can be processed + if eventZetaSent != nil { + if err := k.ProcessZetaSentEvent(ctx, eventZetaSent, emittingContract, txOrigin, tss); err != nil { return err } } @@ -84,15 +126,9 @@ func (k Keeper) ProcessLogs(ctx sdk.Context, logs []*ethtypes.Log, emittingContr // ProcessZRC20WithdrawalEvent creates a new CCTX to process the withdrawal event // error indicates system error and non-recoverable; should abort -func (k Keeper) ProcessZRC20WithdrawalEvent(ctx sdk.Context, event *zrc20.ZRC20Withdrawal, emittingContract ethcommon.Address, txOrigin string) error { - if !k.zetaObserverKeeper.IsInboundEnabled(ctx) { - return types.ErrNotEnoughPermissions - } - ctx.Logger().Info("ZRC20 withdrawal to %s amount %d\n", hex.EncodeToString(event.To), event.Value) - tss, found := k.zetaObserverKeeper.GetTSS(ctx) - if !found { - return errorsmod.Wrap(types.ErrCannotFindTSSKeys, "ProcessZRC20WithdrawalEvent: cannot be processed without TSS keys") - } +func (k Keeper) ProcessZRC20WithdrawalEvent(ctx sdk.Context, event *zrc20.ZRC20Withdrawal, emittingContract ethcommon.Address, txOrigin string, tss observertypes.TSS) error { + + ctx.Logger().Info(fmt.Sprintf("ZRC20 withdrawal to %s amount %d", hex.EncodeToString(event.To), event.Value)) foreignCoin, found := k.fungibleKeeper.GetForeignCoins(ctx, event.Raw.Address.Hex()) if !found { return fmt.Errorf("cannot find foreign coin with emittingContract address %s", event.Raw.Address.Hex()) @@ -137,7 +173,6 @@ func (k Keeper) ProcessZRC20WithdrawalEvent(ctx sdk.Context, event *zrc20.ZRC20W // Get gas price and amount gasprice, found := k.GetGasPrice(ctx, receiverChain.ChainId) if !found { - fmt.Printf("gasprice not found for %s\n", receiverChain) return fmt.Errorf("gasprice not found for %s", receiverChain) } cctx.GetCurrentOutTxParam().OutboundTxGasPrice = fmt.Sprintf("%d", gasprice.Prices[gasprice.MedianIndex]) @@ -147,10 +182,7 @@ func (k Keeper) ProcessZRC20WithdrawalEvent(ctx sdk.Context, event *zrc20.ZRC20W return k.ProcessCCTX(ctx, cctx, receiverChain) } -func (k Keeper) ProcessZetaSentEvent(ctx sdk.Context, event *connectorzevm.ZetaConnectorZEVMZetaSent, emittingContract ethcommon.Address, txOrigin string) error { - if !k.zetaObserverKeeper.IsInboundEnabled(ctx) { - return types.ErrNotEnoughPermissions - } +func (k Keeper) ProcessZetaSentEvent(ctx sdk.Context, event *connectorzevm.ZetaConnectorZEVMZetaSent, emittingContract ethcommon.Address, txOrigin string, tss observertypes.TSS) error { ctx.Logger().Info(fmt.Sprintf( "Zeta withdrawal to %s amount %d to chain with chainId %d", hex.EncodeToString(event.DestinationAddress), @@ -158,10 +190,6 @@ func (k Keeper) ProcessZetaSentEvent(ctx sdk.Context, event *connectorzevm.ZetaC event.DestinationChainId, )) - tss, found := k.zetaObserverKeeper.GetTSS(ctx) - if !found { - return errorsmod.Wrap(types.ErrCannotFindTSSKeys, "ProcessZetaSentEvent: cannot be processed without TSS keys") - } if err := k.bankKeeper.BurnCoins( ctx, fungibletypes.ModuleName, @@ -175,7 +203,7 @@ func (k Keeper) ProcessZetaSentEvent(ctx sdk.Context, event *connectorzevm.ZetaC receiverChain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, receiverChainID.Int64()) if receiverChain == nil { - return zetaObserverTypes.ErrSupportedChains + return observertypes.ErrSupportedChains } // Validation if we want to send ZETA to an external chain, but there is no ZETA token. chainParams, found := k.zetaObserverKeeper.GetChainParamsByChainID(ctx, receiverChain.ChainId) @@ -242,10 +270,9 @@ func (k Keeper) ProcessCCTX(ctx sdk.Context, cctx types.CrossChainTx, receiverCh return nil } -// ParseZRC20WithdrawalEvent tries extracting Withdrawal event from registered ZRC20 contract; -// returns error if the log entry is not a Withdrawal event, or is not emitted from a -// registered ZRC20 contract -func (k Keeper) ParseZRC20WithdrawalEvent(ctx sdk.Context, log ethtypes.Log) (*zrc20.ZRC20Withdrawal, error) { +// ParseZRC20WithdrawalEvent tries extracting ZRC20Withdrawal event from the input logs using the zrc20 contract; +// It only returns a not-nil event if the event has been correctly validated as a valid withdrawal event +func ParseZRC20WithdrawalEvent(log ethtypes.Log) (*zrc20.ZRC20Withdrawal, error) { zrc20ZEVM, err := zrc20.NewZRC20Filterer(log.Address, bind.ContractFilterer(nil)) if err != nil { return nil, err @@ -257,28 +284,33 @@ func (k Keeper) ParseZRC20WithdrawalEvent(ctx sdk.Context, log ethtypes.Log) (*z if err != nil { return nil, err } + return event, nil +} + +// ValidateZrc20WithdrawEvent checks if the ZRC20Withdrawal event is valid +// It verifies event information for BTC chains and returns an error if the event is invalid +func ValidateZrc20WithdrawEvent(event *zrc20.ZRC20Withdrawal, chainID int64) error { + // The event was parsed; that means the user has deposited tokens to the contract. - coin, found := k.fungibleKeeper.GetForeignCoins(ctx, event.Raw.Address.Hex()) - if !found { - return nil, fmt.Errorf("ParseZRC20WithdrawalEvent: cannot find foreign coin with contract address %s", event.Raw.Address.Hex()) - } - chainID := coin.ForeignChainId if common.IsBitcoinChain(chainID) { if event.Value.Cmp(big.NewInt(0)) <= 0 { - return nil, fmt.Errorf("ParseZRC20WithdrawalEvent: invalid amount %s", event.Value.String()) + return fmt.Errorf("ParseZRC20WithdrawalEvent: invalid amount %s", event.Value.String()) } addr, err := common.DecodeBtcAddress(string(event.To), chainID) if err != nil { - return nil, fmt.Errorf("ParseZRC20WithdrawalEvent: invalid address %s: %s", event.To, err) + return fmt.Errorf("ParseZRC20WithdrawalEvent: invalid address %s: %s", event.To, err) } _, ok := addr.(*btcutil.AddressWitnessPubKeyHash) if !ok { - return nil, fmt.Errorf("ParseZRC20WithdrawalEvent: invalid address %s (not P2WPKH address)", event.To) + return fmt.Errorf("ParseZRC20WithdrawalEvent: invalid address %s (not P2WPKH address)", event.To) } } - return event, nil + return nil } +// ParseZetaSentEvent tries extracting ZetaSent event from connectorZEVM contract; +// returns error if the log entry is not a ZetaSent event, or is not emitted from connectorZEVM +// It only returns a not-nil event if all the error checks pass func ParseZetaSentEvent(log ethtypes.Log, connectorZEVM ethcommon.Address) (*connectorzevm.ZetaConnectorZEVMZetaSent, error) { zetaConnectorZEVM, err := connectorzevm.NewZetaConnectorZEVMFilterer(log.Address, bind.ContractFilterer(nil)) if err != nil { diff --git a/x/crosschain/keeper/evm_hooks_test.go b/x/crosschain/keeper/evm_hooks_test.go new file mode 100644 index 0000000000..ba09512bd8 --- /dev/null +++ b/x/crosschain/keeper/evm_hooks_test.go @@ -0,0 +1,96 @@ +package keeper_test + +import ( + "encoding/json" + "math/big" + "testing" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/common" + crosschainkeeper "github.com/zeta-chain/zetacore/x/crosschain/keeper" +) + +// + +func TestValidateZrc20WithdrawEvent(t *testing.T) { + t.Run("valid event", func(t *testing.T) { + btcMainNetWithdrawalEvent, err := crosschainkeeper.ParseZRC20WithdrawalEvent(*GetValidSampleBlock(t).Logs[3]) + require.NoError(t, err) + err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, common.BtcMainnetChain().ChainId) + require.NoError(t, err) + }) + t.Run("invalid value", func(t *testing.T) { + btcMainNetWithdrawalEvent, err := crosschainkeeper.ParseZRC20WithdrawalEvent(*GetValidSampleBlock(t).Logs[3]) + require.NoError(t, err) + btcMainNetWithdrawalEvent.Value = big.NewInt(0) + err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, common.BtcMainnetChain().ChainId) + require.ErrorContains(t, err, "ParseZRC20WithdrawalEvent: invalid amount") + }) + t.Run("invalid chain ID", func(t *testing.T) { + btcMainNetWithdrawalEvent, err := crosschainkeeper.ParseZRC20WithdrawalEvent(*GetValidSampleBlock(t).Logs[3]) + require.NoError(t, err) + err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, common.BtcTestNetChain().ChainId) + require.ErrorContains(t, err, "address is not for network testnet3") + }) + t.Run("invalid address type", func(t *testing.T) { + btcMainNetWithdrawalEvent, err := crosschainkeeper.ParseZRC20WithdrawalEvent(*GetValidSampleBlock(t).Logs[3]) + require.NoError(t, err) + btcMainNetWithdrawalEvent.To = []byte("1EYVvXLusCxtVuEwoYvWRyN5EZTXwPVvo3") + err = crosschainkeeper.ValidateZrc20WithdrawEvent(btcMainNetWithdrawalEvent, common.BtcTestNetChain().ChainId) + require.ErrorContains(t, err, "decode address failed: unknown address type") + }) +} +func TestParseZRC20WithdrawalEvent(t *testing.T) { + t.Run("invalid address", func(t *testing.T) { + for i, log := range GetSampleBlockLegacyToAddress(t).Logs { + event, err := crosschainkeeper.ParseZRC20WithdrawalEvent(*log) + if i < 3 { + require.ErrorContains(t, err, "event signature mismatch") + require.Nil(t, event) + continue + } + require.NoError(t, err) + require.NotNil(t, event) + require.Equal(t, "1EYVvXLusCxtVuEwoYvWRyN5EZTXwPVvo3", string(event.To)) + + } + }) + t.Run("valid address", func(t *testing.T) { + for i, log := range GetValidSampleBlock(t).Logs { + event, err := crosschainkeeper.ParseZRC20WithdrawalEvent(*log) + if i < 3 { + require.ErrorContains(t, err, "event signature mismatch") + require.Nil(t, event) + continue + } + require.NoError(t, err) + require.NotNil(t, event) + require.Equal(t, "bc1qysd4sp9q8my59ul9wsf5rvs9p387hf8vfwatzu", string(event.To)) + } + }) + t.Run("valid address remove topics", func(t *testing.T) { + for _, log := range GetValidSampleBlock(t).Logs { + log.Topics = nil + event, err := crosschainkeeper.ParseZRC20WithdrawalEvent(*log) + require.ErrorContains(t, err, "invalid log - no topics") + require.Nil(t, event) + } + }) +} + +// receiver is 1EYVvXLusCxtVuEwoYvWRyN5EZTXwPVvo3 +func GetSampleBlockLegacyToAddress(t *testing.T) (receipt ethtypes.Receipt) { + block := "{\n \"type\": \"0x2\",\n \"root\": \"0x\",\n \"status\": \"0x1\",\n \"cumulativeGasUsed\": \"0x4e7a38\",\n \"logsBloom\": \"0x00000000000000000000010000020000000000000000000000000000000000020000000100000000000000000000000080000000000000000000000400200000200000000002000000000008000000000000000000000000000000000000000000000000020000000000000000800800000040000000000000000010000000000000000000000000000000000000000000000000000004000000000000000000020000000000000000000000000000000000000000000000000000000000010000000002000000000000000000000000000000000000000000000000000020000010000000000000000001000000000000000000040200000000000000000000\",\n \"logs\": [\n {\n \"address\": \"0x13a0c5930c028511dc02665e7285134b6d11a5f4\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000313e74f7755afbae4f90e02ca49f8f09ff934a37\",\n \"0x000000000000000000000000735b14bb79463307aacbed86daf3322b1e6226ab\"\n ],\n \"data\": \"0x0000000000000000000000000000000000000000000000000000000000003790\",\n \"blockNumber\": \"0x1a2ad3\",\n \"transactionHash\": \"0x81126c18c7ca7d1fb7ded6644a87802e91bf52154ee4af7a5b379354e24fb6e0\",\n \"transactionIndex\": \"0x10\",\n \"blockHash\": \"0x5cb338544f64a226f4bfccb7a8d977f861c13ad73f7dd4317b66b00dd95de51c\",\n \"logIndex\": \"0x46\",\n \"removed\": false\n },\n {\n \"address\": \"0x13a0c5930c028511dc02665e7285134b6d11a5f4\",\n \"topics\": [\n \"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\n \"0x000000000000000000000000313e74f7755afbae4f90e02ca49f8f09ff934a37\",\n \"0x00000000000000000000000013a0c5930c028511dc02665e7285134b6d11a5f4\"\n ],\n \"data\": \"0x00000000000000000000000000000000000000000000000000000000006a1217\",\n \"blockNumber\": \"0x1a2ad3\",\n \"transactionHash\": \"0x81126c18c7ca7d1fb7ded6644a87802e91bf52154ee4af7a5b379354e24fb6e0\",\n \"transactionIndex\": \"0x10\",\n \"blockHash\": \"0x5cb338544f64a226f4bfccb7a8d977f861c13ad73f7dd4317b66b00dd95de51c\",\n \"logIndex\": \"0x47\",\n \"removed\": false\n },\n {\n \"address\": \"0x13a0c5930c028511dc02665e7285134b6d11a5f4\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000313e74f7755afbae4f90e02ca49f8f09ff934a37\",\n \"0x0000000000000000000000000000000000000000000000000000000000000000\"\n ],\n \"data\": \"0x00000000000000000000000000000000000000000000000000000000006a0c70\",\n \"blockNumber\": \"0x1a2ad3\",\n \"transactionHash\": \"0x81126c18c7ca7d1fb7ded6644a87802e91bf52154ee4af7a5b379354e24fb6e0\",\n \"transactionIndex\": \"0x10\",\n \"blockHash\": \"0x5cb338544f64a226f4bfccb7a8d977f861c13ad73f7dd4317b66b00dd95de51c\",\n \"logIndex\": \"0x48\",\n \"removed\": false\n },\n {\n \"address\": \"0x13a0c5930c028511dc02665e7285134b6d11a5f4\",\n \"topics\": [\n \"0x9ffbffc04a397460ee1dbe8c9503e098090567d6b7f4b3c02a8617d800b6d955\",\n \"0x000000000000000000000000313e74f7755afbae4f90e02ca49f8f09ff934a37\"\n ],\n \"data\": \"0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000006a0c700000000000000000000000000000000000000000000000000000000000003790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000223145595676584c7573437874567545776f59765752794e35455a5458775056766f33000000000000000000000000000000000000000000000000000000000000\",\n \"blockNumber\": \"0x1a2ad3\",\n \"transactionHash\": \"0x81126c18c7ca7d1fb7ded6644a87802e91bf52154ee4af7a5b379354e24fb6e0\",\n \"transactionIndex\": \"0x10\",\n \"blockHash\": \"0x5cb338544f64a226f4bfccb7a8d977f861c13ad73f7dd4317b66b00dd95de51c\",\n \"logIndex\": \"0x49\",\n \"removed\": false\n }\n ],\n \"transactionHash\": \"0x81126c18c7ca7d1fb7ded6644a87802e91bf52154ee4af7a5b379354e24fb6e0\",\n \"contractAddress\": \"0x0000000000000000000000000000000000000000\",\n \"gasUsed\": \"0x12521\",\n \"blockHash\": \"0x5cb338544f64a226f4bfccb7a8d977f861c13ad73f7dd4317b66b00dd95de51c\",\n \"blockNumber\": \"0x1a2ad3\",\n \"transactionIndex\": \"0x10\"\n}\n" + err := json.Unmarshal([]byte(block), &receipt) + require.NoError(t, err) + return +} + +// receiver is bc1qysd4sp9q8my59ul9wsf5rvs9p387hf8vfwatzu +func GetValidSampleBlock(t *testing.T) (receipt ethtypes.Receipt) { + block := "{\"type\":\"0x2\",\"root\":\"0x\",\"status\":\"0x1\",\"cumulativeGasUsed\":\"0x1f25ed\",\"logsBloom\":\"0x00000000000000000000000000020000000000000000000000000000000000020000000100000000000000000040000080000000000000000000000400200000200000000002000000000008000000000000000000000000000000000000000000000000020000000000000000800800000000000000000000000010000000000000000000000000000000000000000000000000000004000000000000000000020000000001000000000000000000000000000000000000000000000000010000000002000000000000000010000000000000000000000000000000000020000010000000000000000000000000000000000000040200000000000000000000\",\"logs\":[{\"address\":\"0x13a0c5930c028511dc02665e7285134b6d11a5f4\",\"topics\":[\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\"0x00000000000000000000000033ead83db0d0c682b05ead61e8d8f481bb1b4933\",\"0x000000000000000000000000735b14bb79463307aacbed86daf3322b1e6226ab\"],\"data\":\"0x0000000000000000000000000000000000000000000000000000000000003d84\",\"blockNumber\":\"0x1a00f3\",\"transactionHash\":\"0x9aaefece38fd2bd87077038a63fffb7c84cc8dd1ed01de134a8504a1f9a410c3\",\"transactionIndex\":\"0x8\",\"blockHash\":\"0x9517356f0b3877990590421266f02a4ff349b7476010ee34dd5f0dfc85c2684f\",\"logIndex\":\"0x28\",\"removed\":false},{\"address\":\"0x13a0c5930c028511dc02665e7285134b6d11a5f4\",\"topics\":[\"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925\",\"0x00000000000000000000000033ead83db0d0c682b05ead61e8d8f481bb1b4933\",\"0x00000000000000000000000013a0c5930c028511dc02665e7285134b6d11a5f4\"],\"data\":\"0x0000000000000000000000000000000000000000000000000000000000978c98\",\"blockNumber\":\"0x1a00f3\",\"transactionHash\":\"0x9aaefece38fd2bd87077038a63fffb7c84cc8dd1ed01de134a8504a1f9a410c3\",\"transactionIndex\":\"0x8\",\"blockHash\":\"0x9517356f0b3877990590421266f02a4ff349b7476010ee34dd5f0dfc85c2684f\",\"logIndex\":\"0x29\",\"removed\":false},{\"address\":\"0x13a0c5930c028511dc02665e7285134b6d11a5f4\",\"topics\":[\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\"0x00000000000000000000000033ead83db0d0c682b05ead61e8d8f481bb1b4933\",\"0x0000000000000000000000000000000000000000000000000000000000000000\"],\"data\":\"0x0000000000000000000000000000000000000000000000000000000000003039\",\"blockNumber\":\"0x1a00f3\",\"transactionHash\":\"0x9aaefece38fd2bd87077038a63fffb7c84cc8dd1ed01de134a8504a1f9a410c3\",\"transactionIndex\":\"0x8\",\"blockHash\":\"0x9517356f0b3877990590421266f02a4ff349b7476010ee34dd5f0dfc85c2684f\",\"logIndex\":\"0x2a\",\"removed\":false},{\"address\":\"0x13a0c5930c028511dc02665e7285134b6d11a5f4\",\"topics\":[\"0x9ffbffc04a397460ee1dbe8c9503e098090567d6b7f4b3c02a8617d800b6d955\",\"0x00000000000000000000000033ead83db0d0c682b05ead61e8d8f481bb1b4933\"],\"data\":\"0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000030390000000000000000000000000000000000000000000000000000000000003d840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a626331717973643473703971386d793539756c3977736635727673397033383768663876667761747a7500000000000000000000000000000000000000000000\",\"blockNumber\":\"0x1a00f3\",\"transactionHash\":\"0x9aaefece38fd2bd87077038a63fffb7c84cc8dd1ed01de134a8504a1f9a410c3\",\"transactionIndex\":\"0x8\",\"blockHash\":\"0x9517356f0b3877990590421266f02a4ff349b7476010ee34dd5f0dfc85c2684f\",\"logIndex\":\"0x2b\",\"removed\":false}],\"transactionHash\":\"0x9aaefece38fd2bd87077038a63fffb7c84cc8dd1ed01de134a8504a1f9a410c3\",\"contractAddress\":\"0x0000000000000000000000000000000000000000\",\"gasUsed\":\"0x12575\",\"blockHash\":\"0x9517356f0b3877990590421266f02a4ff349b7476010ee34dd5f0dfc85c2684f\",\"blockNumber\":\"0x1a00f3\",\"transactionIndex\":\"0x8\"}\n" + err := json.Unmarshal([]byte(block), &receipt) + require.NoError(t, err) + return +} diff --git a/x/crosschain/types/errors.go b/x/crosschain/types/errors.go index 0f7fb8341a..680e9b6096 100644 --- a/x/crosschain/types/errors.go +++ b/x/crosschain/types/errors.go @@ -44,4 +44,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") + + ErrProcessingZRC20Withdrawal = errorsmod.Register(ModuleName, 1151, "error processing zrc20 withdrawal") ) diff --git a/x/fungible/keeper/evm.go b/x/fungible/keeper/evm.go index 0555c0cb95..53fe3c9859 100644 --- a/x/fungible/keeper/evm.go +++ b/x/fungible/keeper/evm.go @@ -583,7 +583,6 @@ func (k Keeper) CallEVM( if ok { errMes = fmt.Sprintf("%s, reason: %v", errMes, revertErr.ErrorData()) } - return resp, cosmoserrors.Wrapf(err, errMes) } return resp, nil diff --git a/x/observer/types/errors.go b/x/observer/types/errors.go index fd61f4ea4d..0add35d4ce 100644 --- a/x/observer/types/errors.go +++ b/x/observer/types/errors.go @@ -37,4 +37,6 @@ var ( ErrMinDelegationNotFound = errorsmod.Register(ModuleName, 1129, "min delegation not found") ErrObserverSetNotFound = errorsmod.Register(ModuleName, 1130, "observer set not found") ErrTssNotFound = errorsmod.Register(ModuleName, 1131, "tss not found") + + ErrInboundDisabled = errorsmod.Register(ModuleName, 1132, "inbound tx processing is disabled") )