Skip to content

Commit 0e1a083

Browse files
committed
feat: IBCv2 timeout handler
1 parent 22b96eb commit 0e1a083

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

x/wasm/keeper/ibc2.go

+44
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,15 @@ func (module IBC2Handler) OnTimeoutPacket(
7373
payload channeltypesv2.Payload,
7474
relayer sdk.AccAddress,
7575
) error {
76+
contractAddr, err := ContractFromPortID2(payload.SourcePort)
77+
if err != nil {
78+
return errorsmod.Wrapf(err, "contract port id")
79+
}
80+
msg := wasmvmtypes.IBC2PacketTimeoutMsg{Payload: newIBC2Payload(payload), Relayer: relayer.String()}
81+
err = module.keeper.OnTimeoutPacket(ctx, contractAddr, msg)
82+
if err != nil {
83+
return errorsmod.Wrap(err, "on timeout")
84+
}
7685
return nil
7786
}
7887

@@ -165,6 +174,41 @@ func (k Keeper) OnRecvIBC2Packet(
165174
}
166175
}
167176

177+
// OnTimeoutPacket calls the contract to let it know the packet was never received on the destination chain within
178+
// the timeout boundaries.
179+
// The contract should handle this on the application level and undo the original operation
180+
func (k Keeper) OnTimeoutIBC2Packet(
181+
ctx sdk.Context,
182+
contractAddr sdk.AccAddress,
183+
msg wasmvmtypes.IBC2PacketTimeoutMsg,
184+
) error {
185+
defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "ibc-timeout-packet")
186+
187+
contractInfo, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddr)
188+
if err != nil {
189+
return err
190+
}
191+
192+
env := types.NewEnv(ctx, contractAddr)
193+
querier := k.newQueryHandler(ctx, contractAddr)
194+
195+
gasLeft := k.runtimeGasForContract(ctx)
196+
res, gasUsed, execErr := k.wasmVM.IBC2PacketTimeout(codeInfo.CodeHash, env, msg, prefixStore, cosmwasmAPI, querier, ctx.GasMeter(), gasLeft, costJSONDeserialization)
197+
k.consumeRuntimeGas(ctx, gasUsed)
198+
if execErr != nil {
199+
return errorsmod.Wrap(types.ErrExecuteFailed, execErr.Error())
200+
}
201+
if res == nil {
202+
// If this gets executed, that's a bug in wasmvm
203+
return errorsmod.Wrap(types.ErrVMError, "internal wasmvm error")
204+
}
205+
if res.Err != "" {
206+
return types.MarkErrorDeterministic(errorsmod.Wrap(types.ErrExecuteFailed, res.Err))
207+
}
208+
209+
return k.handleIBCBasicContractResponse(ctx, contractAddr, contractInfo.IBCPortID, res.Ok)
210+
}
211+
168212
func newIBC2Payload(payload channeltypesv2.Payload) wasmvmtypes.IBC2Payload {
169213
return wasmvmtypes.IBC2Payload{
170214
SourcePort: payload.SourcePort,

x/wasm/types/exported_keepers.go

+5
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,9 @@ type IBC2ContractKeeper interface {
146146
contractAddr sdk.AccAddress,
147147
msg wasmvmtypes.IBC2PacketReceiveMsg,
148148
) channeltypesv2.RecvPacketResult
149+
OnTimeoutIBC2Packet(
150+
ctx sdk.Context,
151+
contractAddr sdk.AccAddress,
152+
msg wasmvmtypes.IBC2PacketReceiveMsg,
153+
) channeltypesv2.RecvPacketResult
149154
}

0 commit comments

Comments
 (0)