Omnichain Liquidity Routing on Rootstock with LI.FI
Rootstock is natively supported by LI.FI, a cross-chain liquidity aggregator. LI.FI routes swaps and bridges across dozens of chains and protocols, including Hop, Stargate, Across, and Gas.zip. It delivers the specific destination token your users select (for example, bridged USDC on Rootstock), straight to Rootstock, in a single transaction.
This guide covers three integration paths:
- LI.FI Widget - embed a pre-configured, customizable UI component
@lifi/sdk- fetch quotes and execute routes programmaticallygetContractCallsQuote(Advanced) - bridge assets and call a Rootstock contract atomically in one user click
Prerequisites
- Node.js 18+
- A Next.js or React project
- Basic familiarity with
viemand EVM wallets - LI.FI API access (no API key required for basic rate limits; register at portal.li.fi for higher limits)
Rootstock does not have native USDC issued by Circle. USDC on Rootstock is bridged from other networks via protocols such as LayerZero or Stargate. Always verify the exact contract address of the bridged asset you wish to interact with on Rootstock before deploying.
Integration 1: The LI.FI Widget
The LI.FI Widget is a self-contained React component. Lock the destination chain to Rootstock so users always land on Chain ID 30. The widget handles wallet connection, route selection, approvals, and transaction execution automatically.
Set Up a Project
Before installing the widget, you need a Next.js or React project with a configured wallet provider. If you do not already have one, start from a Rootstock quick start such as the Rootstock Dynamic starter kit, which ships with Wagmi, viem, and wallet connection wired up out of the box.
Install
npm install @lifi/widget @lifi/wallet-management
Embed and Configure
// app/bridge/page.tsx
"use client";
import { LiFiWidget, WidgetConfig } from "@lifi/widget";
// Lock the destination to Rootstock (Chain ID 30)
// and pre-fill a default destination token (bridged USDC on Rootstock)
const widgetConfig: WidgetConfig = {
toChain: 30,
// Replace with the exact bridged USDC address your dApp uses on Rootstock
toToken: "0x74C9F2B00581F1b11Aa7Ff05aa9f608B7389de67",
appearance: "light",
theme: {
palette: {
primary: { main: "#FF6B00" },
},
container: {
border: "1px solid rgb(234, 234, 234)",
borderRadius: "16px",
},
},
// Hide the destination chain selector so users cannot change the target chain
hiddenUI: ["toChain"],
// Replace with your integrator identifier for analytics (max 23 chars, alphanumeric)
integrator: "my-rootstock-dapp",
};
export default function BridgePage() {
return (
<main className="flex justify-center p-8">
<LiFiWidget config={widgetConfig} integrator="my-rootstock-dapp" />
</main>
);
}
Once rendered, the widget appears as a self-contained bridge UI in your app:

If your dApp already uses Wagmi, wrap the widget inside your WagmiProvider. The widget detects the existing context and reuses your wallet setup automatically, with no extra configuration required.
Users pick a source chain and token, and the widget routes everything to Rootstock. Visit the LI.FI Playground to preview customization options before shipping.
Integration 2: The @lifi/sdk
Use the SDK when you need programmatic control over quotes, route selection, or execution. This is the right path for custom swap UIs or automated liquidity flows.
Install
npm install @lifi/sdk viem
Configure the EVM Provider
The SDK v3 is function-based and requires a one-time setup with an EVM provider before you can execute any routes. Call createConfig once at app startup.
// lib/lifi-config.ts
import { createConfig, EVM } from "@lifi/sdk";
import { getWalletClient, switchChain } from "@wagmi/core";
import { wagmiConfig } from "./wagmi";
// Initialize the SDK once at app startup
// Pass your Wagmi config so the SDK can sign and submit transactions
createConfig({
integrator: "my-rootstock-dapp",
providers: [
EVM({
getWalletClient: () => getWalletClient(wagmiConfig),
switchChain: async (chainId) => {
const chain = await switchChain(wagmiConfig, { chainId });
return getWalletClient(wagmiConfig, { chainId: chain.id });
},
}),
],
// Recommended: provide authenticated RPC URLs in production to avoid public rate limits
rpcUrls: {
// Example: point the SDK at a dedicated Rootstock RPC endpoint
// 30: ["https://public-node.rsk.co"],
},
});
Fetch a Quote and Execute
// lib/lifi-bridge.ts
// Import the config initializer to guarantee it runs before any SDK call
import "./lifi-config";
import { getQuote, executeRoute } from "@lifi/sdk";
export async function bridgeUsdcToRootstock(userAddress: `0x${string}`) {
// Native USDC contract on Arbitrum
const ARBITRUM_USDC = "0xaf88d065e77c8cC2239327C5EDb3A432268e5831";
// Bridged USDC address on Rootstock - verify against the Rootstock token registry
const ROOTSTOCK_USDC = "0x74C9F2B00581F1b11Aa7Ff05aa9f608B7389de67";
// Request the single best quote for 100 USDC from Arbitrum to Rootstock
const quote = await getQuote({
fromChain: 42161,
toChain: 30,
fromToken: ARBITRUM_USDC,
toToken: ROOTSTOCK_USDC,
// Amount in the token's smallest unit: 100 USDC at 6 decimals
fromAmount: "100000000",
fromAddress: userAddress,
});
// executeRoute manages approvals, chain switching, and transaction submission
const result = await executeRoute(quote, {
// updateRouteHook fires whenever the route object receives a status update
updateRouteHook(updatedRoute) {
console.log("Bridge status:", updatedRoute.steps[0].execution?.status);
},
// acceptExchangeRateUpdateHook is called if the rate changes mid-execution
// Return true to continue or false to abort
acceptExchangeRateUpdateHook: async () => true,
});
return result;
}
Always implement acceptExchangeRateUpdateHook in production. Without it, routes where the exchange rate shifts during execution abort silently.
Integration 3: Advanced Destination Calls via the Composer
This integration uses getContractCallsQuote from the SDK v3. It bridges tokens from another chain and, in the same atomic user action, calls a function on a Rootstock contract on arrival. The user signs one transaction on Arbitrum and ends up with yield-bearing positions on Rootstock.