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

     1  package keeper_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math/big"
     7  
     8  	"github.com/ethereum/go-ethereum/common"
     9  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    10  	erc20Keeper "github.com/fibonacci-chain/fbc/x/erc20/keeper"
    11  	"github.com/fibonacci-chain/fbc/x/erc20/types"
    12  	evmtypes "github.com/fibonacci-chain/fbc/x/evm/types"
    13  )
    14  
    15  const (
    16  	IbcDenom    = "ibc/ddcd907790b8aa2bf9b2b3b614718fa66bfc7540e832ce3e3696ea717dceff49"
    17  	NativeDenom = "usdt"
    18  )
    19  
    20  func (suite *KeeperTestSuite) TestConvertVouchers() {
    21  	addr1 := common.BigToAddress(big.NewInt(1))
    22  	addr1Bech := sdk.AccAddress(addr1.Bytes())
    23  
    24  	amount := int64(123)
    25  	amountDec := sdk.NewDec(amount)
    26  
    27  	testCases := []struct {
    28  		msg       string
    29  		from      string
    30  		vouchers  sdk.SysCoins
    31  		malleate  func()
    32  		postcheck func()
    33  		expError  error
    34  	}{
    35  		{
    36  			"Wrong from address",
    37  			"test",
    38  			sdk.NewCoins(sdk.NewCoin(IbcDenom, sdk.NewInt(1))),
    39  			func() {},
    40  			func() {},
    41  			errors.New("encoding/hex: invalid byte: U+0074 't'"),
    42  		},
    43  		{
    44  			"Empty address",
    45  			"",
    46  			sdk.NewCoins(sdk.NewCoin(IbcDenom, sdk.NewInt(1))),
    47  			func() {},
    48  			func() {},
    49  			errors.New("empty from address string is not allowed"),
    50  		},
    51  		{
    52  			"Correct address with non supported coin denom",
    53  			addr1Bech.String(),
    54  			sdk.NewCoins(sdk.NewCoin("fake", sdk.NewInt(1))),
    55  			func() {},
    56  			func() {},
    57  			errors.New("coin fake is not supported for wrapping"),
    58  		},
    59  		{
    60  			"Correct address with not enough IBC evm token",
    61  			addr1Bech.String(),
    62  			sdk.NewCoins(sdk.NewCoin(IbcDenom, sdk.NewInt(123))),
    63  			func() {
    64  				coin := sdk.NewCoin(IbcDenom, amountDec.Sub(sdk.NewDec(3)))
    65  				err := suite.MintCoins(addr1Bech, sdk.NewCoins(coin))
    66  				suite.Require().NoError(err)
    67  
    68  				params := types.DefaultParams()
    69  				params.EnableAutoDeployment = true
    70  				suite.app.Erc20Keeper.SetParams(suite.ctx, params)
    71  
    72  				suite.app.Erc20Keeper.InitInternalTemplateContract(suite.ctx)
    73  
    74  				evmParams := evmtypes.DefaultParams()
    75  				evmParams.EnableCreate = true
    76  				evmParams.EnableCall = true
    77  				suite.app.EvmKeeper.SetParams(suite.ctx, evmParams)
    78  			},
    79  			func() {},
    80  			fmt.Errorf("insufficient funds: insufficient account funds; 120.000000000000000000%s < 123.000000000000000000%s",
    81  				IbcDenom, IbcDenom),
    82  		},
    83  		{
    84  			"Correct address with not enough IBC token",
    85  			addr1Bech.String(),
    86  			sdk.NewCoins(sdk.NewCoin(CorrectIbcDenom, amountDec)),
    87  			func() {
    88  				coin := sdk.NewCoin(CorrectIbcDenom, amountDec.Sub(sdk.NewDec(3)))
    89  				err := suite.MintCoins(addr1Bech, sdk.NewCoins(coin))
    90  				suite.Require().NoError(err)
    91  
    92  				params := types.DefaultParams()
    93  				params.EnableAutoDeployment = true
    94  				suite.app.Erc20Keeper.SetParams(suite.ctx, params)
    95  
    96  				suite.app.Erc20Keeper.InitInternalTemplateContract(suite.ctx)
    97  
    98  				evmParams := evmtypes.DefaultParams()
    99  				evmParams.EnableCreate = true
   100  				evmParams.EnableCall = true
   101  				suite.app.EvmKeeper.SetParams(suite.ctx, evmParams)
   102  			},
   103  			func() {},
   104  			fmt.Errorf("insufficient funds: insufficient account funds; 120.000000000000000000%s < 123.000000000000000000%s",
   105  				CorrectIbcDenom, CorrectIbcDenom),
   106  		},
   107  		{
   108  			"Correct address with IBC token : Should receive ERC20 tokens",
   109  			addr1Bech.String(),
   110  			sdk.NewDecCoinsFromDec(CorrectIbcDenom, amountDec),
   111  			func() {
   112  				coin := sdk.NewCoin(CorrectIbcDenom, amountDec)
   113  				err := suite.MintCoins(addr1Bech, sdk.NewCoins(coin))
   114  				suite.Require().NoError(err)
   115  
   116  				balance := suite.GetBalance(addr1Bech, CorrectIbcDenom)
   117  				suite.Require().Equal(coin, balance)
   118  
   119  				params := types.DefaultParams()
   120  				params.EnableAutoDeployment = true
   121  				suite.app.Erc20Keeper.SetParams(suite.ctx, params)
   122  
   123  				suite.app.Erc20Keeper.InitInternalTemplateContract(suite.ctx)
   124  
   125  				evmParams := evmtypes.DefaultParams()
   126  				evmParams.EnableCreate = true
   127  				evmParams.EnableCall = true
   128  				suite.app.EvmKeeper.SetParams(suite.ctx, evmParams)
   129  			},
   130  			func() {
   131  				coin := sdk.NewCoin(CorrectIbcDenom, amountDec)
   132  
   133  				// 1. Verify balance IBC coin post operation
   134  				balance := suite.GetBalance(addr1Bech, CorrectIbcDenom)
   135  				suite.Require().Equal(sdk.NewDec(0), balance.Amount)
   136  				// 2. Verify ERC20 contract be created
   137  				contract, found := suite.app.Erc20Keeper.GetContractByDenom(suite.ctx, CorrectIbcDenom)
   138  				suite.Require().True(found)
   139  				// 3. Verify balance IBC coin for contract address
   140  				balance = suite.GetBalance(sdk.AccAddress(contract.Bytes()), CorrectIbcDenom)
   141  				suite.Require().Equal(coin, balance)
   142  				// 4. Verify ERC20 balance post operation
   143  				ret, err := suite.app.Erc20Keeper.CallModuleERC20(suite.ctx, contract, "balanceOf", common.BytesToAddress(addr1Bech.Bytes()))
   144  				suite.Require().NoError(err)
   145  				suite.Require().Equal(amountDec.BigInt(), big.NewInt(0).SetBytes(ret))
   146  			},
   147  			nil,
   148  		},
   149  	}
   150  
   151  	for _, tc := range testCases {
   152  		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
   153  			suite.SetupTest()
   154  			tc.malleate()
   155  
   156  			err := suite.app.Erc20Keeper.ConvertVouchers(suite.ctx, tc.from, tc.vouchers)
   157  			if tc.expError != nil {
   158  				suite.Require().EqualError(err, tc.expError.Error(), tc.msg)
   159  			} else {
   160  				suite.Require().NoError(err, tc.msg)
   161  				tc.postcheck()
   162  			}
   163  		})
   164  	}
   165  }
   166  
   167  func (suite *KeeperTestSuite) TestIbcTransferVouchers() {
   168  	addr1 := common.BigToAddress(big.NewInt(1))
   169  	addr1Bech := sdk.AccAddress(addr1.Bytes())
   170  
   171  	testCases := []struct {
   172  		name      string
   173  		from      string
   174  		to        string
   175  		coin      sdk.Coins
   176  		malleate  func()
   177  		expError  error
   178  		postCheck func()
   179  	}{
   180  		{
   181  			"Wrong from address",
   182  			"test",
   183  			"to",
   184  			sdk.NewCoins(sdk.NewCoin(CorrectIbcDenom, sdk.NewInt(1))),
   185  			func() {},
   186  			errors.New("encoding/hex: invalid byte: U+0074 't'"),
   187  			func() {},
   188  		},
   189  		{
   190  			"Empty address",
   191  			"",
   192  			"to",
   193  			sdk.NewCoins(sdk.NewCoin(CorrectIbcDenom, sdk.NewInt(1))),
   194  			func() {},
   195  			errors.New("empty from address string is not allowed"),
   196  			func() {},
   197  		},
   198  		{
   199  			"Correct address with non supported coin denom",
   200  			addr1Bech.String(),
   201  			"to",
   202  			sdk.NewCoins(sdk.NewCoin("fake", sdk.NewInt(1))),
   203  			func() {},
   204  			errors.New("coin fake is not supported"),
   205  			func() {},
   206  		},
   207  		//{
   208  		//	"Correct address with too small amount EVM token",
   209  		//	addr1Bech.String(),
   210  		//	"to",
   211  		//	sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(123))),
   212  		//	func() {},
   213  		//	nil,
   214  		//	func() {},
   215  		//},
   216  		//{
   217  		//	"Correct address with not enough EVM token",
   218  		//	addr1Bech.String(),
   219  		//	"to",
   220  		//	sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(fibo000000000))),
   221  		//	func() {},
   222  		//	errors.New("0aphoton is smaller than 000000000aphoton: insufficient funds"),
   223  		//	func() {},
   224  		//},
   225  		//{
   226  		//	"Correct address with enough EVM token : Should receive IBC evm token",
   227  		//	addr1Bech.String(),
   228  		//	"to",
   229  		//	sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(000000000))),
   230  		//	func() {
   231  		//		// Mint Coin to user and module
   232  		//		suite.MintCoins(addr1Bech, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(000000000))))
   233  		//		suite.MintCoinsToModule(types.ModuleName, sdk.NewCoins(sdk.NewCoin(types.IbcDenomDefaultValue, sdk.NewInt(123))))
   234  		//		// Verify balance IBC coin pre operation
   235  		//		ibcCoin := suite.GetBalance(addr1Bech, types.IbcDenomDefaultValue)
   236  		//		suite.Require().Equal(sdk.NewInt(0), ibcCoin.Amount)
   237  		//		// Verify balance EVM coin pre operation
   238  		//		evmCoin := suite.GetBalance(addr1Bech, sdk.DefaultBondDenom)
   239  		//		suite.Require().Equal(sdk.NewInt(000000000), evmCoin.Amount)
   240  		//	},
   241  		//	nil,
   242  		//	func() {
   243  		//		// Verify balance IBC coin post operation
   244  		//		ibcCoin := suite.GetBalance(addr1Bech, types.IbcDenomDefaultValue)
   245  		//		suite.Require().Equal(sdk.NewInt(123), ibcCoin.Amount)
   246  		//		// Verify balance EVM coin post operation
   247  		//		evmCoin := suite.GetBalance(addr1Bech, sdk.DefaultBondDenom)
   248  		//		suite.Require().Equal(sdk.NewInt(0), evmCoin.Amount)
   249  		//	},
   250  		//},
   251  		{
   252  			"Correct address with non correct IBC token denom",
   253  			addr1Bech.String(),
   254  			"to",
   255  			sdk.NewCoins(sdk.NewCoin("incorrect", sdk.NewInt(123))),
   256  			func() {
   257  				// Add support for the IBC token
   258  				suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, "incorrect", common.HexToAddress("0x11"))
   259  			},
   260  			errors.New("ibc denom is invalid: incorrect is invalid"),
   261  			func() {
   262  			},
   263  		},
   264  		{
   265  			"Correct address with correct IBC token denom",
   266  			addr1Bech.String(),
   267  			"to",
   268  			sdk.NewCoins(sdk.NewCoin(CorrectIbcDenom, sdk.NewInt(123))),
   269  			func() {
   270  				// Mint IBC token for user
   271  				suite.MintCoins(addr1Bech, sdk.NewCoins(sdk.NewCoin(CorrectIbcDenom, sdk.NewInt(123))))
   272  				// Add support for the IBC token
   273  				suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, CorrectIbcDenom, common.HexToAddress("0x11"))
   274  			},
   275  			nil,
   276  			func() {},
   277  		},
   278  	}
   279  
   280  	for _, tc := range testCases {
   281  		suite.Run(tc.name, func() {
   282  			suite.SetupTest() // reset
   283  			// Create erc20 Keeper with mock transfer keeper
   284  			erc20Keeper := erc20Keeper.NewKeeper(
   285  				suite.app.Codec(),
   286  				suite.app.GetKey(types.StoreKey),
   287  				suite.app.GetSubspace(types.ModuleName),
   288  				suite.app.AccountKeeper,
   289  				suite.app.SupplyKeeper,
   290  				suite.app.BankKeeper,
   291  				suite.app.EvmKeeper,
   292  				IbcKeeperMock{},
   293  			)
   294  			suite.app.Erc20Keeper = erc20Keeper
   295  
   296  			tc.malleate()
   297  			err := suite.app.Erc20Keeper.IbcTransferVouchers(suite.ctx, tc.from, tc.to, tc.coin)
   298  			if tc.expError != nil {
   299  				suite.Require().EqualError(err, tc.expError.Error())
   300  			} else {
   301  				suite.Require().NoError(err)
   302  				tc.postCheck()
   303  			}
   304  		})
   305  	}
   306  }
   307  
   308  func (suite *KeeperTestSuite) TestConvertNatives() {
   309  	addr1 := common.BigToAddress(big.NewInt(1))
   310  	addr1Bech := sdk.AccAddress(addr1.Bytes())
   311  
   312  	nativeAddr := common.BigToAddress(big.NewInt(2))
   313  
   314  	amount := int64(123)
   315  	amountDec := sdk.NewDec(amount)
   316  
   317  	testCases := []struct {
   318  		msg       string
   319  		from      string
   320  		natives   sdk.SysCoins
   321  		malleate  func()
   322  		postcheck func()
   323  		expError  error
   324  	}{
   325  		{
   326  			"Wrong from address",
   327  			"test",
   328  			sdk.NewCoins(sdk.NewCoin(NativeDenom, sdk.NewInt(1))),
   329  			func() {},
   330  			func() {},
   331  			errors.New("encoding/hex: invalid byte: U+0074 't'"),
   332  		},
   333  		{
   334  			"Empty address",
   335  			"",
   336  			sdk.NewCoins(sdk.NewCoin(NativeDenom, sdk.NewInt(1))),
   337  			func() {},
   338  			func() {},
   339  			errors.New("empty from address string is not allowed"),
   340  		},
   341  		{
   342  			"Correct address with and Correct native denom",
   343  			addr1Bech.String(),
   344  			sdk.NewCoins(sdk.NewCoin("fake", sdk.NewInt(1))),
   345  			func() {},
   346  			func() {},
   347  			nil,
   348  		},
   349  		{
   350  			"Correct address with not enough IBC evm token",
   351  			addr1Bech.String(),
   352  			sdk.NewCoins(sdk.NewCoin(NativeDenom, sdk.NewInt(123))),
   353  			func() {
   354  				coin := sdk.NewCoin(NativeDenom, amountDec.Sub(sdk.NewDec(3)))
   355  				err := suite.MintCoins(addr1Bech, sdk.NewCoins(coin))
   356  				suite.Require().NoError(err)
   357  
   358  				suite.app.Erc20Keeper.InitInternalTemplateContract(suite.ctx)
   359  				suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, NativeDenom, nativeAddr)
   360  
   361  				evmParams := evmtypes.DefaultParams()
   362  				evmParams.EnableCreate = true
   363  				evmParams.EnableCall = true
   364  				suite.app.EvmKeeper.SetParams(suite.ctx, evmParams)
   365  			},
   366  			func() {},
   367  			fmt.Errorf("insufficient funds: insufficient account funds; 120.000000000000000000%s < 123.000000000000000000%s",
   368  				NativeDenom, NativeDenom),
   369  		},
   370  		{
   371  			"Correct address with not enough IBC token",
   372  			addr1Bech.String(),
   373  			sdk.NewCoins(sdk.NewCoin(CorrectIbcDenom, amountDec)),
   374  			func() {
   375  				coin := sdk.NewCoin(CorrectIbcDenom, amountDec.Sub(sdk.NewDec(3)))
   376  				err := suite.MintCoins(addr1Bech, sdk.NewCoins(coin))
   377  				suite.Require().NoError(err)
   378  
   379  				suite.app.Erc20Keeper.InitInternalTemplateContract(suite.ctx)
   380  				suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, CorrectIbcDenom, nativeAddr)
   381  
   382  				evmParams := evmtypes.DefaultParams()
   383  				evmParams.EnableCreate = true
   384  				evmParams.EnableCall = true
   385  				suite.app.EvmKeeper.SetParams(suite.ctx, evmParams)
   386  			},
   387  			func() {},
   388  			fmt.Errorf("insufficient funds: insufficient account funds; 120.000000000000000000%s < 123.000000000000000000%s",
   389  				CorrectIbcDenom, CorrectIbcDenom),
   390  		},
   391  		{
   392  			"Correct address with IBC token : Should receive ERC20 tokens",
   393  			addr1Bech.String(),
   394  			sdk.NewDecCoinsFromDec(NativeDenom, amountDec),
   395  			func() {
   396  				coin := sdk.NewCoin(NativeDenom, amountDec)
   397  				err := suite.MintCoins(addr1Bech, sdk.NewCoins(coin))
   398  				suite.Require().NoError(err)
   399  
   400  				balance := suite.GetBalance(addr1Bech, NativeDenom)
   401  				suite.Require().Equal(coin, balance)
   402  
   403  				evmParams := evmtypes.DefaultParams()
   404  				evmParams.EnableCreate = true
   405  				evmParams.EnableCall = true
   406  				suite.app.EvmKeeper.SetParams(suite.ctx, evmParams)
   407  
   408  				suite.app.Erc20Keeper.InitInternalTemplateContract(suite.ctx)
   409  				contract, err := suite.app.Erc20Keeper.DeployModuleERC20(suite.ctx, "native20")
   410  				suite.Require().NoError(err)
   411  				suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, NativeDenom, contract)
   412  			},
   413  			func() {
   414  				// 1. Verify balance native coin post operation
   415  				balance := suite.GetBalance(addr1Bech, NativeDenom)
   416  				suite.Require().Equal(sdk.NewDec(0), balance.Amount)
   417  				// 2. Verify ERC20 contract be created
   418  				contract, found := suite.app.Erc20Keeper.GetContractByDenom(suite.ctx, NativeDenom)
   419  				suite.Require().True(found)
   420  				// 3. Verify ERC20 balance post operation
   421  				ret, err := suite.app.Erc20Keeper.CallModuleERC20(suite.ctx, contract, "balanceOf", common.BytesToAddress(addr1Bech.Bytes()))
   422  				suite.Require().NoError(err)
   423  				suite.Require().Equal(amountDec.BigInt(), big.NewInt(0).SetBytes(ret))
   424  			},
   425  			nil,
   426  		},
   427  	}
   428  
   429  	for _, tc := range testCases {
   430  		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
   431  			suite.SetupTest()
   432  			tc.malleate()
   433  
   434  			err := suite.app.Erc20Keeper.ConvertNatives(suite.ctx, tc.from, tc.natives)
   435  			if tc.expError != nil {
   436  				suite.Require().EqualError(err, tc.expError.Error(), tc.msg)
   437  			} else {
   438  				suite.Require().NoError(err, tc.msg)
   439  				tc.postcheck()
   440  			}
   441  		})
   442  	}
   443  }