package keeper import ( "encoding/binary" "encoding/json" "fmt" "github.com/tendermint/tendermint/libs/rand" "io/ioutil" "testing" "time" "github.com/CosmWasm/wasmd/x/wasm/internal/types" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" params2 "github.com/cosmos/cosmos-sdk/simapp/params" "github.com/cosmos/cosmos-sdk/std" "github.com/cosmos/cosmos-sdk/store" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "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/capability" capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" "github.com/cosmos/cosmos-sdk/x/crisis" crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" "github.com/cosmos/cosmos-sdk/x/distribution" distrclient "github.com/cosmos/cosmos-sdk/x/distribution/client" distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" "github.com/cosmos/cosmos-sdk/x/evidence" "github.com/cosmos/cosmos-sdk/x/gov" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" transfer "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer" ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" ibc "github.com/cosmos/cosmos-sdk/x/ibc/core" ibchost "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" ibckeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper" "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" paramproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal" "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/cosmos/cosmos-sdk/x/upgrade" upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" ) var ModuleBasics = module.NewBasicManager( auth.AppModuleBasic{}, bank.AppModuleBasic{}, capability.AppModuleBasic{}, staking.AppModuleBasic{}, mint.AppModuleBasic{}, distribution.AppModuleBasic{}, gov.NewAppModuleBasic( paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, ), params.AppModuleBasic{}, crisis.AppModuleBasic{}, slashing.AppModuleBasic{}, ibc.AppModuleBasic{}, upgrade.AppModuleBasic{}, evidence.AppModuleBasic{}, transfer.AppModuleBasic{}, ) func MakeTestCodec(t *testing.T) codec.Marshaler { return MakeEncodingConfig(t).Marshaler } func MakeEncodingConfig(_ *testing.T) params2.EncodingConfig { amino := codec.NewLegacyAmino() interfaceRegistry := codectypes.NewInterfaceRegistry() marshaler := codec.NewProtoCodec(interfaceRegistry) txCfg := tx.NewTxConfig(marshaler, tx.DefaultSignModes) std.RegisterInterfaces(interfaceRegistry) std.RegisterLegacyAminoCodec(amino) ModuleBasics.RegisterLegacyAminoCodec(amino) ModuleBasics.RegisterInterfaces(interfaceRegistry) return params2.EncodingConfig{ InterfaceRegistry: interfaceRegistry, Marshaler: marshaler, TxConfig: txCfg, Amino: amino, } } var TestingStakeParams = stakingtypes.Params{ UnbondingTime: 100, MaxValidators: 10, MaxEntries: 10, HistoricalEntries: 10, BondDenom: "stake", } type TestKeepers struct { AccountKeeper authkeeper.AccountKeeper StakingKeeper stakingkeeper.Keeper DistKeeper distributionkeeper.Keeper BankKeeper bankkeeper.Keeper GovKeeper govkeeper.Keeper WasmKeeper *Keeper IBCKeeper *ibckeeper.Keeper } // CreateDefaultTestInput common settings for CreateTestInput func CreateDefaultTestInput(t *testing.T) (sdk.Context, TestKeepers) { return CreateTestInput(t, false, "staking", nil, nil) } // encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default) func CreateTestInput(t *testing.T, isCheckTx bool, supportedFeatures string, encoders *MessageEncoders, queriers *QueryPlugins) (sdk.Context, TestKeepers) { tempDir := t.TempDir() keyWasm := sdk.NewKVStoreKey(types.StoreKey) keyAcc := sdk.NewKVStoreKey(authtypes.StoreKey) keyBank := sdk.NewKVStoreKey(banktypes.StoreKey) keyStaking := sdk.NewKVStoreKey(stakingtypes.StoreKey) keyDistro := sdk.NewKVStoreKey(distributiontypes.StoreKey) keyParams := sdk.NewKVStoreKey(paramstypes.StoreKey) tkeyParams := sdk.NewTransientStoreKey(paramstypes.TStoreKey) keyGov := sdk.NewKVStoreKey(govtypes.StoreKey) keyIBC := sdk.NewKVStoreKey(ibchost.StoreKey) keyCapability := sdk.NewKVStoreKey(capabilitytypes.StoreKey) keyCapabilityTransient := storetypes.NewMemoryStoreKey(capabilitytypes.MemStoreKey) db := dbm.NewMemDB() ms := store.NewCommitMultiStore(db) ms.MountStoreWithDB(keyWasm, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyBank, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyStaking, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyDistro, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db) ms.MountStoreWithDB(keyGov, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyIBC, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyCapability, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(keyCapabilityTransient, sdk.StoreTypeMemory, 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()) encodingConfig := MakeEncodingConfig(t) appCodec, legacyAmino := encodingConfig.Marshaler, encodingConfig.Amino paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, keyParams, tkeyParams) paramsKeeper.Subspace(authtypes.ModuleName) paramsKeeper.Subspace(banktypes.ModuleName) paramsKeeper.Subspace(stakingtypes.ModuleName) paramsKeeper.Subspace(minttypes.ModuleName) paramsKeeper.Subspace(distributiontypes.ModuleName) paramsKeeper.Subspace(slashingtypes.ModuleName) paramsKeeper.Subspace(crisistypes.ModuleName) paramsKeeper.Subspace(ibctransfertypes.ModuleName) paramsKeeper.Subspace(capabilitytypes.ModuleName) paramsKeeper.Subspace(ibchost.ModuleName) 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}, } authSubsp, _ := paramsKeeper.GetSubspace(authtypes.ModuleName) authKeeper := authkeeper.NewAccountKeeper( appCodec, keyAcc, // target store authSubsp, authtypes.ProtoBaseAccount, // prototype maccPerms, ) blockedAddrs := make(map[string]bool) for acc := range maccPerms { allowReceivingFunds := acc != distributiontypes.ModuleName blockedAddrs[authtypes.NewModuleAddress(acc).String()] = allowReceivingFunds } bankSubsp, _ := paramsKeeper.GetSubspace(banktypes.ModuleName) bankKeeper := bankkeeper.NewBaseKeeper( appCodec, keyBank, authKeeper, bankSubsp, blockedAddrs, ) bankParams := banktypes.DefaultParams() bankParams = bankParams.SetSendEnabledParam("stake", true) bankKeeper.SetParams(ctx, bankParams) stakingSubsp, _ := paramsKeeper.GetSubspace(stakingtypes.ModuleName) stakingKeeper := stakingkeeper.NewKeeper(appCodec, keyStaking, authKeeper, bankKeeper, stakingSubsp) stakingKeeper.SetParams(ctx, TestingStakeParams) distSubsp, _ := paramsKeeper.GetSubspace(distributiontypes.ModuleName) distKeeper := distributionkeeper.NewKeeper(appCodec, keyDistro, distSubsp, authKeeper, bankKeeper, stakingKeeper, authtypes.FeeCollectorName, nil) distKeeper.SetParams(ctx, distributiontypes.DefaultParams()) stakingKeeper.SetHooks(distKeeper.Hooks()) // set genesis items required for distribution distKeeper.SetFeePool(ctx, distributiontypes.InitialFeePool()) // set some funds ot pay out validatores, based on code from: // https://github.com/cosmos/cosmos-sdk/blob/fea231556aee4d549d7551a6190389c4328194eb/x/distribution/keeper/keeper_test.go#L50-L57 distrAcc := distKeeper.GetDistributionAccount(ctx) err := bankKeeper.SetBalances(ctx, distrAcc.GetAddress(), sdk.NewCoins( sdk.NewCoin("stake", sdk.NewInt(2000000)), )) require.NoError(t, err) authKeeper.SetModuleAccount(ctx, distrAcc) capabilityKeeper := capabilitykeeper.NewKeeper(appCodec, keyCapability, keyCapabilityTransient) scopedIBCKeeper := capabilityKeeper.ScopeToModule(ibchost.ModuleName) scopedWasmKeeper := capabilityKeeper.ScopeToModule(types.ModuleName) ibcSubsp, _ := paramsKeeper.GetSubspace(ibchost.ModuleName) ibcKeeper := ibckeeper.NewKeeper( appCodec, keyIBC, ibcSubsp, stakingKeeper, scopedIBCKeeper, ) router := baseapp.NewRouter() bh := bank.NewHandler(bankKeeper) router.AddRoute(sdk.NewRoute(banktypes.RouterKey, bh)) sh := staking.NewHandler(stakingKeeper) router.AddRoute(sdk.NewRoute(stakingtypes.RouterKey, sh)) dh := distribution.NewHandler(distKeeper) router.AddRoute(sdk.NewRoute(distributiontypes.RouterKey, dh)) // Load default wasm config wasmConfig := types.DefaultWasmConfig() keeper := NewKeeper( appCodec, keyWasm, paramsKeeper.Subspace(types.DefaultParamspace), authKeeper, bankKeeper, stakingKeeper, distKeeper, ibcKeeper.ChannelKeeper, &ibcKeeper.PortKeeper, scopedWasmKeeper, router, tempDir, wasmConfig, supportedFeatures, encoders, queriers, ) keeper.setParams(ctx, types.DefaultParams()) // add wasm handler so we can loop-back (contracts calling contracts) router.AddRoute(sdk.NewRoute(types.RouterKey, TestHandler(&keeper))) govRouter := govtypes.NewRouter(). AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(paramsKeeper)). AddRoute(distributiontypes.RouterKey, distribution.NewCommunityPoolSpendProposalHandler(distKeeper)). AddRoute(types.RouterKey, NewWasmProposalHandler(keeper, types.EnableAllProposals)) govKeeper := govkeeper.NewKeeper( appCodec, keyGov, paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govtypes.ParamKeyTable()), authKeeper, bankKeeper, stakingKeeper, govRouter, ) govKeeper.SetProposalID(ctx, govtypes.DefaultStartingProposalID) govKeeper.SetDepositParams(ctx, govtypes.DefaultDepositParams()) govKeeper.SetVotingParams(ctx, govtypes.DefaultVotingParams()) govKeeper.SetTallyParams(ctx, govtypes.DefaultTallyParams()) keepers := TestKeepers{ AccountKeeper: authKeeper, StakingKeeper: stakingKeeper, DistKeeper: distKeeper, WasmKeeper: &keeper, BankKeeper: bankKeeper, GovKeeper: govKeeper, IBCKeeper: ibcKeeper, } return ctx, keepers } // TestHandler returns a wasm handler for tests (to avoid circular imports) func TestHandler(k *Keeper) sdk.Handler { return 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, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) } } } func handleStoreCode(ctx sdk.Context, k *Keeper, msg *types.MsgStoreCode) (*sdk.Result, error) { senderAddr, err := sdk.AccAddressFromBech32(msg.Sender) if err != nil { return nil, sdkerrors.Wrap(err, "sender") } codeID, err := k.Create(ctx, senderAddr, msg.WASMByteCode, msg.Source, msg.Builder, 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 *Keeper, msg *types.MsgInstantiateContract) (*sdk.Result, error) { senderAddr, err := sdk.AccAddressFromBech32(msg.Sender) if err != nil { return nil, sdkerrors.Wrap(err, "sender") } var adminAddr sdk.AccAddress if msg.Admin != "" { if adminAddr, err = sdk.AccAddressFromBech32(msg.Admin); err != nil { return nil, sdkerrors.Wrap(err, "admin") } } contractAddr, err := k.Instantiate(ctx, msg.CodeID, senderAddr, adminAddr, msg.InitMsg, 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 *Keeper, msg *types.MsgExecuteContract) (*sdk.Result, error) { senderAddr, err := sdk.AccAddressFromBech32(msg.Sender) if err != nil { return nil, sdkerrors.Wrap(err, "sender") } contractAddr, err := sdk.AccAddressFromBech32(msg.Contract) if err != nil { return nil, sdkerrors.Wrap(err, "admin") } res, err := k.Execute(ctx, contractAddr, senderAddr, msg.Msg, msg.Funds) if err != nil { return nil, err } res.Events = ctx.EventManager().Events().ToABCIEvents() return res, nil } func RandomAccountAddress(_ *testing.T) sdk.AccAddress { _, _, addr := keyPubAddr() return addr } func RandomBech32AccountAddress(t *testing.T) string { return RandomAccountAddress(t).String() } type ExampleContract struct { InitialAmount sdk.Coins Creator crypto.PrivKey CreatorAddr sdk.AccAddress CodeID uint64 } func StoreHackatomExampleContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) ExampleContract { return StoreExampleContract(t, ctx, keepers, "./testdata/hackatom.wasm") } func StoreBurnerExampleContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) ExampleContract { return StoreExampleContract(t, ctx, keepers, "./testdata/burner.wasm") } func StoreIBCReflectContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) ExampleContract { return StoreExampleContract(t, ctx, keepers, "./testdata/ibc_reflect.wasm") } func StoreReflectContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) uint64 { wasmCode, err := ioutil.ReadFile("./testdata/reflect.wasm") require.NoError(t, err) _, _, creatorAddr := keyPubAddr() codeID, err := keepers.WasmKeeper.Create(ctx, creatorAddr, wasmCode, "", "", nil) require.NoError(t, err) return codeID } func StoreExampleContract(t *testing.T, ctx sdk.Context, keepers TestKeepers, wasmFile string) ExampleContract { anyAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 1000)) creator, _, creatorAddr := keyPubAddr() fundAccounts(t, ctx, keepers.AccountKeeper, keepers.BankKeeper, creatorAddr, anyAmount) wasmCode, err := ioutil.ReadFile(wasmFile) require.NoError(t, err) codeID, err := keepers.WasmKeeper.Create(ctx, creatorAddr, wasmCode, "", "", nil) require.NoError(t, err) return ExampleContract{anyAmount, creator, creatorAddr, codeID} } var wasmIdent = []byte("\x00\x61\x73\x6D") type ExampleContractInstance struct { ExampleContract Contract sdk.AccAddress } // SeedNewContractInstance sets the mock wasmerEngine in keeper and calls store + instantiate to init the contract's metadata func SeedNewContractInstance(t *testing.T, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) ExampleContractInstance { anyAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 1000)) creator, _, creatorAddr := keyPubAddr() fundAccounts(t, ctx, keepers.AccountKeeper, keepers.BankKeeper, creatorAddr, anyAmount) keepers.WasmKeeper.wasmer = mock wasmCode := append(wasmIdent, rand.Bytes(10)...) codeID, err := keepers.WasmKeeper.Create(ctx, creatorAddr, wasmCode, "", "", nil) require.NoError(t, err) contractAddr, err := keepers.WasmKeeper.Instantiate(ctx, codeID, creatorAddr, creatorAddr, []byte(`{}`), "", nil) require.NoError(t, err) return ExampleContractInstance{ ExampleContract: ExampleContract{InitialAmount: anyAmount, Creator: creator, CreatorAddr: creatorAddr, CodeID: codeID}, Contract: contractAddr, } } type HackatomExampleInstance struct { ExampleContract Contract sdk.AccAddress Verifier crypto.PrivKey VerifierAddr sdk.AccAddress Beneficiary crypto.PrivKey BeneficiaryAddr sdk.AccAddress } // InstantiateHackatomExampleContract load and instantiate the "./testdata/hackatom.wasm" contract func InstantiateHackatomExampleContract(t *testing.T, 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 := HackatomExampleInitMsg{ Verifier: verifierAddr, Beneficiary: beneficiaryAddr, }.GetBytes(t) initialAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 100)) adminAddr := contract.CreatorAddr contractAddr, err := keepers.WasmKeeper.Instantiate(ctx, contract.CodeID, contract.CreatorAddr, adminAddr, initMsgBz, "demo contract to query", initialAmount) require.NoError(t, err) return HackatomExampleInstance{ ExampleContract: contract, Contract: contractAddr, Verifier: verifier, VerifierAddr: verifierAddr, Beneficiary: beneficiary, BeneficiaryAddr: beneficiaryAddr, } } type HackatomExampleInitMsg struct { Verifier sdk.AccAddress `json:"verifier"` Beneficiary sdk.AccAddress `json:"beneficiary"` } func (m HackatomExampleInitMsg) GetBytes(t *testing.T) []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 } // InstantiateIBCReflectContract load and instantiate the "./testdata/ibc_reflect.wasm" contract func InstantiateIBCReflectContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) IBCReflectExampleInstance { reflectID := StoreReflectContract(t, ctx, keepers) ibcReflectID := StoreIBCReflectContract(t, ctx, keepers).CodeID initMsgBz := IBCReflectInitMsg{ ReflectCodeID: reflectID, }.GetBytes(t) adminAddr := RandomAccountAddress(t) contractAddr, err := keepers.WasmKeeper.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.T) []byte { initMsgBz, err := json.Marshal(m) require.NoError(t, err) return initMsgBz } type BurnerExampleInitMsg struct { Payout sdk.AccAddress `json:"payout"` } func (m BurnerExampleInitMsg) GetBytes(t *testing.T) []byte { initMsgBz, err := json.Marshal(m) require.NoError(t, err) return initMsgBz } func createFakeFundedAccount(t *testing.T, ctx sdk.Context, am authkeeper.AccountKeeper, bank bankkeeper.Keeper, coins sdk.Coins) sdk.AccAddress { _, _, addr := keyPubAddr() fundAccounts(t, ctx, am, bank, addr, coins) return addr } func fundAccounts(t *testing.T, ctx sdk.Context, am authkeeper.AccountKeeper, bank bankkeeper.Keeper, addr sdk.AccAddress, coins sdk.Coins) { acc := am.NewAccountWithAddress(ctx, addr) am.SetAccount(ctx, acc) require.NoError(t, bank.SetBalances(ctx, addr, coins)) } var keyCounter uint64 = 0 // 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, crypto.PubKey, 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, pub, addr }