Skip to content

🏗️ Composable Cross-Chain Orchestration

This tutorial shows how to:

  1. Bridge USDC from Arbitrum to Base using Across
  2. Swap bridged USDC → WETH on Base via Uniswap V3
  3. Supply the WETH to Morpho RE7’s WETH pool
  4. 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 confirmSingle click → drastically lower drop-off
Confusing gas settings on multiple chainsOne token, one fee shown up front
Support tickets about stuck “dust”No residual balances, fewer refunds
Weeks of Solidity + auditsAll 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

ConceptWhy it’s needed
Fusion triggerStarts orchestration from an empty EOA with one transfer / permit
runtimeERC20BalanceOfInjects whatever tokens arrive from bridge or swap
Constraint greaterThanOrEqualToEnsures 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:

  1. Approve USDC to Across
  2. 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 meets executionConstraints.

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.