github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/wasm/keeper/test_common.go (about) 1 package keeper 2 3 import ( 4 "encoding/binary" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "testing" 10 "time" 11 12 "github.com/fibonacci-chain/fbc/x/wasm/keeper/testdata" 13 14 fbexchaincodec "github.com/fibonacci-chain/fbc/app/codec" 15 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/baseapp" 16 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client" 17 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 18 interfacetypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec/types" 19 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store" 20 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/mpt" 21 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 22 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 23 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/module" 24 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth" 25 cosmoscryptocodec "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/ibc-tx" 26 ibc_tx "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/ibc-tx" 27 authkeeper "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/keeper" 28 authtypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/types" 29 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/bank" 30 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability" 31 capabilitykeeper "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/keeper" 32 capabilitytypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/types" 33 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/crisis" 34 crisistypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/crisis" 35 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/evidence" 36 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/mint" 37 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/slashing" 38 slashingtypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/slashing" 39 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/supply" 40 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/upgrade" 41 upgradekeeper "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/upgrade" 42 upgradetypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/upgrade" 43 "github.com/fibonacci-chain/fbc/x/ammswap" 44 dex "github.com/fibonacci-chain/fbc/x/dex/types" 45 distr "github.com/fibonacci-chain/fbc/x/distribution" 46 "github.com/fibonacci-chain/fbc/x/erc20" 47 "github.com/fibonacci-chain/fbc/x/evm" 48 "github.com/fibonacci-chain/fbc/x/farm" 49 "github.com/fibonacci-chain/fbc/x/order" 50 "github.com/fibonacci-chain/fbc/x/staking" 51 token "github.com/fibonacci-chain/fbc/x/token/types" 52 53 fbexchain "github.com/fibonacci-chain/fbc/app/types" 54 55 //upgradeclient "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/upgrade/client" 56 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer" 57 ibctransfertypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/types" 58 ibc "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core" 59 ibchost "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host" 60 ibckeeper "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/keeper" 61 tmproto "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 62 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto" 63 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/ed25519" 64 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 65 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/rand" 66 dbm "github.com/fibonacci-chain/fbc/libs/tm-db" 67 "github.com/fibonacci-chain/fbc/x/distribution" 68 distrclient "github.com/fibonacci-chain/fbc/x/distribution/client" 69 distributionkeeper "github.com/fibonacci-chain/fbc/x/distribution/keeper" 70 distributiontypes "github.com/fibonacci-chain/fbc/x/distribution/types" 71 "github.com/fibonacci-chain/fbc/x/gov" 72 govkeeper "github.com/fibonacci-chain/fbc/x/gov/keeper" 73 govtypes "github.com/fibonacci-chain/fbc/x/gov/types" 74 "github.com/fibonacci-chain/fbc/x/params" 75 paramproposal "github.com/fibonacci-chain/fbc/x/params" 76 paramskeeper "github.com/fibonacci-chain/fbc/x/params" 77 paramstypes "github.com/fibonacci-chain/fbc/x/params" 78 paramsclient "github.com/fibonacci-chain/fbc/x/params/client" 79 stakingkeeper "github.com/fibonacci-chain/fbc/x/staking/keeper" 80 stakingtypes "github.com/fibonacci-chain/fbc/x/staking/types" 81 "github.com/fibonacci-chain/fbc/x/wasm/keeper/wasmtesting" 82 "github.com/fibonacci-chain/fbc/x/wasm/types" 83 "github.com/stretchr/testify/require" 84 ) 85 86 // EncodingConfig specifies the concrete encoding types to use for a given app. 87 // This is provided for compatibility between protobuf and amino implementations. 88 type EncodingConfig struct { 89 InterfaceRegistry interfacetypes.InterfaceRegistry 90 Marshaler codec.CodecProxy 91 TxConfig client.TxConfig 92 Amino *codec.Codec 93 } 94 95 var moduleBasics = module.NewBasicManager( 96 auth.AppModuleBasic{}, 97 bank.AppModuleBasic{}, 98 capability.AppModuleBasic{}, 99 staking.AppModuleBasic{}, 100 mint.AppModuleBasic{}, 101 distribution.AppModuleBasic{}, 102 supply.AppModuleBasic{}, 103 gov.NewAppModuleBasic( 104 paramsclient.ProposalHandler, distrclient.ChangeDistributionTypeProposalHandler, 105 paramsclient.ProposalHandler, distrclient.CommunityPoolSpendProposalHandler, 106 ), 107 params.AppModuleBasic{}, 108 crisis.AppModuleBasic{}, 109 slashing.AppModuleBasic{}, 110 ibc.AppModuleBasic{}, 111 upgrade.AppModuleBasic{}, 112 evidence.AppModuleBasic{}, 113 transfer.AppModuleBasic{}, 114 ) 115 116 func MakeTestCodec(t testing.TB) codec.CodecProxy { 117 return MakeEncodingConfig(t).Marshaler 118 } 119 120 func MakeEncodingConfig(_ testing.TB) EncodingConfig { 121 codecProxy, interfaceReg := fbexchaincodec.MakeCodecSuit(moduleBasics) 122 txConfig := ibc_tx.NewTxConfig(codecProxy.GetProtocMarshal(), ibc_tx.DefaultSignModes) 123 encodingConfig := EncodingConfig{ 124 InterfaceRegistry: interfaceReg, 125 Marshaler: *codecProxy, 126 Amino: codecProxy.GetCdc(), 127 TxConfig: txConfig} 128 amino := encodingConfig.Amino 129 interfaceRegistry := encodingConfig.InterfaceRegistry 130 cosmoscryptocodec.PubKeyRegisterInterfaces(interfaceReg) 131 // add wasmd types 132 types.RegisterInterfaces(interfaceRegistry) 133 types.RegisterLegacyAminoCodec(amino) 134 135 return encodingConfig 136 } 137 138 var TestingStakeParams = stakingtypes.Params{ 139 UnbondingTime: 100, 140 MaxValidators: 10, 141 Epoch: 10, 142 MaxValsToAddShares: 1, 143 MinDelegation: sdk.OneDec(), 144 MinSelfDelegation: sdk.OneDec(), 145 HistoricalEntries: 10, 146 } 147 148 type TestFaucet struct { 149 t testing.TB 150 bankKeeper bank.Keeper 151 supplyKeeper supply.Keeper 152 sender sdk.AccAddress 153 balance sdk.Coins 154 minterModuleName string 155 } 156 157 func NewTestFaucet(t testing.TB, ctx sdk.Context, bankKeeper bank.Keeper, supplyKeeper supply.Keeper, minterModuleName string, initialAmount ...sdk.Coin) *TestFaucet { 158 require.NotEmpty(t, initialAmount) 159 r := &TestFaucet{t: t, bankKeeper: bankKeeper, minterModuleName: minterModuleName, supplyKeeper: supplyKeeper} 160 _, _, addr := keyPubAddr() 161 r.sender = addr 162 r.Mint(ctx, addr, initialAmount...) 163 r.balance = initialAmount 164 return r 165 } 166 167 func (f *TestFaucet) Mint(parentCtx sdk.Context, addr sdk.AccAddress, amounts ...sdk.Coin) { 168 require.NotEmpty(f.t, amounts) 169 ctx := parentCtx.SetEventManager(sdk.NewEventManager()) // discard all faucet related events 170 171 err := f.supplyKeeper.MintCoins(*ctx, f.minterModuleName, amounts) 172 require.NoError(f.t, err) 173 err = f.supplyKeeper.SendCoinsFromModuleToAccount(*ctx, f.minterModuleName, addr, amounts) 174 require.NoError(f.t, err) 175 f.balance = f.balance.Add(amounts...) 176 } 177 178 func (f *TestFaucet) Fund(parentCtx sdk.Context, receiver sdk.AccAddress, amounts ...sdk.Coin) { 179 require.NotEmpty(f.t, amounts) 180 // ensure faucet is always filled 181 if !f.balance.IsAllGTE(amounts) { 182 f.Mint(parentCtx, f.sender, amounts...) 183 } 184 ctx := parentCtx.SetEventManager(sdk.NewEventManager()) // discard all faucet related events 185 err := f.bankKeeper.SendCoins(*ctx, f.sender, receiver, amounts) 186 require.NoError(f.t, err) 187 f.balance = f.balance.Sub(amounts) 188 } 189 190 func (f *TestFaucet) NewFundedAccount(ctx sdk.Context, amounts ...sdk.Coin) sdk.AccAddress { 191 _, _, addr := keyPubAddr() 192 f.Fund(ctx, addr, amounts...) 193 return addr 194 } 195 196 type TestKeepers struct { 197 AccountKeeper authkeeper.AccountKeeper 198 supplyKeepr supply.Keeper 199 StakingKeeper stakingkeeper.Keeper 200 DistKeeper distributionkeeper.Keeper 201 BankKeeper bank.Keeper 202 GovKeeper govkeeper.Keeper 203 ContractKeeper types.ContractOpsKeeper 204 WasmKeeper *Keeper 205 IBCKeeper *ibckeeper.Keeper 206 Router *baseapp.Router 207 EncodingConfig EncodingConfig 208 Faucet *TestFaucet 209 MultiStore sdk.CommitMultiStore 210 } 211 212 // CreateDefaultTestInput common settings for CreateTestInput 213 func CreateDefaultTestInput(t testing.TB) (sdk.Context, TestKeepers) { 214 return CreateTestInput(t, false, "staking") 215 } 216 217 // CreateTestInput encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default) 218 func CreateTestInput(t testing.TB, isCheckTx bool, supportedFeatures string, opts ...Option) (sdk.Context, TestKeepers) { 219 // Load default wasm config 220 return createTestInput(t, isCheckTx, supportedFeatures, types.DefaultWasmConfig(), dbm.NewMemDB(), opts...) 221 } 222 223 // encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default) 224 func createTestInput( 225 t testing.TB, 226 isCheckTx bool, 227 supportedFeatures string, 228 wasmConfig types.WasmConfig, 229 db dbm.DB, 230 opts ...Option, 231 ) (sdk.Context, TestKeepers) { 232 tempDir := t.TempDir() 233 t.Cleanup(func() { 234 os.RemoveAll(tempDir) 235 }) 236 237 keys := sdk.NewKVStoreKeys( 238 auth.StoreKey, staking.StoreKey, 239 supply.StoreKey, mint.StoreKey, distr.StoreKey, slashing.StoreKey, 240 gov.StoreKey, params.StoreKey, upgrade.StoreKey, evidence.StoreKey, 241 evm.StoreKey, token.StoreKey, token.KeyLock, dex.StoreKey, dex.TokenPairStoreKey, 242 order.OrderStoreKey, ammswap.StoreKey, farm.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, 243 ibchost.StoreKey, 244 erc20.StoreKey, 245 mpt.StoreKey, 246 types.StoreKey, 247 ) 248 ms := store.NewCommitMultiStore(db) 249 for _, v := range keys { 250 ms.MountStoreWithDB(v, sdk.StoreTypeIAVL, db) 251 } 252 tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) 253 for _, v := range tkeys { 254 ms.MountStoreWithDB(v, sdk.StoreTypeTransient, db) 255 } 256 257 memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) 258 for _, v := range memKeys { 259 ms.MountStoreWithDB(v, sdk.StoreTypeMemory, db) 260 } 261 262 require.NoError(t, ms.LoadLatestVersion()) 263 264 ctx := sdk.NewContext(ms, tmproto.Header{ 265 Height: 1234567, 266 Time: time.Date(2020, time.April, 22, 12, 0, 0, 0, time.UTC), 267 }, isCheckTx, log.NewNopLogger()) 268 ctx = types.WithTXCounter(ctx, 0) 269 270 encodingConfig := MakeEncodingConfig(t) 271 appCodec, legacyAmino := encodingConfig.Marshaler, encodingConfig.Amino 272 273 paramsKeeper := paramskeeper.NewKeeper( 274 legacyAmino, 275 keys[paramstypes.StoreKey], 276 tkeys[paramstypes.TStoreKey], 277 ctx.Logger(), 278 ) 279 for _, m := range []string{authtypes.ModuleName, 280 bank.ModuleName, 281 stakingtypes.ModuleName, 282 mint.ModuleName, 283 distributiontypes.ModuleName, 284 slashingtypes.ModuleName, 285 crisistypes.ModuleName, 286 ibctransfertypes.ModuleName, 287 capabilitytypes.ModuleName, 288 ibchost.ModuleName, 289 govtypes.ModuleName, 290 types.ModuleName, 291 } { 292 paramsKeeper.Subspace(m) 293 } 294 subspace := func(m string) paramstypes.Subspace { 295 r, ok := paramsKeeper.GetSubspace(m) 296 require.True(t, ok) 297 return r 298 } 299 maccPerms := map[string][]string{ // module account permissions 300 auth.FeeCollectorName: nil, 301 distr.ModuleName: nil, 302 mint.ModuleName: {supply.Minter}, 303 staking.BondedPoolName: {supply.Burner, supply.Staking}, 304 staking.NotBondedPoolName: {supply.Burner, supply.Staking}, 305 gov.ModuleName: nil, 306 token.ModuleName: {supply.Minter, supply.Burner}, 307 dex.ModuleName: nil, 308 order.ModuleName: nil, 309 ammswap.ModuleName: {supply.Minter, supply.Burner}, 310 farm.ModuleName: nil, 311 farm.YieldFarmingAccount: nil, 312 farm.MintFarmingAccount: {supply.Burner}, 313 ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, 314 erc20.ModuleName: {authtypes.Minter, authtypes.Burner}, 315 types.ModuleName: nil, 316 } 317 accountKeeper := auth.NewAccountKeeper(legacyAmino, keys[authtypes.StoreKey], keys[mpt.StoreKey], subspace(authtypes.ModuleName), fbexchain.ProtoAccount) 318 blockedAddrs := make(map[string]bool) 319 for acc := range maccPerms { 320 blockedAddrs[authtypes.NewModuleAddress(acc).String()] = true 321 } 322 bankKeeper := bank.NewBaseKeeperWithMarshal( 323 &accountKeeper, &appCodec, subspace(bank.ModuleName), blockedAddrs, 324 ) 325 bankKeeper.SetSendEnabled(ctx, true) 326 327 supplyKeeper := supply.NewKeeper( 328 legacyAmino, keys[supply.StoreKey], &accountKeeper, bank.NewBankKeeperAdapter(bankKeeper), maccPerms, 329 ) 330 stakingKeeper := stakingkeeper.NewKeeper( 331 &appCodec, 332 keys[stakingtypes.StoreKey], 333 supplyKeeper, 334 subspace(stakingtypes.ModuleName), 335 ) 336 stakingKeeper.SetParams(ctx, TestingStakeParams) 337 338 distKeeper := distributionkeeper.NewKeeper( 339 legacyAmino, 340 keys[distributiontypes.StoreKey], 341 subspace(distributiontypes.ModuleName), 342 stakingKeeper, 343 supplyKeeper, 344 authtypes.FeeCollectorName, 345 blockedAddrs, 346 ) 347 distKeeper.SetParams(ctx, distributiontypes.DefaultParams()) 348 stakingKeeper.SetHooks(distKeeper.Hooks()) 349 350 // set genesis items required for distribution 351 distKeeper.SetFeePool(ctx, distributiontypes.InitialFeePool()) 352 353 upgradeKeeper := upgradekeeper.NewKeeper( 354 map[int64]bool{}, 355 keys[upgradetypes.StoreKey], 356 legacyAmino, 357 ) 358 359 faucet := NewTestFaucet(t, ctx, bankKeeper, supplyKeeper, mint.ModuleName, sdk.NewCoin("stake", sdk.NewInt(100_000_000_000))) 360 361 // set some funds ot pay out validatores, based on code from: 362 // https://github.com/fibonacci-chain/fbc/libs/cosmos-sdk/blob/fea231556aee4d549d7551a6190389c4328194eb/x/distribution/keeper/keeper_test.go#L50-L57 363 distrAcc := distKeeper.GetDistributionAccount(ctx) 364 faucet.Fund(ctx, distrAcc.GetAddress(), sdk.NewCoin("stake", sdk.NewInt(2000000))) 365 366 supplyKeeper.SetModuleAccount(ctx, distrAcc) 367 368 capabilityKeeper := capabilitykeeper.NewKeeper( 369 &appCodec, 370 keys[capabilitytypes.StoreKey], 371 memKeys[capabilitytypes.MemStoreKey], 372 ) 373 scopedIBCKeeper := capabilityKeeper.ScopeToModule(ibchost.ModuleName) 374 scopedWasmKeeper := capabilityKeeper.ScopeToModule(types.ModuleName) 375 376 ibcKeeper := ibckeeper.NewKeeper( 377 &appCodec, 378 keys[ibchost.StoreKey], 379 subspace(ibchost.ModuleName), 380 stakingKeeper, 381 upgradeKeeper, 382 &scopedIBCKeeper, 383 encodingConfig.InterfaceRegistry, 384 ) 385 386 router := baseapp.NewRouter() 387 bh := bank.NewHandler(bankKeeper) 388 router.AddRoute(bank.RouterKey, bh) 389 sh := staking.NewHandler(stakingKeeper) 390 router.AddRoute(stakingtypes.RouterKey, sh) 391 dh := distribution.NewHandler(distKeeper) 392 router.AddRoute(distributiontypes.RouterKey, dh) 393 394 querier := baseapp.NewGRPCQueryRouter() 395 querier.SetInterfaceRegistry(encodingConfig.InterfaceRegistry) 396 msgRouter := baseapp.NewMsgServiceRouter() 397 msgRouter.SetInterfaceRegistry(encodingConfig.InterfaceRegistry) 398 399 cfg := sdk.GetConfig() 400 cfg.SetAddressVerifier(types.VerifyAddressLen()) 401 402 keeper := NewKeeper( 403 &appCodec, 404 keys[types.StoreKey], 405 subspace(types.ModuleName), 406 &accountKeeper, 407 bank.NewBankKeeperAdapter(bankKeeper), 408 ibcKeeper.ChannelKeeper, 409 &ibcKeeper.PortKeeper, 410 scopedWasmKeeper, 411 wasmtesting.MockIBCTransferKeeper{}, 412 msgRouter, 413 querier, 414 tempDir, 415 wasmConfig, 416 supportedFeatures, 417 opts..., 418 ) 419 keeper.SetParams(ctx, types.TestParams()) 420 // add wasm handler so we can loop-back (contracts calling contracts) 421 contractKeeper := NewDefaultPermissionKeeper(&keeper) 422 router.AddRoute(types.RouterKey, TestHandler(contractKeeper)) 423 424 am := module.NewManager( // minimal module set that we use for message/ query tests 425 bank.NewAppModule(bankKeeper, accountKeeper, supplyKeeper), 426 staking.NewAppModule(stakingKeeper, accountKeeper, supplyKeeper), 427 distribution.NewAppModule(distKeeper, supplyKeeper), 428 supply.NewAppModule(supplyKeeper, accountKeeper), 429 ) 430 configurator := module.NewConfigurator(legacyAmino, msgRouter, querier) 431 am.RegisterServices(configurator) 432 types.RegisterMsgServer(msgRouter, NewMsgServerImpl(NewDefaultPermissionKeeper(keeper))) 433 types.RegisterQueryServer(querier, NewGrpcQuerier(appCodec, keys[types.ModuleName], keeper, keeper.queryGasLimit)) 434 435 govRouter := gov.NewRouter(). 436 AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). 437 AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(¶msKeeper)). 438 AddRoute(distributiontypes.RouterKey, distribution.NewDistributionProposalHandler(distKeeper)) 439 //AddRoute(types.RouterKey, NewWasmProposalHandler(&keeper, types.EnableAllProposals)) 440 441 govProposalHandlerRouter := govkeeper.NewProposalHandlerRouter() 442 govProposalHandlerRouter.AddRoute(params.RouterKey, ¶msKeeper) 443 444 govKeeper := gov.NewKeeper( 445 legacyAmino, keys[govtypes.StoreKey], paramsKeeper, subspace(govtypes.ModuleName), 446 supplyKeeper, &stakingKeeper, gov.DefaultParamspace, govRouter, 447 bankKeeper, govProposalHandlerRouter, auth.FeeCollectorName, 448 ) 449 450 //govKeeper.SetProposalID(ctx, govtypes.DefaultStartingProposalID) 451 //govKeeper.SetDepositParams(ctx, govtypes.DefaultDepositParams()) 452 //govKeeper.SetVotingParams(ctx, govtypes.DefaultVotingParams()) 453 //govKeeper.SetTallyParams(ctx, govtypes.DefaultTallyParams()) 454 455 keepers := TestKeepers{ 456 AccountKeeper: accountKeeper, 457 StakingKeeper: stakingKeeper, 458 supplyKeepr: supplyKeeper, 459 DistKeeper: distKeeper, 460 ContractKeeper: contractKeeper, 461 WasmKeeper: &keeper, 462 BankKeeper: bankKeeper, 463 GovKeeper: govKeeper, 464 IBCKeeper: ibcKeeper, 465 Router: router, 466 EncodingConfig: encodingConfig, 467 Faucet: faucet, 468 MultiStore: ms, 469 } 470 return ctx, keepers 471 } 472 473 // TestHandler returns a wasm handler for tests (to avoid circular imports) 474 func TestHandler(k types.ContractOpsKeeper) sdk.Handler { 475 return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 476 ctx = *ctx.SetEventManager(sdk.NewEventManager()) 477 switch msg := msg.(type) { 478 case *types.MsgStoreCode: 479 return handleStoreCode(ctx, k, msg) 480 case *types.MsgInstantiateContract: 481 return handleInstantiate(ctx, k, msg) 482 case *types.MsgExecuteContract: 483 return handleExecute(ctx, k, msg) 484 default: 485 errMsg := fmt.Sprintf("unrecognized wasm message type: %T", msg) 486 return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) 487 } 488 } 489 } 490 491 func handleStoreCode(ctx sdk.Context, k types.ContractOpsKeeper, msg *types.MsgStoreCode) (*sdk.Result, error) { 492 senderAddr, err := sdk.AccAddressFromBech32(msg.Sender) 493 if err != nil { 494 return nil, sdkerrors.Wrap(err, "sender") 495 } 496 codeID, err := k.Create(ctx, senderAddr, msg.WASMByteCode, msg.InstantiatePermission) 497 if err != nil { 498 return nil, err 499 } 500 501 return &sdk.Result{ 502 Data: []byte(fmt.Sprintf("%d", codeID)), 503 Events: ctx.EventManager().Events(), 504 }, nil 505 } 506 507 func handleInstantiate(ctx sdk.Context, k types.ContractOpsKeeper, msg *types.MsgInstantiateContract) (*sdk.Result, error) { 508 senderAddr, err := sdk.AccAddressFromBech32(msg.Sender) 509 if err != nil { 510 return nil, sdkerrors.Wrap(err, "sender") 511 } 512 var adminAddr sdk.AccAddress 513 if msg.Admin != "" { 514 if adminAddr, err = sdk.AccAddressFromBech32(msg.Admin); err != nil { 515 return nil, sdkerrors.Wrap(err, "admin") 516 } 517 } 518 519 contractAddr, _, err := k.Instantiate(ctx, msg.CodeID, senderAddr, adminAddr, msg.Msg, msg.Label, sdk.CoinAdaptersToCoins(msg.Funds)) 520 if err != nil { 521 return nil, err 522 } 523 524 return &sdk.Result{ 525 Data: contractAddr, 526 Events: ctx.EventManager().Events(), 527 }, nil 528 } 529 530 func handleExecute(ctx sdk.Context, k types.ContractOpsKeeper, msg *types.MsgExecuteContract) (*sdk.Result, error) { 531 senderAddr, err := sdk.AccAddressFromBech32(msg.Sender) 532 if err != nil { 533 return nil, sdkerrors.Wrap(err, "sender") 534 } 535 contractAddr, err := sdk.AccAddressFromBech32(msg.Contract) 536 if err != nil { 537 return nil, sdkerrors.Wrap(err, "admin") 538 } 539 data, err := k.Execute(ctx, contractAddr, senderAddr, msg.Msg, sdk.CoinAdaptersToCoins(msg.Funds)) 540 if err != nil { 541 return nil, err 542 } 543 544 return &sdk.Result{ 545 Data: data, 546 Events: ctx.EventManager().Events(), 547 }, nil 548 } 549 550 var PubKeyCache = make(map[string]crypto.PubKey) 551 552 func RandomAccountAddress(_ testing.TB) sdk.AccAddress { 553 _, pub, addr := keyPubAddr() 554 PubKeyCache[addr.String()] = pub 555 return addr 556 } 557 558 func RandomBech32AccountAddress(t testing.TB) string { 559 return RandomAccountAddress(t).String() 560 } 561 562 type ExampleContract struct { 563 InitialAmount sdk.Coins 564 Creator crypto.PrivKey 565 CreatorAddr sdk.AccAddress 566 CodeID uint64 567 } 568 569 func StoreHackatomExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleContract { 570 return StoreExampleContract(t, ctx, keepers, "./testdata/hackatom.wasm") 571 } 572 573 func StoreBurnerExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleContract { 574 return StoreExampleContract(t, ctx, keepers, "./testdata/burner.wasm") 575 } 576 577 func StoreIBCReflectContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleContract { 578 return StoreExampleContract(t, ctx, keepers, "./testdata/ibc_reflect.wasm") 579 } 580 581 func StoreReflectContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) uint64 { 582 _, _, creatorAddr := keyPubAddr() 583 codeID, err := keepers.ContractKeeper.Create(ctx, creatorAddr, testdata.ReflectContractWasm(), nil) 584 require.NoError(t, err) 585 return codeID 586 } 587 588 func StoreExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers, wasmFile string) ExampleContract { 589 anyAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 1000)) 590 creator, _, creatorAddr := keyPubAddr() 591 fundAccounts(t, ctx, keepers.AccountKeeper, keepers.BankKeeper, keepers.supplyKeepr, creatorAddr, anyAmount) 592 593 wasmCode, err := ioutil.ReadFile(wasmFile) 594 require.NoError(t, err) 595 596 codeID, err := keepers.ContractKeeper.Create(ctx, creatorAddr, wasmCode, nil) 597 require.NoError(t, err) 598 return ExampleContract{anyAmount, creator, creatorAddr, codeID} 599 } 600 601 var wasmIdent = []byte("\x00\x61\x73\x6D") 602 603 type ExampleContractInstance struct { 604 ExampleContract 605 Contract sdk.AccAddress 606 } 607 608 // SeedNewContractInstance sets the mock wasmerEngine in keeper and calls store + instantiate to init the contract's metadata 609 func SeedNewContractInstance(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) ExampleContractInstance { 610 t.Helper() 611 exampleContract := StoreRandomContract(t, ctx, keepers, mock) 612 contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, exampleContract.CodeID, exampleContract.CreatorAddr, exampleContract.CreatorAddr, []byte(`{}`), "", nil) 613 require.NoError(t, err) 614 return ExampleContractInstance{ 615 ExampleContract: exampleContract, 616 Contract: contractAddr, 617 } 618 } 619 620 // StoreRandomContract sets the mock wasmerEngine in keeper and calls store 621 func StoreRandomContract(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) ExampleContract { 622 return StoreRandomContractWithAccessConfig(t, ctx, keepers, mock, nil) 623 } 624 625 func StoreRandomContractWithAccessConfig( 626 t testing.TB, ctx sdk.Context, 627 keepers TestKeepers, 628 mock types.WasmerEngine, 629 cfg *types.AccessConfig, 630 ) ExampleContract { 631 t.Helper() 632 anyAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 1000)) 633 creator, _, creatorAddr := keyPubAddr() 634 fundAccounts(t, ctx, keepers.AccountKeeper, keepers.BankKeeper, keepers.supplyKeepr, creatorAddr, anyAmount) 635 keepers.WasmKeeper.wasmVM = mock 636 wasmCode := append(wasmIdent, rand.Bytes(10)...) //nolint:gocritic 637 codeID, err := keepers.ContractKeeper.Create(ctx, creatorAddr, wasmCode, cfg) 638 require.NoError(t, err) 639 exampleContract := ExampleContract{InitialAmount: anyAmount, Creator: creator, CreatorAddr: creatorAddr, CodeID: codeID} 640 return exampleContract 641 } 642 643 type HackatomExampleInstance struct { 644 ExampleContract 645 Contract sdk.AccAddress 646 Verifier crypto.PrivKey 647 VerifierAddr sdk.AccAddress 648 Beneficiary crypto.PrivKey 649 BeneficiaryAddr sdk.AccAddress 650 } 651 652 // InstantiateHackatomExampleContract load and instantiate the "./testdata/hackatom.wasm" contract 653 func InstantiateHackatomExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) HackatomExampleInstance { 654 contract := StoreHackatomExampleContract(t, ctx, keepers) 655 656 verifier, _, verifierAddr := keyPubAddr() 657 fundAccounts(t, ctx, keepers.AccountKeeper, keepers.BankKeeper, keepers.supplyKeepr, verifierAddr, contract.InitialAmount) 658 659 beneficiary, _, beneficiaryAddr := keyPubAddr() 660 initMsgBz := HackatomExampleInitMsg{ 661 Verifier: verifierAddr, 662 Beneficiary: beneficiaryAddr, 663 }.GetBytes(t) 664 initialAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 100)) 665 666 adminAddr := contract.CreatorAddr 667 contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, contract.CodeID, contract.CreatorAddr, adminAddr, initMsgBz, "demo contract to query", initialAmount) 668 require.NoError(t, err) 669 return HackatomExampleInstance{ 670 ExampleContract: contract, 671 Contract: contractAddr, 672 Verifier: verifier, 673 VerifierAddr: verifierAddr, 674 Beneficiary: beneficiary, 675 BeneficiaryAddr: beneficiaryAddr, 676 } 677 } 678 679 type HackatomExampleInitMsg struct { 680 Verifier sdk.AccAddress `json:"verifier"` 681 Beneficiary sdk.AccAddress `json:"beneficiary"` 682 } 683 684 func (m HackatomExampleInitMsg) GetBytes(t testing.TB) []byte { 685 initMsgBz, err := json.Marshal(m) 686 require.NoError(t, err) 687 return initMsgBz 688 } 689 690 type IBCReflectExampleInstance struct { 691 Contract sdk.AccAddress 692 Admin sdk.AccAddress 693 CodeID uint64 694 ReflectCodeID uint64 695 } 696 697 // InstantiateIBCReflectContract load and instantiate the "./testdata/ibc_reflect.wasm" contract 698 func InstantiateIBCReflectContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) IBCReflectExampleInstance { 699 reflectID := StoreReflectContract(t, ctx, keepers) 700 ibcReflectID := StoreIBCReflectContract(t, ctx, keepers).CodeID 701 702 initMsgBz := IBCReflectInitMsg{ 703 ReflectCodeID: reflectID, 704 }.GetBytes(t) 705 adminAddr := RandomAccountAddress(t) 706 707 contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, ibcReflectID, adminAddr, adminAddr, initMsgBz, "ibc-reflect-factory", nil) 708 require.NoError(t, err) 709 return IBCReflectExampleInstance{ 710 Admin: adminAddr, 711 Contract: contractAddr, 712 CodeID: ibcReflectID, 713 ReflectCodeID: reflectID, 714 } 715 } 716 717 type IBCReflectInitMsg struct { 718 ReflectCodeID uint64 `json:"reflect_code_id"` 719 } 720 721 func (m IBCReflectInitMsg) GetBytes(t testing.TB) []byte { 722 initMsgBz, err := json.Marshal(m) 723 require.NoError(t, err) 724 return initMsgBz 725 } 726 727 type BurnerExampleInitMsg struct { 728 Payout sdk.AccAddress `json:"payout"` 729 } 730 731 func (m BurnerExampleInitMsg) GetBytes(t testing.TB) []byte { 732 initMsgBz, err := json.Marshal(m) 733 require.NoError(t, err) 734 return initMsgBz 735 } 736 737 func fundAccounts(t testing.TB, ctx sdk.Context, am authkeeper.AccountKeeper, bank bank.Keeper, supplyKeeper supply.Keeper, addr sdk.AccAddress, coins sdk.Coins) { 738 acc := am.NewAccountWithAddress(ctx, addr) 739 am.SetAccount(ctx, acc) 740 NewTestFaucet(t, ctx, bank, supplyKeeper, mint.ModuleName, coins...).Fund(ctx, addr, coins...) 741 } 742 743 var keyCounter uint64 744 745 // we need to make this deterministic (same every test run), as encoded address size and thus gas cost, 746 // depends on the actual bytes (due to ugly CanonicalAddress encoding) 747 func keyPubAddr() (crypto.PrivKey, crypto.PubKey, sdk.AccAddress) { 748 keyCounter++ 749 seed := make([]byte, 8) 750 binary.BigEndian.PutUint64(seed, keyCounter) 751 752 key := ed25519.GenPrivKeyFromSecret(seed) 753 pub := key.PubKey() 754 addr := sdk.AccAddress(pub.Address()) 755 return key, pub, addr 756 }