Choosing a bridge: the Router and the Bridge enum
One argument selects LayerZero, Axelar or same-chain execution. What the Router does with it, what it refuses, and which routes are coming.
Three steps: find the Hub address, build and sign an OrderRequest, call createOrder(). Everything you need to store, and the two calls you may need later.
The promise on the home page is an integration in under an hour. Here is the hour. We assume you have read Intent 103 and know the Order struct; if not, keep it open in another tab.
Every supported chain has an OrderHub and an OrderSpoke deployed with Create3, so the addresses are deterministic and consistent across EVM chains. Take the Hub address of your source chain from the Deployments page in the docs. You will need the Spoke address of the destination chain only if you plan to fill orders yourself.
struct OrderRequest {
uint64 deadline; // request validity, not the order deadline
uint64 nonce; // incremental: bigger than the last one you used
Order order;
}
The nonce does not need to be consecutive, only larger than the previous one. The request deadline is the time after which the order will not be created anymore, so keep it short. Inside goes the Order, with outputs and filler taken from the quote you accepted on the RFQ.
Addresses become bytes32 with BytesUtils.addressToBytes32(addr). Token approvals: both EOAs and smart contract accounts must approve the inputs to the Hub before creation, or attach ERC-2612 permits in the next step.
Sign the order with EIP-712. Smart contract accounts sign through EIP-1271 and the Hub verifies either.
function createOrder(
OrderRequest memory request,
bytes[] memory permits, // one per input, optional gasless approvals
bytes memory signature,
IRouter.Bridge bridgeSelector,
bytes memory extra
) external payable nonReentrant returns (bytes32 orderId, uint64 orderNonce)
permits: one blob per input token, or empty if you approved on-chain. A mismatch reverts with InvalidOrderInputApprovals.bridgeSelector: LAYERZERO, AXELAR, or NULL for same-chain. See Choosing a bridge.extra: bridge-specific data, usually empty.payable: send the native value needed for native inputs and for the bridge fee, or get InsufficientGasValue.Store orderId and orderNonce. They are how you track the order and how you withdraw it if it expires.
function withdrawOrder(Order memory order, uint64 orderNonce) external nonReentrant
If the order expires unfilled, pass the struct and the nonce after deadline + timeBuffer and the Hub returns the inputs. To fill someone else’s order you call fillOrder() on the OrderSpoke of the destination chain: the Solvers post covers that side.
orderId and orderNonce stored.That is the whole integration. No bridge SDK, no chain-specific adapters, no custom audit of a bridging layer you wrote yourself.
Next in the developer track: the Router, the Bridge enum, and what NULL is for.
One argument selects LayerZero, Axelar or same-chain execution. What the Router does with it, what it refuses, and which routes are coming.