Proper systemerror follow-up (#715)
* 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 <alpe@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package keeper
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
@@ -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 {
|
||||
@@ -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{
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user