package keeper import ( "bytes" "encoding/binary" "encoding/json" "fmt" "os" "testing" "time" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/libs/rand" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/ibc-go/v10/modules/apps/transfer" ibctransfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" ibc "github.com/cosmos/ibc-go/v10/modules/core" ibcapi "github.com/cosmos/ibc-go/v10/modules/core/api" ibcexported "github.com/cosmos/ibc-go/v10/modules/core/exported" ibckeeper "github.com/cosmos/ibc-go/v10/modules/core/keeper" "github.com/stretchr/testify/require" errorsmod "cosmossdk.io/errors" "cosmossdk.io/log" sdkmath "cosmossdk.io/math" "cosmossdk.io/store" storemetrics "cosmossdk.io/store/metrics" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/evidence" evidencetypes "cosmossdk.io/x/evidence/types" "cosmossdk.io/x/feegrant" "cosmossdk.io/x/upgrade" upgradekeeper "cosmossdk.io/x/upgrade/keeper" upgradetypes "cosmossdk.io/x/upgrade/types" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/std" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/module" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" "github.com/cosmos/cosmos-sdk/x/auth" authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" "github.com/cosmos/cosmos-sdk/x/bank" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/crisis" crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" "github.com/cosmos/cosmos-sdk/x/distribution" distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" "github.com/cosmos/cosmos-sdk/x/gov" govclient "github.com/cosmos/cosmos-sdk/x/gov/client" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" "github.com/cosmos/cosmos-sdk/x/mint" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" "github.com/cosmos/cosmos-sdk/x/params" paramsclient "github.com/cosmos/cosmos-sdk/x/params/client" paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/cosmos/cosmos-sdk/x/slashing" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/CosmWasm/wasmd/x/wasm/keeper/testdata" "github.com/CosmWasm/wasmd/x/wasm/keeper/wasmtesting" "github.com/CosmWasm/wasmd/x/wasm/types" ) var moduleBasics = module.NewBasicManager( auth.AppModuleBasic{}, bank.AppModuleBasic{}, staking.AppModuleBasic{}, mint.AppModuleBasic{}, distribution.AppModuleBasic{}, gov.NewAppModuleBasic([]govclient.ProposalHandler{ paramsclient.ProposalHandler, }), params.AppModuleBasic{}, crisis.AppModuleBasic{}, slashing.AppModuleBasic{}, ibc.AppModuleBasic{}, upgrade.AppModuleBasic{}, evidence.AppModuleBasic{}, transfer.AppModuleBasic{}, vesting.AppModuleBasic{}, ) func MakeTestCodec(t testing.TB) codec.Codec { return MakeEncodingConfig(t).Codec } func MakeEncodingConfig(_ testing.TB) moduletestutil.TestEncodingConfig { encodingConfig := moduletestutil.MakeTestEncodingConfig( auth.AppModule{}, bank.AppModule{}, staking.AppModule{}, mint.AppModule{}, slashing.AppModule{}, gov.AppModule{}, crisis.AppModule{}, ibc.AppModule{}, transfer.AppModule{}, vesting.AppModule{}, ) amino := encodingConfig.Amino interfaceRegistry := encodingConfig.InterfaceRegistry std.RegisterInterfaces(interfaceRegistry) moduleBasics.RegisterInterfaces(interfaceRegistry) // add wasmd types types.RegisterInterfaces(interfaceRegistry) types.RegisterLegacyAminoCodec(amino) return encodingConfig } var TestingStakeParams = stakingtypes.Params{ UnbondingTime: 100, MaxValidators: 10, MaxEntries: 10, HistoricalEntries: 10, BondDenom: "stake", MinCommissionRate: stakingtypes.DefaultMinCommissionRate, } type TestFaucet struct { t testing.TB bankKeeper bankkeeper.Keeper sender sdk.AccAddress balance sdk.Coins minterModuleName string } func NewTestFaucet(t testing.TB, ctx sdk.Context, bankKeeper bankkeeper.Keeper, minterModuleName string, initialAmount ...sdk.Coin) *TestFaucet { require.NotEmpty(t, initialAmount) r := &TestFaucet{t: t, bankKeeper: bankKeeper, minterModuleName: minterModuleName} _, addr := keyPubAddr() r.sender = addr r.Mint(ctx, addr, initialAmount...) r.balance = initialAmount return r } func (f *TestFaucet) Mint(parentCtx sdk.Context, addr sdk.AccAddress, amounts ...sdk.Coin) { require.NotEmpty(f.t, amounts) ctx := parentCtx.WithEventManager(sdk.NewEventManager()) // discard all faucet related events err := f.bankKeeper.MintCoins(ctx, f.minterModuleName, amounts) require.NoError(f.t, err) err = f.bankKeeper.SendCoinsFromModuleToAccount(ctx, f.minterModuleName, addr, amounts) require.NoError(f.t, err) f.balance = f.balance.Add(amounts...) } func (f *TestFaucet) Fund(parentCtx sdk.Context, receiver sdk.AccAddress, amounts ...sdk.Coin) { require.NotEmpty(f.t, amounts) // ensure faucet is always filled if !f.balance.IsAllGTE(amounts) { f.Mint(parentCtx, f.sender, amounts...) } ctx := parentCtx.WithEventManager(sdk.NewEventManager()) // discard all faucet related events err := f.bankKeeper.SendCoins(ctx, f.sender, receiver, amounts) require.NoError(f.t, err) f.balance = f.balance.Sub(amounts...) } func (f *TestFaucet) NewFundedRandomAccount(ctx sdk.Context, amounts ...sdk.Coin) sdk.AccAddress { _, addr := keyPubAddr() f.Fund(ctx, addr, amounts...) return addr } type TestKeepers struct { AccountKeeper authkeeper.AccountKeeper StakingKeeper *stakingkeeper.Keeper DistKeeper distributionkeeper.Keeper BankKeeper bankkeeper.Keeper GovKeeper *govkeeper.Keeper ContractKeeper types.ContractOpsKeeper WasmKeeper *Keeper IBCKeeper *ibckeeper.Keeper Router MessageRouter EncodingConfig moduletestutil.TestEncodingConfig Faucet *TestFaucet MultiStore storetypes.CommitMultiStore WasmStoreKey *storetypes.KVStoreKey } // CreateDefaultTestInput common settings for CreateTestInput func CreateDefaultTestInput(t testing.TB) (sdk.Context, TestKeepers) { return CreateTestInput(t, false, []string{"staking"}) } // CreateTestInput encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default) func CreateTestInput(t testing.TB, isCheckTx bool, availableCapabilities []string, opts ...Option) (sdk.Context, TestKeepers) { // Load default wasm config return createTestInput(t, isCheckTx, availableCapabilities, types.DefaultNodeConfig(), types.VMConfig{}, dbm.NewMemDB(), opts...) } // encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default) func createTestInput( t testing.TB, isCheckTx bool, availableCapabilities []string, nodeConfig types.NodeConfig, vmConfig types.VMConfig, db dbm.DB, opts ...Option, ) (sdk.Context, TestKeepers) { tempDir := t.TempDir() keys := storetypes.NewKVStoreKeys( authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distributiontypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibcexported.StoreKey, upgradetypes.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, feegrant.StoreKey, authzkeeper.StoreKey, types.StoreKey, ) logger := log.NewTestLogger(t) ms := store.NewCommitMultiStore(db, logger, storemetrics.NewNoOpMetrics()) for _, v := range keys { ms.MountStoreWithDB(v, storetypes.StoreTypeIAVL, db) } tkeys := storetypes.NewTransientStoreKeys(paramstypes.TStoreKey) for _, v := range tkeys { ms.MountStoreWithDB(v, storetypes.StoreTypeTransient, db) } require.NoError(t, ms.LoadLatestVersion()) ctx := sdk.NewContext(ms, tmproto.Header{ Height: 1234567, Time: time.Date(2020, time.April, 22, 12, 0, 0, 0, time.UTC), }, isCheckTx, log.NewNopLogger()) ctx = types.WithTXCounter(ctx, 0) encodingConfig := MakeEncodingConfig(t) appCodec, legacyAmino := encodingConfig.Codec, encodingConfig.Amino paramsKeeper := paramskeeper.NewKeeper( appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.StoreKey], ) for _, m := range []string{ authtypes.ModuleName, banktypes.ModuleName, stakingtypes.ModuleName, minttypes.ModuleName, distributiontypes.ModuleName, slashingtypes.ModuleName, crisistypes.ModuleName, ibctransfertypes.ModuleName, ibcexported.ModuleName, govtypes.ModuleName, types.ModuleName, } { paramsKeeper.Subspace(m) } subspace := func(m string) paramstypes.Subspace { r, ok := paramsKeeper.GetSubspace(m) require.True(t, ok) return r } maccPerms := map[string][]string{ // module account permissions authtypes.FeeCollectorName: nil, distributiontypes.ModuleName: nil, minttypes.ModuleName: {authtypes.Minter}, stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, govtypes.ModuleName: {authtypes.Burner}, ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, types.ModuleName: {authtypes.Burner}, } accountKeeper := authkeeper.NewAccountKeeper( appCodec, runtime.NewKVStoreService(keys[authtypes.StoreKey]), authtypes.ProtoBaseAccount, maccPerms, authcodec.NewBech32Codec(sdk.Bech32MainPrefix), sdk.Bech32MainPrefix, authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) blockedAddrs := make(map[string]bool) for acc := range maccPerms { blockedAddrs[authtypes.NewModuleAddress(acc).String()] = true } require.NoError(t, accountKeeper.Params.Set(ctx, authtypes.DefaultParams())) bankKeeper := bankkeeper.NewBaseKeeper( appCodec, runtime.NewKVStoreService(keys[banktypes.StoreKey]), accountKeeper, blockedAddrs, authtypes.NewModuleAddress(banktypes.ModuleName).String(), logger, ) require.NoError(t, bankKeeper.SetParams(ctx, banktypes.DefaultParams())) stakingKeeper := stakingkeeper.NewKeeper( appCodec, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), accountKeeper, bankKeeper, authtypes.NewModuleAddress(stakingtypes.ModuleName).String(), authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), ) stakingtypes.DefaultParams() require.NoError(t, stakingKeeper.SetParams(ctx, TestingStakeParams)) distKeeper := distributionkeeper.NewKeeper( appCodec, runtime.NewKVStoreService(keys[distributiontypes.StoreKey]), accountKeeper, bankKeeper, stakingKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(distributiontypes.ModuleName).String(), ) require.NoError(t, distKeeper.Params.Set(ctx, distributiontypes.DefaultParams())) require.NoError(t, distKeeper.FeePool.Set(ctx, distributiontypes.InitialFeePool())) stakingKeeper.SetHooks(distKeeper.Hooks()) upgradeKeeper := upgradekeeper.NewKeeper( map[int64]bool{}, runtime.NewKVStoreService(keys[upgradetypes.StoreKey]), appCodec, tempDir, nil, authtypes.NewModuleAddress(upgradetypes.ModuleName).String(), ) faucet := NewTestFaucet(t, ctx, bankKeeper, minttypes.ModuleName, sdk.NewCoin("stake", sdkmath.NewInt(100_000_000_000))) // set some funds to pay out validators, based on code from: // https://github.com/cosmos/cosmos-sdk/blob/fea231556aee4d549d7551a6190389c4328194eb/x/distribution/keeper/keeper_test.go#L50-L57 distrAcc := distKeeper.GetDistributionAccount(ctx) faucet.Fund(ctx, distrAcc.GetAddress(), sdk.NewCoin("stake", sdkmath.NewInt(2000000))) accountKeeper.SetModuleAccount(ctx, distrAcc) ibcKeeper := ibckeeper.NewKeeper( appCodec, runtime.NewKVStoreService(keys[ibcexported.StoreKey]), subspace(ibcexported.ModuleName), upgradeKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) querier := baseapp.NewGRPCQueryRouter() querier.SetInterfaceRegistry(encodingConfig.InterfaceRegistry) msgRouter := baseapp.NewMsgServiceRouter() msgRouter.SetInterfaceRegistry(encodingConfig.InterfaceRegistry) cfg := sdk.GetConfig() cfg.SetAddressVerifier(types.VerifyAddressLen()) keeper := NewKeeper( appCodec, runtime.NewKVStoreService(keys[types.StoreKey]), accountKeeper, bankKeeper, stakingKeeper, distributionkeeper.NewQuerier(distKeeper), ibcKeeper.ChannelKeeper, // ICS4Wrapper ibcKeeper.ChannelKeeper, ibcKeeper.ChannelKeeperV2, wasmtesting.MockIBCTransferKeeper{}, msgRouter, querier, tempDir, nodeConfig, vmConfig, availableCapabilities, authtypes.NewModuleAddress(govtypes.ModuleName).String(), ibcapi.NewRouter(), opts..., ) require.NoError(t, keeper.SetParams(ctx, types.DefaultParams())) // add wasm handler so we can loop-back (contracts calling contracts) contractKeeper := NewDefaultPermissionKeeper(&keeper) govKeeper := govkeeper.NewKeeper( appCodec, runtime.NewKVStoreService(keys[govtypes.StoreKey]), accountKeeper, bankKeeper, stakingKeeper, distKeeper, msgRouter, govtypes.DefaultConfig(), authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) require.NoError(t, govKeeper.Params.Set(ctx, govv1.DefaultParams())) am := module.NewManager( // minimal module set that we use for message/ query tests bank.NewAppModule(appCodec, bankKeeper, accountKeeper, subspace(banktypes.ModuleName)), staking.NewAppModule(appCodec, stakingKeeper, accountKeeper, bankKeeper, subspace(stakingtypes.ModuleName)), distribution.NewAppModule(appCodec, distKeeper, accountKeeper, bankKeeper, stakingKeeper, subspace(distributiontypes.ModuleName)), gov.NewAppModule(appCodec, govKeeper, accountKeeper, bankKeeper, subspace(govtypes.ModuleName)), ) am.RegisterServices(module.NewConfigurator(appCodec, msgRouter, querier)) //nolint:errcheck types.RegisterMsgServer(msgRouter, NewMsgServerImpl(&keeper)) types.RegisterQueryServer(querier, NewGrpcQuerier(appCodec, runtime.NewKVStoreService(keys[types.ModuleName]), keeper, keeper.queryGasLimit)) keepers := TestKeepers{ AccountKeeper: accountKeeper, StakingKeeper: stakingKeeper, DistKeeper: distKeeper, ContractKeeper: contractKeeper, WasmKeeper: &keeper, BankKeeper: bankKeeper, GovKeeper: govKeeper, IBCKeeper: ibcKeeper, Router: msgRouter, EncodingConfig: encodingConfig, Faucet: faucet, MultiStore: ms, WasmStoreKey: keys[types.StoreKey], } return ctx, keepers } // TestHandler returns a wasm handler for tests (to avoid circular imports) func TestHandler(k types.ContractOpsKeeper) MessageRouter { return MessageRouterFunc(func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { case *types.MsgStoreCode: return handleStoreCode(ctx, k, msg) case *types.MsgInstantiateContract: return handleInstantiate(ctx, k, msg) case *types.MsgExecuteContract: return handleExecute(ctx, k, msg) default: errMsg := fmt.Sprintf("unrecognized wasm message type: %T", msg) return nil, errorsmod.Wrap(sdkerrors.ErrUnknownRequest, errMsg) } }) } var _ MessageRouter = MessageRouterFunc(nil) type MessageRouterFunc func(ctx sdk.Context, req sdk.Msg) (*sdk.Result, error) func (m MessageRouterFunc) Handler(_ sdk.Msg) baseapp.MsgServiceHandler { return m } func handleStoreCode(ctx sdk.Context, k types.ContractOpsKeeper, msg *types.MsgStoreCode) (*sdk.Result, error) { senderAddr, err := sdk.AccAddressFromBech32(msg.Sender) if err != nil { return nil, errorsmod.Wrap(err, "sender") } codeID, _, err := k.Create(ctx, senderAddr, msg.WASMByteCode, msg.InstantiatePermission) if err != nil { return nil, err } return &sdk.Result{ Data: []byte(fmt.Sprintf("%d", codeID)), Events: ctx.EventManager().ABCIEvents(), }, nil } func handleInstantiate(ctx sdk.Context, k types.ContractOpsKeeper, msg *types.MsgInstantiateContract) (*sdk.Result, error) { senderAddr, err := sdk.AccAddressFromBech32(msg.Sender) if err != nil { return nil, errorsmod.Wrap(err, "sender") } var adminAddr sdk.AccAddress if msg.Admin != "" { if adminAddr, err = sdk.AccAddressFromBech32(msg.Admin); err != nil { return nil, errorsmod.Wrap(err, "admin") } } contractAddr, _, err := k.Instantiate(ctx, msg.CodeID, senderAddr, adminAddr, msg.Msg, msg.Label, msg.Funds) if err != nil { return nil, err } return &sdk.Result{ Data: contractAddr, Events: ctx.EventManager().Events().ToABCIEvents(), }, nil } func handleExecute(ctx sdk.Context, k types.ContractOpsKeeper, msg *types.MsgExecuteContract) (*sdk.Result, error) { senderAddr, err := sdk.AccAddressFromBech32(msg.Sender) if err != nil { return nil, errorsmod.Wrap(err, "sender") } contractAddr, err := sdk.AccAddressFromBech32(msg.Contract) if err != nil { return nil, errorsmod.Wrap(err, "admin") } data, err := k.Execute(ctx, contractAddr, senderAddr, msg.Msg, msg.Funds) if err != nil { return nil, err } return &sdk.Result{ Data: data, Events: ctx.EventManager().Events().ToABCIEvents(), }, nil } func RandomAccountAddress(_ testing.TB) sdk.AccAddress { _, addr := keyPubAddr() return addr } // DeterministicAccountAddress creates a test address with v repeated to valid address size func DeterministicAccountAddress(_ testing.TB, v byte) sdk.AccAddress { return bytes.Repeat([]byte{v}, address.Len) } func RandomBech32AccountAddress(t testing.TB) string { return RandomAccountAddress(t).String() } type ExampleContract struct { InitialAmount sdk.Coins Creator crypto.PrivKey CreatorAddr sdk.AccAddress CodeID uint64 Checksum []byte } func StoreHackatomExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleContract { return StoreExampleContractWasm(t, ctx, keepers, testdata.HackatomContractWasm()) } func StoreBurnerExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleContract { return StoreExampleContractWasm(t, ctx, keepers, testdata.BurnerContractWasm()) } func StoreIBCReflectContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleContract { return StoreExampleContractWasm(t, ctx, keepers, testdata.IBCReflectContractWasm()) } func StoreReflectContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleContract { return StoreExampleContractWasm(t, ctx, keepers, testdata.ReflectContractWasm()) } func StoreExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers, wasmFile string) ExampleContract { wasmCode, err := os.ReadFile(wasmFile) require.NoError(t, err) return StoreExampleContractWasm(t, ctx, keepers, wasmCode) } func StoreExampleContractWasm(t testing.TB, ctx sdk.Context, keepers TestKeepers, wasmCode []byte) ExampleContract { anyAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 1000)) creator, creatorAddr := keyPubAddr() fundAccounts(t, ctx, keepers.AccountKeeper, keepers.BankKeeper, creatorAddr, anyAmount) codeID, _, err := keepers.ContractKeeper.Create(ctx, creatorAddr, wasmCode, nil) require.NoError(t, err) hash := keepers.WasmKeeper.GetCodeInfo(ctx, codeID).CodeHash return ExampleContract{anyAmount, creator, creatorAddr, codeID, hash} } var wasmIdent = []byte("\x00\x61\x73\x6D") type ExampleContractInstance struct { ExampleContract Contract sdk.AccAddress } // SeedNewContractInstance sets the mock WasmEngine in keeper and calls store + instantiate to init the contract's metadata func SeedNewContractInstance(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmEngine) ExampleContractInstance { t.Helper() exampleContract := StoreRandomContract(t, ctx, keepers, mock) contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, exampleContract.CodeID, exampleContract.CreatorAddr, exampleContract.CreatorAddr, []byte(`{}`), "", nil) require.NoError(t, err) return ExampleContractInstance{ ExampleContract: exampleContract, Contract: contractAddr, } } // StoreRandomContract sets the mock WasmEngine in keeper and calls store func StoreRandomContract(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmEngine) ExampleContract { return StoreRandomContractWithAccessConfig(t, ctx, keepers, mock, nil) } func StoreRandomContractWithAccessConfig( t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmEngine, cfg *types.AccessConfig, ) ExampleContract { t.Helper() anyAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 1000)) creator, creatorAddr := keyPubAddr() fundAccounts(t, ctx, keepers.AccountKeeper, keepers.BankKeeper, creatorAddr, anyAmount) keepers.WasmKeeper.wasmVM = mock wasmCode := append(wasmIdent, rand.Bytes(10)...) codeID, checksum, err := keepers.ContractKeeper.Create(ctx, creatorAddr, wasmCode, cfg) require.NoError(t, err) exampleContract := ExampleContract{InitialAmount: anyAmount, Creator: creator, CreatorAddr: creatorAddr, CodeID: codeID, Checksum: checksum} return exampleContract } type HackatomExampleInstance struct { ExampleContract Contract sdk.AccAddress Verifier crypto.PrivKey VerifierAddr sdk.AccAddress Beneficiary crypto.PrivKey BeneficiaryAddr sdk.AccAddress Label string Deposit sdk.Coins } // InstantiateHackatomExampleContract load and instantiate the "./testdata/hackatom.wasm" contract func InstantiateHackatomExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) HackatomExampleInstance { contract := StoreHackatomExampleContract(t, ctx, keepers) verifier, verifierAddr := keyPubAddr() fundAccounts(t, ctx, keepers.AccountKeeper, keepers.BankKeeper, verifierAddr, contract.InitialAmount) beneficiary, beneficiaryAddr := keyPubAddr() initMsgBz, err := json.Marshal(HackatomExampleInitMsg{ Verifier: verifierAddr, Beneficiary: beneficiaryAddr, }) require.NoError(t, err) initialAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 100)) adminAddr := contract.CreatorAddr label := "hackatom contract" contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, contract.CodeID, contract.CreatorAddr, adminAddr, initMsgBz, label, initialAmount) require.NoError(t, err) return HackatomExampleInstance{ ExampleContract: contract, Contract: contractAddr, Verifier: verifier, VerifierAddr: verifierAddr, Beneficiary: beneficiary, BeneficiaryAddr: beneficiaryAddr, Label: label, Deposit: initialAmount, } } type ExampleInstance struct { ExampleContract Contract sdk.AccAddress Label string Deposit sdk.Coins } // InstantiateReflectExampleContract load and instantiate the "./testdata/reflect_2_0.wasm" contract func InstantiateReflectExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleInstance { example := StoreReflectContract(t, ctx, keepers) initialAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 100)) label := "reflect contract" contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, example.CodeID, example.CreatorAddr, example.CreatorAddr, []byte("{}"), label, initialAmount) require.NoError(t, err) return ExampleInstance{ ExampleContract: example, Contract: contractAddr, Label: label, Deposit: initialAmount, } } // InstantiateReflectExampleContractWithPortID load and instantiate the "./testdata/reflect_2_0.wasm" contract with defined port ID func InstantiateReflectExampleContractWithPortID(t testing.TB, ctx sdk.Context, keepers TestKeepers, portID string) ExampleInstance { example := StoreReflectContract(t, ctx, keepers) initialAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 100)) label := "reflect contract with port id" contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, example.CodeID, example.CreatorAddr, example.CreatorAddr, []byte("{}"), label, initialAmount) require.NoError(t, err) cInfo := keepers.WasmKeeper.GetContractInfo(ctx, contractAddr) cInfo.IBCPortID = portID keepers.WasmKeeper.mustStoreContractInfo(ctx, contractAddr, cInfo) return ExampleInstance{ ExampleContract: example, Contract: contractAddr, Label: label, Deposit: initialAmount, } } type HackatomExampleInitMsg struct { Verifier sdk.AccAddress `json:"verifier"` Beneficiary sdk.AccAddress `json:"beneficiary"` } func (m HackatomExampleInitMsg) GetBytes(t testing.TB) []byte { initMsgBz, err := json.Marshal(m) require.NoError(t, err) return initMsgBz } type IBCReflectExampleInstance struct { Contract sdk.AccAddress Admin sdk.AccAddress CodeID uint64 ReflectCodeID uint64 } func (m IBCReflectExampleInstance) GetBytes(t testing.TB) []byte { initMsgBz, err := json.Marshal(m) require.NoError(t, err) return initMsgBz } // InstantiateIBCReflectContract load and instantiate the "./testdata/ibc_reflect.wasm" contract func InstantiateIBCReflectContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) IBCReflectExampleInstance { reflectID := StoreReflectContract(t, ctx, keepers).CodeID ibcReflectID := StoreIBCReflectContract(t, ctx, keepers).CodeID initMsgBz, err := json.Marshal(IBCReflectInitMsg{ ReflectCodeID: reflectID, }) require.NoError(t, err) adminAddr := RandomAccountAddress(t) contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, ibcReflectID, adminAddr, adminAddr, initMsgBz, "ibc-reflect-factory", nil) require.NoError(t, err) return IBCReflectExampleInstance{ Admin: adminAddr, Contract: contractAddr, CodeID: ibcReflectID, ReflectCodeID: reflectID, } } type IBCReflectInitMsg struct { ReflectCodeID uint64 `json:"reflect_code_id"` } func (m IBCReflectInitMsg) GetBytes(t testing.TB) []byte { initMsgBz, err := json.Marshal(m) require.NoError(t, err) return initMsgBz } type BurnerExampleInitMsg struct { Payout sdk.AccAddress `json:"payout"` Delete uint32 `json:"delete"` } func (m BurnerExampleInitMsg) GetBytes(t testing.TB) []byte { initMsgBz, err := json.Marshal(m) require.NoError(t, err) return initMsgBz } func fundAccounts(t testing.TB, ctx sdk.Context, am authkeeper.AccountKeeper, bank bankkeeper.Keeper, addr sdk.AccAddress, coins sdk.Coins) { acc := am.NewAccountWithAddress(ctx, addr) am.SetAccount(ctx, acc) NewTestFaucet(t, ctx, bank, minttypes.ModuleName, coins...).Fund(ctx, addr, coins...) } var keyCounter uint64 // we need to make this deterministic (same every test run), as encoded address size and thus gas cost, // depends on the actual bytes (due to ugly CanonicalAddress encoding) func keyPubAddr() (crypto.PrivKey, sdk.AccAddress) { keyCounter++ seed := make([]byte, 8) binary.BigEndian.PutUint64(seed, keyCounter) key := ed25519.GenPrivKeyFromSecret(seed) pub := key.PubKey() addr := sdk.AccAddress(pub.Address()) return key, addr }