laconicd-deprecated/x/wasm/keeper/test_common.go
2023-02-28 15:05:49 +05:30

760 lines
26 KiB
Go

package keeper
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
"os"
"testing"
"time"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/std"
"github.com/cosmos/cosmos-sdk/store"
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"
"github.com/cosmos/cosmos-sdk/x/auth"
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/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"
evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
"github.com/cosmos/cosmos-sdk/x/feegrant"
"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"
"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"
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
"github.com/cosmos/ibc-go/v4/modules/apps/transfer"
ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types"
ibc "github.com/cosmos/ibc-go/v4/modules/core"
ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host"
ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/libs/rand"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
wasmappparams "github.com/cerc-io/laconicd/app/params"
"github.com/cerc-io/laconicd/x/wasm/keeper/wasmtesting"
"github.com/cerc-io/laconicd/x/wasm/types"
)
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{},
vesting.AppModuleBasic{},
)
func MakeTestCodec(t testing.TB) codec.Codec {
return MakeEncodingConfig(t).Marshaler
}
func MakeEncodingConfig(_ testing.TB) wasmappparams.EncodingConfig {
encodingConfig := wasmappparams.MakeEncodingConfig()
amino := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
std.RegisterInterfaces(interfaceRegistry)
std.RegisterLegacyAminoCodec(amino)
moduleBasics.RegisterLegacyAminoCodec(amino)
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",
}
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 *baseapp.Router
EncodingConfig wasmappparams.EncodingConfig
Faucet *TestFaucet
MultiStore sdk.CommitMultiStore
ScopedWasmKeeper capabilitykeeper.ScopedKeeper
}
// CreateDefaultTestInput common settings for CreateTestInput
func CreateDefaultTestInput(t testing.TB) (sdk.Context, TestKeepers) {
return CreateTestInput(t, false, "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.DefaultWasmConfig(), 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,
wasmConfig types.WasmConfig,
db dbm.DB,
opts ...Option,
) (sdk.Context, TestKeepers) {
tempDir := t.TempDir()
keys := sdk.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
minttypes.StoreKey, distributiontypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey,
evidencetypes.StoreKey, ibctransfertypes.StoreKey,
capabilitytypes.StoreKey, feegrant.StoreKey, authzkeeper.StoreKey,
types.StoreKey,
)
ms := store.NewCommitMultiStore(db)
for _, v := range keys {
ms.MountStoreWithDB(v, sdk.StoreTypeIAVL, db)
}
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey)
for _, v := range tkeys {
ms.MountStoreWithDB(v, sdk.StoreTypeTransient, db)
}
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
for _, v := range memKeys {
ms.MountStoreWithDB(v, 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())
ctx = types.WithTXCounter(ctx, 0)
encodingConfig := MakeEncodingConfig(t)
appCodec, legacyAmino := encodingConfig.Marshaler, encodingConfig.Amino
paramsKeeper := paramskeeper.NewKeeper(
appCodec,
legacyAmino,
keys[paramstypes.StoreKey],
tkeys[paramstypes.TStoreKey],
)
for _, m := range []string{
authtypes.ModuleName,
banktypes.ModuleName,
stakingtypes.ModuleName,
minttypes.ModuleName,
distributiontypes.ModuleName,
slashingtypes.ModuleName,
crisistypes.ModuleName,
ibctransfertypes.ModuleName,
capabilitytypes.ModuleName,
ibchost.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,
keys[authtypes.StoreKey], // target store
subspace(authtypes.ModuleName),
authtypes.ProtoBaseAccount, // prototype
maccPerms,
)
blockedAddrs := make(map[string]bool)
for acc := range maccPerms {
blockedAddrs[authtypes.NewModuleAddress(acc).String()] = true
}
bankKeeper := bankkeeper.NewBaseKeeper(
appCodec,
keys[banktypes.StoreKey],
accountKeeper,
subspace(banktypes.ModuleName),
blockedAddrs,
)
bankKeeper.SetParams(ctx, banktypes.DefaultParams())
stakingKeeper := stakingkeeper.NewKeeper(
appCodec,
keys[stakingtypes.StoreKey],
accountKeeper,
bankKeeper,
subspace(stakingtypes.ModuleName),
)
stakingKeeper.SetParams(ctx, TestingStakeParams)
distKeeper := distributionkeeper.NewKeeper(
appCodec,
keys[distributiontypes.StoreKey],
subspace(distributiontypes.ModuleName),
accountKeeper,
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())
upgradeKeeper := upgradekeeper.NewKeeper(
map[int64]bool{},
keys[upgradetypes.StoreKey],
appCodec,
tempDir,
nil,
)
faucet := NewTestFaucet(t, ctx, bankKeeper, minttypes.ModuleName, sdk.NewCoin("stake", sdk.NewInt(100_000_000_000)))
// 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)
faucet.Fund(ctx, distrAcc.GetAddress(), sdk.NewCoin("stake", sdk.NewInt(2000000)))
accountKeeper.SetModuleAccount(ctx, distrAcc)
capabilityKeeper := capabilitykeeper.NewKeeper(
appCodec,
keys[capabilitytypes.StoreKey],
memKeys[capabilitytypes.MemStoreKey],
)
scopedIBCKeeper := capabilityKeeper.ScopeToModule(ibchost.ModuleName)
scopedWasmKeeper := capabilityKeeper.ScopeToModule(types.ModuleName)
ibcKeeper := ibckeeper.NewKeeper(
appCodec,
keys[ibchost.StoreKey],
subspace(ibchost.ModuleName),
stakingKeeper,
upgradeKeeper,
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))
querier := baseapp.NewGRPCQueryRouter()
querier.SetInterfaceRegistry(encodingConfig.InterfaceRegistry)
msgRouter := baseapp.NewMsgServiceRouter()
msgRouter.SetInterfaceRegistry(encodingConfig.InterfaceRegistry)
cfg := sdk.GetConfig()
cfg.SetAddressVerifier(types.VerifyAddressLen())
keeper := NewKeeper(
appCodec,
keys[types.StoreKey],
subspace(types.ModuleName),
accountKeeper,
bankKeeper,
stakingKeeper,
distKeeper,
ibcKeeper.ChannelKeeper,
&ibcKeeper.PortKeeper,
scopedWasmKeeper,
wasmtesting.MockIBCTransferKeeper{},
msgRouter,
querier,
tempDir,
wasmConfig,
availableCapabilities,
opts...,
)
keeper.SetParams(ctx, types.DefaultParams())
// add wasm handler so we can loop-back (contracts calling contracts)
contractKeeper := NewDefaultPermissionKeeper(&keeper)
router.AddRoute(sdk.NewRoute(types.RouterKey, TestHandler(contractKeeper)))
am := module.NewManager( // minimal module set that we use for message/ query tests
bank.NewAppModule(appCodec, bankKeeper, accountKeeper),
staking.NewAppModule(appCodec, stakingKeeper, accountKeeper, bankKeeper),
distribution.NewAppModule(appCodec, distKeeper, accountKeeper, bankKeeper, stakingKeeper),
)
am.RegisterServices(module.NewConfigurator(appCodec, msgRouter, querier))
types.RegisterMsgServer(msgRouter, NewMsgServerImpl(NewDefaultPermissionKeeper(keeper)))
types.RegisterQueryServer(querier, NewGrpcQuerier(appCodec, keys[types.ModuleName], keeper, keeper.queryGasLimit))
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,
keys[govtypes.StoreKey],
subspace(govtypes.ModuleName).WithKeyTable(govtypes.ParamKeyTable()),
accountKeeper,
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: accountKeeper,
StakingKeeper: stakingKeeper,
DistKeeper: distKeeper,
ContractKeeper: contractKeeper,
WasmKeeper: &keeper,
BankKeeper: bankKeeper,
GovKeeper: govKeeper,
IBCKeeper: ibcKeeper,
Router: router,
EncodingConfig: encodingConfig,
Faucet: faucet,
MultiStore: ms,
ScopedWasmKeeper: scopedWasmKeeper,
}
return ctx, keepers
}
// TestHandler returns a wasm handler for tests (to avoid circular imports)
func TestHandler(k types.ContractOpsKeeper) 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 types.ContractOpsKeeper, 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.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, 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.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, sdkerrors.Wrap(err, "sender")
}
contractAddr, err := sdk.AccAddressFromBech32(msg.Contract)
if err != nil {
return nil, sdkerrors.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 StoreExampleContract(t, ctx, keepers, "./testdata/hackatom.wasm")
}
func StoreBurnerExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleContract {
return StoreExampleContract(t, ctx, keepers, "./testdata/burner.wasm")
}
func StoreIBCReflectContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleContract {
return StoreExampleContract(t, ctx, keepers, "./testdata/ibc_reflect.wasm")
}
func StoreReflectContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleContract {
return StoreExampleContract(t, ctx, keepers, "./testdata/reflect.wasm")
}
func StoreExampleContract(t testing.TB, 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 := os.ReadFile(wasmFile)
require.NoError(t, err)
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 wasmerEngine in keeper and calls store + instantiate to init the contract's metadata
func SeedNewContractInstance(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) 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 wasmerEngine in keeper and calls store
func StoreRandomContract(t testing.TB, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) ExampleContract {
return StoreRandomContractWithAccessConfig(t, ctx, keepers, mock, nil)
}
func StoreRandomContractWithAccessConfig(
t testing.TB, ctx sdk.Context,
keepers TestKeepers,
mock types.WasmerEngine,
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)...) //nolint:gocritic
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 := HackatomExampleInitMsg{
Verifier: verifierAddr,
Beneficiary: beneficiaryAddr,
}.GetBytes(t)
initialAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 100))
adminAddr := contract.CreatorAddr
label := "demo contract to query"
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.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 := "demo contract to query"
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,
}
}
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
}
// 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 := IBCReflectInitMsg{
ReflectCodeID: reflectID,
}.GetBytes(t)
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"`
}
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, 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
}