Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ require (
replace (
// Use the cosmos-flavored keyring library
github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
github.com/CosmWasm/wasmvm => github.com/sei-protocol/sei-wasmvm v1.5.4-sei.0.0.2
github.com/CosmWasm/wasmvm => github.com/sei-protocol/sei-wasmvm v1.5.4-sei.0.0.3.0.20250819144601-14afbfe2bf78
github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.56
github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.1.9
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -782,8 +782,8 @@ github.com/sei-protocol/sei-tendermint v0.5.9 h1:GLAuHGuCd1eDLfoU4uFMbqQo7z47XSV
github.com/sei-protocol/sei-tendermint v0.5.9/go.mod h1:ip8M5kkQf8JC05np1xd4KR33ttJoseJi28Ea28ui85E=
github.com/sei-protocol/sei-tm-db v0.0.5 h1:3WONKdSXEqdZZeLuWYfK5hP37TJpfaUa13vAyAlvaQY=
github.com/sei-protocol/sei-tm-db v0.0.5/go.mod h1:Cpa6rGyczgthq7/0pI31jys2Fw0Nfrc+/jKdP1prVqY=
github.com/sei-protocol/sei-wasmvm v1.5.4-sei.0.0.2 h1:bhfjHJFhYe/Ffq83UsSJrCcZPkAx5TSEJl1z5lBd6ow=
github.com/sei-protocol/sei-wasmvm v1.5.4-sei.0.0.2/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq8FLCyys=
github.com/sei-protocol/sei-wasmvm v1.5.4-sei.0.0.3.0.20250819144601-14afbfe2bf78 h1:jVFJVae967/K3lydMGQ+CtGowE3nLaZ7kxbxPDZ9fCE=
github.com/sei-protocol/sei-wasmvm v1.5.4-sei.0.0.3.0.20250819144601-14afbfe2bf78/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq8FLCyys=
github.com/sei-protocol/tm-db v0.0.4 h1:7Y4EU62Xzzg6wKAHEotm7SXQR0aPLcGhKHkh3qd0tnk=
github.com/sei-protocol/tm-db v0.0.4/go.mod h1:PWsIWOTwdwC7Ow/GUvx8HgUJTO691pBuorIQD8JvwAs=
github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
Expand Down
4 changes: 2 additions & 2 deletions x/wasm/artifacts/v152/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ func (vm *VM) IBCChannelOpen(
gasMeter GasMeter,
gasLimit uint64,
deserCost types.UFraction,
) (*types.IBC3ChannelOpenResponse, uint64, error) {
) (*types.IBCChannelOpenResult, uint64, error) {
envBin, err := json.Marshal(env)
if err != nil {
return nil, 0, err
Expand All @@ -377,7 +377,7 @@ func (vm *VM) IBCChannelOpen(
if resp.Err != "" {
return nil, gasReport.UsedInternally, fmt.Errorf("%s", resp.Err)
}
return resp.Ok, gasReport.UsedInternally, nil
return &resp, gasReport.UsedInternally, nil
}

// IBCChannelConnect is available on IBC-enabled contracts and is a hook to call into
Expand Down
4 changes: 2 additions & 2 deletions x/wasm/artifacts/v155/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ func (vm *VM) IBCChannelOpen(
gasMeter GasMeter,
gasLimit uint64,
deserCost types.UFraction,
) (*types.IBC3ChannelOpenResponse, uint64, error) {
) (*types.IBCChannelOpenResult, uint64, error) {
envBin, err := json.Marshal(env)
if err != nil {
return nil, 0, err
Expand All @@ -377,7 +377,7 @@ func (vm *VM) IBCChannelOpen(
if resp.Err != "" {
return nil, gasReport.UsedInternally, fmt.Errorf("%s", resp.Err)
}
return resp.Ok, gasReport.UsedInternally, nil
return &resp, gasReport.UsedInternally, nil
}

// IBCChannelConnect is available on IBC-enabled contracts and is a hook to call into
Expand Down
12 changes: 8 additions & 4 deletions x/wasm/keeper/msg_dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,18 @@ func (d MessageDispatcher) dispatchMsgWithGasLimit(ctx sdk.Context, contractAddr
// catch out of gas panic and just charge the entire gas limit
defer func() {
if r := recover(); r != nil {
// if it's not an OutOfGas error, raise it again
if _, ok := r.(sdk.ErrorOutOfGas); !ok {
if _, ok := r.(sdk.ErrorOutOfGas); ok {
// consume the gas limit for the submessage and turn panic into error
ctx.GasMeter().ConsumeGas(gasLimit, "Sub-Message OutOfGas panic")
err = sdkerrors.Wrap(sdkerrors.ErrOutOfGas, "SubMsg hit gas limit")
} else {
// if it's not an ErrorOutOfGas, consume the gas used in the sub-context and raise it again
spent := subCtx.GasMeter().GasConsumed()
ctx.GasMeter().ConsumeGas(spent, "From limited Sub-Message")
// log it to get the original stack trace somewhere (as panic(r) keeps message but stacktrace to here
moduleLogger(ctx).Info("SubMsg rethrowing panic: %#v", r)
panic(r)
}
ctx.GasMeter().ConsumeGas(gasLimit, "Sub-Message OutOfGas panic")
err = sdkerrors.Wrap(sdkerrors.ErrOutOfGas, "SubMsg hit gas limit")
}
}()
events, data, err = d.messenger.DispatchMsg(subCtx, contractAddr, ibcPort, msg, info, codeInfo)
Expand Down
19 changes: 14 additions & 5 deletions x/wasm/keeper/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ func (k Keeper) OnOpenChannel(
msg wasmvmtypes.IBCChannelOpenMsg,
) (string, error) {
defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "ibc-open-channel")
version := ""

_, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddr)
if err != nil {
return "", err
Expand All @@ -37,15 +35,26 @@ func (k Keeper) OnOpenChannel(
gas := k.runtimeGasForContract(ctx)
res, gasUsed, execErr := k.getWasmer(ctx).IBCChannelOpen(codeInfo.CodeHash, env, msg, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gas, costJSONDeserialization)
k.consumeRuntimeGas(ctx, gasUsed)
// check if contract panicked / VM failed
if execErr != nil {
return "", sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
}

if res != nil {
version = res.Version
if res == nil {
// If this gets executed, that's a bug in wasmvm
return "", sdkerrors.Wrap(types.ErrVMError, "internal wasmvm error")
}
// check contract result
if res.Err != "" {
return "", types.MarkErrorDeterministic(sdkerrors.Wrap(types.ErrExecuteFailed, res.Err))
}
if res.Ok == nil {
// a nil "ok" value is a valid response and means the contract accepts the incoming channel version
// see https://docs.rs/cosmwasm-std/2.2.2/cosmwasm_std/type.IbcChannelOpenResponse.html
return "", nil
}

return version, nil
return res.Ok.Version, nil
}

// OnConnectChannel calls the contract to let it know the IBC channel was established.
Expand Down
4 changes: 2 additions & 2 deletions x/wasm/keeper/relay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ func TestOnOpenChannel(t *testing.T) {
t.Run(name, func(t *testing.T) {
myChannel := wasmvmtypes.IBCChannel{Version: "my test channel"}
myMsg := wasmvmtypes.IBCChannelOpenMsg{OpenTry: &wasmvmtypes.IBCOpenTry{Channel: myChannel, CounterpartyVersion: "foo"}}
m.IBCChannelOpenFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error) {
m.IBCChannelOpenFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCChannelOpenResult, uint64, error) {
assert.Equal(t, myMsg, msg)
return &wasmvmtypes.IBC3ChannelOpenResponse{}, spec.contractGas * DefaultGasMultiplier, spec.contractErr
return &wasmvmtypes.IBCChannelOpenResult{}, spec.contractGas * DefaultGasMultiplier, spec.contractErr
}

ctx, _ := parentCtx.CacheContext()
Expand Down
6 changes: 3 additions & 3 deletions x/wasm/keeper/wasmtesting/mock_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type MockWasmer struct {
ReplyFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error)
GetCodeFn func(codeID wasmvm.Checksum) (wasmvm.WasmCode, error)
CleanupFn func()
IBCChannelOpenFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error)
IBCChannelOpenFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCChannelOpenResult, uint64, error)
IBCChannelConnectFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error)
IBCChannelCloseFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error)
IBCPacketReceiveFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResult, uint64, error)
Expand All @@ -38,7 +38,7 @@ type MockWasmer struct {
GetMetricsFn func() (*wasmvmtypes.Metrics, error)
}

func (m *MockWasmer) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error) {
func (m *MockWasmer) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCChannelOpenResult, uint64, error) {
if m.IBCChannelOpenFn == nil {
panic("not supposed to be called!")
}
Expand Down Expand Up @@ -210,7 +210,7 @@ type IBCContractCallbacks interface {
gasMeter wasmvm.GasMeter,
gasLimit uint64,
deserCost wasmvmtypes.UFraction,
) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error)
) (*wasmvmtypes.IBCChannelOpenResult, uint64, error)

IBCChannelConnect(
codeID wasmvm.Checksum,
Expand Down
6 changes: 3 additions & 3 deletions x/wasm/relay_pingpong_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,11 @@ func (p *player) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmt
}

// OnIBCChannelOpen ensures to accept only configured version
func (p player) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error) {
func (p player) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCChannelOpenResult, uint64, error) {
if msg.GetChannel().Version != p.actor {
return &wasmvmtypes.IBC3ChannelOpenResponse{}, 0, nil
return &wasmvmtypes.IBCChannelOpenResult{}, 0, nil
}
return &wasmvmtypes.IBC3ChannelOpenResponse{}, 0, nil
return &wasmvmtypes.IBCChannelOpenResult{}, 0, nil
}

// OnIBCChannelConnect persists connection endpoints
Expand Down
4 changes: 2 additions & 2 deletions x/wasm/relay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -604,8 +604,8 @@ func (c *errorReceiverContract) IBCPacketReceive(codeID wasmvm.Checksum, env was
// simple helper struct that implements connection setup methods.
type contractStub struct{}

func (s *contractStub) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error) {
return &wasmvmtypes.IBC3ChannelOpenResponse{}, 0, nil
func (s *contractStub) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCChannelOpenResult, uint64, error) {
return &wasmvmtypes.IBCChannelOpenResult{}, 0, nil
}

func (s *contractStub) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) {
Expand Down
36 changes: 35 additions & 1 deletion x/wasm/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ var (
// ErrExceedMaxQueryStackSize error if max query stack size is exceeded
ErrExceedMaxQueryStackSize = sdkErrors.Register(DefaultCodespace, 27, "max query stack size exceeded")

// unused 28..29
// unused 28

// ErrVMError means an error occurred in wasmvm (not in the contract itself, but in the host environment)
ErrVMError = sdkErrors.Register(DefaultCodespace, 29, "wasmvm error")

// ErrExceedMaxCallDepth error if max query stack size is exceeded
ErrExceedMaxCallDepth = sdkErrors.Register(DefaultCodespace, 30, "max call depth exceeded")
Expand All @@ -109,3 +112,34 @@ func (m *ErrNoSuchContract) ABCICode() uint32 {
func (m *ErrNoSuchContract) Codespace() string {
return DefaultCodespace
}

// DeterministicError is a wrapper type around an error that the creator guarantees to have
// a deterministic error message.
// This means that the `Error()` function must always return the same string on all nodes.
// The DeterministicError has the same error message as the wrapped error.
// DeterministicErrors are not redacted when returned to a contract,
// so not upholding this guarantee can lead to consensus failures.
type DeterministicError struct {
error
}

var _ error = DeterministicError{}

// MarkErrorDeterministic marks an error as deterministic.
// Make sure to only do that if the error message is deterministic between systems.
// See [DeterministicError] for more details.
func MarkErrorDeterministic(e error) DeterministicError {
return DeterministicError{error: e}
}

// Unwrap implements the built-in errors.Unwrap
func (e DeterministicError) Unwrap() error {
return e.error
}

// Cause is the same as unwrap but used by ABCIInfo
// By returning the wrapped error here, we ensure that the DeterministicError inherits
// the ABCIInfo of the wrapped error.
func (e DeterministicError) Cause() error {
return e.Unwrap()
}
2 changes: 1 addition & 1 deletion x/wasm/types/wasmer_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ type WasmerEngine interface {
gasMeter wasmvm.GasMeter,
gasLimit uint64,
deserCost wasmvmtypes.UFraction,
) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error)
) (*wasmvmtypes.IBCChannelOpenResult, uint64, error)

// IBCChannelConnect is available on IBC-enabled contracts and is a hook to call into
// during the handshake pahse
Expand Down
Loading