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 }