wasmd/tests/integration/msg_server_integration_test.go

1230 lines
36 KiB
Go

package integration
import (
_ "embed"
"encoding/json"
"testing"
"time"
wasmvm "github.com/CosmWasm/wasmvm/v3"
wasmvmtypes "github.com/CosmWasm/wasmvm/v3/types"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/CosmWasm/wasmd/app"
"github.com/CosmWasm/wasmd/x/wasm/keeper"
"github.com/CosmWasm/wasmd/x/wasm/types"
)
//go:embed testdata/reflect_1_5.wasm
var wasmContract []byte
//go:embed testdata/hackatom.wasm
var hackatomContract []byte
func TestStoreCode(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContext(false)
_, _, 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, err := wasmvm.CreateChecksum(wasmContract)
require.NoError(t, err)
assert.Equal(t, expHash[:], wasmvmtypes.Checksum(result.Checksum))
// and
info := wasmApp.WasmKeeper.GetCodeInfo(ctx, 1)
assert.NotNil(t, info)
assert.Equal(t, expHash[:], wasmvmtypes.Checksum(info.CodeHash))
assert.Equal(t, sender.String(), info.Creator)
assert.Equal(t, types.DefaultParams().InstantiateDefaultPermission.With(sender), info.InstantiateConfig)
}
func TestUpdateParams(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContext(false)
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
oneAddressAccessConfig = types.AccessTypeAnyOfAddresses.With(myAddress)
govAuthority = wasmApp.WasmKeeper.GetAuthority()
)
specs := map[string]struct {
src types.MsgUpdateParams
expUploadConfig types.AccessConfig
expInstantiateType types.AccessType
}{
"update upload permission param": {
src: types.MsgUpdateParams{
Authority: govAuthority,
Params: types.Params{
CodeUploadAccess: types.AllowNobody,
InstantiateDefaultPermission: types.AccessTypeEverybody,
},
},
expUploadConfig: types.AllowNobody,
expInstantiateType: types.AccessTypeEverybody,
},
"update upload permission with same as current value": {
src: types.MsgUpdateParams{
Authority: govAuthority,
Params: types.Params{
CodeUploadAccess: types.AllowEverybody,
InstantiateDefaultPermission: types.AccessTypeEverybody,
},
},
expUploadConfig: types.AllowEverybody,
expInstantiateType: types.AccessTypeEverybody,
},
"update upload permission param with address": {
src: types.MsgUpdateParams{
Authority: govAuthority,
Params: types.Params{
CodeUploadAccess: oneAddressAccessConfig,
InstantiateDefaultPermission: types.AccessTypeEverybody,
},
},
expUploadConfig: oneAddressAccessConfig,
expInstantiateType: types.AccessTypeEverybody,
},
"update instantiate param": {
src: types.MsgUpdateParams{
Authority: govAuthority,
Params: types.Params{
CodeUploadAccess: types.AllowEverybody,
InstantiateDefaultPermission: types.AccessTypeNobody,
},
},
expUploadConfig: types.AllowEverybody,
expInstantiateType: types.AccessTypeNobody,
},
"update instantiate param as default": {
src: types.MsgUpdateParams{
Authority: govAuthority,
Params: types.Params{
CodeUploadAccess: types.AllowEverybody,
InstantiateDefaultPermission: types.AccessTypeEverybody,
},
},
expUploadConfig: types.AllowEverybody,
expInstantiateType: types.AccessTypeEverybody,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
err := wasmApp.WasmKeeper.SetParams(ctx, types.DefaultParams())
require.NoError(t, err)
// when
rsp, err := wasmApp.MsgServiceRouter().Handler(&spec.src)(ctx, &spec.src) //nolint:gosec
require.NoError(t, err)
var result types.MsgUpdateParamsResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result))
// then
assert.True(t, spec.expUploadConfig.Equals(wasmApp.WasmKeeper.GetParams(ctx).CodeUploadAccess),
"got %#v not %#v", wasmApp.WasmKeeper.GetParams(ctx).CodeUploadAccess, spec.expUploadConfig)
assert.Equal(t, spec.expInstantiateType, wasmApp.WasmKeeper.GetParams(ctx).InstantiateDefaultPermission)
})
}
}
func TestAddCodeUploadParamsAddresses(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContext(false)
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
_, _, otherAddr = testdata.KeyTestPubAddr()
govAuthority = wasmApp.WasmKeeper.GetAuthority()
)
specs := map[string]struct {
src types.MsgAddCodeUploadParamsAddresses
uploadConfig types.AccessConfig
expUploadConfig types.AccessConfig
expErr bool
}{
"authority can add addresses when permission is any of addresses": {
src: types.MsgAddCodeUploadParamsAddresses{
Authority: govAuthority,
Addresses: []string{otherAddr.String()},
},
uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress),
expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr),
},
"add existing address": {
src: types.MsgAddCodeUploadParamsAddresses{
Authority: govAuthority,
Addresses: []string{myAddress.String()},
},
uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress),
expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress),
},
"authority cannot add addresses when permission is allow everybody": {
src: types.MsgAddCodeUploadParamsAddresses{
Authority: govAuthority,
Addresses: []string{otherAddr.String()},
},
uploadConfig: types.AllowEverybody,
expUploadConfig: types.AllowEverybody,
expErr: true,
},
"authority cannot add addresses when permission is allow nobody": {
src: types.MsgAddCodeUploadParamsAddresses{
Authority: govAuthority,
Addresses: []string{otherAddr.String()},
},
uploadConfig: types.AllowNobody,
expUploadConfig: types.AllowNobody,
expErr: true,
},
"authority cannot add duplicate addresses when permission is any of addresses": {
src: types.MsgAddCodeUploadParamsAddresses{
Authority: govAuthority,
Addresses: []string{otherAddr.String(), otherAddr.String()},
},
uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress),
expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress),
expErr: true,
},
"other address cannot add addresses when permission is any of addresses": {
src: types.MsgAddCodeUploadParamsAddresses{
Authority: otherAddr.String(),
Addresses: []string{otherAddr.String()},
},
uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress),
expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr),
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
err := wasmApp.WasmKeeper.SetParams(ctx, types.Params{
CodeUploadAccess: spec.uploadConfig,
InstantiateDefaultPermission: types.AccessTypeEverybody,
})
require.NoError(t, err)
// when
rsp, err := wasmApp.MsgServiceRouter().Handler(&spec.src)(ctx, &spec.src) //nolint:gosec
if spec.expErr {
require.Error(t, err)
require.Nil(t, rsp)
return
}
require.NoError(t, err)
require.Len(t, rsp.MsgResponses, 1)
assert.IsType(t, rsp.MsgResponses[0].GetCachedValue(), &types.MsgAddCodeUploadParamsAddressesResponse{})
// then
gotUploadConfig := wasmApp.WasmKeeper.GetParams(ctx).CodeUploadAccess
assert.True(t, spec.expUploadConfig.Equals(gotUploadConfig),
"got %#v not %#v", gotUploadConfig, spec.expUploadConfig)
})
}
}
func TestRemoveCodeUploadParamsAddresses(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContext(false)
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
_, _, otherAddr = testdata.KeyTestPubAddr()
govAuthority = wasmApp.WasmKeeper.GetAuthority()
)
specs := map[string]struct {
src types.MsgRemoveCodeUploadParamsAddresses
uploadConfig types.AccessConfig
expUploadConfig types.AccessConfig
expErr bool
}{
"authority can remove addresses when permission is any of addresses": {
src: types.MsgRemoveCodeUploadParamsAddresses{
Authority: govAuthority,
Addresses: []string{otherAddr.String()},
},
uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr),
expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress),
},
"authority cannot remove not existing addresses when permission is any of addresses": {
src: types.MsgRemoveCodeUploadParamsAddresses{
Authority: govAuthority,
Addresses: []string{otherAddr.String()},
},
uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress),
expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress),
},
"authority cannot remove addresses when permission is allow everybody": {
src: types.MsgRemoveCodeUploadParamsAddresses{
Authority: govAuthority,
Addresses: []string{otherAddr.String()},
},
uploadConfig: types.AllowEverybody,
expUploadConfig: types.AllowEverybody,
expErr: true,
},
"authority cannot remove addresses when permission is allow nobody": {
src: types.MsgRemoveCodeUploadParamsAddresses{
Authority: govAuthority,
Addresses: []string{otherAddr.String()},
},
uploadConfig: types.AllowNobody,
expUploadConfig: types.AllowNobody,
expErr: true,
},
"authority cannot remove duplicate addresses when permission is any of addresses": {
src: types.MsgRemoveCodeUploadParamsAddresses{
Authority: govAuthority,
Addresses: []string{otherAddr.String(), otherAddr.String()},
},
uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr),
expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr),
expErr: true,
},
"other address cannot remove addresses when permission is any of addresses": {
src: types.MsgRemoveCodeUploadParamsAddresses{
Authority: otherAddr.String(),
Addresses: []string{otherAddr.String()},
},
uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr),
expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr),
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
err := wasmApp.WasmKeeper.SetParams(ctx, types.Params{
CodeUploadAccess: spec.uploadConfig,
InstantiateDefaultPermission: types.AccessTypeEverybody,
})
require.NoError(t, err)
// when
rsp, err := wasmApp.MsgServiceRouter().Handler(&spec.src)(ctx, &spec.src) //nolint:gosec
if spec.expErr {
require.Error(t, err)
require.Nil(t, rsp)
return
}
require.NoError(t, err)
require.Len(t, rsp.MsgResponses, 1)
assert.IsType(t, rsp.MsgResponses[0].GetCachedValue(), &types.MsgRemoveCodeUploadParamsAddressesResponse{})
// then
gotUploadConfig := wasmApp.WasmKeeper.GetParams(ctx).CodeUploadAccess
assert.True(t, spec.expUploadConfig.Equals(gotUploadConfig),
"got %#v not %#v", gotUploadConfig, spec.expUploadConfig)
})
}
}
func TestPinCodes(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContext(false)
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
)
specs := map[string]struct {
addr string
expErr bool
}{
"authority can pin codes": {
addr: authority,
expErr: false,
},
"other address cannot pin codes": {
addr: myAddress.String(),
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// setup
_, _, sender := testdata.KeyTestPubAddr()
msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) {
m.WASMByteCode = wasmContract
m.Sender = sender.String()
})
// store code
rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
require.NoError(t, err)
var result types.MsgStoreCodeResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result))
require.False(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID))
// when
msgPinCodes := &types.MsgPinCodes{
Authority: spec.addr,
CodeIDs: []uint64{result.CodeID},
}
_, err = wasmApp.MsgServiceRouter().Handler(msgPinCodes)(ctx, msgPinCodes)
// then
if spec.expErr {
require.Error(t, err)
assert.False(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID))
} else {
require.NoError(t, err)
assert.True(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID))
}
})
}
}
func TestUnpinCodes(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContext(false)
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
)
specs := map[string]struct {
addr string
expErr bool
}{
"authority can unpin codes": {
addr: authority,
expErr: false,
},
"other address cannot unpin codes": {
addr: myAddress.String(),
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// setup
_, _, sender := testdata.KeyTestPubAddr()
msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) {
m.WASMByteCode = wasmContract
m.Sender = sender.String()
})
// store code
rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
require.NoError(t, err)
var result types.MsgStoreCodeResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result))
// pin code
msgPin := &types.MsgPinCodes{
Authority: authority,
CodeIDs: []uint64{result.CodeID},
}
_, err = wasmApp.MsgServiceRouter().Handler(msgPin)(ctx, msgPin)
require.NoError(t, err)
assert.True(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID))
// when
msgUnpinCodes := &types.MsgUnpinCodes{
Authority: spec.addr,
CodeIDs: []uint64{result.CodeID},
}
_, err = wasmApp.MsgServiceRouter().Handler(msgUnpinCodes)(ctx, msgUnpinCodes)
// then
if spec.expErr {
require.Error(t, err)
assert.True(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID))
} else {
require.NoError(t, err)
assert.False(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID))
}
})
}
}
func TestSudoContract(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()})
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
)
type StealMsg struct {
Recipient string `json:"recipient"`
Amount []sdk.Coin `json:"amount"`
}
stealMsg := struct {
Steal StealMsg `json:"steal_funds"`
}{Steal: StealMsg{
Recipient: myAddress.String(),
Amount: []sdk.Coin{},
}}
stealMsgBz, err := json.Marshal(stealMsg)
require.NoError(t, err)
specs := map[string]struct {
addr string
expErr bool
}{
"authority can call sudo on a contract": {
addr: authority,
expErr: false,
},
"other address cannot call sudo on a contract": {
addr: myAddress.String(),
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// setup
_, _, sender := testdata.KeyTestPubAddr()
msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) {
m.WASMByteCode = hackatomContract
m.Sender = sender.String()
})
// store code
rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
require.NoError(t, err)
var storeCodeResponse types.MsgStoreCodeResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeCodeResponse))
// instantiate contract
initMsg := keeper.HackatomExampleInitMsg{
Verifier: sender,
Beneficiary: myAddress,
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
msgInstantiate := &types.MsgInstantiateContract{
Sender: sender.String(),
Admin: sender.String(),
CodeID: storeCodeResponse.CodeID,
Label: "test",
Msg: initMsgBz,
Funds: sdk.Coins{},
}
rsp, err = wasmApp.MsgServiceRouter().Handler(msgInstantiate)(ctx, msgInstantiate)
require.NoError(t, err)
var instantiateResponse types.MsgInstantiateContractResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &instantiateResponse))
// when
msgSudoContract := &types.MsgSudoContract{
Authority: spec.addr,
Msg: stealMsgBz,
Contract: instantiateResponse.Address,
}
_, err = wasmApp.MsgServiceRouter().Handler(msgSudoContract)(ctx, msgSudoContract)
// then
if spec.expErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
func TestStoreAndInstantiateContract(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()})
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
)
specs := map[string]struct {
addr string
permission *types.AccessConfig
expErr bool
}{
"authority can store and instantiate a contract when permission is nobody": {
addr: authority,
permission: &types.AllowNobody,
expErr: false,
},
"other address cannot store and instantiate a contract when permission is nobody": {
addr: myAddress.String(),
permission: &types.AllowNobody,
expErr: true,
},
"authority can store and instantiate a contract when permission is everybody": {
addr: authority,
permission: &types.AllowEverybody,
expErr: false,
},
"other address can store and instantiate a contract when permission is everybody": {
addr: myAddress.String(),
permission: &types.AllowEverybody,
expErr: false,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// when
msg := &types.MsgStoreAndInstantiateContract{
Authority: spec.addr,
WASMByteCode: wasmContract,
InstantiatePermission: spec.permission,
Admin: myAddress.String(),
UnpinCode: false,
Label: "test",
Msg: []byte(`{}`),
Funds: sdk.Coins{},
}
_, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
// then
if spec.expErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
func TestUpdateAdmin(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()})
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
_, _, otherAddr = testdata.KeyTestPubAddr()
)
specs := map[string]struct {
addr string
expErr bool
}{
"authority can update admin": {
addr: authority,
expErr: false,
},
"admin can update admin": {
addr: myAddress.String(),
expErr: false,
},
"other address cannot update admin": {
addr: otherAddr.String(),
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
_, _, newAdmin := testdata.KeyTestPubAddr()
// setup
msg := &types.MsgStoreAndInstantiateContract{
Authority: spec.addr,
WASMByteCode: wasmContract,
InstantiatePermission: &types.AllowEverybody,
Admin: myAddress.String(),
UnpinCode: false,
Label: "test",
Msg: []byte(`{}`),
Funds: sdk.Coins{},
}
rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
require.NoError(t, err)
var storeAndInstantiateResponse types.MsgStoreAndInstantiateContractResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeAndInstantiateResponse))
// when
msgUpdateAdmin := &types.MsgUpdateAdmin{
Sender: spec.addr,
NewAdmin: newAdmin.String(),
Contract: storeAndInstantiateResponse.Address,
}
_, err = wasmApp.MsgServiceRouter().Handler(msgUpdateAdmin)(ctx, msgUpdateAdmin)
// then
if spec.expErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
func TestClearAdmin(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()})
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
_, _, otherAddr = testdata.KeyTestPubAddr()
)
specs := map[string]struct {
addr string
expErr bool
}{
"authority can clear admin": {
addr: authority,
expErr: false,
},
"admin can clear admin": {
addr: myAddress.String(),
expErr: false,
},
"other address cannot clear admin": {
addr: otherAddr.String(),
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// setup
msg := &types.MsgStoreAndInstantiateContract{
Authority: spec.addr,
WASMByteCode: wasmContract,
InstantiatePermission: &types.AllowEverybody,
Admin: myAddress.String(),
UnpinCode: false,
Label: "test",
Msg: []byte(`{}`),
Funds: sdk.Coins{},
}
rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
require.NoError(t, err)
var storeAndInstantiateResponse types.MsgStoreAndInstantiateContractResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeAndInstantiateResponse))
// when
msgClearAdmin := &types.MsgClearAdmin{
Sender: spec.addr,
Contract: storeAndInstantiateResponse.Address,
}
_, err = wasmApp.MsgServiceRouter().Handler(msgClearAdmin)(ctx, msgClearAdmin)
// then
if spec.expErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
func TestMigrateContract(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()})
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
_, _, otherAddr = testdata.KeyTestPubAddr()
)
specs := map[string]struct {
addr string
expErr bool
}{
"authority can migrate a contract": {
addr: authority,
expErr: false,
},
"admin can migrate a contract": {
addr: myAddress.String(),
expErr: false,
},
"other address cannot migrate a contract": {
addr: otherAddr.String(),
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// setup
_, _, sender := testdata.KeyTestPubAddr()
msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) {
m.WASMByteCode = hackatomContract
m.Sender = sender.String()
})
// store code
rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
require.NoError(t, err)
var storeCodeResponse types.MsgStoreCodeResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeCodeResponse))
// instantiate contract
initMsg := keeper.HackatomExampleInitMsg{
Verifier: sender,
Beneficiary: myAddress,
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
msgInstantiate := &types.MsgInstantiateContract{
Sender: sender.String(),
Admin: myAddress.String(),
CodeID: storeCodeResponse.CodeID,
Label: "test",
Msg: initMsgBz,
Funds: sdk.Coins{},
}
rsp, err = wasmApp.MsgServiceRouter().Handler(msgInstantiate)(ctx, msgInstantiate)
require.NoError(t, err)
var instantiateResponse types.MsgInstantiateContractResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &instantiateResponse))
// when
migMsg := struct {
Verifier sdk.AccAddress `json:"verifier"`
}{Verifier: myAddress}
migMsgBz, err := json.Marshal(migMsg)
require.NoError(t, err)
msgMigrateContract := &types.MsgMigrateContract{
Sender: spec.addr,
Msg: migMsgBz,
Contract: instantiateResponse.Address,
CodeID: storeCodeResponse.CodeID,
}
_, err = wasmApp.MsgServiceRouter().Handler(msgMigrateContract)(ctx, msgMigrateContract)
// then
if spec.expErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
func TestInstantiateContract(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()})
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
)
specs := map[string]struct {
addr string
permission *types.AccessConfig
expErr bool
}{
"authority can instantiate a contract when permission is nobody": {
addr: authority,
permission: &types.AllowNobody,
expErr: false,
},
"other address cannot instantiate a contract when permission is nobody": {
addr: myAddress.String(),
permission: &types.AllowNobody,
expErr: true,
},
"authority can instantiate a contract when permission is everybody": {
addr: authority,
permission: &types.AllowEverybody,
expErr: false,
},
"other address can instantiate a contract when permission is everybody": {
addr: myAddress.String(),
permission: &types.AllowEverybody,
expErr: false,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// setup
_, _, sender := testdata.KeyTestPubAddr()
msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) {
m.WASMByteCode = wasmContract
m.Sender = sender.String()
m.InstantiatePermission = spec.permission
})
// store code
rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
require.NoError(t, err)
var result types.MsgStoreCodeResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result))
// when
msgInstantiate := &types.MsgInstantiateContract{
Sender: spec.addr,
Admin: myAddress.String(),
CodeID: result.CodeID,
Label: "test",
Msg: []byte(`{}`),
Funds: sdk.Coins{},
}
_, err = wasmApp.MsgServiceRouter().Handler(msgInstantiate)(ctx, msgInstantiate)
// then
if spec.expErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
func TestInstantiateContract2(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()})
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
)
specs := map[string]struct {
addr string
salt string
permission *types.AccessConfig
expErr bool
}{
"authority can instantiate a contract when permission is nobody": {
addr: authority,
permission: &types.AllowNobody,
salt: "salt1",
expErr: false,
},
"other address cannot instantiate a contract when permission is nobody": {
addr: myAddress.String(),
permission: &types.AllowNobody,
salt: "salt2",
expErr: true,
},
"authority can instantiate a contract when permission is everybody": {
addr: authority,
permission: &types.AllowEverybody,
salt: "salt3",
expErr: false,
},
"other address can instantiate a contract when permission is everybody": {
addr: myAddress.String(),
permission: &types.AllowEverybody,
salt: "salt4",
expErr: false,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// setup
_, _, sender := testdata.KeyTestPubAddr()
msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) {
m.WASMByteCode = wasmContract
m.Sender = sender.String()
m.InstantiatePermission = spec.permission
})
// store code
rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
require.NoError(t, err)
var result types.MsgStoreCodeResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result))
// when
msgInstantiate := &types.MsgInstantiateContract2{
Sender: spec.addr,
Admin: myAddress.String(),
CodeID: result.CodeID,
Label: "label",
Msg: []byte(`{}`),
Funds: sdk.Coins{},
Salt: []byte(spec.salt),
FixMsg: true,
}
_, err = wasmApp.MsgServiceRouter().Handler(msgInstantiate)(ctx, msgInstantiate)
// then
if spec.expErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
func TestUpdateInstantiateConfig(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()})
var (
creator sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
)
specs := map[string]struct {
addr string
permission *types.AccessConfig
expErr bool
}{
"authority can update instantiate config when permission is subset": {
addr: authority,
permission: &types.AllowNobody,
expErr: false,
},
"creator can update instantiate config when permission is subset": {
addr: creator.String(),
permission: &types.AllowNobody,
expErr: false,
},
"authority can update instantiate config when permission is not subset": {
addr: authority,
permission: &types.AllowEverybody,
expErr: false,
},
"creator cannot update instantiate config when permission is not subset": {
addr: creator.String(),
permission: &types.AllowEverybody,
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// setup
err := wasmApp.WasmKeeper.SetParams(ctx, types.Params{
CodeUploadAccess: types.AllowEverybody,
InstantiateDefaultPermission: types.AccessTypeNobody,
})
require.NoError(t, err)
msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) {
m.WASMByteCode = wasmContract
m.Sender = creator.String()
m.InstantiatePermission = &types.AllowNobody
})
// store code
rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
require.NoError(t, err)
var result types.MsgStoreCodeResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result))
// when
msgUpdateInstantiateConfig := &types.MsgUpdateInstantiateConfig{
Sender: spec.addr,
CodeID: result.CodeID,
NewInstantiatePermission: spec.permission,
}
_, err = wasmApp.MsgServiceRouter().Handler(msgUpdateInstantiateConfig)(ctx, msgUpdateInstantiateConfig)
// then
if spec.expErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
func TestStoreAndMigrateContract(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()})
checksum, err := wasmvm.CreateChecksum(hackatomContract)
require.NoError(t, err)
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
)
specs := map[string]struct {
addr string
permission *types.AccessConfig
expChecksum []byte
expErr bool
}{
"authority can store and migrate a contract when permission is nobody": {
addr: authority,
permission: &types.AllowNobody,
expChecksum: checksum,
},
"authority can store and migrate a contract when permission is everybody": {
addr: authority,
permission: &types.AllowEverybody,
expChecksum: checksum,
},
"other address can store and migrate a contract when permission is everybody": {
addr: myAddress.String(),
permission: &types.AllowEverybody,
expChecksum: checksum,
},
"other address cannot store and migrate a contract when permission is nobody": {
addr: myAddress.String(),
permission: &types.AllowNobody,
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// setup
initMsg := keeper.HackatomExampleInitMsg{
Verifier: myAddress,
Beneficiary: myAddress,
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)
storeAndInstantiateMsg := &types.MsgStoreAndInstantiateContract{
Authority: spec.addr,
WASMByteCode: hackatomContract,
InstantiatePermission: &types.AllowEverybody,
Admin: myAddress.String(),
UnpinCode: false,
Label: "test",
Msg: initMsgBz,
Funds: sdk.Coins{},
}
rsp, err := wasmApp.MsgServiceRouter().Handler(storeAndInstantiateMsg)(ctx, storeAndInstantiateMsg)
require.NoError(t, err)
var storeAndInstantiateResponse types.MsgStoreAndInstantiateContractResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeAndInstantiateResponse))
contractAddr := storeAndInstantiateResponse.Address
// when
migMsg := struct {
Verifier sdk.AccAddress `json:"verifier"`
}{Verifier: myAddress}
migMsgBz, err := json.Marshal(migMsg)
require.NoError(t, err)
msg := &types.MsgStoreAndMigrateContract{
Authority: spec.addr,
WASMByteCode: hackatomContract,
InstantiatePermission: spec.permission,
Msg: migMsgBz,
Contract: contractAddr,
}
rsp, err = wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
// then
if spec.expErr {
require.Error(t, err)
require.Nil(t, rsp)
return
}
require.NoError(t, err)
var result types.MsgStoreAndMigrateContractResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result))
assert.Equal(t, spec.expChecksum, result.Checksum)
require.NotZero(t, result.CodeID)
})
}
}
func TestUpdateContractLabel(t *testing.T) {
wasmApp := app.Setup(t)
ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()})
var (
myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen)
authority = wasmApp.WasmKeeper.GetAuthority()
_, _, otherAddr = testdata.KeyTestPubAddr()
)
specs := map[string]struct {
addr string
newLabel string
expErr bool
}{
"authority can update contract label": {
addr: authority,
newLabel: "new label",
expErr: false,
},
"admin can update contract label": {
addr: myAddress.String(),
newLabel: "new label",
expErr: false,
},
"other address cannot update contract label": {
addr: otherAddr.String(),
newLabel: "new label",
expErr: true,
},
"empty new label": {
addr: authority,
expErr: true,
},
"invalid new label": {
addr: authority,
newLabel: " start with space ",
expErr: true,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// setup
msg := &types.MsgStoreAndInstantiateContract{
Authority: spec.addr,
WASMByteCode: wasmContract,
InstantiatePermission: &types.AllowEverybody,
Admin: myAddress.String(),
UnpinCode: false,
Label: "old label",
Msg: []byte(`{}`),
Funds: sdk.Coins{},
}
rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg)
require.NoError(t, err)
var storeAndInstantiateResponse types.MsgStoreAndInstantiateContractResponse
require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeAndInstantiateResponse))
contract := storeAndInstantiateResponse.Address
contractAddr, err := sdk.AccAddressFromBech32(contract)
require.NoError(t, err)
require.Equal(t, "old label", wasmApp.WasmKeeper.GetContractInfo(ctx, contractAddr).Label)
// when
msgUpdateLabel := &types.MsgUpdateContractLabel{
Sender: spec.addr,
NewLabel: spec.newLabel,
Contract: storeAndInstantiateResponse.Address,
}
_, err = wasmApp.MsgServiceRouter().Handler(msgUpdateLabel)(ctx, msgUpdateLabel)
// then
if spec.expErr {
require.Error(t, err)
require.Equal(t, "old label", wasmApp.WasmKeeper.GetContractInfo(ctx, contractAddr).Label)
} else {
require.NoError(t, err)
require.Equal(t, spec.newLabel, wasmApp.WasmKeeper.GetContractInfo(ctx, contractAddr).Label)
}
})
}
}