github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/erc20/keeper/keeper_test.go (about) 1 package keeper_test 2 3 import ( 4 "errors" 5 "fmt" 6 "math/big" 7 "testing" 8 "time" 9 10 "github.com/ethereum/go-ethereum/accounts/abi" 11 "github.com/ethereum/go-ethereum/common" 12 "github.com/stretchr/testify/suite" 13 14 "github.com/fibonacci-chain/fbc/app" 15 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 16 minttypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/mint" 17 transfertypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/types" 18 clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types" 19 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 20 tmbytes "github.com/fibonacci-chain/fbc/libs/tendermint/libs/bytes" 21 "github.com/fibonacci-chain/fbc/x/erc20/keeper" 22 "github.com/fibonacci-chain/fbc/x/erc20/types" 23 evmtypes "github.com/fibonacci-chain/fbc/x/evm/types" 24 ) 25 26 var ( 27 Uint256, _ = abi.NewType("uint256", "", nil) 28 ) 29 30 func TestKeeperTestSuite(t *testing.T) { 31 suite.Run(t, new(KeeperTestSuite)) 32 } 33 34 type KeeperTestSuite struct { 35 suite.Suite 36 37 ctx sdk.Context 38 app *app.FBChainApp 39 40 querier sdk.Querier 41 } 42 43 func (suite *KeeperTestSuite) SetupTest() { 44 checkTx := false 45 46 suite.app = app.Setup(checkTx) 47 suite.ctx = suite.app.NewContext(checkTx, abci.Header{ 48 Height: 1, 49 ChainID: "ethermint-3", 50 Time: time.Now().UTC(), 51 }) 52 suite.querier = keeper.NewQuerier(suite.app.Erc20Keeper) 53 suite.app.Erc20Keeper.SetParams(suite.ctx, types.DefaultParams()) 54 } 55 56 func (suite *KeeperTestSuite) MintCoins(address sdk.AccAddress, coins sdk.Coins) error { 57 err := suite.app.SupplyKeeper.MintCoins(suite.ctx, minttypes.ModuleName, coins) 58 if err != nil { 59 return err 60 } 61 err = suite.app.SupplyKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, address, coins) 62 if err != nil { 63 return err 64 } 65 return nil 66 } 67 68 func (suite *KeeperTestSuite) GetBalance(address sdk.AccAddress, denom string) sdk.Coin { 69 acc := suite.app.AccountKeeper.GetAccount(suite.ctx, address) 70 return sdk.Coin{denom, acc.GetCoins().AmountOf(denom)} 71 } 72 73 type IbcKeeperMock struct{} 74 75 func (i IbcKeeperMock) SendTransfer(ctx sdk.Context, sourcePort, sourceChannel string, token sdk.CoinAdapter, 76 sender sdk.AccAddress, receiver string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64) error { 77 return nil 78 } 79 80 func (i IbcKeeperMock) DenomPathFromHash(ctx sdk.Context, denom string) (string, error) { //nolint 81 if denom == "ibc/ddcd907790b8aa2bf9b2b3b614718fa66bfc7540e832ce3e3696ea717dceff49" { 82 return "transfer/channel-0", nil 83 } 84 if denom == "ibc/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" { 85 return "transfer/channel-0", nil 86 } 87 return "", errors.New("not fount") 88 } 89 90 func (i IbcKeeperMock) GetDenomTrace(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) (transfertypes.DenomTrace, bool) { 91 return transfertypes.DenomTrace{}, false 92 } 93 94 func (suite *KeeperTestSuite) TestDenomContractMap() { 95 denom1 := "testdenom1" 96 denom2 := "testdenom2" 97 98 autoContract := common.BigToAddress(big.NewInt(1)) 99 externalContract := common.BigToAddress(big.NewInt(2)) 100 101 testCases := []struct { 102 name string 103 malleate func() 104 }{ 105 { 106 "success, happy path", 107 func() { 108 keeper := suite.app.Erc20Keeper 109 110 contract, found := keeper.GetContractByDenom(suite.ctx, denom1) 111 suite.Require().False(found) 112 113 keeper.SetContractForDenom(suite.ctx, denom1, autoContract) 114 115 contract, found = keeper.GetContractByDenom(suite.ctx, denom1) 116 suite.Require().True(found) 117 suite.Require().Equal(autoContract, contract) 118 119 denom, found := keeper.GetDenomByContract(suite.ctx, contract) 120 suite.Require().True(found) 121 suite.Require().Equal(denom1, denom) 122 123 keeper.SetContractForDenom(suite.ctx, denom1, externalContract) 124 125 contract, found = keeper.GetContractByDenom(suite.ctx, denom1) 126 suite.Require().True(found) 127 suite.Require().Equal(externalContract, contract) 128 }, 129 }, 130 { 131 "failure, multiple denoms map to same contract", 132 func() { 133 keeper := suite.app.Erc20Keeper 134 keeper.SetContractForDenom(suite.ctx, denom1, autoContract) 135 err := keeper.SetContractForDenom(suite.ctx, denom2, autoContract) 136 suite.Require().Error(err) 137 }, 138 }, 139 { 140 "failure, multiple denoms map to same external contract", 141 func() { 142 keeper := suite.app.Erc20Keeper 143 err := keeper.SetContractForDenom(suite.ctx, denom1, externalContract) 144 suite.Require().NoError(err) 145 err = keeper.SetContractForDenom(suite.ctx, denom2, externalContract) 146 suite.Require().Error(err) 147 }, 148 }, 149 { 150 "success, delete contract", 151 func() { 152 keeper := suite.app.Erc20Keeper 153 r := keeper.DeleteContractForDenom(suite.ctx, denom1) 154 suite.Require().Equal(r, false) 155 err := keeper.SetContractForDenom(suite.ctx, denom1, externalContract) 156 suite.Require().NoError(err) 157 r = keeper.DeleteContractForDenom(suite.ctx, denom1) 158 suite.Require().Equal(r, true) 159 }, 160 }, 161 { 162 "success, multiple denoms map to different contracts", 163 func() { 164 keeper := suite.app.Erc20Keeper 165 err := keeper.SetContractForDenom(suite.ctx, denom1, autoContract) 166 suite.Require().NoError(err) 167 err = keeper.SetContractForDenom(suite.ctx, denom2, externalContract) 168 suite.Require().NoError(err) 169 out := keeper.GetContracts(suite.ctx) 170 suite.Require().Equal(out[0].Contract, autoContract.String()) 171 suite.Require().Equal(out[1].Contract, externalContract.String()) 172 }, 173 }, 174 } 175 176 for _, tc := range testCases { 177 suite.Run(tc.name, func() { 178 suite.SetupTest() 179 tc.malleate() 180 }) 181 } 182 } 183 184 func (suite *KeeperTestSuite) TestProxyContractRedirect() { 185 denom := "testdenom1" 186 addr1 := common.BigToAddress(big.NewInt(2)) 187 188 testCases := []struct { 189 name string 190 malleate func() 191 }{ 192 { 193 "success, proxy contract redirect owner", 194 func() { 195 suite.app.Erc20Keeper.InitInternalTemplateContract(suite.ctx) 196 evmParams := evmtypes.DefaultParams() 197 evmParams.EnableCreate = true 198 evmParams.EnableCall = true 199 suite.app.EvmKeeper.SetParams(suite.ctx, evmParams) 200 suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, denom, addr1) 201 err := suite.app.Erc20Keeper.ProxyContractRedirect(suite.ctx, denom, types.RedirectOwner, addr1) 202 suite.Require().NoError(err) 203 }, 204 }, 205 { 206 "success, proxy contract redirect contract", 207 func() { 208 suite.app.Erc20Keeper.InitInternalTemplateContract(suite.ctx) 209 evmParams := evmtypes.DefaultParams() 210 evmParams.EnableCreate = true 211 evmParams.EnableCall = true 212 suite.app.EvmKeeper.SetParams(suite.ctx, evmParams) 213 suite.app.Erc20Keeper.SetContractForDenom(suite.ctx, denom, addr1) 214 err := suite.app.Erc20Keeper.ProxyContractRedirect(suite.ctx, denom, types.RedirectImplementation, addr1) 215 suite.Require().NoError(err) 216 }, 217 }, 218 } 219 220 for _, tc := range testCases { 221 suite.Run(tc.name, func() { 222 suite.SetupTest() 223 tc.malleate() 224 }) 225 } 226 } 227 228 func (suite *KeeperTestSuite) TestSetGetTemplateContract() { 229 f := func(bin string) string { 230 json := `[{ "inputs": [{"internalType": "uint256","name": "a","type": "uint256" },{ "internalType": "uint256","name": "b","type": "uint256"}],"stateMutability": "nonpayable","type": "constructor"}]` 231 str := fmt.Sprintf(`{"abi":%s,"bin":"%s"}`, json, bin) 232 return str 233 } 234 235 testCases := []struct { 236 name string 237 malleate func() 238 }{ 239 { 240 "success, there is no data ", 241 func() { 242 _, found := suite.app.Erc20Keeper.GetImplementTemplateContract(suite.ctx) 243 suite.Require().Equal(found, false) 244 }, 245 }, 246 { 247 "success,set contract first", 248 func() { 249 c1 := f("c1") 250 err := suite.app.Erc20Keeper.SetTemplateContract(suite.ctx, types.ProposalTypeContextTemplateImpl, c1) 251 suite.Require().NoError(err) 252 c11, found := suite.app.Erc20Keeper.GetImplementTemplateContract(suite.ctx) 253 suite.Require().NoError(err) 254 suite.Require().Equal(found, true) 255 suite.Require().NotEqual(c11, types.ModuleERC20Contract) 256 suite.Require().Equal(c11.Bin, "c1") 257 }, 258 }, 259 { 260 "success, set contract twice", 261 func() { 262 c1 := f("c1") 263 c2 := f("c2") 264 err := suite.app.Erc20Keeper.SetTemplateContract(suite.ctx, types.ProposalTypeContextTemplateImpl, c1) 265 suite.Require().NoError(err) 266 err = suite.app.Erc20Keeper.SetTemplateContract(suite.ctx, types.ProposalTypeContextTemplateImpl, c2) 267 suite.Require().NoError(err) 268 c11, found := suite.app.Erc20Keeper.GetImplementTemplateContract(suite.ctx) 269 suite.Require().Equal(found, true) 270 suite.Require().NoError(err) 271 suite.Require().NotEqual(c11, types.ModuleERC20Contract) 272 suite.Require().NotEqual(c11.Bin, "c1") 273 suite.Require().Equal(c11.Bin, "c2") 274 }, 275 }, 276 { 277 "success ,no proxy contract", 278 func() { 279 _, found := suite.app.Erc20Keeper.GetProxyTemplateContract(suite.ctx) 280 suite.Require().Equal(false, found) 281 }, 282 }, 283 { 284 "success ,set proxy contract", 285 func() { 286 _, found := suite.app.Erc20Keeper.GetProxyTemplateContract(suite.ctx) 287 suite.Require().Equal(false, found) 288 proxy := f("proxy") 289 suite.app.Erc20Keeper.SetTemplateContract(suite.ctx, types.ProposalTypeContextTemplateProxy, proxy) 290 cc, found := suite.app.Erc20Keeper.GetProxyTemplateContract(suite.ctx) 291 suite.Require().Equal(true, found) 292 suite.Require().Equal(cc.Bin, "proxy") 293 }, 294 }, 295 } 296 297 for _, tc := range testCases { 298 suite.Run(tc.name, func() { 299 suite.SetupTest() 300 tc.malleate() 301 }) 302 } 303 }