Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add transfer and call #334

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
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
71 changes: 71 additions & 0 deletions docs/guides/transfer-and-call.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Transfer and Call Pattern

## Overview

The **Transfer and Call Pattern** enables a contract to both bridge assets via Hyperlane Warp Routes and execute an action on the destination chain after the assets arrive.

This pattern is useful for cases where an action depends on token balances after bridging, such as:

- automated deposits
- staking
- contract interactions.

While Warp Routes handle cross-chain token transfers, this pattern extends their capabilities by using Interchain Accounts (ICA) to execute arbitrary logic on the destination chain.

## Use Cases

Some scenarios include:

- A user deposits assets on an L2, mints a derivative, and then needs to bridge the underlying asset to an L1 vault for further use.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- A user deposits assets on an L2, mints a derivative, and then needs to bridge the underlying asset to an L1 vault for further use.
- A user deposits assets on an L2, mints a derivative, and then needs to bridge the underlying asset to an L1 vault for collateralization.

- A protocol facilitates faster withdrawals by using an L1 liquidity pool, allowing users to bypass extended bridge withdrawal delays, while still ensuring final settlement occurs through the rollup bridge.

## How It Works

1. Tokens are transferred from the sender to the contract.
2. An [Interchain Account (ICA)](/docs/reference/applications/interchain-account) is derived for the contract on the destination chain.
3. The Warp Route transfer is initiated, sending the tokens cross-chain.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
3. The Warp Route transfer is initiated, sending the tokens cross-chain.
3. The Warp Route transfer is initiated, sending the tokens crosschain to the interchain account

4. A remote contract call is executed after the tokens arrive.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
4. A remote contract call is executed after the tokens arrive.
4. A remote contract call is executed on the destination chain from the interchain account after the tokens arrive.


The Solidity function below demonstrates this pattern:

```solidity
function transferAndCall(
uint32 destination,
uint256 amount,
IERC20 asset, // Tokens to transfer (not derivable from TokenRouter)
TokenRouter warpRoute,
CallLib.Call[] calldata calls // Array of calls to execute on the destination chain
) external payable {

// Transfer the specified amount of tokens from the sender to this contract
asset.transferFrom(msg.sender, address(this), amount);

// Get the interchain account address for the contract on the destination chain
bytes32 self = interchainAccountRouter
.getRemoteInterchainAccount(destination, address(this))
.addressToBytes32();

// Quote the gas fee for the warp route payment
uint256 warpFee = warpRoute.quoteGasPayment(destination);

// Initiate the warp route transfer to send tokens cross-chain
warpRoute.transferRemote{value: warpFee}(destination, self, amount);

// Execute the specified interchain calls using the remaining gas funds
interchainAccountRouter.callRemote{value: msg.value - warpFee}(
destination,
calls
);
}
```

:::note

- The contract must ensure the tokens arrive before executing the follow-up action.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a note about most calls requiring a token balance will revert before the tokens arrive and that the relayer retries with backoff to deliver the ICA call

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also that the ICA may need to do an ERC20 approval call in addition to a deposit

- If the contract executing the action is not permissioned, anyone could call it (depending on its implementation).

:::

## Diagram

[to_do]
7 changes: 6 additions & 1 deletion sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ const sidebars = {
type: "doc",
id: "protocol/warp-routes/warp-routes-yield-routes",
label: "Deploy Yield Routes",
},
},
{
type: "doc",
id: "protocol/warp-routes/warp-routes-custom-gas-fast-native",
Expand All @@ -114,6 +114,11 @@ const sidebars = {
id: "guides/extending-warp-route",
label: "Extending a Warp Route",
},
{
type: "doc",
id: "guides/transfer-and-call",
label: "Transfer and Call Pattern",
},
{
type: "doc",
id: "guides/xerc20-warp-route-guide",
Expand Down