Skip to content

Commit

Permalink
reject inactive smart contract call
Browse files Browse the repository at this point in the history
  • Loading branch information
Yongwoo Lee committed Apr 27, 2021
1 parent d766bfd commit 1eca526
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 0 deletions.
9 changes: 9 additions & 0 deletions x/wasm/internal/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,9 @@ func (k Keeper) Execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller
if err != nil {
return nil, err
}
if contractInfo.Status != types.ContractStatusActive {
return nil, sdkerrors.Wrap(types.ErrInvalid, "inactive contract")
}

if !k.IsPinnedCode(ctx, contractInfo.CodeID) {
ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: execute")
Expand Down Expand Up @@ -380,6 +383,9 @@ func (k Keeper) migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller
if contractInfo == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "unknown contract")
}
if contractInfo.Status != types.ContractStatusActive {
return nil, sdkerrors.Wrap(types.ErrInvalid, "inactive contract")
}
if !authZ.CanModifyContract(contractInfo.AdminAddr(), caller) {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "can not migrate")
}
Expand Down Expand Up @@ -558,6 +564,9 @@ func (k Keeper) setContractAdmin(ctx sdk.Context, contractAddress, caller, newAd
if contractInfo == nil {
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "unknown contract")
}
if contractInfo.Status != types.ContractStatusActive {
return sdkerrors.Wrap(types.ErrInvalid, "inactive contract")
}
if !authZ.CanModifyContract(contractInfo.AdminAddr(), caller) {
return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "can not modify contract")
}
Expand Down
144 changes: 144 additions & 0 deletions x/wasm/internal/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,43 @@ func TestExecuteWithStorageLoop(t *testing.T) {
require.True(t, false, "We must panic before this line")
}

func TestExecuteInactiveContract(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, SupportedFeatures, nil, nil)
accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.WasmKeeper, keepers.BankKeeper

deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := createFakeFundedAccount(t, ctx, accKeeper, bankKeeper, deposit.Add(deposit...))
fred := createFakeFundedAccount(t, ctx, accKeeper, bankKeeper, topUp)

wasmCode, err := ioutil.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)

contractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
require.NoError(t, err)

_, _, bob := keyPubAddr()
initMsg := HackatomExampleInitMsg{
Verifier: fred,
Beneficiary: bob,
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)

addr, _, err := keeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 3", deposit)
require.NoError(t, err)
require.Equal(t, "link18vd8fpwxzck93qlwghaj6arh4p7c5n89fvcmzu", addr.String())

// execute inactive contract
params := keeper.GetParams(ctx)
params.ContractStatusAccess = types.AccessTypeOnlyAddress.With(creator)
keeper.setParams(ctx, params)
err = keeper.UpdateContractStatus(ctx, addr, creator, types.ContractStatusInactive)
require.NoError(t, err)
_, err = keeper.Execute(ctx, addr, fred, []byte(`{"release":{}}`), topUp)
require.True(t, types.ErrInvalid.Is(err), "expected %v but got %+v", types.ErrInvalid, err)
}

func TestMigrate(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, SupportedFeatures, nil, nil)
accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.WasmKeeper, keepers.BankKeeper
Expand Down Expand Up @@ -1048,6 +1085,41 @@ func TestMigrateWithDispatchedMessage(t *testing.T) {
assert.Equal(t, deposit, balance)
}

func TestMigrateInactiveContract(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, SupportedFeatures, nil, nil)
accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.WasmKeeper, keepers.BankKeeper

deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := createFakeFundedAccount(t, ctx, accKeeper, bankKeeper, deposit.Add(deposit...))
fred := createFakeFundedAccount(t, ctx, accKeeper, bankKeeper, topUp)

originalCodeID := StoreHackatomExampleContract(t, ctx, keepers).CodeID
newCodeID := StoreHackatomExampleContract(t, ctx, keepers).CodeID
require.NotEqual(t, originalCodeID, newCodeID)

anyAddr := RandomAccountAddress(t)
newVerifierAddr := RandomAccountAddress(t)
initMsgBz := HackatomExampleInitMsg{
Verifier: fred,
Beneficiary: anyAddr,
}.GetBytes(t)
migMsg := struct {
Verifier sdk.AccAddress `json:"verifier"`
}{Verifier: newVerifierAddr}
migMsgBz, err := json.Marshal(migMsg)

contractAddr, _, err := keeper.Instantiate(ctx, originalCodeID, creator, creator, initMsgBz, "demo contract", nil)

params := keeper.GetParams(ctx)
params.ContractStatusAccess = types.AccessTypeOnlyAddress.With(creator)
keeper.setParams(ctx, params)
err = keeper.UpdateContractStatus(ctx, contractAddr, creator, types.ContractStatusInactive)
require.NoError(t, err)
_, err = keeper.Migrate(ctx, contractAddr, creator, newCodeID, migMsgBz)
require.True(t, types.ErrInvalid.Is(err), "expected %v but got %+v", types.ErrInvalid, err)
}

type sudoMsg struct {
// This is a tongue-in-check demo command. This is not the intended purpose of Sudo.
// Here we show that some priviledged Go module can make a call that should never be exposed
Expand Down Expand Up @@ -1215,6 +1287,42 @@ func TestUpdateContractAdmin(t *testing.T) {
}
}

func TestUpdateContractAdminInactiveContract(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, SupportedFeatures, nil, nil)
accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.WasmKeeper, keepers.BankKeeper

deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := createFakeFundedAccount(t, ctx, accKeeper, bankKeeper, deposit.Add(deposit...))
fred := createFakeFundedAccount(t, ctx, accKeeper, bankKeeper, topUp)

wasmCode, err := ioutil.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)

originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
require.NoError(t, err)

_, _, anyAddr := keyPubAddr()
initMsg := HackatomExampleInitMsg{
Verifier: fred,
Beneficiary: anyAddr,
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)

addr, _, err := keeper.Instantiate(ctx, originalContractID, creator, fred, initMsgBz, "demo contract", nil)
require.NoError(t, err)

params := keeper.GetParams(ctx)
params.ContractStatusAccess = types.AccessTypeOnlyAddress.With(creator)
keeper.setParams(ctx, params)
err = keeper.UpdateContractStatus(ctx, addr, creator, types.ContractStatusInactive)
require.NoError(t, err)

err = keeper.UpdateContractAdmin(ctx, addr, fred, anyAddr)
require.True(t, types.ErrInvalid.Is(err), "expected %v but got %+v", types.ErrInvalid, err)
}

func TestClearContractAdmin(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, SupportedFeatures, nil, nil)
accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.WasmKeeper, keepers.BankKeeper
Expand Down Expand Up @@ -1281,6 +1389,42 @@ func TestClearContractAdmin(t *testing.T) {
}
}

func TestClearContractAdminInactiveContract(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, SupportedFeatures, nil, nil)
accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.WasmKeeper, keepers.BankKeeper

deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
creator := createFakeFundedAccount(t, ctx, accKeeper, bankKeeper, deposit.Add(deposit...))
fred := createFakeFundedAccount(t, ctx, accKeeper, bankKeeper, topUp)

wasmCode, err := ioutil.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)

originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
require.NoError(t, err)

_, _, anyAddr := keyPubAddr()
initMsg := HackatomExampleInitMsg{
Verifier: fred,
Beneficiary: anyAddr,
}
initMsgBz, err := json.Marshal(initMsg)
require.NoError(t, err)

addr, _, err := keeper.Instantiate(ctx, originalContractID, creator, fred, initMsgBz, "demo contract", nil)
require.NoError(t, err)

params := keeper.GetParams(ctx)
params.ContractStatusAccess = types.AccessTypeOnlyAddress.With(creator)
keeper.setParams(ctx, params)
err = keeper.UpdateContractStatus(ctx, addr, creator, types.ContractStatusInactive)
require.NoError(t, err)

err = keeper.ClearContractAdmin(ctx, addr, fred)
require.True(t, types.ErrInvalid.Is(err), "expected %v but got %+v", types.ErrInvalid, err)
}

func TestUpdateContractStatus(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, SupportedFeatures, nil, nil)
accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.WasmKeeper, keepers.BankKeeper
Expand Down

0 comments on commit 1eca526

Please sign in to comment.