Packet Forward Middleware Flows
This document outlines some example flows leveraging packet forward middleware and formats of the memo field.
Example Scenarios
Successful Transfer forwarding through chain B
Memo for simple forward
- The packet-forward-middleware integrated on Chain B.
- The packet data
receiver
for theMsgTransfer
on Chain A is set to"pfm"
or some other invalid bech32 string.* - The packet
memo
is included inMsgTransfer
by user on Chain A.
{
"forward": {
"receiver": "chain-c-bech32-address",
"port": "transfer",
"channel": "channel-123"
}
}
Error on Forwarding Hop, Refund to A
Forwarding with Retry and Timeout Logic
A -> B -> C full success
A
This sends packet over underlying ICS-004 wrapper with memo as is.B
This receives packet and parses it into ICS-020 packet.B
Validatesforward
packet on this step, returnACK
error if fails.B
If other middleware not yet called ICS-020, call it and ACK error on fail. Tokens minted or unescrowed here.B
Handle denom. If denom prefix is fromB
, remove it. If denom prefix is other chain - addB
prefix.B
Take fee, create new ICS-004 packet with timeout from forward for next step, and remaining innermemo
.B
Send transfer toC
with parameters obtained frommemo
. Tokens burnt or escrowed here.B
Store trackingin flight packet
under next(channel, port, ICS-20 transfer sequence)
, do notACK
packet yet.C
Handle ICS-020 packet as usual.B
On ICS-020 ACK fromC
findin flight packet
, delete it and writeACK
for original packet fromA
.A
Handle ICS-020ACK
as usual
Example of USDC transfer from Osmosis -> Noble -> Sei
A -> B -> C with C error ACK
B
On ICS-020 ACK fromC
findin flight packet
, delete itB
Burns or escrows tokens.B
And write errorACK
for original packet fromA
.A
Handle ICS-020 timeout as usualC
writes successACK
for packet fromB
Same behavior in case of timeout on C
A packet timeouts on B before C timeouts packet from B
A
Cannot timeout becausein flight packet
has proof onB
of packet inclusion.B
waits for ACK or timeout fromC
.B
timeout fromC
becomes failACK
onB
forA
A
receives success or failACK
, but not timeout
In this case A
assets hang
until final hop timeouts or ACK.
Memo for Retry and Timeout Logic, with Nested Memo (2 forwards)
- The packet-forward-middleware integrated on Chain B and Chain C.
- The packet data
receiver
for theMsgTransfer
on Chain A is set to"pfm"
or some other invalid bech32 string. - The forward metadata
receiver
for the hop from Chain B to Chain C is set to"pfm"
or some other invalid bech32 string. - The packet
memo
is included inMsgTransfer
by user on Chain A. - A packet timeout of 10 minutes and 2 retries is set for both forwards.
In the case of a timeout after 10 minutes for either forward, the packet would be retried up to 2 times, afterwards an error ack would be written to issue a refund on the prior chain.
next
is the memo
to pass for the next transfer hop. Per memo
intended usage of a JSON string, it should be either JSON which will be Marshaled retaining key order, or an escaped JSON string which will be passed directly.
next
as JSON
{
"forward": {
"receiver": "pfm", // intentionally invalid
"port": "transfer",
"channel": "channel-123",
"timeout": "10m",
"retries": 2,
"next": {
"forward": {
"receiver": "chain-d-bech32-address",
"port": "transfer",
"channel": "channel-234",
"timeout": "10m",
"retries": 2
}
}
}
}
Intermediate Address Security
Intermediate chains don’t need a valid receiver address. Instead, they derive a secure address from the packet’s sender and channel, preventing users from forwarding tokens to arbitrary accounts.
To avoid accidental transfers to chains without PFM, use an invalid bech32 address (e.g., "pfm") for intermediate receivers.