Skip to content

Commit

Permalink
Proper systemerror follow-up (cosmos#715)
Browse files Browse the repository at this point in the history
* Add custom NoSuchContract error

* Return custom NoSuchContract error from WasmQuerier

* Add custom NoSuchContract error

* Use custom ErrNoSuchContract error

Map to corresponding wasmvmtypes error

* Handle wrapped errors

Co-authored-by: Alex Peters <[email protected]>
  • Loading branch information
maurolacy and alpe authored Jan 20, 2022
1 parent b8319aa commit bf84b19
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
12 changes: 10 additions & 2 deletions x/wasm/keeper/query_plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"encoding/json"
"errors"
"fmt"

"github.com/cosmos/cosmos-sdk/baseapp"
Expand Down Expand Up @@ -52,7 +53,14 @@ func (q QueryHandler) Query(request wasmvmtypes.QueryRequest, gasLimit uint64) (
defer func() {
q.Ctx.GasMeter().ConsumeGas(subCtx.GasMeter().GasConsumed(), "contract sub-query")
}()
return q.Plugins.HandleQuery(subCtx, q.Caller, request)

res, err := q.Plugins.HandleQuery(subCtx, q.Caller, request)
// Error mapping
var noSuchContract *types.ErrNoSuchContract
if ok := errors.As(err, &noSuchContract); ok {
return res, wasmvmtypes.NoSuchContract{Addr: noSuchContract.Addr}
}
return res, err
}

func (q QueryHandler) GasConsumed() uint64 {
Expand Down Expand Up @@ -483,7 +491,7 @@ func WasmQuerier(k wasmQueryKeeper) func(ctx sdk.Context, request *wasmvmtypes.W
}
info := k.GetContractInfo(ctx, addr)
if info == nil {
return nil, wasmvmtypes.NoSuchContract{Addr: request.ContractInfo.ContractAddr}
return nil, &types.ErrNoSuchContract{Addr: request.ContractInfo.ContractAddr}
}

res := wasmvmtypes.ContractInfoResponse{
Expand Down
31 changes: 31 additions & 0 deletions x/wasm/keeper/query_plugins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"encoding/json"
"testing"

"github.com/cosmos/cosmos-sdk/store"
dbm "github.com/tendermint/tm-db"

wasmvmtypes "github.com/CosmWasm/wasmvm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
Expand Down Expand Up @@ -442,6 +445,34 @@ func TestContractInfoWasmQuerier(t *testing.T) {
}
}

func TestQueryErrors(t *testing.T) {
specs := map[string]struct {
src error
expErr error
}{
"no error": {},
"no such contract": {
src: &types.ErrNoSuchContract{Addr: "contract-addr"},
expErr: wasmvmtypes.NoSuchContract{Addr: "contract-addr"},
},
"no such contract - wrapped": {
src: sdkerrors.Wrap(&types.ErrNoSuchContract{Addr: "contract-addr"}, "my additional data"),
expErr: wasmvmtypes.NoSuchContract{Addr: "contract-addr"},
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
mock := WasmVMQueryHandlerFn(func(ctx sdk.Context, caller sdk.AccAddress, request wasmvmtypes.QueryRequest) ([]byte, error) {
return nil, spec.src
})
ctx := sdk.Context{}.WithGasMeter(sdk.NewInfiniteGasMeter()).WithMultiStore(store.NewCommitMultiStore(dbm.NewMemDB()))
q := NewQueryHandler(ctx, mock, sdk.AccAddress{}, NewDefaultWasmGasRegister())
_, gotErr := q.Query(wasmvmtypes.QueryRequest{}, 1)
assert.Equal(t, spec.expErr, gotErr)
})
}
}

type mockWasmQueryKeeper struct {
GetContractInfoFn func(ctx sdk.Context, contractAddress sdk.AccAddress) *types.ContractInfo
QueryRawFn func(ctx sdk.Context, contractAddress sdk.AccAddress, key []byte) []byte
Expand Down
19 changes: 19 additions & 0 deletions x/wasm/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,23 @@ var (

// ErrInvalidEvent error if an attribute/event from the contract is invalid
ErrInvalidEvent = sdkErrors.Register(DefaultCodespace, 21, "invalid event")

// error if an address does not belong to a contract (just for registration)
_ = sdkErrors.Register(DefaultCodespace, 22, "no such contract")
)

type ErrNoSuchContract struct {
Addr string
}

func (m *ErrNoSuchContract) Error() string {
return "no such contract: " + m.Addr
}

func (m *ErrNoSuchContract) ABCICode() uint32 {
return 22
}

func (m *ErrNoSuchContract) Codespace() string {
return DefaultCodespace
}

0 comments on commit bf84b19

Please sign in to comment.