@@ -73,6 +73,15 @@ func (module IBC2Handler) OnTimeoutPacket(
73
73
payload channeltypesv2.Payload ,
74
74
relayer sdk.AccAddress ,
75
75
) 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
+ }
76
85
return nil
77
86
}
78
87
@@ -165,6 +174,41 @@ func (k Keeper) OnRecvIBC2Packet(
165
174
}
166
175
}
167
176
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
+
168
212
func newIBC2Payload (payload channeltypesv2.Payload ) wasmvmtypes.IBC2Payload {
169
213
return wasmvmtypes.IBC2Payload {
170
214
SourcePort : payload .SourcePort ,
0 commit comments