Make contract addresses predictable

This commit is contained in:
Alex Peters 2022-08-26 15:06:03 +02:00
parent d9f9f91d13
commit ccb2fdd0b6
No known key found for this signature in database
GPG Key ID: 55CCC24B5703B7D6
43 changed files with 1169 additions and 507 deletions

View File

@ -71,6 +71,29 @@ func setup(t testing.TB, withGenesis bool, invCheckPeriod uint, opts ...wasm.Opt
return app, GenesisState{}
}
// Setup initializes a new WasmApp with DefaultNodeHome for integration tests
func Setup(isCheckTx bool, opts ...wasm.Option) *WasmApp {
db := dbm.NewMemDB()
app := NewWasmApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 5, MakeEncodingConfig(), wasm.EnableAllProposals, EmptyBaseAppOptions{}, opts)
if !isCheckTx {
genesisState := NewDefaultGenesisState()
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
if err != nil {
panic(err)
}
app.InitChain(
abci.RequestInitChain{
Validators: []abci.ValidatorUpdate{},
ConsensusParams: DefaultConsensusParams,
AppStateBytes: stateBytes,
},
)
}
return app
}
// SetupWithGenesisValSet initializes a new WasmApp with a validator set and genesis accounts
// that also act as delegators. For simplicity, each validator is bonded with a delegation
// of one consensus engine unit (10^6) in the default token of the WasmApp from first genesis

View File

@ -430,6 +430,7 @@ MsgStoreCodeResponse returns store result data.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `code_id` | [uint64](#uint64) | | CodeID is the reference to the stored WASM code |
| `checksum` | [bytes](#bytes) | | Checksum is the sha256 hash of the stored code |

View File

@ -41,6 +41,8 @@ message MsgStoreCode {
message MsgStoreCodeResponse {
// CodeID is the reference to the stored WASM code
uint64 code_id = 1 [ (gogoproto.customname) = "CodeID" ];
// Checksum is the sha256 hash of the stored code
bytes checksum = 2;
}
// MsgInstantiateContract create a new smart contract instance for the given

View File

@ -86,7 +86,6 @@ var (
ErrQueryFailed = types.ErrQueryFailed
ErrInvalidMsg = types.ErrInvalidMsg
KeyLastCodeID = types.KeyLastCodeID
KeyLastInstanceID = types.KeyLastInstanceID
CodeKeyPrefix = types.CodeKeyPrefix
ContractKeyPrefix = types.ContractKeyPrefix
ContractStorePrefix = types.ContractStorePrefix

View File

@ -103,7 +103,7 @@ func GenesisInstantiateContractCmd(defaultNodeHome string, genesisMutator Genesi
}
return genesisMutator.AlterWasmModuleState(cmd, func(state *types.GenesisState, appState map[string]json.RawMessage) error {
// simple sanity check that sender has some balance although it may be consumed by appState previous message already
// simple sanity check that sender has some balance, although it may be consumed by appState previous message already
switch ok, err := hasAccountBalance(cmd, appState, senderAddr, msg.Funds); {
case err != nil:
return err
@ -112,7 +112,7 @@ func GenesisInstantiateContractCmd(defaultNodeHome string, genesisMutator Genesi
}
// does code id exists?
codeInfos, err := GetAllCodes(state)
codeInfos := GetAllCodes(state)
if err != nil {
return err
}
@ -171,7 +171,7 @@ func GenesisExecuteContractCmd(defaultNodeHome string, genesisMutator GenesisMut
}
return genesisMutator.AlterWasmModuleState(cmd, func(state *types.GenesisState, appState map[string]json.RawMessage) error {
// simple sanity check that sender has some balance although it may be consumed by appState previous message already
// simple sanity check that sender has some balance, although it may be consumed by appState previous message already
switch ok, err := hasAccountBalance(cmd, appState, senderAddr, msg.Funds); {
case err != nil:
return err
@ -211,7 +211,7 @@ func GenesisListCodesCmd(defaultNodeHome string, genReader GenesisReader) *cobra
if err != nil {
return err
}
all, err := GetAllCodes(g.WasmModuleState)
all := GetAllCodes(g.WasmModuleState)
if err != nil {
return err
}
@ -236,7 +236,10 @@ func GenesisListContractsCmd(defaultNodeHome string, genReader GenesisReader) *c
return err
}
state := g.WasmModuleState
all := GetAllContracts(state)
all, err := GetAllContracts(state)
if err != nil {
return err
}
return printJSONOutput(cmd, all)
},
}
@ -245,7 +248,7 @@ func GenesisListContractsCmd(defaultNodeHome string, genReader GenesisReader) *c
return cmd
}
// clientCtx marshaller works only with proto or bytes so we marshal the output ourself
// clientCtx marshaller works only with proto or bytes, so we marshal the output ourselves
func printJSONOutput(cmd *cobra.Command, obj interface{}) error {
clientCtx := client.GetClientContextFromCmd(cmd)
bz, err := json.MarshalIndent(obj, "", " ")
@ -260,7 +263,7 @@ type CodeMeta struct {
Info types.CodeInfo `json:"info"`
}
func GetAllCodes(state *types.GenesisState) ([]CodeMeta, error) {
func GetAllCodes(state *types.GenesisState) []CodeMeta {
all := make([]CodeMeta, len(state.Codes))
for i, c := range state.Codes {
all[i] = CodeMeta{
@ -277,10 +280,7 @@ func GetAllCodes(state *types.GenesisState) ([]CodeMeta, error) {
accessConfig = *msg.InstantiatePermission
} else {
// default
creator, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return nil, fmt.Errorf("sender: %s", err)
}
creator := sdk.MustAccAddressFromBech32(msg.Sender)
accessConfig = state.Params.InstantiateDefaultPermission.With(creator)
}
hash := sha256.Sum256(msg.WASMByteCode)
@ -295,7 +295,7 @@ func GetAllCodes(state *types.GenesisState) ([]CodeMeta, error) {
seq++
}
}
return all, nil
return all
}
type ContractMeta struct {
@ -303,7 +303,18 @@ type ContractMeta struct {
Info types.ContractInfo `json:"info"`
}
func GetAllContracts(state *types.GenesisState) []ContractMeta {
// returns nil when not found
func codeHashByID(state *types.GenesisState, codeID uint64) []byte {
codes := GetAllCodes(state)
for _, v := range codes {
if v.CodeID == codeID {
return v.Info.CodeHash
}
}
return nil
}
func GetAllContracts(state *types.GenesisState) ([]ContractMeta, error) {
all := make([]ContractMeta, len(state.Contracts))
for i, c := range state.Contracts {
all[i] = ContractMeta{
@ -312,11 +323,18 @@ func GetAllContracts(state *types.GenesisState) []ContractMeta {
}
}
// add inflight
seq := contractSeqValue(state)
for _, m := range state.GenMsgs {
if msg := m.GetInstantiateContract(); msg != nil {
senderAddr, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
panic(fmt.Sprintf("unsupported address %q: %s", msg.Sender, err))
}
codeHash := codeHashByID(state, msg.CodeID)
if codeHash == nil {
return nil, types.ErrNotFound.Wrapf("hash for code-id: %d", msg.CodeID)
}
all = append(all, ContractMeta{
ContractAddress: keeper.BuildContractAddress(msg.CodeID, seq).String(),
ContractAddress: keeper.BuildContractAddress(codeHash, senderAddr, msg.Label).String(),
Info: types.ContractInfo{
CodeID: msg.CodeID,
Creator: msg.Sender,
@ -324,10 +342,9 @@ func GetAllContracts(state *types.GenesisState) []ContractMeta {
Label: msg.Label,
},
})
seq++
}
}
return all
return all, nil
}
func hasAccountBalance(cmd *cobra.Command, appState map[string]json.RawMessage, sender sdk.AccAddress, coins sdk.Coins) (bool, error) {
@ -354,13 +371,19 @@ func hasContract(state *types.GenesisState, contractAddr string) bool {
return true
}
}
seq := contractSeqValue(state)
for _, m := range state.GenMsgs {
if msg := m.GetInstantiateContract(); msg != nil {
if keeper.BuildContractAddress(msg.CodeID, seq).String() == contractAddr {
senderAddr, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
panic(fmt.Sprintf("unsupported address %q: %s", msg.Sender, err))
}
hash := codeHashByID(state, msg.CodeID)
if hash == nil {
panic(fmt.Sprintf("unknown code id: %d", msg.CodeID))
}
if keeper.BuildContractAddress(hash, senderAddr, msg.Label).String() == contractAddr {
return true
}
seq++
}
}
return false
@ -453,19 +476,6 @@ func (x DefaultGenesisIO) AlterWasmModuleState(cmd *cobra.Command, callback func
return genutil.ExportGenesisFile(g.GenDoc, g.GenesisFile)
}
// contractSeqValue reads the contract sequence from the genesis or
// returns default start value used in the keeper
func contractSeqValue(state *types.GenesisState) uint64 {
var seq uint64 = 1
for _, s := range state.Sequences {
if bytes.Equal(s.IDKey, types.KeyLastInstanceID) {
seq = s.Value
break
}
}
return seq
}
// codeSeqValue reads the code sequence from the genesis or
// returns default start value used in the keeper
func codeSeqValue(state *types.GenesisState) uint64 {

View File

@ -1,12 +1,15 @@
package cli
import (
"bytes"
"context"
"encoding/json"
"os"
"path"
"testing"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/hd"
@ -363,7 +366,8 @@ func TestInstantiateContractCmd(t *testing.T) {
}
func TestExecuteContractCmd(t *testing.T) {
const firstContractAddress = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr"
mySenderAddr := sdk.AccAddress(bytes.Repeat([]byte{1}, address.Len))
myFirstContractAddress := keeper.BuildContractAddress([]byte("myCodeHash"), mySenderAddr, "my").String()
minimalWasmGenesis := types.GenesisState{
Params: types.DefaultParams(),
}
@ -390,7 +394,7 @@ func TestExecuteContractCmd(t *testing.T) {
},
Contracts: []types.Contract{
{
ContractAddress: firstContractAddress,
ContractAddress: myFirstContractAddress,
ContractInfo: types.ContractInfoFixture(func(info *types.ContractInfo) {
info.Created = nil
}),
@ -399,53 +403,34 @@ func TestExecuteContractCmd(t *testing.T) {
},
},
mutator: func(cmd *cobra.Command) {
cmd.SetArgs([]string{firstContractAddress, `{}`})
cmd.SetArgs([]string{myFirstContractAddress, `{}`})
flagSet := cmd.Flags()
flagSet.Set("run-as", myWellFundedAccount)
},
expMsgCount: 1,
},
"all good with contract from genesis store messages without initial sequence": {
"all good with contract from genesis store messages": {
srcGenesis: types.GenesisState{
Params: types.DefaultParams(),
Codes: []types.Code{
{
CodeID: 1,
CodeInfo: types.CodeInfoFixture(),
CodeID: 1,
CodeInfo: types.CodeInfoFixture(func(info *types.CodeInfo) {
info.CodeHash = []byte("myCodeHash")
}),
CodeBytes: wasmIdent,
},
},
GenMsgs: []types.GenesisState_GenMsgs{
{Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: types.MsgInstantiateContractFixture()}},
{Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: types.MsgInstantiateContractFixture(
func(m *types.MsgInstantiateContract) {
m.Sender = mySenderAddr.String()
m.Label = "my"
})}},
},
},
mutator: func(cmd *cobra.Command) {
cmd.SetArgs([]string{firstContractAddress, `{}`})
flagSet := cmd.Flags()
flagSet.Set("run-as", myWellFundedAccount)
},
expMsgCount: 2,
},
"all good with contract from genesis store messages and contract sequence set": {
srcGenesis: types.GenesisState{
Params: types.DefaultParams(),
Codes: []types.Code{
{
CodeID: 1,
CodeInfo: types.CodeInfoFixture(),
CodeBytes: wasmIdent,
},
},
GenMsgs: []types.GenesisState_GenMsgs{
{Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: types.MsgInstantiateContractFixture()}},
},
Sequences: []types.Sequence{
{IDKey: types.KeyLastInstanceID, Value: 100},
},
},
mutator: func(cmd *cobra.Command) {
// See TestBuildContractAddress in keeper_test.go
cmd.SetArgs([]string{"cosmos1mujpjkwhut9yjw4xueyugc02evfv46y0dtmnz4lh8xxkkdapym9stu5qm8", `{}`})
cmd.SetArgs([]string{myFirstContractAddress, `{}`})
flagSet := cmd.Flags()
flagSet.Set("run-as", myWellFundedAccount)
},
@ -472,7 +457,7 @@ func TestExecuteContractCmd(t *testing.T) {
},
Contracts: []types.Contract{
{
ContractAddress: firstContractAddress,
ContractAddress: myFirstContractAddress,
ContractInfo: types.ContractInfoFixture(func(info *types.ContractInfo) {
info.Created = nil
}),
@ -481,7 +466,7 @@ func TestExecuteContractCmd(t *testing.T) {
},
},
mutator: func(cmd *cobra.Command) {
cmd.SetArgs([]string{firstContractAddress, `{}`})
cmd.SetArgs([]string{myFirstContractAddress, `{}`})
flagSet := cmd.Flags()
flagSet.Set("run-as", keeper.RandomBech32AccountAddress(t))
},
@ -499,7 +484,7 @@ func TestExecuteContractCmd(t *testing.T) {
},
Contracts: []types.Contract{
{
ContractAddress: firstContractAddress,
ContractAddress: myFirstContractAddress,
ContractInfo: types.ContractInfoFixture(func(info *types.ContractInfo) {
info.Created = nil
}),
@ -508,7 +493,7 @@ func TestExecuteContractCmd(t *testing.T) {
},
},
mutator: func(cmd *cobra.Command) {
cmd.SetArgs([]string{firstContractAddress, `{}`})
cmd.SetArgs([]string{myFirstContractAddress, `{}`})
flagSet := cmd.Flags()
flagSet.Set("run-as", myWellFundedAccount)
flagSet.Set("amount", "100stake")
@ -527,7 +512,7 @@ func TestExecuteContractCmd(t *testing.T) {
},
Contracts: []types.Contract{
{
ContractAddress: firstContractAddress,
ContractAddress: myFirstContractAddress,
ContractInfo: types.ContractInfoFixture(func(info *types.ContractInfo) {
info.Created = nil
}),
@ -536,7 +521,7 @@ func TestExecuteContractCmd(t *testing.T) {
},
},
mutator: func(cmd *cobra.Command) {
cmd.SetArgs([]string{firstContractAddress, `{}`})
cmd.SetArgs([]string{myFirstContractAddress, `{}`})
flagSet := cmd.Flags()
flagSet.Set("run-as", keeper.RandomBech32AccountAddress(t))
flagSet.Set("amount", "10stake")
@ -565,6 +550,9 @@ func TestExecuteContractCmd(t *testing.T) {
}
func TestGetAllContracts(t *testing.T) {
creatorAddr1 := sdk.AccAddress(bytes.Repeat([]byte{1}, address.Len))
creatorAddr2 := sdk.AccAddress(bytes.Repeat([]byte{2}, address.Len))
specs := map[string]struct {
src types.GenesisState
exp []ContractMeta
@ -595,68 +583,55 @@ func TestGetAllContracts(t *testing.T) {
},
"read from message state": {
src: types.GenesisState{
Codes: []types.Code{{CodeID: 1, CodeInfo: types.CodeInfo{CodeHash: []byte("firstCodeHash")}}},
GenMsgs: []types.GenesisState_GenMsgs{
{Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{Label: "first"}}},
{Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{Label: "second"}}},
{Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{Sender: creatorAddr1.String(), Label: "first", CodeID: 1}}},
{Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{Sender: creatorAddr2.String(), Label: "second", CodeID: 1}}},
},
},
exp: []ContractMeta{
{
ContractAddress: keeper.BuildContractAddress(0, 1).String(),
Info: types.ContractInfo{Label: "first"},
ContractAddress: keeper.BuildContractAddress([]byte("firstCodeHash"), creatorAddr1, "first").String(),
Info: types.ContractInfo{Creator: creatorAddr1.String(), Label: "first", CodeID: 1},
},
{
ContractAddress: keeper.BuildContractAddress(0, 2).String(),
Info: types.ContractInfo{Label: "second"},
},
},
},
"read from message state with contract sequence": {
src: types.GenesisState{
Sequences: []types.Sequence{
{IDKey: types.KeyLastInstanceID, Value: 100},
},
GenMsgs: []types.GenesisState_GenMsgs{
{Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{Label: "hundred"}}},
},
},
exp: []ContractMeta{
{
ContractAddress: keeper.BuildContractAddress(0, 100).String(),
Info: types.ContractInfo{Label: "hundred"},
ContractAddress: keeper.BuildContractAddress([]byte("firstCodeHash"), creatorAddr2, "second").String(),
Info: types.ContractInfo{Creator: creatorAddr2.String(), Label: "second", CodeID: 1},
},
},
},
"read from contract and message state with contract sequence": {
src: types.GenesisState{
Codes: []types.Code{
{CodeID: 1, CodeInfo: types.CodeInfo{CodeHash: []byte("firstCodeHash")}},
{CodeID: 100, CodeInfo: types.CodeInfo{CodeHash: []byte("otherCodeHash")}},
},
Contracts: []types.Contract{
{
ContractAddress: "first-contract",
ContractInfo: types.ContractInfo{Label: "first"},
ContractAddress: keeper.BuildContractAddress([]byte("firstCodeHash"), creatorAddr1, "first").String(),
ContractInfo: types.ContractInfo{Label: "first", CodeID: 1},
},
},
Sequences: []types.Sequence{
{IDKey: types.KeyLastInstanceID, Value: 100},
},
GenMsgs: []types.GenesisState_GenMsgs{
{Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{Label: "hundred"}}},
{Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{Sender: creatorAddr1.String(), Label: "hundred", CodeID: 100}}},
},
},
exp: []ContractMeta{
{
ContractAddress: "first-contract",
Info: types.ContractInfo{Label: "first"},
ContractAddress: keeper.BuildContractAddress([]byte("firstCodeHash"), creatorAddr1, "first").String(),
Info: types.ContractInfo{Label: "first", CodeID: 1},
},
{
ContractAddress: keeper.BuildContractAddress(0, 100).String(),
Info: types.ContractInfo{Label: "hundred"},
ContractAddress: keeper.BuildContractAddress([]byte("otherCodeHash"), creatorAddr1, "hundred").String(),
Info: types.ContractInfo{Creator: creatorAddr1.String(), Label: "hundred", CodeID: 100},
},
},
},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
got := GetAllContracts(&spec.src)
got, err := GetAllContracts(&spec.src)
require.NoError(t, err)
assert.Equal(t, spec.exp, got)
})
}

View File

@ -17,6 +17,7 @@ import (
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"github.com/CosmWasm/wasmd/x/wasm/keeper"
"github.com/CosmWasm/wasmd/x/wasm/types"
)
@ -39,6 +40,7 @@ func GetQueryCmd() *cobra.Command {
GetCmdListPinnedCode(),
GetCmdLibVersion(),
GetCmdQueryParams(),
GetCmdBuildAddress(),
)
return queryCmd
}
@ -63,6 +65,33 @@ func GetCmdLibVersion() *cobra.Command {
return cmd
}
// GetCmdBuildAddress build a contract address
func GetCmdBuildAddress() *cobra.Command {
cmd := &cobra.Command{
Use: "build-address [code-hash] [creator-address] [label]",
Short: "build contract address",
Aliases: []string{"address"},
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
codeHash, err := hex.DecodeString(args[0])
if err != nil {
return fmt.Errorf("code-hash: %s", err)
}
creator, err := sdk.AccAddressFromBech32(args[1])
if err != nil {
return fmt.Errorf("creator: %s", err)
}
label := args[2]
if err := types.ValidateLabel(label); err != nil {
return fmt.Errorf("label: %s", err)
}
cmd.Println(keeper.BuildContractAddress(codeHash, creator, label).String())
return nil
},
}
return cmd
}
// GetCmdListCode lists all wasm code uploaded
func GetCmdListCode() *cobra.Command {
cmd := &cobra.Command{
@ -117,6 +146,9 @@ func GetCmdListContractByCode() *cobra.Command {
if err != nil {
return err
}
if codeID == 0 {
return errors.New("empty code id")
}
pageReq, err := client.ReadPageRequest(withPageKeyDecoded(cmd.Flags()))
if err != nil {

View File

@ -13,8 +13,8 @@ func TestInitGenesis(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := data.faucet.NewFundedAccount(data.ctx, deposit.Add(deposit...)...)
fred := data.faucet.NewFundedAccount(data.ctx, topUp...)
creator := data.faucet.NewFundedRandomAccount(data.ctx, deposit.Add(deposit...)...)
fred := data.faucet.NewFundedRandomAccount(data.ctx, topUp...)
h := data.module.Route().Handler()
q := data.module.LegacyQuerierHandler(nil)

View File

@ -62,6 +62,7 @@ func (chain *TestChain) StoreCode(byteCode []byte) types.MsgStoreCodeResponse {
var pInstResp types.MsgStoreCodeResponse
require.NoError(chain.t, pInstResp.Unmarshal(protoResult.Data[0].Data))
require.NotEmpty(chain.t, pInstResp.CodeID)
require.NotEmpty(chain.t, pInstResp.Checksum)
return pInstResp
}

View File

@ -10,7 +10,7 @@ var _ types.ContractOpsKeeper = PermissionedKeeper{}
// decoratedKeeper contains a subset of the wasm keeper that are already or can be guarded by an authorization policy in the future
type decoratedKeeper interface {
create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, instantiateAccess *types.AccessConfig, authZ AuthorizationPolicy) (codeID uint64, err error)
create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, instantiateAccess *types.AccessConfig, authZ AuthorizationPolicy) (codeID uint64, checksum []byte, err error)
instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.AccAddress, initMsg []byte, label string, deposit sdk.Coins, authZ AuthorizationPolicy) (sdk.AccAddress, []byte, error)
migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, newCodeID uint64, msg []byte, authZ AuthorizationPolicy) ([]byte, error)
setContractAdmin(ctx sdk.Context, contractAddress, caller, newAdmin sdk.AccAddress, authZ AuthorizationPolicy) error
@ -39,7 +39,7 @@ func NewDefaultPermissionKeeper(nested decoratedKeeper) *PermissionedKeeper {
return NewPermissionedKeeper(nested, DefaultAuthorizationPolicy{})
}
func (p PermissionedKeeper) Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, instantiateAccess *types.AccessConfig) (codeID uint64, err error) {
func (p PermissionedKeeper) Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, instantiateAccess *types.AccessConfig) (codeID uint64, checksum []byte, err error) {
return p.nested.create(ctx, creator, wasmCode, instantiateAccess, p.authZPolicy)
}

View File

@ -35,7 +35,6 @@ func InitGenesis(ctx sdk.Context, keeper *Keeper, data types.GenesisState, staki
}
}
var maxContractID int
for i, contract := range data.Contracts {
contractAddr, err := sdk.AccAddressFromBech32(contract.ContractAddress)
if err != nil {
@ -45,7 +44,6 @@ func InitGenesis(ctx sdk.Context, keeper *Keeper, data types.GenesisState, staki
if err != nil {
return nil, sdkerrors.Wrapf(err, "contract number %d", i)
}
maxContractID = i + 1 // not ideal but max(contractID) is not persisted otherwise
}
for i, seq := range data.Sequences {
@ -60,10 +58,6 @@ func InitGenesis(ctx sdk.Context, keeper *Keeper, data types.GenesisState, staki
if seqVal <= maxCodeID {
return nil, sdkerrors.Wrapf(types.ErrInvalid, "seq %s with value: %d must be greater than: %d ", string(types.KeyLastCodeID), seqVal, maxCodeID)
}
seqVal = keeper.PeekAutoIncrementID(ctx, types.KeyLastInstanceID)
if seqVal <= uint64(maxContractID) {
return nil, sdkerrors.Wrapf(types.ErrInvalid, "seq %s with value: %d must be greater than: %d ", string(types.KeyLastInstanceID), seqVal, maxContractID)
}
if len(data.GenMsgs) == 0 {
return nil, nil
@ -117,7 +111,7 @@ func ExportGenesis(ctx sdk.Context, keeper *Keeper) *types.GenesisState {
return false
})
for _, k := range [][]byte{types.KeyLastCodeID, types.KeyLastInstanceID} {
for _, k := range [][]byte{types.KeyLastCodeID} {
genState.Sequences = append(genState.Sequences, types.Sequence{
IDKey: k,
Value: keeper.PeekAutoIncrementID(ctx, k),

View File

@ -11,6 +11,10 @@ import (
"testing"
"time"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/store"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -65,7 +69,7 @@ func TestGenesisExportImport(t *testing.T) {
creatorAddr, err := sdk.AccAddressFromBech32(codeInfo.Creator)
require.NoError(t, err)
codeID, err := contractKeeper.Create(srcCtx, creatorAddr, wasmCode, &codeInfo.InstantiateConfig)
codeID, checksum, err := contractKeeper.Create(srcCtx, creatorAddr, wasmCode, &codeInfo.InstantiateConfig)
require.NoError(t, err)
if pinned {
contractKeeper.PinCode(srcCtx, codeID)
@ -80,7 +84,7 @@ func TestGenesisExportImport(t *testing.T) {
}
contract.CodeID = codeID
contractAddr := wasmKeeper.generateContractAddress(srcCtx, codeID)
contractAddr := BuildContractAddress(checksum, creatorAddr, "testing")
wasmKeeper.storeContractInfo(srcCtx, contractAddr, &contract)
wasmKeeper.appendToContractHistory(srcCtx, contractAddr, history...)
wasmKeeper.importContractState(srcCtx, contractAddr, stateModels)
@ -156,6 +160,16 @@ func TestGenesisInit(t *testing.T) {
require.NoError(t, err)
myCodeInfo := wasmTypes.CodeInfoFixture(wasmTypes.WithSHA256CodeHash(wasmCode))
mySenderAddr := sdk.AccAddress(bytes.Repeat([]byte{1}, address.Len))
myLabel := "testing"
myContractInfoFixture := func(mutators ...func(*types.ContractInfo)) types.ContractInfo {
return types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) {
c.CodeID = 1
c.Creator = mySenderAddr.String()
c.Label = myLabel
}, types.OnlyGenesisFields)
}
specs := map[string]struct {
src types.GenesisState
stakingMock StakingKeeperMock
@ -171,7 +185,6 @@ func TestGenesisInit(t *testing.T) {
}},
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 2},
{IDKey: types.KeyLastInstanceID, Value: 1},
},
Params: types.DefaultParams(),
},
@ -190,7 +203,6 @@ func TestGenesisInit(t *testing.T) {
}},
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 10},
{IDKey: types.KeyLastInstanceID, Value: 1},
},
Params: types.DefaultParams(),
},
@ -210,7 +222,6 @@ func TestGenesisInit(t *testing.T) {
Contracts: nil,
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 3},
{IDKey: types.KeyLastInstanceID, Value: 1},
},
Params: types.DefaultParams(),
},
@ -267,13 +278,12 @@ func TestGenesisInit(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
ContractAddress: BuildContractAddress(myCodeInfo.CodeHash, mySenderAddr, myLabel).String(),
ContractInfo: myContractInfoFixture(),
},
},
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 2},
{IDKey: types.KeyLastInstanceID, Value: 2},
},
Params: types.DefaultParams(),
},
@ -288,16 +298,17 @@ func TestGenesisInit(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
ContractAddress: BuildContractAddress(myCodeInfo.CodeHash, mySenderAddr, myLabel).String(),
ContractInfo: myContractInfoFixture(),
}, {
ContractAddress: BuildContractAddress(1, 2).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
ContractAddress: BuildContractAddress(myCodeInfo.CodeHash, mySenderAddr, "other-label").String(),
ContractInfo: myContractInfoFixture(func(i *wasmTypes.ContractInfo) {
i.Label = "other-label"
}),
},
},
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 2},
{IDKey: types.KeyLastInstanceID, Value: 3},
},
Params: types.DefaultParams(),
},
@ -307,8 +318,8 @@ func TestGenesisInit(t *testing.T) {
src: types.GenesisState{
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
ContractAddress: BuildContractAddress(myCodeInfo.CodeHash, mySenderAddr, myLabel).String(),
ContractInfo: myContractInfoFixture(),
},
},
Params: types.DefaultParams(),
@ -323,11 +334,11 @@ func TestGenesisInit(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
ContractAddress: BuildContractAddress(myCodeInfo.CodeHash, mySenderAddr, myLabel).String(),
ContractInfo: myContractInfoFixture(),
}, {
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
ContractAddress: BuildContractAddress(myCodeInfo.CodeHash, mySenderAddr, myLabel).String(),
ContractInfo: myContractInfoFixture(),
},
},
Params: types.DefaultParams(),
@ -342,8 +353,8 @@ func TestGenesisInit(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
ContractAddress: BuildContractAddress(myCodeInfo.CodeHash, mySenderAddr, myLabel).String(),
ContractInfo: myContractInfoFixture(),
ContractState: []types.Model{
{
Key: []byte{0x1},
@ -381,26 +392,6 @@ func TestGenesisInit(t *testing.T) {
Params: types.DefaultParams(),
},
},
"prevent contract id seq init value == count contracts": {
src: types.GenesisState{
Codes: []types.Code{{
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}},
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddress(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }, types.OnlyGenesisFields),
},
},
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 2},
{IDKey: types.KeyLastInstanceID, Value: 1},
},
Params: types.DefaultParams(),
},
},
"validator set update called for any genesis messages": {
src: wasmTypes.GenesisState{
GenMsgs: []types.GenesisState_GenMsgs{
@ -559,16 +550,17 @@ func TestImportContractWithCodeHistoryReset(t *testing.T) {
}
assert.Equal(t, expHistory, keeper.GetContractHistory(ctx, contractAddr))
assert.Equal(t, uint64(2), keeper.PeekAutoIncrementID(ctx, types.KeyLastCodeID))
assert.Equal(t, uint64(3), keeper.PeekAutoIncrementID(ctx, types.KeyLastInstanceID))
}
func TestSupportedGenMsgTypes(t *testing.T) {
wasmCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)
wasmHash := sha256.Sum256(wasmCode)
var (
myAddress sdk.AccAddress = bytes.Repeat([]byte{1}, types.ContractAddrLen)
verifierAddress sdk.AccAddress = bytes.Repeat([]byte{2}, types.ContractAddrLen)
beneficiaryAddress sdk.AccAddress = bytes.Repeat([]byte{3}, types.ContractAddrLen)
contractAddr = BuildContractAddress(wasmHash[:], myAddress, "testing")
)
const denom = "stake"
importState := types.GenesisState{
@ -600,7 +592,7 @@ func TestSupportedGenMsgTypes(t *testing.T) {
Sum: &types.GenesisState_GenMsgs_ExecuteContract{
ExecuteContract: &types.MsgExecuteContract{
Sender: verifierAddress.String(),
Contract: BuildContractAddress(1, 1).String(),
Contract: contractAddr.String(),
Msg: []byte(`{"release":{}}`),
},
},
@ -625,7 +617,7 @@ func TestSupportedGenMsgTypes(t *testing.T) {
require.NotNil(t, codeInfo)
// verify contract instantiated
cInfo := keeper.GetContractInfo(ctx, BuildContractAddress(1, 1))
cInfo := keeper.GetContractInfo(ctx, contractAddr)
require.NotNil(t, cInfo)
// verify contract executed
@ -668,7 +660,24 @@ func setupKeeper(t *testing.T) (*Keeper, sdk.Context, []sdk.StoreKey) {
wasmConfig := wasmTypes.DefaultWasmConfig()
pk := paramskeeper.NewKeeper(encodingConfig.Marshaler, encodingConfig.Amino, keyParams, tkeyParams)
srcKeeper := NewKeeper(encodingConfig.Marshaler, keyWasm, pk.Subspace(wasmTypes.ModuleName), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, tempDir, wasmConfig, AvailableCapabilities)
srcKeeper := NewKeeper(
encodingConfig.Marshaler,
keyWasm,
pk.Subspace(wasmTypes.ModuleName),
authkeeper.AccountKeeper{},
&bankkeeper.BaseKeeper{},
stakingkeeper.Keeper{},
distributionkeeper.Keeper{},
nil,
nil,
nil,
nil,
nil,
nil,
tempDir,
wasmConfig,
AvailableCapabilities,
)
return &srcKeeper, ctx, []sdk.StoreKey{keyWasm, keyParams}
}

View File

@ -327,7 +327,7 @@ func TestBurnCoinMessageHandlerIntegration(t *testing.T) {
// picks the message in the default handler chain
ctx, keepers := CreateDefaultTestInput(t)
// set some supply
keepers.Faucet.NewFundedAccount(ctx, sdk.NewCoin("denom", sdk.NewInt(10_000_000)))
keepers.Faucet.NewFundedRandomAccount(ctx, sdk.NewCoin("denom", sdk.NewInt(10_000_000)))
k := keepers.WasmKeeper
example := InstantiateHackatomExampleContract(t, ctx, keepers) // with deposit of 100 stake

View File

@ -4,6 +4,8 @@ import (
"fmt"
"testing"
"github.com/tendermint/tendermint/libs/rand"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert"
@ -41,7 +43,7 @@ func TestBindingPortForIBCContractOnInstantiate(t *testing.T) {
}
func TestContractFromPortID(t *testing.T) {
contractAddr := BuildContractAddress(1, 100)
contractAddr := BuildContractAddress(rand.Bytes(32), RandomAccountAddress(t), "testing")
specs := map[string]struct {
srcPort string
expAddr sdk.AccAddress

View File

@ -4,22 +4,25 @@ import (
"bytes"
"context"
"encoding/binary"
"encoding/hex"
"fmt"
"math"
"path/filepath"
"reflect"
"strconv"
"strings"
"time"
"github.com/cosmos/cosmos-sdk/types/address"
wasmvm "github.com/CosmWasm/wasmvm"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store/prefix"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/tendermint/tendermint/libs/log"
@ -54,6 +57,13 @@ type CoinTransferrer interface {
TransferCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
}
// CoinPruner handles the balances for accounts that are pruned on contract instantiate.
// This is an extension point to attach custom logic
type CoinPruner interface {
// PruneBalances handle balances for given address
PruneBalances(ctx sdk.Context, contractAddress sdk.AccAddress) error
}
// WasmVMResponseHandler is an extension point to handles the response data returned by a contract call.
type WasmVMResponseHandler interface {
// Handle processes the data returned by a contract invocation.
@ -66,6 +76,25 @@ type WasmVMResponseHandler interface {
) ([]byte, error)
}
// list of account types that are accepted for wasm contracts. Chains importing wasmd
// can overwrite this list with the WithAcceptedAccountTypesOnContractInstantiation option.
var defaultAcceptedAccountTypes = map[reflect.Type]struct{}{
reflect.TypeOf(&authtypes.BaseAccount{}): {},
}
// list of account types that are replaced with base accounts. Chains importing wasmd
// can overwrite this list with the WithPruneAccountTypesOnContractInstantiation option.
//
// contains vesting account types that can be created post genesis
var defaultPruneAccountTypes = map[reflect.Type]struct{}{
reflect.TypeOf(&vestingtypes.DelayedVestingAccount{}): {},
reflect.TypeOf(&vestingtypes.ContinuousVestingAccount{}): {},
// intentionally not added: genesis account types
// reflect.TypeOf(&vestingtypes.BaseVestingAccount{}): {},
// reflect.TypeOf(&vestingtypes.PeriodicVestingAccount{}): {},
// reflect.TypeOf(&vestingtypes.PermanentLockedAccount{}): {},
}
// Keeper will have a reference to Wasmer with it's own data directory.
type Keeper struct {
storeKey sdk.StoreKey
@ -79,10 +108,13 @@ type Keeper struct {
wasmVMResponseHandler WasmVMResponseHandler
messenger Messenger
// queryGasLimit is the max wasmvm gas that can be spent on executing a query with a contract
queryGasLimit uint64
paramSpace paramtypes.Subspace
gasRegister GasRegister
maxQueryStackSize uint32
queryGasLimit uint64
paramSpace paramtypes.Subspace
gasRegister GasRegister
maxQueryStackSize uint32
acceptedAccountTypes map[reflect.Type]struct{}
pruneAccountTypes map[reflect.Type]struct{}
coinPruner CoinPruner
}
// NewKeeper creates a new contract Keeper instance
@ -116,18 +148,21 @@ func NewKeeper(
}
keeper := &Keeper{
storeKey: storeKey,
cdc: cdc,
wasmVM: wasmer,
accountKeeper: accountKeeper,
bank: NewBankCoinTransferrer(bankKeeper),
portKeeper: portKeeper,
capabilityKeeper: capabilityKeeper,
messenger: NewDefaultMessageHandler(router, channelKeeper, capabilityKeeper, bankKeeper, cdc, portSource),
queryGasLimit: wasmConfig.SmartQueryGasLimit,
paramSpace: paramSpace,
gasRegister: NewDefaultWasmGasRegister(),
maxQueryStackSize: types.DefaultMaxQueryStackSize,
storeKey: storeKey,
cdc: cdc,
wasmVM: wasmer,
accountKeeper: accountKeeper,
bank: NewBankCoinTransferrer(bankKeeper),
coinPruner: NewCoinBurner(bankKeeper),
portKeeper: portKeeper,
capabilityKeeper: capabilityKeeper,
messenger: NewDefaultMessageHandler(router, channelKeeper, capabilityKeeper, bankKeeper, cdc, portSource),
queryGasLimit: wasmConfig.SmartQueryGasLimit,
paramSpace: paramSpace,
gasRegister: NewDefaultWasmGasRegister(),
maxQueryStackSize: types.DefaultMaxQueryStackSize,
acceptedAccountTypes: defaultAcceptedAccountTypes,
pruneAccountTypes: defaultPruneAccountTypes,
}
keeper.wasmVMQueryHandler = DefaultQueryPlugins(bankKeeper, stakingKeeper, distKeeper, channelKeeper, queryRouter, keeper)
for _, o := range opts {
@ -161,13 +196,13 @@ func (k Keeper) SetParams(ctx sdk.Context, ps types.Params) {
k.paramSpace.SetParamSet(ctx, &ps)
}
func (k Keeper) create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, instantiateAccess *types.AccessConfig, authZ AuthorizationPolicy) (codeID uint64, err error) {
func (k Keeper) create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, instantiateAccess *types.AccessConfig, authZ AuthorizationPolicy) (codeID uint64, checksum []byte, err error) {
if creator == nil {
return 0, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "cannot be nil")
return 0, checksum, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "cannot be nil")
}
if !authZ.CanCreateCode(k.getUploadAccessConfig(ctx), creator) {
return 0, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "can not create code")
return 0, checksum, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "can not create code")
}
// figure out proper instantiate access
defaultAccessConfig := k.getInstantiateAccessConfig(ctx).With(creator)
@ -175,25 +210,25 @@ func (k Keeper) create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte,
instantiateAccess = &defaultAccessConfig
} else if !instantiateAccess.IsSubset(defaultAccessConfig) {
// we enforce this must be subset of default upload access
return 0, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "instantiate access must be subset of default upload access")
return 0, checksum, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "instantiate access must be subset of default upload access")
}
if ioutils.IsGzip(wasmCode) {
ctx.GasMeter().ConsumeGas(k.gasRegister.UncompressCosts(len(wasmCode)), "Uncompress gzip bytecode")
wasmCode, err = ioutils.Uncompress(wasmCode, uint64(types.MaxWasmSize))
if err != nil {
return 0, sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
return 0, checksum, sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
}
}
ctx.GasMeter().ConsumeGas(k.gasRegister.CompileCosts(len(wasmCode)), "Compiling wasm bytecode")
checksum, err := k.wasmVM.Create(wasmCode)
checksum, err = k.wasmVM.Create(wasmCode)
if err != nil {
return 0, sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
return 0, checksum, sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
}
report, err := k.wasmVM.AnalyzeCode(checksum)
if err != nil {
return 0, sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
return 0, checksum, sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
}
codeID = k.autoIncrementID(ctx, types.KeyLastCodeID)
k.Logger(ctx).Debug("storing new contract", "capabilities", report.RequiredCapabilities, "code_id", codeID)
@ -203,13 +238,14 @@ func (k Keeper) create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte,
evt := sdk.NewEvent(
types.EventTypeStoreCode,
sdk.NewAttribute(types.AttributeKeyCodeID, strconv.FormatUint(codeID, 10)),
sdk.NewAttribute(types.AttributeKeyChecksum, hex.EncodeToString(checksum)),
)
for _, f := range strings.Split(report.RequiredCapabilities, ",") {
evt.AppendAttributes(sdk.NewAttribute(types.AttributeKeyRequiredCapability, strings.TrimSpace(f)))
}
ctx.EventManager().EmitEvent(evt)
return codeID, nil
return codeID, checksum, nil
}
func (k Keeper) storeCodeInfo(ctx sdk.Context, codeID uint64, codeInfo types.CodeInfo) {
@ -244,31 +280,15 @@ func (k Keeper) importCode(ctx sdk.Context, codeID uint64, codeInfo types.CodeIn
return nil
}
func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.AccAddress, initMsg []byte, label string, deposit sdk.Coins, authZ AuthorizationPolicy) (sdk.AccAddress, []byte, error) {
func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.AccAddress, initMsg []byte, label string, deposit sdk.Coins, authPolicy AuthorizationPolicy) (sdk.AccAddress, []byte, error) {
defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "instantiate")
if creator == nil {
return nil, nil, types.ErrEmpty.Wrap("creator")
}
instanceCosts := k.gasRegister.NewContractInstanceCosts(k.IsPinnedCode(ctx, codeID), len(initMsg))
ctx.GasMeter().ConsumeGas(instanceCosts, "Loading CosmWasm module: instantiate")
// create contract address
contractAddress := k.generateContractAddress(ctx, codeID)
existingAcct := k.accountKeeper.GetAccount(ctx, contractAddress)
if existingAcct != nil {
return nil, nil, sdkerrors.Wrap(types.ErrAccountExists, existingAcct.GetAddress().String())
}
// deposit initial contract funds
if !deposit.IsZero() {
if err := k.bank.TransferCoins(ctx, creator, contractAddress, deposit); err != nil {
return nil, nil, err
}
} else {
// create an empty account (so we don't have issues later)
// TODO: can we remove this?
contractAccount := k.accountKeeper.NewAccountWithAddress(ctx, contractAddress)
k.accountKeeper.SetAccount(ctx, contractAccount)
}
// get contact info
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.GetCodeKey(codeID))
@ -278,10 +298,53 @@ func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A
var codeInfo types.CodeInfo
k.cdc.MustUnmarshal(bz, &codeInfo)
if !authZ.CanInstantiateContract(codeInfo.InstantiateConfig, creator) {
if !authPolicy.CanInstantiateContract(codeInfo.InstantiateConfig, creator) {
return nil, nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "can not instantiate")
}
contractAddress := BuildContractAddress(codeInfo.CodeHash, creator, label)
if k.HasContractInfo(ctx, contractAddress) {
return nil, nil, types.ErrDuplicate.Wrap("instance with this code id, sender and label exists: try a different label")
}
// check account
// every cosmos module can define custom account types when needed. The cosmos-sdk comes with extension points
// to support this and a set of base and vesting account types that we integrated in our default lists.
// But not all account types of other modules are known or may make sense for contracts, therefore we kept this
// decision logic also very flexible and extendable. We provide new options to overwrite the default settings via WithAcceptedAccountTypesOnContractInstantiation and
// WithPruneAccountTypesOnContractInstantiation as constructor arguments
existingAcct := k.accountKeeper.GetAccount(ctx, contractAddress)
if existingAcct != nil {
if existingAcct.GetSequence() != 0 || existingAcct.GetPubKey() != nil {
return nil, nil, types.ErrAccountExists.Wrap("address is claimed by external account")
}
if _, accept := k.acceptedAccountTypes[reflect.TypeOf(existingAcct)]; accept {
// keep account and balance as it is
k.Logger(ctx).Info("instantiate contract with existing account", "address", contractAddress.String())
} else if _, clear := k.pruneAccountTypes[reflect.TypeOf(existingAcct)]; clear {
k.Logger(ctx).Info("pruning existing account for contract instantiation", "address", contractAddress.String())
// consider an account in the wasmd namespace spam and overwrite it.
contractAccount := k.accountKeeper.NewAccountWithAddress(ctx, contractAddress)
k.accountKeeper.SetAccount(ctx, contractAccount)
// also handle balance to not open cases where these accounts are abused and become liquid
if err := k.coinPruner.PruneBalances(ctx, contractAddress); err != nil {
return nil, nil, err
}
} else { // unknown account type
return nil, nil, types.ErrAccountExists.Wrapf("refusing to overwrite special account type:: %T", existingAcct)
}
} else {
// create an empty account (so we don't have issues later)
contractAccount := k.accountKeeper.NewAccountWithAddress(ctx, contractAddress)
k.accountKeeper.SetAccount(ctx, contractAccount)
}
// deposit initial contract funds
if !deposit.IsZero() {
if err := k.bank.TransferCoins(ctx, creator, contractAddress, deposit); err != nil {
return nil, nil, err
}
}
// prepare params for contract instantiate call
env := types.NewEnv(ctx, contractAddress)
info := types.NewInfo(creator, deposit)
@ -955,18 +1018,19 @@ func (k Keeper) consumeRuntimeGas(ctx sdk.Context, gas uint64) {
}
}
// generates a contract address from codeID + instanceID
func (k Keeper) generateContractAddress(ctx sdk.Context, codeID uint64) sdk.AccAddress {
instanceID := k.autoIncrementID(ctx, types.KeyLastInstanceID)
return BuildContractAddress(codeID, instanceID)
}
// BuildContractAddress builds an sdk account address for a contract.
func BuildContractAddress(codeID, instanceID uint64) sdk.AccAddress {
contractID := make([]byte, 16)
binary.BigEndian.PutUint64(contractID[:8], codeID)
binary.BigEndian.PutUint64(contractID[8:], instanceID)
return address.Module(types.ModuleName, contractID)[:types.ContractAddrLen]
// BuildContractAddress generates a contract address for the wasm module with len = types.ContractAddrLen using the
// Cosmos SDK address.Module function.
// Internally a key is built containing (len(checksum) | checksum | len(sender_address) | sender_address | len(label) | label).
// All method parameter values must be valid and not be empty or nil.
func BuildContractAddress(checksum []byte, creator sdk.AccAddress, label string) sdk.AccAddress {
checksum = address.MustLengthPrefix(checksum)
creator = address.MustLengthPrefix(creator)
labelBz := address.MustLengthPrefix([]byte(label))
key := make([]byte, len(checksum)+len(creator)+len(labelBz))
copy(key[0:], checksum)
copy(key[len(checksum):], creator)
copy(key[len(checksum)+len(creator):], labelBz)
return address.Module(types.ModuleName, key)[:types.ContractAddrLen]
}
func (k Keeper) autoIncrementID(ctx sdk.Context, lastIDKey []byte) uint64 {
@ -1097,6 +1161,34 @@ func (c BankCoinTransferrer) TransferCoins(parentCtx sdk.Context, fromAddr sdk.A
return nil
}
var _ CoinPruner = CoinBurner{}
// CoinBurner default implementation for CoinPruner to burn the coins
type CoinBurner struct {
bank types.BankKeeper
}
// NewCoinBurner constructor
func NewCoinBurner(bank types.BankKeeper) CoinBurner {
if bank == nil {
panic("bank keeper must not be nil")
}
return CoinBurner{bank: bank}
}
// PruneBalances burns all coins owned by the account.
func (b CoinBurner) PruneBalances(ctx sdk.Context, address sdk.AccAddress) error {
if amt := b.bank.GetAllBalances(ctx, address); !amt.IsZero() {
if err := b.bank.SendCoinsFromAccountToModule(ctx, address, types.ModuleName, amt); err != nil {
return sdkerrors.Wrap(err, "prune account balance")
}
if err := b.bank.BurnCoins(ctx, types.ModuleName, amt); err != nil {
return sdkerrors.Wrap(err, "burn account balance")
}
}
return nil
}
type msgDispatcher interface {
DispatchSubmessages(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error)
}

View File

@ -2,19 +2,24 @@ package keeper
import (
"bytes"
_ "embed"
"encoding/hex"
"encoding/json"
"errors"
"math"
"os"
"strings"
"testing"
"time"
wasmvm "github.com/CosmWasm/wasmvm"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
stypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
fuzz "github.com/google/gofuzz"
@ -27,15 +32,7 @@ import (
"github.com/CosmWasm/wasmd/x/wasm/types"
)
// When migrated to go 1.16, embed package should be used instead.
func init() {
b, err := os.ReadFile("./testdata/hackatom.wasm")
if err != nil {
panic(err)
}
hackatomWasm = b
}
//go:embed testdata/hackatom.wasm
var hackatomWasm []byte
const AvailableCapabilities = "iterator,staking,stargate,cosmwasm_1_1"
@ -50,10 +47,10 @@ func TestCreateSuccess(t *testing.T) {
keeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
em := sdk.NewEventManager()
contractID, err := keeper.Create(ctx.WithEventManager(em), creator, hackatomWasm, nil)
contractID, _, err := keeper.Create(ctx.WithEventManager(em), creator, hackatomWasm, nil)
require.NoError(t, err)
require.Equal(t, uint64(1), contractID)
// and verify content
@ -61,32 +58,33 @@ func TestCreateSuccess(t *testing.T) {
require.NoError(t, err)
require.Equal(t, hackatomWasm, storedCode)
// and events emitted
exp := sdk.Events{sdk.NewEvent("store_code", sdk.NewAttribute("code_id", "1"))}
codeHash := "13a1fc994cc6d1c81b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2a5"
exp := sdk.Events{sdk.NewEvent("store_code", sdk.NewAttribute("code_id", "1"), sdk.NewAttribute("code_checksum", codeHash))}
assert.Equal(t, exp, em.Events())
}
func TestCreateNilCreatorAddress(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
_, err := keepers.ContractKeeper.Create(ctx, nil, hackatomWasm, nil)
_, _, err := keepers.ContractKeeper.Create(ctx, nil, hackatomWasm, nil)
require.Error(t, err, "nil creator is not allowed")
}
func TestCreateNilWasmCode(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
_, err := keepers.ContractKeeper.Create(ctx, creator, nil, nil)
_, _, err := keepers.ContractKeeper.Create(ctx, creator, nil, nil)
require.Error(t, err, "nil WASM code is not allowed")
}
func TestCreateInvalidWasmCode(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
_, err := keepers.ContractKeeper.Create(ctx, creator, []byte("potatoes"), nil)
_, _, err := keepers.ContractKeeper.Create(ctx, creator, []byte("potatoes"), nil)
require.Error(t, err, "potatoes are not valid WASM code")
}
@ -127,7 +125,7 @@ func TestCreateStoresInstantiatePermission(t *testing.T) {
})
fundAccounts(t, ctx, accKeeper, bankKeeper, myAddr, deposit)
codeID, err := keeper.Create(ctx, myAddr, hackatomWasm, nil)
codeID, _, err := keeper.Create(ctx, myAddr, hackatomWasm, nil)
require.NoError(t, err)
codeInfo := keepers.WasmKeeper.GetCodeInfo(ctx, codeID)
@ -142,8 +140,8 @@ func TestCreateWithParamPermissions(t *testing.T) {
keeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
otherAddr := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
otherAddr := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
specs := map[string]struct {
srcPermission types.AccessConfig
@ -172,7 +170,7 @@ func TestCreateWithParamPermissions(t *testing.T) {
params := types.DefaultParams()
params.CodeUploadAccess = spec.srcPermission
keepers.WasmKeeper.SetParams(ctx, params)
_, err := keeper.Create(ctx, creator, hackatomWasm, nil)
_, _, err := keeper.Create(ctx, creator, hackatomWasm, nil)
require.True(t, spec.expError.Is(err), err)
if spec.expError != nil {
return
@ -189,8 +187,8 @@ func TestEnforceValidPermissionsOnCreate(t *testing.T) {
contractKeeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
other := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
other := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
onlyCreator := types.AccessTypeOnlyAddress.With(creator)
onlyOther := types.AccessTypeOnlyAddress.With(other)
@ -249,7 +247,7 @@ func TestEnforceValidPermissionsOnCreate(t *testing.T) {
params := types.DefaultParams()
params.InstantiateDefaultPermission = spec.defaultPermssion
keeper.SetParams(ctx, params)
codeID, err := contractKeeper.Create(ctx, creator, hackatomWasm, spec.requestedPermission)
codeID, _, err := contractKeeper.Create(ctx, creator, hackatomWasm, spec.requestedPermission)
require.True(t, spec.expError.Is(err), err)
if spec.expError == nil {
codeInfo := keeper.GetCodeInfo(ctx, codeID)
@ -264,15 +262,15 @@ func TestCreateDuplicate(t *testing.T) {
keeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
// create one copy
contractID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
contractID, _, err := keeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)
require.Equal(t, uint64(1), contractID)
// create second copy
duplicateID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
duplicateID, _, err := keeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)
require.Equal(t, uint64(2), duplicateID)
@ -292,18 +290,18 @@ func TestCreateWithSimulation(t *testing.T) {
WithGasMeter(stypes.NewInfiniteGasMeter())
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
// create this once in simulation mode
contractID, err := keepers.ContractKeeper.Create(ctx, creator, hackatomWasm, nil)
contractID, _, err := keepers.ContractKeeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)
require.Equal(t, uint64(1), contractID)
// then try to create it in non-simulation mode (should not fail)
ctx, keepers = CreateTestInput(t, false, AvailableCapabilities)
ctx = ctx.WithGasMeter(sdk.NewGasMeter(10_000_000))
creator = keepers.Faucet.NewFundedAccount(ctx, deposit...)
contractID, err = keepers.ContractKeeper.Create(ctx, creator, hackatomWasm, nil)
creator = keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
contractID, _, err = keepers.ContractKeeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)
require.Equal(t, uint64(1), contractID)
@ -344,12 +342,12 @@ func TestCreateWithGzippedPayload(t *testing.T) {
keeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
wasmCode, err := os.ReadFile("./testdata/hackatom.wasm.gzip")
require.NoError(t, err, "reading gzipped WASM code")
contractID, err := keeper.Create(ctx, creator, wasmCode, nil)
contractID, _, err := keeper.Create(ctx, creator, wasmCode, nil)
require.NoError(t, err)
require.Equal(t, uint64(1), contractID)
// and verify content
@ -363,34 +361,30 @@ func TestCreateWithBrokenGzippedPayload(t *testing.T) {
keeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
wasmCode, err := os.ReadFile("./testdata/broken_crc.gzip")
require.NoError(t, err, "reading gzipped WASM code")
gm := sdk.NewInfiniteGasMeter()
contractID, err := keeper.Create(ctx.WithGasMeter(gm), creator, wasmCode, nil)
codeID, checksum, err := keeper.Create(ctx.WithGasMeter(gm), creator, wasmCode, nil)
require.Error(t, err)
assert.Empty(t, contractID)
assert.Empty(t, codeID)
assert.Empty(t, checksum)
assert.GreaterOrEqual(t, gm.GasConsumed(), sdk.Gas(121384)) // 809232 * 0.15 (default uncompress costs) = 121384
}
func TestInstantiate(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
keeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
codeID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)
_, _, bob := keyPubAddr()
_, _, fred := keyPubAddr()
creator := sdk.AccAddress(bytes.Repeat([]byte{1}, address.Len))
keepers.Faucet.Fund(ctx, creator, deposit...)
example := StoreHackatomExampleContract(t, ctx, keepers)
initMsg := HackatomExampleInitMsg{
Verifier: fred,
Beneficiary: bob,
Verifier: RandomAccountAddress(t),
Beneficiary: RandomAccountAddress(t),
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
@ -399,25 +393,25 @@ func TestInstantiate(t *testing.T) {
em := sdk.NewEventManager()
// create with no balance is also legal
gotContractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx.WithEventManager(em), codeID, creator, nil, initMsgBz, "demo contract 1", nil)
gotContractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx.WithEventManager(em), example.CodeID, creator, nil, initMsgBz, "demo contract 1", nil)
require.NoError(t, err)
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", gotContractAddr.String())
require.Equal(t, "cosmos1xaq0tcwz9fsqmtxlpzwjn2zr8gw66ljjr079ltfc5pelepcs7sjsk28n5n", gotContractAddr.String())
gasAfter := ctx.GasMeter().GasConsumed()
if types.EnableGasVerification {
require.Equal(t, uint64(0x18db5), gasAfter-gasBefore)
require.Equal(t, uint64(0x187b8), gasAfter-gasBefore)
}
// ensure it is stored properly
info := keepers.WasmKeeper.GetContractInfo(ctx, gotContractAddr)
require.NotNil(t, info)
assert.Equal(t, creator.String(), info.Creator)
assert.Equal(t, codeID, info.CodeID)
assert.Equal(t, example.CodeID, info.CodeID)
assert.Equal(t, "demo contract 1", info.Label)
exp := []types.ContractCodeHistoryEntry{{
Operation: types.ContractCodeHistoryOperationTypeInit,
CodeID: codeID,
CodeID: example.CodeID,
Updated: types.NewAbsoluteTxPosition(ctx),
Msg: initMsgBz,
}}
@ -439,12 +433,9 @@ func TestInstantiateWithDeposit(t *testing.T) {
fred = bytes.Repeat([]byte{2}, types.SDKAddrLen)
deposit = sdk.NewCoins(sdk.NewInt64Coin("denom", 100))
initMsg = HackatomExampleInitMsg{Verifier: fred, Beneficiary: bob}
initMsg = mustMarshal(t, HackatomExampleInitMsg{Verifier: fred, Beneficiary: bob})
)
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
specs := map[string]struct {
srcActor sdk.AccAddress
expError bool
@ -472,11 +463,11 @@ func TestInstantiateWithDeposit(t *testing.T) {
if spec.fundAddr {
fundAccounts(t, ctx, accKeeper, bankKeeper, spec.srcActor, sdk.NewCoins(sdk.NewInt64Coin("denom", 200)))
}
contractID, err := keeper.Create(ctx, spec.srcActor, hackatomWasm, nil)
contractID, _, err := keeper.Create(ctx, spec.srcActor, hackatomWasm, nil)
require.NoError(t, err)
// when
addr, _, err := keepers.ContractKeeper.Instantiate(ctx, contractID, spec.srcActor, nil, initMsgBz, "my label", deposit)
addr, _, err := keepers.ContractKeeper.Instantiate(ctx, contractID, spec.srcActor, nil, initMsg, "my label", deposit)
// then
if spec.expError {
require.Error(t, err)
@ -527,6 +518,7 @@ func TestInstantiateWithPermissions(t *testing.T) {
srcActor: myAddr,
},
"onlyAddress with non matching address": {
srcActor: myAddr,
srcPermission: types.AccessTypeOnlyAddress.With(otherAddr),
expError: sdkerrors.ErrUnauthorized,
},
@ -537,7 +529,7 @@ func TestInstantiateWithPermissions(t *testing.T) {
accKeeper, bankKeeper, keeper := keepers.AccountKeeper, keepers.BankKeeper, keepers.ContractKeeper
fundAccounts(t, ctx, accKeeper, bankKeeper, spec.srcActor, deposit)
contractID, err := keeper.Create(ctx, myAddr, hackatomWasm, &spec.srcPermission)
contractID, _, err := keeper.Create(ctx, myAddr, hackatomWasm, &spec.srcPermission)
require.NoError(t, err)
_, _, err = keepers.ContractKeeper.Instantiate(ctx, contractID, spec.srcActor, nil, initMsgBz, "demo contract 1", nil)
@ -546,11 +538,195 @@ func TestInstantiateWithPermissions(t *testing.T) {
}
}
func TestInstantiateWithUniqueContractAddress(t *testing.T) {
parentCtx, keepers := CreateTestInput(t, false, AvailableCapabilities)
example := InstantiateHackatomExampleContract(t, parentCtx, keepers)
otherExample := InstantiateReflectExampleContract(t, parentCtx, keepers)
initMsg := mustMarshal(t, HackatomExampleInitMsg{Verifier: example.VerifierAddr, Beneficiary: example.BeneficiaryAddr})
otherAddress := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(parentCtx, otherAddress, sdk.NewInt64Coin("denom", 100000000))
used := make(map[string]struct{})
specs := map[string]struct {
codeID uint64
sender sdk.AccAddress
label string
initMsg json.RawMessage
expErr error
}{
"reject duplicate which generates the same address": {
codeID: example.CodeID,
sender: example.CreatorAddr,
label: example.Label,
initMsg: initMsg,
expErr: types.ErrDuplicate,
},
"different sender": {
codeID: example.CodeID,
sender: otherAddress,
label: example.Label,
initMsg: initMsg,
},
"different code": {
codeID: otherExample.CodeID,
sender: example.CreatorAddr,
label: example.Label,
initMsg: []byte(`{}`),
},
"different label": {
codeID: example.CodeID,
sender: example.CreatorAddr,
label: "other label",
initMsg: initMsg,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
ctx, _ := parentCtx.CacheContext()
gotAddr, _, gotErr := keepers.ContractKeeper.Instantiate(ctx, spec.codeID, spec.sender, nil, spec.initMsg, spec.label, example.Deposit)
if spec.expErr != nil {
assert.ErrorIs(t, gotErr, spec.expErr)
return
}
require.NoError(t, gotErr)
expAddr := BuildContractAddress(keepers.WasmKeeper.GetCodeInfo(ctx, spec.codeID).CodeHash, spec.sender, spec.label)
assert.Equal(t, expAddr.String(), gotAddr.String())
require.NotContains(t, used, gotAddr.String())
used[gotAddr.String()] = struct{}{}
})
}
}
func TestInstantiateWithAccounts(t *testing.T) {
parentCtx, keepers := CreateTestInput(t, false, AvailableCapabilities)
example := StoreHackatomExampleContract(t, parentCtx, keepers)
require.Equal(t, uint64(1), example.CodeID)
initMsg := mustMarshal(t, HackatomExampleInitMsg{Verifier: RandomAccountAddress(t), Beneficiary: RandomAccountAddress(t)})
senderAddr := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(parentCtx, senderAddr, sdk.NewInt64Coin("denom", 100000000))
const myLabel = "testing"
contractAddr := BuildContractAddress(example.Checksum, senderAddr, myLabel)
lastAccountNumber := keepers.AccountKeeper.GetAccount(parentCtx, senderAddr).GetAccountNumber()
specs := map[string]struct {
acceptList Option
account authtypes.AccountI
initBalance sdk.Coin
deposit sdk.Coins
expErr error
expAccount authtypes.AccountI
expBalance sdk.Coins
}{
"unused BaseAccount exists": {
account: authtypes.NewBaseAccount(contractAddr, nil, 0, 0),
initBalance: sdk.NewInt64Coin("denom", 100000000),
expAccount: authtypes.NewBaseAccount(contractAddr, nil, lastAccountNumber+1, 0), // +1 for next seq
expBalance: sdk.NewCoins(sdk.NewInt64Coin("denom", 100000000)),
},
"BaseAccount with sequence exists": {
account: authtypes.NewBaseAccount(contractAddr, nil, 0, 1),
expErr: types.ErrAccountExists,
},
"BaseAccount with pubkey exists": {
account: authtypes.NewBaseAccount(contractAddr, &ed25519.PubKey{}, 0, 0),
expErr: types.ErrAccountExists,
},
"no account existed": {
expAccount: authtypes.NewBaseAccount(contractAddr, nil, lastAccountNumber+1, 0), // +1 for next seq,
expBalance: sdk.NewCoins(),
},
"no account existed before create with deposit": {
expAccount: authtypes.NewBaseAccount(contractAddr, nil, lastAccountNumber+1, 0), // +1 for next seq
deposit: sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1_000))),
expBalance: sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1_000))),
},
"prune listed DelayedVestingAccount gets overwritten": {
account: vestingtypes.NewDelayedVestingAccount(
authtypes.NewBaseAccount(contractAddr, nil, 0, 0),
sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1_000))), time.Now().Add(30*time.Hour).Unix()),
initBalance: sdk.NewCoin("denom", sdk.NewInt(1_000)),
deposit: sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1))),
expAccount: authtypes.NewBaseAccount(contractAddr, nil, lastAccountNumber+2, 0), // +1 for next seq, +1 for spec.account created
expBalance: sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1))),
},
"prune listed ContinuousVestingAccount gets overwritten": {
account: vestingtypes.NewContinuousVestingAccount(
authtypes.NewBaseAccount(contractAddr, nil, 0, 0),
sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1_000))), time.Now().Add(time.Hour).Unix(), time.Now().Add(2*time.Hour).Unix()),
initBalance: sdk.NewCoin("denom", sdk.NewInt(1_000)),
deposit: sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1))),
expAccount: authtypes.NewBaseAccount(contractAddr, nil, lastAccountNumber+2, 0), // +1 for next seq, +1 for spec.account created
expBalance: sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1))),
},
"prune listed account without balance gets overwritten": {
account: vestingtypes.NewContinuousVestingAccount(
authtypes.NewBaseAccount(contractAddr, nil, 0, 0),
sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(0))), time.Now().Add(time.Hour).Unix(), time.Now().Add(2*time.Hour).Unix()),
expAccount: authtypes.NewBaseAccount(contractAddr, nil, lastAccountNumber+2, 0), // +1 for next seq, +1 for spec.account created
expBalance: sdk.NewCoins(),
},
"unknown account type creates error": {
account: authtypes.NewModuleAccount(
authtypes.NewBaseAccount(contractAddr, nil, 0, 0),
"testing",
),
initBalance: sdk.NewCoin("denom", sdk.NewInt(1_000)),
expErr: types.ErrAccountExists,
},
"with option used to set non default type to accept list": {
acceptList: WithAcceptedAccountTypesOnContractInstantiation(&vestingtypes.DelayedVestingAccount{}),
account: vestingtypes.NewDelayedVestingAccount(
authtypes.NewBaseAccount(contractAddr, nil, 0, 0),
sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1_000))), time.Now().Add(30*time.Hour).Unix()),
initBalance: sdk.NewCoin("denom", sdk.NewInt(1_000)),
deposit: sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1))),
expAccount: vestingtypes.NewDelayedVestingAccount(authtypes.NewBaseAccount(contractAddr, nil, lastAccountNumber+1, 0),
sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1_000))), time.Now().Add(30*time.Hour).Unix()),
expBalance: sdk.NewCoins(sdk.NewCoin("denom", sdk.NewInt(1_001))),
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
ctx, _ := parentCtx.CacheContext()
if spec.account != nil {
keepers.AccountKeeper.SetAccount(ctx, keepers.AccountKeeper.NewAccount(ctx, spec.account))
}
if !spec.initBalance.IsNil() {
keepers.Faucet.Fund(ctx, spec.account.GetAddress(), spec.initBalance)
}
if spec.acceptList != nil {
spec.acceptList.apply(keepers.WasmKeeper)
}
defer func() {
if spec.acceptList != nil { // reset
WithAcceptedAccountTypesOnContractInstantiation(&authtypes.BaseAccount{}).apply(keepers.WasmKeeper)
}
}()
// when
gotAddr, _, gotErr := keepers.ContractKeeper.Instantiate(ctx, 1, senderAddr, nil, initMsg, myLabel, spec.deposit)
if spec.expErr != nil {
assert.ErrorIs(t, gotErr, spec.expErr)
return
}
require.NoError(t, gotErr)
assert.Equal(t, contractAddr, gotAddr)
// and
gotAcc := keepers.AccountKeeper.GetAccount(ctx, contractAddr)
assert.Equal(t, spec.expAccount, gotAcc)
// and
gotBalance := keepers.BankKeeper.GetAllBalances(ctx, contractAddr)
assert.Equal(t, spec.expBalance, gotBalance)
})
}
}
func TestInstantiateWithNonExistingCodeID(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
initMsg := HackatomExampleInitMsg{}
initMsgBz, err := json.Marshal(initMsg)
@ -585,13 +761,14 @@ func TestExecute(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedAccount(ctx, topUp...)
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(ctx, creator, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedRandomAccount(ctx, topUp...)
bob := RandomAccountAddress(t)
contractID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
contractID, _, err := keeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)
_, _, bob := keyPubAddr()
initMsg := HackatomExampleInitMsg{
Verifier: fred,
Beneficiary: bob,
@ -601,7 +778,8 @@ func TestExecute(t *testing.T) {
addr, _, err := keepers.ContractKeeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 3", deposit)
require.NoError(t, err)
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", addr.String())
// cosmos1eycfqpgtcp4gc9g24cvg6useyncxspq8qurv2z7cs0wzcgvmffaquzwe2e build with code-id 1, DeterministicAccountAddress(t, 1) and label `demo contract 3`
require.Equal(t, "cosmos1eycfqpgtcp4gc9g24cvg6useyncxspq8qurv2z7cs0wzcgvmffaquzwe2e", addr.String())
// ensure bob doesn't exist
bobAcct := accKeeper.GetAccount(ctx, bob)
@ -638,7 +816,7 @@ func TestExecute(t *testing.T) {
// make sure gas is properly deducted from ctx
gasAfter := ctx.GasMeter().GasConsumed()
if types.EnableGasVerification {
require.Equal(t, uint64(0x17cd2), gasAfter-gasBefore)
require.Equal(t, uint64(0x17d87), gasAfter-gasBefore)
}
// ensure bob now exists and got both payments released
bobAcct = accKeeper.GetAccount(ctx, bob)
@ -725,7 +903,7 @@ func TestExecuteWithDeposit(t *testing.T) {
if spec.fundAddr {
fundAccounts(t, ctx, accKeeper, bankKeeper, spec.srcActor, sdk.NewCoins(sdk.NewInt64Coin("denom", 200)))
}
codeID, err := keeper.Create(ctx, spec.srcActor, hackatomWasm, nil)
codeID, _, err := keeper.Create(ctx, spec.srcActor, hackatomWasm, nil)
require.NoError(t, err)
initMsg := HackatomExampleInitMsg{Verifier: spec.srcActor, Beneficiary: spec.beneficiary}
@ -755,7 +933,8 @@ func TestExecuteWithNonExistingAddress(t *testing.T) {
keeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(ctx, creator, deposit.Add(deposit...)...)
// unauthorized - trialCtx so we don't change state
nonExistingAddress := RandomAccountAddress(t)
@ -769,10 +948,11 @@ func TestExecuteWithPanic(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedAccount(ctx, topUp...)
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(ctx, creator, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedRandomAccount(ctx, topUp...)
contractID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
contractID, _, err := keeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)
_, _, bob := keyPubAddr()
@ -800,10 +980,11 @@ func TestExecuteWithCpuLoop(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedAccount(ctx, topUp...)
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(ctx, creator, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedRandomAccount(ctx, topUp...)
contractID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
contractID, _, err := keeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)
_, _, bob := keyPubAddr()
@ -841,10 +1022,11 @@ func TestExecuteWithStorageLoop(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedAccount(ctx, topUp...)
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(ctx, creator, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedRandomAccount(ctx, topUp...)
contractID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
contractID, _, err := keeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)
_, _, bob := keyPubAddr()
@ -877,21 +1059,23 @@ func TestExecuteWithStorageLoop(t *testing.T) {
}
func TestMigrate(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
parentCtx, keepers := CreateTestInput(t, false, AvailableCapabilities)
keeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedAccount(ctx, topUp...)
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(parentCtx, creator, deposit.Add(deposit...)...)
fred := DeterministicAccountAddress(t, 2)
keepers.Faucet.Fund(parentCtx, fred, topUp...)
originalCodeID := StoreHackatomExampleContract(t, ctx, keepers).CodeID
newCodeID := StoreHackatomExampleContract(t, ctx, keepers).CodeID
ibcCodeID := StoreIBCReflectContract(t, ctx, keepers).CodeID
originalCodeID := StoreHackatomExampleContract(t, parentCtx, keepers).CodeID
newCodeID := StoreHackatomExampleContract(t, parentCtx, keepers).CodeID
ibcCodeID := StoreIBCReflectContract(t, parentCtx, keepers).CodeID
require.NotEqual(t, originalCodeID, newCodeID)
restrictedCodeExample := StoreHackatomExampleContract(t, ctx, keepers)
require.NoError(t, keeper.SetAccessConfig(ctx, restrictedCodeExample.CodeID, restrictedCodeExample.CreatorAddr, types.AllowNobody))
restrictedCodeExample := StoreHackatomExampleContract(t, parentCtx, keepers)
require.NoError(t, keeper.SetAccessConfig(parentCtx, restrictedCodeExample.CodeID, restrictedCodeExample.CreatorAddr, types.AllowNobody))
require.NotEqual(t, originalCodeID, restrictedCodeExample.CodeID)
anyAddr := RandomAccountAddress(t)
@ -1017,7 +1201,7 @@ func TestMigrate(t *testing.T) {
"fail when no IBC callbacks": {
admin: fred,
caller: fred,
initMsg: IBCReflectInitMsg{ReflectCodeID: StoreReflectContract(t, ctx, keepers)}.GetBytes(t),
initMsg: IBCReflectInitMsg{ReflectCodeID: StoreReflectContract(t, parentCtx, keepers).CodeID}.GetBytes(t),
fromCodeID: ibcCodeID,
toCodeID: newCodeID,
migrateMsg: migMsgBz,
@ -1025,10 +1209,13 @@ func TestMigrate(t *testing.T) {
},
}
blockHeight := parentCtx.BlockHeight()
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
// given a contract instance
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
ctx, _ := parentCtx.WithBlockHeight(blockHeight + 1).CacheContext()
blockHeight++
contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, spec.fromCodeID, creator, spec.admin, spec.initMsg, "demo contract", nil)
require.NoError(t, err)
if spec.overrideContractAddr != nil {
@ -1109,15 +1296,16 @@ func TestMigrateWithDispatchedMessage(t *testing.T) {
keeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedAccount(ctx, sdk.NewInt64Coin("denom", 5000))
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(ctx, creator, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedRandomAccount(ctx, sdk.NewInt64Coin("denom", 5000))
burnerCode, err := os.ReadFile("./testdata/burner.wasm")
require.NoError(t, err)
originalContractID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
originalContractID, _, err := keeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)
burnerContractID, err := keeper.Create(ctx, creator, burnerCode, nil)
burnerContractID, _, err := keeper.Create(ctx, creator, burnerCode, nil)
require.NoError(t, err)
require.NotEqual(t, originalContractID, burnerContractID)
@ -1279,9 +1467,10 @@ func TestSudo(t *testing.T) {
accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.ContractKeeper, keepers.BankKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(ctx, creator, deposit.Add(deposit...)...)
contractID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
contractID, _, err := keeper.Create(ctx, creator, hackatomWasm, nil)
require.NoError(t, err)
_, _, bob := keyPubAddr()
@ -1294,7 +1483,7 @@ func TestSudo(t *testing.T) {
require.NoError(t, err)
addr, _, err := keepers.ContractKeeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 3", deposit)
require.NoError(t, err)
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", addr.String())
require.Equal(t, "cosmos1eycfqpgtcp4gc9g24cvg6useyncxspq8qurv2z7cs0wzcgvmffaquzwe2e", addr.String())
// the community is broke
_, _, community := keyPubAddr()
@ -1358,15 +1547,16 @@ func mustMarshal(t *testing.T, r interface{}) []byte {
}
func TestUpdateContractAdmin(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
parentCtx, keepers := CreateTestInput(t, false, AvailableCapabilities)
keeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedAccount(ctx, topUp...)
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(parentCtx, creator, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedRandomAccount(parentCtx, topUp...)
originalContractID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
originalContractID, _, err := keeper.Create(parentCtx, creator, hackatomWasm, nil)
require.NoError(t, err)
_, _, anyAddr := keyPubAddr()
@ -1409,6 +1599,7 @@ func TestUpdateContractAdmin(t *testing.T) {
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
ctx, _ := parentCtx.CacheContext()
addr, _, err := keepers.ContractKeeper.Instantiate(ctx, originalContractID, creator, spec.instAdmin, initMsgBz, "demo contract", nil)
require.NoError(t, err)
if spec.overrideContractAddr != nil {
@ -1426,15 +1617,16 @@ func TestUpdateContractAdmin(t *testing.T) {
}
func TestClearContractAdmin(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
parentCtx, keepers := CreateTestInput(t, false, AvailableCapabilities)
keeper := keepers.ContractKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedAccount(ctx, topUp...)
creator := DeterministicAccountAddress(t, 1)
keepers.Faucet.Fund(parentCtx, creator, deposit.Add(deposit...)...)
fred := keepers.Faucet.NewFundedRandomAccount(parentCtx, topUp...)
originalContractID, err := keeper.Create(ctx, creator, hackatomWasm, nil)
originalContractID, _, err := keeper.Create(parentCtx, creator, hackatomWasm, nil)
require.NoError(t, err)
_, _, anyAddr := keyPubAddr()
@ -1472,6 +1664,7 @@ func TestClearContractAdmin(t *testing.T) {
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
ctx, _ := parentCtx.CacheContext()
addr, _, err := keepers.ContractKeeper.Instantiate(ctx, originalContractID, creator, spec.instAdmin, initMsgBz, "demo contract", nil)
require.NoError(t, err)
if spec.overrideContractAddr != nil {
@ -1806,52 +1999,103 @@ func TestQueryIsolation(t *testing.T) {
}
func TestBuildContractAddress(t *testing.T) {
x, y := sdk.GetConfig().GetBech32AccountAddrPrefix(), sdk.GetConfig().GetBech32AccountPubPrefix()
t.Cleanup(func() {
sdk.GetConfig().SetBech32PrefixForAccount(x, y)
})
sdk.GetConfig().SetBech32PrefixForAccount("purple", "purple")
// test vectors from https://gist.github.com/webmaster128/e4d401d414bd0e7e6f70482f11877fbe
specs := map[string]struct {
srcCodeID uint64
srcInstanceID uint64
expectedAddr string
checksum []byte
label string
creator string
expAddress string
}{
"initial contract": {
srcCodeID: 1,
srcInstanceID: 1,
expectedAddr: "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr",
"initial account addr example": {
checksum: fromHex("13A1FC994CC6D1C81B746EE0C0FF6F90043875E0BF1D9BE6B7D779FC978DC2A5"),
label: "instance 1",
creator: "purple1nxvenxve42424242hwamhwamenxvenxvhxf2py",
expAddress: "purple1jukvumwqfxapueg6un6rtmafxktcluzv70xc3edz2m5t3slgw49qrmhc03",
},
"demo value": {
srcCodeID: 1,
srcInstanceID: 100,
expectedAddr: "cosmos1mujpjkwhut9yjw4xueyugc02evfv46y0dtmnz4lh8xxkkdapym9stu5qm8",
"account addr with different label": {
checksum: fromHex("13A1FC994CC6D1C81B746EE0C0FF6F90043875E0BF1D9BE6B7D779FC978DC2A5"),
label: "instance 2",
creator: "purple1nxvenxve42424242hwamhwamenxvenxvhxf2py",
expAddress: "purple1jpc2w2vu2t6k7u09p6v8e3w28ptnzvvt2snu5rytlj8qya27dq5sjkwm06",
},
"both below max": {
srcCodeID: math.MaxUint32 - 1,
srcInstanceID: math.MaxUint32 - 1,
"initial contract addr example": {
checksum: fromHex("13A1FC994CC6D1C81B746EE0C0FF6F90043875E0BF1D9BE6B7D779FC978DC2A5"),
label: "instance 1",
creator: "purple1nxvenxve42424242hwamhwamenxvenxvmhwamhwaamhwamhwlllsatsy6m",
expAddress: "purple1wde5zlcveuh79w37w5g244qu9xja3hgfulyfkjvkxvwvjzgd5l3qfraz3c",
},
"both at max": {
srcCodeID: math.MaxUint32,
srcInstanceID: math.MaxUint32,
"contract addr with different label": {
checksum: fromHex("13A1FC994CC6D1C81B746EE0C0FF6F90043875E0BF1D9BE6B7D779FC978DC2A5"),
label: "instance 2",
creator: "purple1nxvenxve42424242hwamhwamenxvenxvmhwamhwaamhwamhwlllsatsy6m",
expAddress: "purple1vae2kf0r3ehtq5q2jmfkg7wp4ckxwrw8dv4pvazz5nlzzu05lxzq878fa9",
},
"codeID > max u32": {
srcCodeID: math.MaxUint32 + 1,
srcInstanceID: 17,
expectedAddr: "cosmos1673hrexz4h6s0ft04l96ygq667djzh2nsr335kstjp49x5dk6rpsf5t0le",
"account addr with different checksum": {
checksum: fromHex("1DA6C16DE2CBAF7AD8CBB66F0925BA33F5C278CB2491762D04658C1480EA229B"),
label: "instance 1",
creator: "purple1nxvenxve42424242hwamhwamenxvenxvhxf2py",
expAddress: "purple1gmgvt9levtn52mpfal3gl5tv60f47zez3wgczrh5c9352sfm9crs47zt0k",
},
"instanceID > max u32": {
srcCodeID: 22,
srcInstanceID: math.MaxUint32 + 1,
expectedAddr: "cosmos10q3pgfvmeyy0veekgtqhxujxkhz0vm9zmalqgc7evrhj68q3l62qrdfg4m",
"account addr with different checksum and label": {
checksum: fromHex("1DA6C16DE2CBAF7AD8CBB66F0925BA33F5C278CB2491762D04658C1480EA229B"),
label: "instance 2",
creator: "purple1nxvenxve42424242hwamhwamenxvenxvhxf2py",
expAddress: "purple13jrcqxknt05rhdxmegjzjel666yay6fj3xvfp6445k7a9q2km4wqa7ss34",
},
"contract addr with different checksum": {
checksum: fromHex("1DA6C16DE2CBAF7AD8CBB66F0925BA33F5C278CB2491762D04658C1480EA229B"),
label: "instance 1",
creator: "purple1nxvenxve42424242hwamhwamenxvenxvmhwamhwaamhwamhwlllsatsy6m",
expAddress: "purple1lu0lf6wmqeuwtrx93ptzvf4l0dyyz2vz6s8h5y9cj42fvhsmracq49pww9",
},
"contract addr with different checksum and label": {
checksum: fromHex("1DA6C16DE2CBAF7AD8CBB66F0925BA33F5C278CB2491762D04658C1480EA229B"),
label: "instance 2",
creator: "purple1nxvenxve42424242hwamhwamenxvenxvmhwamhwaamhwamhwlllsatsy6m",
expAddress: "purple1zmerc8a9ml2au29rq3knuu35fktef3akceurckr6pf370n0wku7sw3c9mj",
},
// regression tests
"min label size": {
checksum: fromHex("13A1FC994CC6D1C81B746EE0C0FF6F90043875E0BF1D9BE6B7D779FC978DC2A5"),
label: "x",
creator: "purple1nxvenxve42424242hwamhwamenxvenxvhxf2py",
expAddress: "purple16pc8gt824lmp3dh2sxvttj0ykcs02n5p3ldswhv3j7y853gghlfq7mqeh9",
},
"max label size": {
checksum: fromHex("13A1FC994CC6D1C81B746EE0C0FF6F90043875E0BF1D9BE6B7D779FC978DC2A5"),
label: strings.Repeat("x", types.MaxLabelSize),
creator: "purple1nxvenxve42424242hwamhwamenxvenxvhxf2py",
expAddress: "purple1prkdvjmvv4s3tnppfxmlpj259v9cplf3wws4qq9qd7w3s4yqzqeqem4759",
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
gotAddr := BuildContractAddress(spec.srcCodeID, spec.srcInstanceID)
require.NotNil(t, gotAddr)
assert.Nil(t, sdk.VerifyAddressFormat(gotAddr))
if len(spec.expectedAddr) > 0 {
require.Equal(t, spec.expectedAddr, gotAddr.String())
}
creatorAddr, err := sdk.AccAddressFromBech32(spec.creator)
require.NoError(t, err)
// when
gotAddr := BuildContractAddress(spec.checksum, creatorAddr, spec.label)
require.Equal(t, spec.expAddress, gotAddr.String())
require.NoError(t, sdk.VerifyAddressFormat(gotAddr))
})
}
}
func fromHex(s string) []byte {
r, err := hex.DecodeString(s)
if err != nil {
panic(err)
}
return r
}
func TestSetAccessConfig(t *testing.T) {
parentCtx, keepers := CreateTestInput(t, false, AvailableCapabilities)
k := keepers.WasmKeeper

View File

@ -21,13 +21,13 @@ func TestLegacyQueryContractState(t *testing.T) {
keeper := keepers.WasmKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
anyAddr := keepers.Faucet.NewFundedAccount(ctx, sdk.NewInt64Coin("denom", 5000))
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit.Add(deposit...)...)
anyAddr := keepers.Faucet.NewFundedRandomAccount(ctx, sdk.NewInt64Coin("denom", 5000))
wasmCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)
contractID, err := keepers.ContractKeeper.Create(ctx, creator, wasmCode, nil)
contractID, _, err := keepers.ContractKeeper.Create(ctx, creator, wasmCode, nil)
require.NoError(t, err)
_, _, bob := keyPubAddr()
@ -159,13 +159,13 @@ func TestLegacyQueryContractListByCodeOrdering(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 1000000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 500))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit.Add(deposit...)...)
anyAddr := keepers.Faucet.NewFundedAccount(ctx, topUp...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit.Add(deposit...)...)
anyAddr := keepers.Faucet.NewFundedRandomAccount(ctx, topUp...)
wasmCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)
codeID, err := keepers.ContractKeeper.Create(ctx, creator, wasmCode, nil)
codeID, _, err := keepers.ContractKeeper.Create(ctx, creator, wasmCode, nil)
require.NoError(t, err)
_, _, bob := keyPubAddr()

View File

@ -0,0 +1,27 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/CosmWasm/wasmd/x/wasm/types"
)
// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
keeper *Keeper
}
// NewMigrator returns a new Migrator.
func NewMigrator(keeper *Keeper) Migrator {
return Migrator{keeper: keeper}
}
var keyLastInstanceID = append(types.SequenceKeyPrefix, []byte("lastContractId")...)
// Migrate1to2 migrates from version 1 to 2.
// Remove the unused sequence for address generation
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
store := ctx.KVStore(m.keeper.storeKey)
store.Delete(keyLastInstanceID)
return nil
}

View File

@ -0,0 +1,20 @@
package keeper
import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert"
)
func TestMigrateV1ToV2(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
store := ctx.KVStore(keepers.WasmKeeper.storeKey)
store.Set(keyLastInstanceID, sdk.Uint64ToBigEndian(100))
// when
NewMigrator(keepers.WasmKeeper).Migrate1to2(ctx)
// then
assert.False(t, store.Has(keyLastInstanceID))
}

View File

@ -32,13 +32,14 @@ func (m msgServer) StoreCode(goCtx context.Context, msg *types.MsgStoreCode) (*t
sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender),
))
codeID, err := m.keeper.Create(ctx, senderAddr, msg.WASMByteCode, msg.InstantiatePermission)
codeID, checksum, err := m.keeper.Create(ctx, senderAddr, msg.WASMByteCode, msg.InstantiatePermission)
if err != nil {
return nil, err
}
return &types.MsgStoreCodeResponse{
CodeID: codeID,
CodeID: codeID,
Checksum: checksum,
}, nil
}

View File

@ -0,0 +1,46 @@
package keeper_test
import (
"crypto/sha256"
_ "embed"
"testing"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/CosmWasm/wasmd/app"
"github.com/CosmWasm/wasmd/x/wasm/types"
)
//go:embed testdata/reflect.wasm
var wasmContract []byte
func TestStoreCode(t *testing.T) {
wasmApp := app.Setup(false)
ctx := wasmApp.BaseApp.NewContext(false, tmproto.Header{})
_, _, sender := testdata.KeyTestPubAddr()
msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) {
m.WASMByteCode = wasmContract
m.Sender = sender.String()
})
// when
rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
// then
require.NoError(t, err)
var result types.MsgStoreCodeResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result))
assert.Equal(t, uint64(1), result.CodeID)
expHash := sha256.Sum256(wasmContract)
assert.Equal(t, expHash[:], result.Checksum)
// and
info := wasmApp.WasmKeeper.GetCodeInfo(ctx, 1)
assert.NotNil(t, info)
assert.Equal(t, expHash[:], info.CodeHash)
assert.Equal(t, sender.String(), info.Creator)
assert.Equal(t, types.DefaultParams().InstantiateDefaultPermission.With(sender), info.InstantiateConfig)
}

View File

@ -2,7 +2,9 @@ package keeper
import (
"fmt"
"reflect"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/prometheus/client_golang/prometheus"
"github.com/CosmWasm/wasmd/x/wasm/types"
@ -89,11 +91,25 @@ func WithMessageEncoders(x *MessageEncoders) Option {
// WithCoinTransferrer is an optional constructor parameter to set a custom coin transferrer
func WithCoinTransferrer(x CoinTransferrer) Option {
if x == nil {
panic("must not be nil")
}
return optsFn(func(k *Keeper) {
k.bank = x
})
}
// WithCoinPruner is an optional constructor parameter to set a custom type that handles balances
// for accounts pruned on contract instantiate
func WithCoinPruner(x CoinPruner) Option {
if x == nil {
panic("must not be nil")
}
return optsFn(func(k *Keeper) {
k.coinPruner = x
})
}
func WithVMCacheMetrics(r prometheus.Registerer) Option {
return optsFn(func(k *Keeper) {
NewWasmVMMetricsCollector(k.wasmVM).Register(r)
@ -104,6 +120,9 @@ func WithVMCacheMetrics(r prometheus.Registerer) Option {
// When the "gas multiplier" for wasmvm gas conversion is modified inside the new register,
// make sure to also use `WithApiCosts` option for non default values
func WithGasRegister(x GasRegister) Option {
if x == nil {
panic("must not be nil")
}
return optsFn(func(k *Keeper) {
k.gasRegister = x
})
@ -123,3 +142,42 @@ func WithMaxQueryStackSize(m uint32) Option {
k.maxQueryStackSize = m
})
}
// WithAcceptedAccountTypesOnContractInstantiation sets the accepted account types. Account types of this list won't be overwritten or cause a failure
// when they exist for an address on contract instantiation.
//
// Values should be references and contain the `*authtypes.BaseAccount` as default bank account type.
func WithAcceptedAccountTypesOnContractInstantiation(accts ...authtypes.AccountI) Option {
m := asTypeMap(accts)
return optsFn(func(k *Keeper) {
k.acceptedAccountTypes = m
})
}
// WithPruneAccountTypesOnContractInstantiation sets the account types that should be cleared. Account types of this list
// will be overwritten with the BaseAccount type and their balance burned, when they exist for an address on contract
// instantiation.
//
// Values should be references and contain the `*vestingtypes.DelayedVestingAccount`, `*vestingtypes.ContinuousVestingAccount`
// as post genesis account types with an open address range.
func WithPruneAccountTypesOnContractInstantiation(accts ...authtypes.AccountI) Option {
m := asTypeMap(accts)
return optsFn(func(k *Keeper) {
k.pruneAccountTypes = m
})
}
func asTypeMap(accts []authtypes.AccountI) map[reflect.Type]struct{} {
m := make(map[reflect.Type]struct{}, len(accts))
for _, a := range accts {
if a == nil {
panic(types.ErrEmpty.Wrap("address"))
}
at := reflect.TypeOf(a)
if _, exists := m[at]; exists {
panic(types.ErrDuplicate.Wrapf("%T", a))
}
m[at] = struct{}{}
}
return m
}

View File

@ -1,9 +1,13 @@
package keeper
import (
"reflect"
"testing"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
@ -81,10 +85,36 @@ func TestConstructorOptions(t *testing.T) {
assert.IsType(t, uint32(1), k.maxQueryStackSize)
},
},
"accepted account types": {
srcOpt: WithAcceptedAccountTypesOnContractInstantiation(&authtypes.BaseAccount{}, &vestingtypes.ContinuousVestingAccount{}),
verify: func(t *testing.T, k Keeper) {
exp := map[reflect.Type]struct{}{
reflect.TypeOf(&authtypes.BaseAccount{}): {},
reflect.TypeOf(&vestingtypes.ContinuousVestingAccount{}): {},
}
assert.Equal(t, exp, k.acceptedAccountTypes)
},
},
"prune account types": {
srcOpt: WithPruneAccountTypesOnContractInstantiation(&authtypes.BaseAccount{}, &vestingtypes.ContinuousVestingAccount{}),
verify: func(t *testing.T, k Keeper) {
exp := map[reflect.Type]struct{}{
reflect.TypeOf(&authtypes.BaseAccount{}): {},
reflect.TypeOf(&vestingtypes.ContinuousVestingAccount{}): {},
}
assert.Equal(t, exp, k.pruneAccountTypes)
},
},
"coin pruner": {
srcOpt: WithCoinPruner(CoinBurner{}),
verify: func(t *testing.T, k Keeper) {
assert.Equal(t, CoinBurner{}, k.coinPruner)
},
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
k := NewKeeper(nil, nil, paramtypes.NewSubspace(nil, nil, nil, nil, ""), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, "tempDir", types.DefaultWasmConfig(), AvailableCapabilities, spec.srcOpt)
k := NewKeeper(nil, nil, paramtypes.NewSubspace(nil, nil, nil, nil, ""), authkeeper.AccountKeeper{}, &bankkeeper.BaseKeeper{}, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, "tempDir", types.DefaultWasmConfig(), AvailableCapabilities, spec.srcOpt)
spec.verify(t, k)
})
}

View File

@ -64,7 +64,7 @@ func handleStoreCodeProposal(ctx sdk.Context, k types.ContractOpsKeeper, p types
if err != nil {
return sdkerrors.Wrap(err, "run as address")
}
codeID, err := k.Create(ctx, runAsAddr, p.WASMByteCode, p.InstantiatePermission)
codeID, _, err := k.Create(ctx, runAsAddr, p.WASMByteCode, p.InstantiatePermission)
if err != nil {
return err
}

View File

@ -2,6 +2,7 @@ package keeper
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
@ -116,9 +117,8 @@ func TestInstantiateProposal(t *testing.T) {
require.NoError(t, err)
// then
contractAddr, err := sdk.AccAddressFromBech32("cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr")
require.NoError(t, err)
codeHash := keepers.WasmKeeper.GetCodeInfo(ctx, 1).CodeHash
contractAddr := BuildContractAddress(codeHash, oneAddress, "testing")
cInfo := wasmKeeper.GetContractInfo(ctx, contractAddr)
require.NotNil(t, cInfo)
assert.Equal(t, uint64(1), cInfo.CodeID)
@ -188,9 +188,8 @@ func TestInstantiateProposal_NoAdmin(t *testing.T) {
require.NoError(t, err)
// then
contractAddr, err := sdk.AccAddressFromBech32("cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr")
require.NoError(t, err)
codeHash := keepers.WasmKeeper.GetCodeInfo(ctx, 1).CodeHash
contractAddr := BuildContractAddress(codeHash, oneAddress, "testing")
cInfo := wasmKeeper.GetContractInfo(ctx, contractAddr)
require.NotNil(t, cInfo)
assert.Equal(t, uint64(1), cInfo.CodeID)
@ -229,9 +228,9 @@ func TestMigrateProposal(t *testing.T) {
require.NoError(t, wasmKeeper.importCode(ctx, 2, codeInfoFixture, wasmCode))
var (
anyAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, types.ContractAddrLen)
otherAddress sdk.AccAddress = bytes.Repeat([]byte{0x2}, types.ContractAddrLen)
contractAddr = BuildContractAddress(1, 1)
anyAddress = DeterministicAccountAddress(t, 1)
otherAddress = DeterministicAccountAddress(t, 2)
contractAddr = BuildContractAddress(codeInfoFixture.CodeHash, RandomAccountAddress(t), "")
)
contractInfoFixture := types.ContractInfoFixture(func(c *types.ContractInfo) {
@ -408,12 +407,13 @@ func TestSudoProposal(t *testing.T) {
}
func TestAdminProposals(t *testing.T) {
var (
otherAddress sdk.AccAddress = bytes.Repeat([]byte{0x2}, types.ContractAddrLen)
contractAddr = BuildContractAddress(1, 1)
)
wasmCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)
var (
otherAddress = DeterministicAccountAddress(t, 2)
codeHash = sha256.Sum256(wasmCode)
contractAddr = BuildContractAddress(codeHash[:], RandomAccountAddress(t), "")
)
specs := map[string]struct {
state types.ContractInfo

View File

@ -158,8 +158,9 @@ func TestQuerySmartContractState(t *testing.T) {
func TestQuerySmartContractPanics(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, AvailableCapabilities)
contractAddr := BuildContractAddress(1, 1)
keepers.WasmKeeper.storeCodeInfo(ctx, 1, types.CodeInfo{})
creator := RandomAccountAddress(t)
contractAddr := BuildContractAddress([]byte("myCodeHash"), creator, "testing")
keepers.WasmKeeper.storeCodeInfo(ctx, 1, types.CodeInfo{CodeHash: []byte("myCodeHash")})
keepers.WasmKeeper.storeContractInfo(ctx, contractAddr, &types.ContractInfo{
CodeID: 1,
Created: types.NewAbsoluteTxPosition(ctx),
@ -262,13 +263,13 @@ func TestQueryContractListByCodeOrdering(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 1000000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 500))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
anyAddr := keepers.Faucet.NewFundedAccount(ctx, topUp...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
anyAddr := keepers.Faucet.NewFundedRandomAccount(ctx, topUp...)
wasmCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)
codeID, err := keepers.ContractKeeper.Create(ctx, creator, wasmCode, nil)
codeID, _, err := keepers.ContractKeeper.Create(ctx, creator, wasmCode, nil)
require.NoError(t, err)
_, _, bob := keyPubAddr()

View File

@ -43,18 +43,18 @@ func TestReflectContractSend(t *testing.T) {
accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.ContractKeeper, keepers.BankKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
_, _, bob := keyPubAddr()
// upload reflect code
reflectID, err := keeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
reflectID, _, err := keeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
require.Equal(t, uint64(1), reflectID)
// upload hackatom escrow code
escrowCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)
escrowID, err := keeper.Create(ctx, creator, escrowCode, nil)
escrowID, _, err := keeper.Create(ctx, creator, escrowCode, nil)
require.NoError(t, err)
require.Equal(t, uint64(2), escrowID)
@ -122,12 +122,12 @@ func TestReflectCustomMsg(t *testing.T) {
accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.ContractKeeper, keepers.BankKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
bob := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
bob := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
_, _, fred := keyPubAddr()
// upload code
codeID, err := keeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
codeID, _, err := keeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
require.Equal(t, uint64(1), codeID)
@ -213,10 +213,10 @@ func TestMaskReflectCustomQuery(t *testing.T) {
keeper := keepers.WasmKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
// upload code
codeID, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
codeID, _, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
require.Equal(t, uint64(1), codeID)
@ -263,10 +263,10 @@ func TestReflectStargateQuery(t *testing.T) {
funds := sdk.NewCoins(sdk.NewInt64Coin("denom", 320000))
contractStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 40000))
expectedBalance := funds.Sub(contractStart)
creator := keepers.Faucet.NewFundedAccount(ctx, funds...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, funds...)
// upload code
codeID, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
codeID, _, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
require.Equal(t, uint64(1), codeID)
@ -303,7 +303,7 @@ func TestReflectTotalSupplyQuery(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, ReflectFeatures, WithMessageEncoders(reflectEncoders(cdc)), WithQueryPlugins(reflectPlugins()))
keeper := keepers.WasmKeeper
// upload code
codeID := StoreReflectContract(t, ctx, keepers)
codeID := StoreReflectContract(t, ctx, keepers).CodeID
// creator instantiates a contract and gives it tokens
creator := RandomAccountAddress(t)
contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, codeID, creator, nil, []byte("{}"), "testing", nil)
@ -356,10 +356,10 @@ func TestReflectInvalidStargateQuery(t *testing.T) {
funds := sdk.NewCoins(sdk.NewInt64Coin("denom", 320000))
contractStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 40000))
creator := keepers.Faucet.NewFundedAccount(ctx, funds...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, funds...)
// upload code
codeID, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
codeID, _, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
require.Equal(t, uint64(1), codeID)
@ -434,10 +434,10 @@ func TestMaskReflectWasmQueries(t *testing.T) {
keeper := keepers.WasmKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
// upload reflect code
reflectID, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
reflectID, _, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
require.Equal(t, uint64(1), reflectID)
@ -504,10 +504,10 @@ func TestWasmRawQueryWithNil(t *testing.T) {
keeper := keepers.WasmKeeper
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
// upload reflect code
reflectID, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
reflectID, _, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
require.Equal(t, uint64(1), reflectID)

View File

@ -55,11 +55,10 @@ func TestSnapshotter(t *testing.T) {
for i, v := range spec.wasmFiles {
wasmCode, err := os.ReadFile(v)
require.NoError(t, err)
codeID, err := contractKeeper.Create(ctx, genesisAddr, wasmCode, nil)
codeID, checksum, err := contractKeeper.Create(ctx, genesisAddr, wasmCode, nil)
require.NoError(t, err)
require.Equal(t, uint64(i+1), codeID)
hash := sha256.Sum256(wasmCode)
srcCodeIDToChecksum[codeID] = hash[:]
srcCodeIDToChecksum[codeID] = checksum
}
// create snapshot
srcWasmApp.Commit()

View File

@ -103,12 +103,12 @@ func TestInitializeStaking(t *testing.T) {
assert.Equal(t, v.GetDelegatorShares(), sdk.NewDec(1234567))
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000), sdk.NewInt64Coin("stake", 500000))
creator := k.Faucet.NewFundedAccount(ctx, deposit...)
creator := k.Faucet.NewFundedRandomAccount(ctx, deposit...)
// upload staking derivates code
stakingCode, err := os.ReadFile("./testdata/staking.wasm")
require.NoError(t, err)
stakingID, err := keeper.Create(ctx, creator, stakingCode, nil)
stakingID, _, err := keeper.Create(ctx, creator, stakingCode, nil)
require.NoError(t, err)
require.Equal(t, uint64(1), stakingID)
@ -186,12 +186,12 @@ func initializeStaking(t *testing.T) initInfo {
assert.Equal(t, v.Status, stakingtypes.Bonded)
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000), sdk.NewInt64Coin("stake", 500000))
creator := k.Faucet.NewFundedAccount(ctx, deposit...)
creator := k.Faucet.NewFundedRandomAccount(ctx, deposit...)
// upload staking derivates code
stakingCode, err := os.ReadFile("./testdata/staking.wasm")
require.NoError(t, err)
stakingID, err := k.ContractKeeper.Create(ctx, creator, stakingCode, nil)
stakingID, _, err := k.ContractKeeper.Create(ctx, creator, stakingCode, nil)
require.NoError(t, err)
require.Equal(t, uint64(1), stakingID)
@ -239,7 +239,7 @@ func TestBonding(t *testing.T) {
// bob has 160k, putting 80k into the contract
full := sdk.NewCoins(sdk.NewInt64Coin("stake", 160000))
funds := sdk.NewCoins(sdk.NewInt64Coin("stake", 80000))
bob := initInfo.faucet.NewFundedAccount(ctx, full...)
bob := initInfo.faucet.NewFundedRandomAccount(ctx, full...)
// check contract state before
assertBalance(t, ctx, keeper, contractAddr, bob, "0")
@ -287,7 +287,7 @@ func TestUnbonding(t *testing.T) {
// bob has 160k, putting 80k into the contract
full := sdk.NewCoins(sdk.NewInt64Coin("stake", 160000))
funds := sdk.NewCoins(sdk.NewInt64Coin("stake", 80000))
bob := initInfo.faucet.NewFundedAccount(ctx, full...)
bob := initInfo.faucet.NewFundedRandomAccount(ctx, full...)
bond := StakingHandleMsg{
Bond: &struct{}{},
@ -354,7 +354,7 @@ func TestReinvest(t *testing.T) {
// full is 2x funds, 1x goes to the contract, other stays on his wallet
full := sdk.NewCoins(sdk.NewInt64Coin("stake", 400000))
funds := sdk.NewCoins(sdk.NewInt64Coin("stake", 200000))
bob := initInfo.faucet.NewFundedAccount(ctx, full...)
bob := initInfo.faucet.NewFundedRandomAccount(ctx, full...)
// we will stake 200k to a validator with 1M self-bond
// this means we should get 1/6 of the rewards
@ -422,7 +422,7 @@ func TestQueryStakingInfo(t *testing.T) {
// full is 2x funds, 1x goes to the contract, other stays on his wallet
full := sdk.NewCoins(sdk.NewInt64Coin("stake", 400000))
funds := sdk.NewCoins(sdk.NewInt64Coin("stake", 200000))
bob := initInfo.faucet.NewFundedAccount(ctx, full...)
bob := initInfo.faucet.NewFundedRandomAccount(ctx, full...)
// we will stake 200k to a validator with 1M self-bond
// this means we should get 1/6 of the rewards
@ -444,10 +444,10 @@ func TestQueryStakingInfo(t *testing.T) {
// STEP 2: Prepare the mask contract
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
creator := initInfo.faucet.NewFundedAccount(ctx, deposit...)
creator := initInfo.faucet.NewFundedRandomAccount(ctx, deposit...)
// upload mask code
maskID, err := initInfo.contractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
maskID, _, err := initInfo.contractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
require.Equal(t, uint64(2), maskID)
@ -599,7 +599,7 @@ func TestQueryStakingPlugin(t *testing.T) {
// full is 2x funds, 1x goes to the contract, other stays on his wallet
full := sdk.NewCoins(sdk.NewInt64Coin("stake", 400000))
funds := sdk.NewCoins(sdk.NewInt64Coin("stake", 200000))
bob := initInfo.faucet.NewFundedAccount(ctx, full...)
bob := initInfo.faucet.NewFundedRandomAccount(ctx, full...)
// we will stake 200k to a validator with 1M self-bond
// this means we should get 1/6 of the rewards
@ -652,7 +652,7 @@ func TestQueryStakingPlugin(t *testing.T) {
// adds a few validators and returns a list of validators that are registered
func addValidator(t *testing.T, ctx sdk.Context, stakingKeeper stakingkeeper.Keeper, faucet *TestFaucet, value sdk.Coin) sdk.ValAddress {
owner := faucet.NewFundedAccount(ctx, value)
owner := faucet.NewFundedRandomAccount(ctx, value)
privKey := secp256k1.GenPrivKey()
pubKey := privKey.PubKey()

View File

@ -26,12 +26,12 @@ func TestDispatchSubMsgSuccessCase(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
contractStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 40000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
creatorBalance := deposit.Sub(contractStart)
_, _, fred := keyPubAddr()
// upload code
codeID, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
codeID, _, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
require.Equal(t, uint64(1), codeID)
@ -110,16 +110,16 @@ func TestDispatchSubMsgErrorHandling(t *testing.T) {
ctx = ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter())
keeper := keepers.WasmKeeper
contractStart := sdk.NewCoins(sdk.NewInt64Coin(fundedDenom, int64(fundedAmount)))
uploader := keepers.Faucet.NewFundedAccount(ctx, contractStart.Add(contractStart...)...)
uploader := keepers.Faucet.NewFundedRandomAccount(ctx, contractStart.Add(contractStart...)...)
// upload code
reflectID, err := keepers.ContractKeeper.Create(ctx, uploader, testdata.ReflectContractWasm(), nil)
reflectID, _, err := keepers.ContractKeeper.Create(ctx, uploader, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
// create hackatom contract for testing (for infinite loop)
hackatomCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)
hackatomID, err := keepers.ContractKeeper.Create(ctx, uploader, hackatomCode, nil)
hackatomID, _, err := keepers.ContractKeeper.Create(ctx, uploader, hackatomCode, nil)
require.NoError(t, err)
_, _, bob := keyPubAddr()
_, _, fred := keyPubAddr()
@ -282,7 +282,7 @@ func TestDispatchSubMsgErrorHandling(t *testing.T) {
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
creator := keepers.Faucet.NewFundedAccount(ctx, contractStart...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, contractStart...)
_, _, empty := keyPubAddr()
contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, reflectID, creator, nil, []byte("{}"), fmt.Sprintf("contract %s", name), contractStart)
@ -366,11 +366,11 @@ func TestDispatchSubMsgEncodeToNoSdkMsg(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
contractStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 40000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
_, _, fred := keyPubAddr()
// upload code
codeID, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
codeID, _, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
// creator instantiates a contract and gives it tokens
@ -432,11 +432,11 @@ func TestDispatchSubMsgConditionalReplyOn(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
contractStart := sdk.NewCoins(sdk.NewInt64Coin("denom", 40000))
creator := keepers.Faucet.NewFundedAccount(ctx, deposit...)
creator := keepers.Faucet.NewFundedRandomAccount(ctx, deposit...)
_, _, fred := keyPubAddr()
// upload code
codeID, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
codeID, _, err := keepers.ContractKeeper.Create(ctx, creator, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
// creator instantiates a contract and gives it tokens

View File

@ -1,6 +1,7 @@
package keeper
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
@ -8,7 +9,9 @@ import (
"testing"
"time"
"github.com/CosmWasm/wasmd/x/wasm/keeper/testdata"
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
@ -91,6 +94,7 @@ var moduleBasics = module.NewBasicManager(
upgrade.AppModuleBasic{},
evidence.AppModuleBasic{},
transfer.AppModuleBasic{},
vesting.AppModuleBasic{},
)
func MakeTestCodec(t testing.TB) codec.Codec {
@ -162,7 +166,7 @@ func (f *TestFaucet) Fund(parentCtx sdk.Context, receiver sdk.AccAddress, amount
f.balance = f.balance.Sub(amounts)
}
func (f *TestFaucet) NewFundedAccount(ctx sdk.Context, amounts ...sdk.Coin) sdk.AccAddress {
func (f *TestFaucet) NewFundedRandomAccount(ctx sdk.Context, amounts ...sdk.Coin) sdk.AccAddress {
_, _, addr := keyPubAddr()
f.Fund(ctx, addr, amounts...)
return addr
@ -464,7 +468,7 @@ func handleStoreCode(ctx sdk.Context, k types.ContractOpsKeeper, msg *types.MsgS
if err != nil {
return nil, sdkerrors.Wrap(err, "sender")
}
codeID, err := k.Create(ctx, senderAddr, msg.WASMByteCode, msg.InstantiatePermission)
codeID, _, err := k.Create(ctx, senderAddr, msg.WASMByteCode, msg.InstantiatePermission)
if err != nil {
return nil, err
}
@ -523,6 +527,11 @@ func RandomAccountAddress(_ testing.TB) sdk.AccAddress {
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()
}
@ -532,6 +541,7 @@ type ExampleContract struct {
Creator crypto.PrivKey
CreatorAddr sdk.AccAddress
CodeID uint64
Checksum []byte
}
func StoreHackatomExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) ExampleContract {
@ -546,11 +556,8 @@ func StoreIBCReflectContract(t testing.TB, ctx sdk.Context, keepers TestKeepers)
return StoreExampleContract(t, ctx, keepers, "./testdata/ibc_reflect.wasm")
}
func StoreReflectContract(t testing.TB, ctx sdk.Context, keepers TestKeepers) uint64 {
_, _, creatorAddr := keyPubAddr()
codeID, err := keepers.ContractKeeper.Create(ctx, creatorAddr, testdata.ReflectContractWasm(), nil)
require.NoError(t, err)
return codeID
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 {
@ -561,9 +568,10 @@ func StoreExampleContract(t testing.TB, ctx sdk.Context, keepers TestKeepers, wa
wasmCode, err := os.ReadFile(wasmFile)
require.NoError(t, err)
codeID, err := keepers.ContractKeeper.Create(ctx, creatorAddr, wasmCode, nil)
codeID, _, err := keepers.ContractKeeper.Create(ctx, creatorAddr, wasmCode, nil)
require.NoError(t, err)
return ExampleContract{anyAmount, creator, creatorAddr, codeID}
hash := keepers.WasmKeeper.GetCodeInfo(ctx, codeID).CodeHash
return ExampleContract{anyAmount, creator, creatorAddr, codeID, hash}
}
var wasmIdent = []byte("\x00\x61\x73\x6D")
@ -602,9 +610,9 @@ func StoreRandomContractWithAccessConfig(
fundAccounts(t, ctx, keepers.AccountKeeper, keepers.BankKeeper, creatorAddr, anyAmount)
keepers.WasmKeeper.wasmVM = mock
wasmCode := append(wasmIdent, rand.Bytes(10)...) //nolint:gocritic
codeID, err := keepers.ContractKeeper.Create(ctx, creatorAddr, wasmCode, cfg)
codeID, checksum, err := keepers.ContractKeeper.Create(ctx, creatorAddr, wasmCode, cfg)
require.NoError(t, err)
exampleContract := ExampleContract{InitialAmount: anyAmount, Creator: creator, CreatorAddr: creatorAddr, CodeID: codeID}
exampleContract := ExampleContract{InitialAmount: anyAmount, Creator: creator, CreatorAddr: creatorAddr, CodeID: codeID, Checksum: checksum}
return exampleContract
}
@ -615,6 +623,8 @@ type HackatomExampleInstance struct {
VerifierAddr sdk.AccAddress
Beneficiary crypto.PrivKey
BeneficiaryAddr sdk.AccAddress
Label string
Deposit sdk.Coins
}
// InstantiateHackatomExampleContract load and instantiate the "./testdata/hackatom.wasm" contract
@ -632,7 +642,8 @@ func InstantiateHackatomExampleContract(t testing.TB, ctx sdk.Context, keepers T
initialAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 100))
adminAddr := contract.CreatorAddr
contractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx, contract.CodeID, contract.CreatorAddr, adminAddr, initMsgBz, "demo contract to query", initialAmount)
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,
@ -641,6 +652,31 @@ func InstantiateHackatomExampleContract(t testing.TB, ctx sdk.Context, keepers T
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, nil, []byte("{}"), label, initialAmount)
require.NoError(t, err)
return ExampleInstance{
ExampleContract: example,
Contract: contractAddr,
Label: label,
Deposit: initialAmount,
}
}
@ -664,7 +700,7 @@ type IBCReflectExampleInstance struct {
// 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)
reflectID := StoreReflectContract(t, ctx, keepers).CodeID
ibcReflectID := StoreIBCReflectContract(t, ctx, keepers).CodeID
initMsgBz := IBCReflectInitMsg{

View File

@ -111,7 +111,7 @@ type AppModule struct {
// module. It should be incremented on each consensus-breaking change
// introduced by the module. To avoid wrong/empty versions, the initial version
// should be set to 1.
func (AppModule) ConsensusVersion() uint64 { return 1 }
func (AppModule) ConsensusVersion() uint64 { return 2 }
// NewAppModule creates a new AppModule object
func NewAppModule(
@ -134,6 +134,11 @@ func NewAppModule(
func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(keeper.NewDefaultPermissionKeeper(am.keeper)))
types.RegisterQueryServer(cfg.QueryServer(), NewQuerier(am.keeper))
m := keeper.NewMigrator(am.keeper)
if err := cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2); err != nil {
panic(err)
}
}
func (am AppModule) LegacyQuerierHandler(amino *codec.LegacyAmino) sdk.Querier { //nolint:staticcheck

View File

@ -1,11 +1,14 @@
package wasm
import (
"bytes"
"encoding/json"
"fmt"
"os"
"testing"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/CosmWasm/wasmd/x/wasm/keeper/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -145,7 +148,8 @@ type state struct {
func TestHandleInstantiate(t *testing.T) {
data := setupTest(t)
creator := data.faucet.NewFundedAccount(data.ctx, sdk.NewInt64Coin("denom", 100000))
creator := sdk.AccAddress(bytes.Repeat([]byte{1}, address.Len))
data.faucet.Fund(data.ctx, creator, sdk.NewInt64Coin("denom", 100000))
h := data.module.Route().Handler()
q := data.module.LegacyQuerierHandler(nil)
@ -179,7 +183,7 @@ func TestHandleInstantiate(t *testing.T) {
require.NoError(t, err)
contractBech32Addr := parseInitResponse(t, res.Data)
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", contractBech32Addr)
require.Equal(t, "cosmos1400ax8h2dxe8ch64sus5sczqdhwv28hpjkkaphpa83he4fhz6k4qcm9kul", contractBech32Addr)
// this should be standard x/wasm init event, nothing from contract
require.Equal(t, 3, len(res.Events), prettyEvents(res.Events))
require.Equal(t, "message", res.Events[0].Type)
@ -206,8 +210,10 @@ func TestHandleExecute(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := data.faucet.NewFundedAccount(data.ctx, deposit.Add(deposit...)...)
fred := data.faucet.NewFundedAccount(data.ctx, topUp...)
creator := sdk.AccAddress(bytes.Repeat([]byte{1}, address.Len))
data.faucet.Fund(data.ctx, creator, sdk.NewInt64Coin("denom", 100000*2))
fred := data.faucet.NewFundedRandomAccount(data.ctx, topUp...)
h := data.module.Route().Handler()
q := data.module.LegacyQuerierHandler(nil)
@ -238,7 +244,7 @@ func TestHandleExecute(t *testing.T) {
require.NoError(t, err)
contractBech32Addr := parseInitResponse(t, res.Data)
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", contractBech32Addr)
require.Equal(t, "cosmos1400ax8h2dxe8ch64sus5sczqdhwv28hpjkkaphpa83he4fhz6k4qcm9kul", contractBech32Addr)
// this should be standard x/wasm message event, init event, plus a bank send event (2), with no custom contract events
require.Equal(t, 6, len(res.Events), prettyEvents(res.Events))
require.Equal(t, "message", res.Events[0].Type)
@ -341,8 +347,9 @@ func TestHandleExecuteEscrow(t *testing.T) {
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := data.faucet.NewFundedAccount(data.ctx, deposit.Add(deposit...)...)
fred := data.faucet.NewFundedAccount(data.ctx, topUp...)
creator := sdk.AccAddress(bytes.Repeat([]byte{1}, address.Len))
data.faucet.Fund(data.ctx, creator, sdk.NewInt64Coin("denom", 100000))
fred := data.faucet.NewFundedRandomAccount(data.ctx, topUp...)
h := data.module.Route().Handler()
@ -370,7 +377,7 @@ func TestHandleExecuteEscrow(t *testing.T) {
res, err = h(data.ctx, &initCmd)
require.NoError(t, err)
contractBech32Addr := parseInitResponse(t, res.Data)
require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", contractBech32Addr)
require.Equal(t, "cosmos1400ax8h2dxe8ch64sus5sczqdhwv28hpjkkaphpa83he4fhz6k4qcm9kul", contractBech32Addr)
handleMsg := map[string]interface{}{
"release": map[string]interface{}{},

View File

@ -15,7 +15,6 @@ func RandomizedGenState(simstate *module.SimulationState) {
Contracts: nil,
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: simstate.Rand.Uint64()},
{IDKey: types.KeyLastInstanceID, Value: simstate.Rand.Uint64()},
},
GenMsgs: nil,
}

View File

@ -23,6 +23,7 @@ const (
AttributeKeyContractAddr = "_contract_address"
AttributeKeyCodeID = "code_id"
AttributeKeyChecksum = "code_checksum"
AttributeKeyResultDataHex = "result"
AttributeKeyRequiredCapability = "required_capability"
)

View File

@ -26,7 +26,7 @@ type ViewKeeper interface {
// ContractOpsKeeper contains mutable operations on a contract.
type ContractOpsKeeper interface {
// Create uploads and compiles a WASM contract, returning a short identifier for the contract
Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, instantiateAccess *AccessConfig) (codeID uint64, err error)
Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, instantiateAccess *AccessConfig) (codeID uint64, checksum []byte, err error)
// Instantiate creates an instance of a WASM contract
Instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.AccAddress, initMsg []byte, label string, deposit sdk.Coins) (sdk.AccAddress, []byte, error)

View File

@ -32,8 +32,7 @@ var (
PinnedCodeIndexPrefix = []byte{0x07}
TXCounterPrefix = []byte{0x08}
KeyLastCodeID = append(SequenceKeyPrefix, []byte("lastCodeId")...)
KeyLastInstanceID = append(SequenceKeyPrefix, []byte("lastContractId")...)
KeyLastCodeID = append(SequenceKeyPrefix, []byte("lastCodeId")...)
)
// GetCodeKey constructs the key for retreiving the ID for the WASM code

View File

@ -170,7 +170,7 @@ func (p InstantiateContractProposal) ValidateBasic() error {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "code id is required")
}
if err := validateLabel(p.Label); err != nil {
if err := ValidateLabel(p.Label); err != nil {
return err
}

View File

@ -95,7 +95,7 @@ func (msg MsgInstantiateContract) ValidateBasic() error {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "code id is required")
}
if err := validateLabel(msg.Label); err != nil {
if err := ValidateLabel(msg.Label); err != nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "label is required")
}

View File

@ -87,6 +87,8 @@ var xxx_messageInfo_MsgStoreCode proto.InternalMessageInfo
type MsgStoreCodeResponse struct {
// CodeID is the reference to the stored WASM code
CodeID uint64 `protobuf:"varint,1,opt,name=code_id,json=codeId,proto3" json:"code_id,omitempty"`
// Checksum is the sha256 hash of the stored code
Checksum []byte `protobuf:"bytes,2,opt,name=checksum,proto3" json:"checksum,omitempty"`
}
func (m *MsgStoreCodeResponse) Reset() { *m = MsgStoreCodeResponse{} }
@ -611,55 +613,55 @@ func init() {
func init() { proto.RegisterFile("cosmwasm/wasm/v1/tx.proto", fileDescriptor_4f74d82755520264) }
var fileDescriptor_4f74d82755520264 = []byte{
// 759 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xcd, 0x6e, 0xd3, 0x4a,
0x14, 0x8e, 0x1b, 0x27, 0x4d, 0x4e, 0x73, 0x7b, 0x23, 0xdf, 0x36, 0x37, 0xf5, 0xbd, 0x72, 0xa2,
0x80, 0x8a, 0x17, 0x60, 0x37, 0x45, 0x62, 0xc3, 0xaa, 0x49, 0x59, 0xb4, 0x92, 0x11, 0x72, 0x55,
0x2a, 0xd8, 0x44, 0x13, 0x7b, 0x6a, 0x2c, 0x1a, 0x4f, 0xf0, 0x71, 0x9b, 0xf6, 0x25, 0x10, 0x3b,
0xde, 0x81, 0xb7, 0x60, 0xd7, 0x15, 0xea, 0x06, 0x89, 0x55, 0x80, 0xf4, 0x2d, 0x58, 0x21, 0xff,
0xa5, 0x6e, 0xea, 0xa4, 0x41, 0x88, 0x4d, 0x32, 0xc7, 0xf3, 0x7d, 0xe7, 0xcc, 0xf9, 0xf4, 0xcd,
0x19, 0x58, 0x33, 0x18, 0xf6, 0x06, 0x04, 0x7b, 0x6a, 0xf0, 0x73, 0xd2, 0x54, 0xbd, 0x53, 0xa5,
0xef, 0x32, 0x8f, 0x09, 0xe5, 0x78, 0x4b, 0x09, 0x7e, 0x4e, 0x9a, 0xa2, 0xe4, 0x7f, 0x61, 0xa8,
0x76, 0x09, 0x52, 0xf5, 0xa4, 0xd9, 0xa5, 0x1e, 0x69, 0xaa, 0x06, 0xb3, 0x9d, 0x90, 0x21, 0xae,
0x58, 0xcc, 0x62, 0xc1, 0x52, 0xf5, 0x57, 0xd1, 0xd7, 0xff, 0x6f, 0x96, 0x38, 0xeb, 0x53, 0x0c,
0x77, 0x1b, 0x1f, 0x39, 0x28, 0x69, 0x68, 0xed, 0x79, 0xcc, 0xa5, 0x6d, 0x66, 0x52, 0xa1, 0x02,
0x79, 0xa4, 0x8e, 0x49, 0xdd, 0x2a, 0x57, 0xe7, 0xe4, 0xa2, 0x1e, 0x45, 0xc2, 0x23, 0x58, 0xf6,
0xf9, 0x9d, 0xee, 0x99, 0x47, 0x3b, 0x06, 0x33, 0x69, 0x75, 0xa1, 0xce, 0xc9, 0xa5, 0x56, 0x79,
0x34, 0xac, 0x95, 0x0e, 0xb6, 0xf6, 0xb4, 0xd6, 0x99, 0x17, 0x64, 0xd0, 0x4b, 0x3e, 0x2e, 0x8e,
0x84, 0x7d, 0xa8, 0xd8, 0x0e, 0x7a, 0xc4, 0xf1, 0x6c, 0xe2, 0xd1, 0x4e, 0x9f, 0xba, 0x3d, 0x1b,
0xd1, 0x66, 0x4e, 0x35, 0x57, 0xe7, 0xe4, 0xa5, 0x4d, 0x49, 0x99, 0xec, 0x53, 0xd9, 0x32, 0x0c,
0x8a, 0xd8, 0x66, 0xce, 0xa1, 0x6d, 0xe9, 0xab, 0x09, 0xf6, 0xb3, 0x31, 0x79, 0x97, 0x2f, 0x64,
0xcb, 0xfc, 0x2e, 0x5f, 0xe0, 0xcb, 0xb9, 0xc6, 0x63, 0x58, 0x49, 0xb6, 0xa0, 0x53, 0xec, 0x33,
0x07, 0xa9, 0x70, 0x07, 0x16, 0xfd, 0x83, 0x76, 0x6c, 0x33, 0xe8, 0x85, 0x6f, 0xc1, 0x68, 0x58,
0xcb, 0xfb, 0x90, 0x9d, 0x6d, 0x3d, 0xef, 0x6f, 0xed, 0x98, 0x8d, 0xb7, 0x0b, 0x50, 0xd1, 0xd0,
0xda, 0xb9, 0xaa, 0xd2, 0x66, 0x8e, 0xe7, 0x12, 0xc3, 0x9b, 0x2a, 0xc5, 0x0a, 0xe4, 0x88, 0xd9,
0xb3, 0x9d, 0x40, 0x81, 0xa2, 0x1e, 0x06, 0xc9, 0x6a, 0xd9, 0x69, 0xd5, 0x7c, 0xea, 0x11, 0xe9,
0xd2, 0xa3, 0x2a, 0x1f, 0x52, 0x83, 0x40, 0x90, 0x21, 0xdb, 0x43, 0x2b, 0x10, 0xa4, 0xd4, 0xaa,
0xfc, 0x18, 0xd6, 0x04, 0x9d, 0x0c, 0xe2, 0x63, 0x68, 0x14, 0x91, 0x58, 0x54, 0xf7, 0x21, 0x02,
0x81, 0xdc, 0xe1, 0xb1, 0x63, 0x62, 0x35, 0x5f, 0xcf, 0xca, 0x4b, 0x9b, 0x6b, 0x4a, 0x68, 0x09,
0xc5, 0xb7, 0x84, 0x12, 0x59, 0x42, 0x69, 0x33, 0xdb, 0x69, 0x6d, 0x9c, 0x0f, 0x6b, 0x99, 0x0f,
0x5f, 0x6b, 0xb2, 0x65, 0x7b, 0xaf, 0x8e, 0xbb, 0x8a, 0xc1, 0x7a, 0x6a, 0xe4, 0x9f, 0xf0, 0xef,
0x01, 0x9a, 0xaf, 0x23, 0x2b, 0xf8, 0x04, 0xd4, 0xc3, 0xcc, 0x8d, 0xa7, 0x20, 0xa5, 0xeb, 0x31,
0xd6, 0xb5, 0x0a, 0x8b, 0xc4, 0x34, 0x5d, 0x8a, 0x18, 0x09, 0x13, 0x87, 0x82, 0x00, 0xbc, 0x49,
0x3c, 0x12, 0x5a, 0x43, 0x0f, 0xd6, 0x8d, 0xcf, 0x1c, 0x08, 0x1a, 0x5a, 0x4f, 0x4e, 0xa9, 0x71,
0x3c, 0x87, 0xb8, 0x22, 0x14, 0x8c, 0x08, 0x13, 0xe9, 0x3b, 0x8e, 0x63, 0x9d, 0xb2, 0xbf, 0xa0,
0x53, 0xee, 0x8f, 0xe9, 0xb4, 0x01, 0xe2, 0xcd, 0xb6, 0xc6, 0x1a, 0xc5, 0x4a, 0x70, 0x09, 0x25,
0xde, 0x87, 0x4a, 0x68, 0xb6, 0xe5, 0x92, 0xdf, 0x54, 0x62, 0x2e, 0xb3, 0x45, 0x72, 0xf1, 0xb7,
0xca, 0x15, 0xf5, 0x32, 0x71, 0xb0, 0x99, 0xbd, 0x10, 0x58, 0xd6, 0xd0, 0xda, 0xef, 0x9b, 0xc4,
0xa3, 0x5b, 0x81, 0xff, 0xa7, 0xb5, 0xf1, 0x1f, 0x14, 0x1d, 0x3a, 0xe8, 0x24, 0x6f, 0x4c, 0xc1,
0xa1, 0x83, 0x90, 0x94, 0xec, 0x31, 0x7b, 0xbd, 0xc7, 0x46, 0x35, 0xb8, 0x98, 0x89, 0x12, 0xf1,
0x81, 0x1a, 0x6d, 0xf8, 0x4b, 0x43, 0xab, 0x7d, 0x44, 0x89, 0x3b, 0xbb, 0xf6, 0xac, 0xf4, 0xff,
0xc2, 0xea, 0xb5, 0x24, 0x71, 0xf6, 0xcd, 0x4f, 0x3c, 0x64, 0x35, 0xb4, 0x84, 0x3d, 0x28, 0x5e,
0x8d, 0xc5, 0x94, 0x31, 0x95, 0x9c, 0x39, 0xe2, 0xfa, 0xec, 0xfd, 0xb1, 0x96, 0x6f, 0xe0, 0x9f,
0xb4, 0x51, 0x23, 0xa7, 0xd2, 0x53, 0x90, 0xe2, 0xc6, 0xbc, 0xc8, 0x71, 0x49, 0x0a, 0x7f, 0x4f,
0x5e, 0xbe, 0xbb, 0xa9, 0x49, 0x26, 0x50, 0xe2, 0xfd, 0x79, 0x50, 0xc9, 0x32, 0x93, 0xce, 0x4e,
0x2f, 0x33, 0x81, 0x9a, 0x52, 0x66, 0x9a, 0x19, 0x5f, 0xc0, 0x52, 0xd2, 0x75, 0xf5, 0x54, 0x72,
0x02, 0x21, 0xca, 0xb7, 0x21, 0xc6, 0xa9, 0x9f, 0x03, 0x24, 0x3c, 0x55, 0x4b, 0xe5, 0x5d, 0x01,
0xc4, 0x7b, 0xb7, 0x00, 0xe2, 0xbc, 0xad, 0xed, 0xf3, 0xef, 0x52, 0xe6, 0x7c, 0x24, 0x71, 0x17,
0x23, 0x89, 0xfb, 0x36, 0x92, 0xb8, 0x77, 0x97, 0x52, 0xe6, 0xe2, 0x52, 0xca, 0x7c, 0xb9, 0x94,
0x32, 0x2f, 0xd7, 0x13, 0x83, 0xa7, 0xcd, 0xb0, 0x77, 0x10, 0x3f, 0xd5, 0xa6, 0x7a, 0x1a, 0x3e,
0xd9, 0xc1, 0xf0, 0xe9, 0xe6, 0x83, 0x07, 0xfb, 0xe1, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x56,
0xd2, 0x4b, 0x17, 0x33, 0x08, 0x00, 0x00,
// 766 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xcb, 0x6e, 0xd3, 0x40,
0x14, 0x8d, 0x1b, 0x27, 0x4d, 0x6e, 0x43, 0x89, 0x4c, 0x1a, 0x52, 0x83, 0x9c, 0x28, 0xa0, 0xe2,
0x05, 0xd8, 0x4d, 0x91, 0xd8, 0x37, 0x29, 0x8b, 0x56, 0x32, 0x42, 0xae, 0x4a, 0x05, 0x9b, 0x68,
0x62, 0x4f, 0x5d, 0xab, 0xb5, 0x27, 0x78, 0x9c, 0xa6, 0xfd, 0x09, 0xc4, 0x8e, 0x7f, 0xe0, 0x2f,
0xd8, 0x75, 0x85, 0xba, 0x41, 0x62, 0x15, 0x20, 0xfd, 0x0b, 0x56, 0xc8, 0xcf, 0xba, 0xa9, 0x93,
0x06, 0x21, 0x36, 0xce, 0xdc, 0x99, 0x73, 0x5f, 0x27, 0x67, 0xee, 0xc0, 0xaa, 0x46, 0xa8, 0x35,
0x44, 0xd4, 0x92, 0xfd, 0xcf, 0x49, 0x4b, 0x76, 0x4f, 0xa5, 0xbe, 0x43, 0x5c, 0xc2, 0x95, 0xa3,
0x23, 0xc9, 0xff, 0x9c, 0xb4, 0x78, 0xc1, 0xdb, 0x21, 0x54, 0xee, 0x21, 0x8a, 0xe5, 0x93, 0x56,
0x0f, 0xbb, 0xa8, 0x25, 0x6b, 0xc4, 0xb4, 0x03, 0x0f, 0xbe, 0x62, 0x10, 0x83, 0xf8, 0x4b, 0xd9,
0x5b, 0x85, 0xbb, 0x0f, 0x6f, 0xa6, 0x38, 0xeb, 0x63, 0x1a, 0x9c, 0x36, 0xbf, 0x30, 0x50, 0x52,
0xa8, 0xb1, 0xeb, 0x12, 0x07, 0x77, 0x88, 0x8e, 0xb9, 0x2a, 0xe4, 0x29, 0xb6, 0x75, 0xec, 0xd4,
0x98, 0x06, 0x23, 0x16, 0xd5, 0xd0, 0xe2, 0x5e, 0xc0, 0xb2, 0xe7, 0xdf, 0xed, 0x9d, 0xb9, 0xb8,
0xab, 0x11, 0x1d, 0xd7, 0x16, 0x1a, 0x8c, 0x58, 0x6a, 0x97, 0xc7, 0xa3, 0x7a, 0x69, 0x7f, 0x73,
0x57, 0x69, 0x9f, 0xb9, 0x7e, 0x04, 0xb5, 0xe4, 0xe1, 0x22, 0x8b, 0xdb, 0x83, 0xaa, 0x69, 0x53,
0x17, 0xd9, 0xae, 0x89, 0x5c, 0xdc, 0xed, 0x63, 0xc7, 0x32, 0x29, 0x35, 0x89, 0x5d, 0xcb, 0x35,
0x18, 0x71, 0x69, 0x43, 0x90, 0x26, 0xfb, 0x94, 0x36, 0x35, 0x0d, 0x53, 0xda, 0x21, 0xf6, 0x81,
0x69, 0xa8, 0x2b, 0x09, 0xef, 0xd7, 0xb1, 0xf3, 0x0e, 0x5b, 0xc8, 0x96, 0xd9, 0x1d, 0xb6, 0xc0,
0x96, 0x73, 0xcd, 0x7d, 0xa8, 0x24, 0x5b, 0x50, 0x31, 0xed, 0x13, 0x9b, 0x62, 0xee, 0x11, 0x2c,
0x7a, 0x85, 0x76, 0x4d, 0xdd, 0xef, 0x85, 0x6d, 0xc3, 0x78, 0x54, 0xcf, 0x7b, 0x90, 0xed, 0x2d,
0x35, 0xef, 0x1d, 0x6d, 0xeb, 0x1c, 0x0f, 0x05, 0xed, 0x10, 0x6b, 0x47, 0x74, 0x60, 0x05, 0x1d,
0xa9, 0xb1, 0xdd, 0xfc, 0xb0, 0x00, 0x55, 0x85, 0x1a, 0xdb, 0x57, 0x15, 0x74, 0x88, 0xed, 0x3a,
0x48, 0x73, 0xa7, 0xd2, 0x54, 0x81, 0x1c, 0xd2, 0x2d, 0xd3, 0xf6, 0x63, 0x15, 0xd5, 0xc0, 0x48,
0x56, 0x92, 0x9d, 0x5a, 0x49, 0x05, 0x72, 0xc7, 0xa8, 0x87, 0x8f, 0x6b, 0x6c, 0xe0, 0xea, 0x1b,
0x9c, 0x08, 0x59, 0x8b, 0x1a, 0x3e, 0x59, 0xa5, 0x76, 0xf5, 0xf7, 0xa8, 0xce, 0xa9, 0x68, 0x18,
0x95, 0xa1, 0x60, 0x4a, 0x91, 0x81, 0x55, 0x0f, 0xc2, 0x21, 0xc8, 0x1d, 0x0c, 0x6c, 0x9d, 0xd6,
0xf2, 0x8d, 0xac, 0xb8, 0xb4, 0xb1, 0x2a, 0x05, 0x72, 0x91, 0x3c, 0xb9, 0x48, 0xa1, 0x5c, 0xa4,
0x0e, 0x31, 0xed, 0xf6, 0xfa, 0xf9, 0xa8, 0x9e, 0xf9, 0xfc, 0xa3, 0x2e, 0x1a, 0xa6, 0x7b, 0x38,
0xe8, 0x49, 0x1a, 0xb1, 0xe4, 0x50, 0x5b, 0xc1, 0xcf, 0x33, 0xaa, 0x1f, 0x85, 0x32, 0xf1, 0x1c,
0xa8, 0x1a, 0x44, 0x6e, 0xbe, 0x02, 0x21, 0x9d, 0x8f, 0x98, 0xf3, 0x1a, 0x2c, 0x22, 0x5d, 0x77,
0x30, 0xa5, 0x21, 0x31, 0x91, 0xc9, 0x71, 0xc0, 0xea, 0xc8, 0x45, 0x21, 0xc9, 0xfe, 0xba, 0xf9,
0x8d, 0x01, 0x4e, 0xa1, 0xc6, 0xcb, 0x53, 0xac, 0x0d, 0xe6, 0x20, 0xd7, 0xfb, 0xaf, 0x42, 0x4c,
0xc8, 0x6f, 0x6c, 0x47, 0x3c, 0x65, 0xff, 0x82, 0xa7, 0xdc, 0x7f, 0xe3, 0x69, 0x1d, 0xf8, 0x9b,
0x6d, 0xc5, 0x1c, 0x45, 0x4c, 0x30, 0x09, 0x26, 0x3e, 0x05, 0x4c, 0x28, 0xa6, 0xe1, 0xa0, 0x7f,
0x64, 0x62, 0x2e, 0xb1, 0x85, 0x74, 0xb1, 0xb7, 0xd2, 0x15, 0xf6, 0x32, 0x51, 0xd8, 0xcc, 0x5e,
0x10, 0x2c, 0x2b, 0xd4, 0xd8, 0xeb, 0xeb, 0xc8, 0xc5, 0x9b, 0xbe, 0xfe, 0xa7, 0xb5, 0xf1, 0x00,
0x8a, 0x36, 0x1e, 0x76, 0x93, 0x37, 0xa6, 0x60, 0xe3, 0x61, 0xe0, 0x94, 0xec, 0x31, 0x7b, 0xbd,
0xc7, 0x66, 0xcd, 0xbf, 0x98, 0x89, 0x14, 0x51, 0x41, 0xcd, 0x0e, 0xdc, 0x51, 0xa8, 0xd1, 0x39,
0xc6, 0xc8, 0x99, 0x9d, 0x7b, 0x56, 0xf8, 0xfb, 0xb0, 0x72, 0x2d, 0x48, 0x14, 0x7d, 0xe3, 0x2b,
0x0b, 0x59, 0x85, 0x1a, 0xdc, 0x2e, 0x14, 0xaf, 0x46, 0x66, 0xca, 0x08, 0x4b, 0xce, 0x23, 0x7e,
0x6d, 0xf6, 0x79, 0xcc, 0xe5, 0x7b, 0xb8, 0x97, 0x36, 0x6a, 0xc4, 0x54, 0xf7, 0x14, 0x24, 0xbf,
0x3e, 0x2f, 0x32, 0x4e, 0x89, 0xe1, 0xee, 0xe4, 0xe5, 0x7b, 0x9c, 0x1a, 0x64, 0x02, 0xc5, 0x3f,
0x9d, 0x07, 0x95, 0x4c, 0x33, 0xa9, 0xec, 0xf4, 0x34, 0x13, 0xa8, 0x29, 0x69, 0xa6, 0x89, 0xf1,
0x2d, 0x2c, 0x25, 0x55, 0xd7, 0x48, 0x75, 0x4e, 0x20, 0x78, 0xf1, 0x36, 0x44, 0x1c, 0xfa, 0x0d,
0x40, 0x42, 0x53, 0xf5, 0x54, 0xbf, 0x2b, 0x00, 0xff, 0xe4, 0x16, 0x40, 0x14, 0xb7, 0xbd, 0x75,
0xfe, 0x4b, 0xc8, 0x9c, 0x8f, 0x05, 0xe6, 0x62, 0x2c, 0x30, 0x3f, 0xc7, 0x02, 0xf3, 0xf1, 0x52,
0xc8, 0x5c, 0x5c, 0x0a, 0x99, 0xef, 0x97, 0x42, 0xe6, 0xdd, 0x5a, 0x62, 0xf0, 0x74, 0x08, 0xb5,
0xf6, 0xa3, 0x67, 0x5c, 0x97, 0x4f, 0x83, 0xe7, 0xdc, 0x1f, 0x3e, 0xbd, 0xbc, 0xff, 0x98, 0x3f,
0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0xef, 0x6b, 0xa0, 0xa3, 0x4f, 0x08, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -1007,6 +1009,13 @@ func (m *MsgStoreCodeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.Checksum) > 0 {
i -= len(m.Checksum)
copy(dAtA[i:], m.Checksum)
i = encodeVarintTx(dAtA, i, uint64(len(m.Checksum)))
i--
dAtA[i] = 0x12
}
if m.CodeID != 0 {
i = encodeVarintTx(dAtA, i, uint64(m.CodeID))
i--
@ -1458,6 +1467,10 @@ func (m *MsgStoreCodeResponse) Size() (n int) {
if m.CodeID != 0 {
n += 1 + sovTx(uint64(m.CodeID))
}
l = len(m.Checksum)
if l > 0 {
n += 1 + l + sovTx(uint64(l))
}
return n
}
@ -1854,6 +1867,40 @@ func (m *MsgStoreCodeResponse) Unmarshal(dAtA []byte) error {
break
}
}
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Checksum", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTx
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthTx
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthTx
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Checksum = append(m.Checksum[:0], dAtA[iNdEx:postIndex]...)
if m.Checksum == nil {
m.Checksum = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTx(dAtA[iNdEx:])

View File

@ -84,6 +84,7 @@ func TestInstantiateContractValidation(t *testing.T) {
badAddress := bad.String()
// proper address size
goodAddress := sdk.AccAddress(make([]byte, 20)).String()
sdk.GetConfig().SetAddressVerifier(VerifyAddressLen())
cases := map[string]struct {
msg MsgInstantiateContract

View File

@ -88,7 +88,7 @@ func (c *ContractInfo) ValidateBasic() error {
return sdkerrors.Wrap(err, "admin")
}
}
if err := validateLabel(c.Label); err != nil {
if err := ValidateLabel(c.Label); err != nil {
return sdkerrors.Wrap(err, "label")
}
if c.Extension == nil {

View File

@ -22,7 +22,8 @@ func validateWasmCode(s []byte) error {
return nil
}
func validateLabel(label string) error {
// ValidateLabel ensure label constraints
func ValidateLabel(label string) error {
if label == "" {
return sdkerrors.Wrap(ErrEmpty, "is required")
}