github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/erc20/keeper/evm_log_handler_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math/big"
     7  	"time"
     8  
     9  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
    10  	connectiontypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types"
    11  	channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types"
    12  	commitmenttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/23-commitment/types"
    13  	host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host"
    14  	ibctmtypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/light-clients/07-tendermint/types"
    15  	ibctesting "github.com/fibonacci-chain/fbc/libs/ibc-go/testing"
    16  
    17  	"github.com/ethereum/go-ethereum/common"
    18  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    19  	types2 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/types"
    20  	"github.com/fibonacci-chain/fbc/x/erc20/keeper"
    21  )
    22  
    23  const CorrectIbcDenom2 = "ibc/3EF3B49764DB0E2284467F8BF7A08C18EACACB30E1AD7ABA8E892F1F679443F9"
    24  const CorrectIbcDenom = "ibc/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
    25  
    26  func (suite *KeeperTestSuite) TestSendToIbcHandler() {
    27  	contract := common.BigToAddress(big.NewInt(1))
    28  	sender := common.BigToAddress(big.NewInt(2))
    29  	invalidDenom := "testdenom"
    30  	validDenom := CorrectIbcDenom
    31  	var data []byte
    32  
    33  	testCases := []struct {
    34  		msg       string
    35  		malleate  func()
    36  		postcheck func()
    37  		error     error
    38  	}{
    39  		{
    40  			"non associated coin denom, expect fail",
    41  			func() {
    42  				coin := sdk.NewCoin(invalidDenom, sdk.NewInt(100))
    43  				err := suite.MintCoins(sdk.AccAddress(contract.Bytes()), sdk.NewCoins(coin))
    44  				suite.Require().NoError(err)
    45  
    46  				balance := suite.GetBalance(sdk.AccAddress(contract.Bytes()), invalidDenom)
    47  				suite.Require().Equal(coin, balance)
    48  
    49  				input, err := keeper.SendToIbcEvent.Inputs.Pack(
    50  					sender,
    51  					"recipient",
    52  					coin.Amount.BigInt(),
    53  				)
    54  				suite.Require().NoError(err)
    55  				data = input
    56  			},
    57  			func() {},
    58  			errors.New("contract 0x0000000000000000000000000000000000000001 is not connected to native token"),
    59  		},
    60  		{
    61  			"non IBC denom, expect fail",
    62  			func() {
    63  				suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, invalidDenom, contract)
    64  				coin := sdk.NewCoin(invalidDenom, sdk.NewInt(100))
    65  				err := suite.MintCoins(sdk.AccAddress(contract.Bytes()), sdk.NewCoins(coin))
    66  				suite.Require().NoError(err)
    67  
    68  				balance := suite.GetBalance(sdk.AccAddress(contract.Bytes()), invalidDenom)
    69  				suite.Require().Equal(coin, balance)
    70  
    71  				input, err := keeper.SendToIbcEvent.Inputs.Pack(
    72  					sender,
    73  					"recipient",
    74  					coin.Amount.BigInt(),
    75  				)
    76  				suite.Require().NoError(err)
    77  				data = input
    78  			},
    79  			func() {},
    80  			errors.New("the native token associated with the contract 0x0000000000000000000000000000000000000001 is not an ibc voucher"),
    81  		},
    82  		{
    83  			"success send to ibc",
    84  			func() {
    85  				amount := sdk.NewInt(100)
    86  				suite.app.TransferKeeper.SetParams(suite.ctx, types2.Params{
    87  					true, true,
    88  				})
    89  				channelA := "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
    90  				suite.app.TransferKeeper.SetDenomTrace(suite.ctx, types2.DenomTrace{
    91  					BaseDenom: "ibc/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Path: "",
    92  				})
    93  				suite.app.TransferKeeper.BindPort(suite.ctx, "transfer")
    94  				cap, _ := suite.app.ScopedTransferKeeper.NewCapability(suite.ctx, host.ChannelCapabilityPath("transfer", channelA))
    95  				suite.app.ScopedIBCKeeper.ClaimCapability(suite.ctx, cap, host.ChannelCapabilityPath("transfer", channelA))
    96  				suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, CorrectIbcDenom2, contract)
    97  				c := channeltypes.Channel{
    98  					State:    channeltypes.OPEN,
    99  					Ordering: channeltypes.UNORDERED,
   100  					Counterparty: channeltypes.Counterparty{
   101  						PortId:    "transfer",
   102  						ChannelId: channelA,
   103  					},
   104  					ConnectionHops: []string{"one"},
   105  					Version:        "version",
   106  				}
   107  
   108  				suite.app.IBCKeeper.V2Keeper.ChannelKeeper.SetNextSequenceSend(suite.ctx, "transfer", channelA, 1)
   109  				suite.app.IBCKeeper.V2Keeper.ChannelKeeper.SetChannel(suite.ctx, "transfer", channelA, c)
   110  				counterparty := connectiontypes.NewCounterparty("client-1", "one", commitmenttypes.NewMerklePrefix([]byte("ibc")))
   111  				conn1 := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "client-1", counterparty, connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions()), 0)
   112  				period := time.Hour * 24 * 7 * 2
   113  				clientState := ibctmtypes.NewClientState("testChainID", ibctmtypes.DefaultTrustLevel, period, period, period, types.NewHeight(0, 5), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
   114  				suite.app.IBCKeeper.V2Keeper.ClientKeeper.SetClientState(suite.ctx, "client-1", clientState)
   115  				consensusState := ibctmtypes.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("root")), []byte("nextValsHash"))
   116  				suite.app.IBCKeeper.V2Keeper.ClientKeeper.SetClientConsensusState(suite.ctx, "client-1", types.NewHeight(0, 5), consensusState)
   117  				suite.app.IBCKeeper.V2Keeper.ConnectionKeeper.SetConnection(suite.ctx, "one", conn1)
   118  				coin := sdk.NewCoin(CorrectIbcDenom2, amount)
   119  				err := suite.MintCoins(sdk.AccAddress(contract.Bytes()), sdk.NewCoins(coin))
   120  				suite.Require().NoError(err)
   121  
   122  				balance := suite.GetBalance(sdk.AccAddress(contract.Bytes()), CorrectIbcDenom2)
   123  				suite.Require().Equal(coin, balance)
   124  
   125  				input, err := keeper.SendToIbcEvent.Inputs.Pack(
   126  					sender,
   127  					"recipient",
   128  					coin.Amount.BigInt(),
   129  				)
   130  				suite.Require().NoError(err)
   131  				data = input
   132  			},
   133  			func() {},
   134  			nil,
   135  		},
   136  		{
   137  			"denomination trace not found",
   138  			func() {
   139  				amount := sdk.NewInt(100)
   140  				suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, validDenom, contract)
   141  				coin := sdk.NewCoin(validDenom, amount)
   142  				err := suite.MintCoins(sdk.AccAddress(contract.Bytes()), sdk.NewCoins(coin))
   143  				suite.Require().NoError(err)
   144  
   145  				balance := suite.GetBalance(sdk.AccAddress(contract.Bytes()), validDenom)
   146  				suite.Require().Equal(coin, balance)
   147  
   148  				input, err := keeper.SendToIbcEvent.Inputs.Pack(
   149  					sender,
   150  					"recipient",
   151  					coin.Amount.BigInt(),
   152  				)
   153  				suite.Require().NoError(err)
   154  				data = input
   155  			},
   156  			func() {},
   157  			errors.New("denomination trace not found: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),
   158  		},
   159  	}
   160  
   161  	for _, tc := range testCases {
   162  		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
   163  			suite.SetupTest()
   164  
   165  			handler := keeper.NewSendToIbcEventHandler(suite.app.Erc20Keeper)
   166  			tc.malleate()
   167  			err := handler.Handle(suite.ctx, contract, data)
   168  			if tc.error != nil {
   169  				suite.Require().EqualError(err, tc.error.Error())
   170  			} else {
   171  				suite.Require().NoError(err)
   172  				tc.postcheck()
   173  			}
   174  		})
   175  	}
   176  }
   177  
   178  func (suite *KeeperTestSuite) TestSendNative20ToIbcHandler() {
   179  	contract := common.BigToAddress(big.NewInt(1))
   180  	sender := common.BigToAddress(big.NewInt(2))
   181  	validDenom := "testdenom"
   182  
   183  	var data []byte
   184  
   185  	testCases := []struct {
   186  		msg       string
   187  		malleate  func()
   188  		postcheck func()
   189  		error     error
   190  	}{
   191  		{
   192  			"non associated coin denom, expect fail",
   193  			func() {
   194  				coin := sdk.NewCoin(validDenom, sdk.NewInt(100))
   195  				err := suite.MintCoins(sdk.AccAddress(contract.Bytes()), sdk.NewCoins(coin))
   196  				suite.Require().NoError(err)
   197  
   198  				balance := suite.GetBalance(sdk.AccAddress(contract.Bytes()), validDenom)
   199  				suite.Require().Equal(coin, balance)
   200  
   201  				input, err := keeper.SendToIbcEvent.Inputs.Pack(
   202  					sender,
   203  					"recipient",
   204  					coin.Amount.BigInt(),
   205  				)
   206  				suite.Require().NoError(err)
   207  				data = input
   208  			},
   209  			func() {},
   210  			errors.New("contract 0x0000000000000000000000000000000000000001 is not connected to native token"),
   211  		},
   212  		{
   213  			"success send to ibc",
   214  			func() {
   215  				amount := sdk.NewInt(100)
   216  				suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, validDenom, contract)
   217  				coin := sdk.NewCoin(validDenom, amount)
   218  				err := suite.MintCoins(sdk.AccAddress(contract.Bytes()), sdk.NewCoins(coin))
   219  				suite.Require().NoError(err)
   220  
   221  				balance := suite.GetBalance(sdk.AccAddress(contract.Bytes()), validDenom)
   222  				suite.Require().Equal(coin, balance)
   223  
   224  				input, err := keeper.SendToIbcEvent.Inputs.Pack(
   225  					sender,
   226  					"recipient",
   227  					amount.BigInt(),
   228  				)
   229  				suite.Require().NoError(err)
   230  				data = input
   231  			},
   232  			func() {},
   233  			nil,
   234  		},
   235  		{
   236  			"portid channel error",
   237  			func() {
   238  
   239  				amount := sdk.NewInt(100)
   240  				suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, validDenom, contract)
   241  				coin := sdk.NewCoin(validDenom, amount)
   242  				err := suite.MintCoins(sdk.AccAddress(contract.Bytes()), sdk.NewCoins(coin))
   243  				suite.Require().NoError(err)
   244  				suite.ctx.SetIsCheckTx(false)
   245  				suite.ctx.SetIsTraceTx(false)
   246  				balance := suite.GetBalance(sdk.AccAddress(contract.Bytes()), validDenom)
   247  				suite.Require().Equal(coin, balance)
   248  				suite.app.TransferKeeper.SetParams(suite.ctx, types2.Params{true, true})
   249  				input, err := keeper.SendNative20ToIbcEvent.Inputs.Pack(
   250  					sender,
   251  					"recipient",
   252  					coin.Amount.BigInt(),
   253  					"transfer",
   254  					"channel-0",
   255  				)
   256  				suite.Require().NoError(err)
   257  				data = input
   258  			},
   259  			func() {},
   260  			errors.New("channel not found: port ID (transfer) channel ID (channel-0)"),
   261  		},
   262  	}
   263  
   264  	for _, tc := range testCases {
   265  		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
   266  			suite.SetupTest()
   267  
   268  			handler := keeper.NewSendNative20ToIbcEventHandler(suite.app.Erc20Keeper)
   269  			tc.malleate()
   270  			err := handler.Handle(suite.ctx, contract, data)
   271  			if tc.error != nil {
   272  				suite.Require().EqualError(err, tc.error.Error())
   273  			} else {
   274  				suite.Require().NoError(err)
   275  				tc.postcheck()
   276  			}
   277  		})
   278  	}
   279  }