🏗️ Composable Cross-Chain Orchestration
This tutorial shows how to:
- Bridge USDC from Arbitrum to Base using Across
- Swap bridged USDC → WETH on Base via Uniswap V3
- Supply the WETH to Morpho RE7’s WETH pool
- Return the RE7 vault tokens back to the user’s EOA
All steps run as one Fusion transaction with gas paid in USDC. We rely on:
📹 Check out the Demo of Composable Orchestration
🔥 Why this matters
With one user signature you can:
- Bridge, swap, stake — any multi-step flow — without asking the user to sign again.
- Pay all gas for every step in one ERC-20 (USDC) instead of native ETH on multiple chains.
- Leave zero “dust”: every last token that isn’t needed is auto-returned to the user.
- Keep the user in a single, familiar wallet; no pop-ups, no chain switching, no scary approvals.
💰 Business impact
❌ Pain today | ✅ Benefit with this flow |
---|---|
Users rage-quit after the 2nd confirm | Single click → drastically lower drop-off |
Confusing gas settings on multiple chains | One token, one fee shown up front |
Support tickets about stuck “dust” | No residual balances, fewer refunds |
Weeks of Solidity + audits | All TypeScript, ship in hours |
Developers get shorter build cycles; users get a smoother checkout-style experience. That’s higher conversion and faster feature delivery with almost no smart-contract risk.
🔑 Key Concepts Used
Concept | Why it’s needed |
---|---|
Fusion trigger | Starts orchestration from an empty EOA with one transfer / permit |
runtimeERC20BalanceOf | Injects whatever tokens arrive from bridge or swap |
Constraint greaterThanOrEqualTo | Ensures we meet minimum slippage tolerance |
balanceNotZeroConstraint (implicit) | Used for ordering when bridged tokens haven’t landed yet |
🚀 Code Walk‑Through
Below we highlight the critical parts of supplyToMorpho.ts
. Full file lives in your repo.
Initialise Multichain Account & MEE Client
const oNexus = await toMultichainNexusAccount({
signer: walletProvider, // Embedded or EOA signer
chains: [arbitrum, base],
transports: [http(), http()],
});
const meeClient = await createMeeClient({ account: oNexus });
Define Trigger & Constraints
const amountConsumed = parseUnits(amount, 6);
const minAfterSlippage = amountConsumed * 80n / 100n; // 20 % tolerance
const executionConstraints = [greaterThanOrEqualTo(minAfterSlippage)];
const transferToNexusTrigger = {
tokenAddress: mcUSDC.addressOn(arbitrum.id),
amount: amountConsumed,
chainId: arbitrum.id,
};
Bridge USDC with Across
Follow the Across Integration Tutorial to learn how to encode Across.
const depositAcrossData = await prepareAcrossBridgeTransaction({
depositor: oNexus.addressOn(arbitrum.id),
recipient: oNexus.addressOn(base.id),
inputToken: mcUSDC.addressOn(arbitrum.id),
outputToken: mcUSDC.addressOn(base.id),
inputAmount: amountConsumed,
originChainId: arbitrum.id,
destinationChainId: base.id,
});
Two instructions are added:
- Approve USDC to Across
- Raw calldata deposit
Swap USDC → WETH on Base
const swapUSDCtoWeth = await oNexus.buildComposable({
type: "default",
data: {
chainId: base.id,
abi: UniswapSwapRouterAbi,
to: mcUniswapSwapRouter.addressOn(base.id),
functionName: "exactInputSingle",
args: [{
tokenIn: mcUSDC.addressOn(base.id),
amountIn: runtimeERC20BalanceOf({
tokenAddress: mcUSDC.addressOn(base.id),
targetAddress: oNexus.addressOn(base.id, true),
constraints: executionConstraints,
}),
tokenOut: weth_Base,
recipient: oNexus.addressOn(base.id, true),
amountOutMinimum: 0n,
fee: 100,
sqrtPriceLimitX96: 0n,
}],
},
});
runtimeERC20BalanceOf
waits until bridged USDC arrives and meetsexecutionConstraints
.
Supply WETH to Morpho & Return Vault Tokens
const supplyToMorpho = await oNexus.buildComposable({
type: "default",
data: {
abi: MorphoPoolAbi,
to: weth_Re7_Morpho_Pool,
chainId: base.id,
functionName: "deposit",
args: [
runtimeERC20BalanceOf({
tokenAddress: weth_Base,
targetAddress: oNexus.addressOn(base.id, true),
constraints: executionConstraints,
}),
oNexus.addressOn(base.id, true),
],
},
});
Then transfer RE7 vault tokens back to the user EOA.
Quote & Execute Fusion Transaction
const quote = await meeClient.getFusionQuote({
trigger: transferToNexusTrigger,
feeToken: toFeeToken({ mcToken: mcUSDC, chainId: arbitrum.id }),
instructions: [
approveUsdcSpendToAcross,
depositAcross,
approveUniswapToSpendUSDC,
swapUSDCtoWeth,
approveMorphoVaultToSpendWeth,
supplyToMorpho,
moveRe7WethBackToEOA,
],
});
const { hash } = await meeClient.executeFusionQuote({ fusionQuote: quote });
✅ What You Achieved
- One signature → multi‑step, cross‑chain flow
- Gas paid in USDC, no ETH needed
- Exact amounts supplied, no guesswork
- Vault tokens automatically returned to user
Extend this flow by adding staking, leverage, or any other operation—without writing Solidity.