Announcing Packet Forward Middleware
Mar 13, 2024
Justin Tieri
Introducing Packet Forward Middleware
Packet Forward Middleware (PFM) is an ICS-30 compliant IBC middleware that is capable of routing packets received on one chain over IBC to some other counterparty chain. Chains using PFM serve as intermediaries between two chains that may not have an existing direct IBC connection to one another. PFM can also compose complex interactions with many chains via one transaction. In one transaction users can express complex action sequences, such as describing a plan to send a token from one chain, receive it on an intermediary chain where they perform a swap in a liquidity pool, then forward the tokens received from the swap to another chain with an NFT marketplace, purchase an NFT, and unwind their leftover tokens back to the original source chain where the token is a native asset. This is just one example of the type of complex packet flows and user experiences that PFM unlocks.
The Value of PFM
PFM seeks to alleviate user experience issues in IBC related to the non-fungibility of tokens, routing, and discoverability. Let’s discuss how PFM reduces user frustration with each of these experiences.
In IBC, tokens that travel over different ports and channels that are non-fungible. Let’s imagine I have some ATOM on the Cosmos Hub. I send that ATOM to Osmosis, then I send that ATOM to Stargaze, and finally I send it back to the Cosmos Hub. I end up with a token that represents ATOM that has traveled from the Cosmos Hub to Osmosis then to Stargaze and finally to the Cosmos Hub. It is not treated identically to the native ATOM token on the Cosmos Hub and will show up as a separate balance inside of wallets such as Keplr, Leap, etc.
To avoid this issue, users have to “unwind” assets back over the same paths that they originally traversed. In our previous example this would mean the user needs to send their ATOM from Stargaze back to Osmosis and then finally back to the Cosmos Hub. This way they will see one balance in their wallets that solely consists of the native ATOM token on the Cosmos Hub. It's easy to see that this is a brittle and very error prone process that can be confusing for newcomers and even veterans of the ecosystem. With PFM, users make their intentions clear via a front end like ibc.fun or TFM. The intentions can be as simple as, “I want to end up with token X on chain B and I currently only have token Y on chain A.” With the use of intelligent routing algorithms that leverage PFM on various intermediary chains, these front ends can build a transaction that, when signed and broadcasted by the user, will result in them swapping token Y for token X that will travel from chain A to chain B, even if the tokens need to travel through some number of intermediary chains to arrive at the intended destination from the current source chain. This increases the fungibility of tokens and removes the burden on the user to determine the proper sequence through the network of chains.
Additionally, PFM helps address the issue of routing. Many connections and channels can exist between any two chains. How does a user know which ones to use? Most applications use one canonical client, connection, and channel to communicate with a counterparty chain in IBC. Failure to use this canonical path can result in stuck packets, such as when there is no relayer on that path or clients expire after tokens are transferred off the original source chain. Using a non-canonical path can also result in the user receiving an illiquid token on the destination chain since tokens that travel over different ports and channels are non-fungible in IBC by default. Rectifying these unintended consequences often requires more resources and/or manual intervention, e.g. governance to revive clients, spinning up relayers on non-canonical paths, etc. By restoring the fungibility of the token, PFM eliminates most of these routing complications.
The last issue that PFM addresses is discoverability. In IBC, data is transmitted in the form of packets, and packets are sent over channels that serve as a pipeline between two chains. To move tokens from Chain A to Chain C, a connection must exist. If Chain A does not have a connection to Chain C then it cannot directly send packets to it. However, if Chain A has a connection to Chain B, and Chain B has a connection to Chain C then Chain A could leverage Chain B as an intermediary to transmit a packet to Chain C. Front end developers can make use of these indirect connections between chains to ensure the user can freely move funds between chains without having to identify a path from the source to the destination ahead of time.
How PFM works
Users can make use of PFM by composing an ICS-20 transfer on a source chain that makes use of the memo field to describe the various hops that should be taken to reach the final destination chain. PFM makes use of a basic struct that describes the receiver address on the destination chain, the IBC port and channel to be used in the hop, the timeout period that should be respected before giving up on the tx and refunding the assets, and also the number of retries that should be attempted before considering the multi-hop tx failed and refunding assets.
type ForwardMetadata struct {Receiver string `json:"receiver,omitempty"`Port string `json:"port,omitempty"`Channel string `json:"channel,omitempty"`Timeout Duration `json:"timeout,omitempty"`Retries *uint8 `json:"retries,omitempty"`Next *JSONObject `json:"next,omitempty"`}
This is converted to and from JSON so that wallets and other front end applications can build multi-hop transactions for users based on their expressed intentions, i.e. what tokens they want to end up with and on what chain, starting with what token they currently have and where those tokens currently reside. Notice that the metadata structure for forwards contains a `Next` field that is a JSON object. This means that any arbitrary number of forwards can be chained together. The user can initiate the multi-hop transaction process with a single signed and broadcasted transaction.
When a multi-hop transaction is broadcasted, PFM will hold the IBC acknowledgement until the very last step is executed. This ensures that a multi-hop transaction is only considered successful if every intermediary hop is successful. Users need only monitor the original source chain to determine if their multi-hop transaction succeeded. In the case that an intermediary hop fails, the user will receive a refund of their assets on the original source chain, so long as there was no non-refundable action taken in the flow. For example, if the user swapped the original asset for another asset during the multi-hop flow, or if some of the assets were used to purchase a NFT, or if any other intermediary action happened that resulted in the user no longer having the same asset they originally sent. In these cases, the transactions will be unwound to the point where the irreversible transaction took place.
Next Steps, The Future, PFM Roadmap?
Curious users can try out ibc.fun or TFM, which both make use of PFM under the hood for token unwinding and providing users with multi-hop transactions to effectively reach their destination chain. Developers can read more about the Skip API, which powers ibc.fun, and how it can be used to provide more seamless cross-chain experiences for users, or read Skip’s blog post on PFM.
PFM is free and open source software that is generally feature complete outside of the maintenance necessary to keep it updated with newer versions of ibc-go. Chain developers interested in integrating PFM with their own chain should read our integration docs.
More details in our repository: https://github.com/cosmos/ibc-apps/tree/main/middleware/packet-forward-middleware