Example: a cross-chain contract call
An order with empty outputs and a hook. Encode the selector, put the calldata in the Order, and a solver runs it on the destination chain.
Bridge and supply in one signature. WETH on Base in, aUSDC on Arbitrum out, and the solver does the staking.
Say we hold WETH on Base and want to provide USDC liquidity on Aave v3 on Arbitrum. The old way: bridge, wait, swap, approve, supply, four transactions on two chains. The iLayer way: one order whose output is the LP token itself.
aUSDC is the token Aave mints when you supply USDC. It is a normal ERC-20 on Arbitrum. So we set aUSDC as the output token of the order and call the OrderHub on Base. We are not asking for USDC and then supplying it; we are asking for the position.
{
sourceChainId: "8453", // Base
destinationChainId: "42161", // Arbitrum
inputs: [
// WETH on Base
{ tokenType: "FUNGIBLE_TOKEN", tokenAddress: "0x…4200000000000000000000000000000000000006", tokenId: "0", amount: "10000000" }
],
outputs: [
// aUSDC on Arbitrum
{ tokenType: "FUNGIBLE_TOKEN", tokenAddress: "0x…", tokenId: "0", amount: "9000000" }
],
...
}
Addresses are bytes32, hence the padded WETH address. Amounts come from the quote you accepted on the RFQ. The rest of the struct (recipient, filler, deadlines, bridge) follows the integration guide.
Solvers hold a numeraire balance, typically USDC. To fill this order a solver on Arbitrum supplies USDC to Aave, receives aUSDC, and hands exactly the quoted amount to the Spoke in a single multicall with fillOrder(). On Base the Hub releases the WETH to the solver, who consolidates it back into USDC. You never touched Arbitrum, held no gas there, and made one signature.
recipient to their address.sponsored; the solver submits it and prices the gas into the quote.Next: an order with no outputs at all, only calldata to run on another chain.
An order with empty outputs and a hook. Encode the selector, put the calldata in the Order, and a solver runs it on the destination chain.