LayerZero
BOB Gateway's LayerZero integration enables seamless cross-chain swaps between Bitcoin and LayerZero-supported chains. All transactions route through BOB as an intermediary, leveraging LayerZero's Omnichain Fungible Token (OFT) protocol for secure cross-chain bridging.
High-Level Developer Overviewโ
How It Worksโ
The LayerZero Gateway Client routes all cross-chain transactions through BOB, acting as the hub for LayerZero connectivity:
Bitcoin โ LayerZero Chain Flowโ
- Bitcoin โ BOB: User sends Bitcoin, receives wBTC on BOB via Gateway
- BOB โ Target Chain: wBTC is bridged via LayerZero OFT to destination chain
- Strategy Execution: BOB strategy contract handles the LayerZero bridging automatically
LayerZero Chain โ Bitcoin Flowโ
- Origin Chain โ BOB: User's tokens are bridged to BOB via LayerZero
- BOB Processing: Offramp composer creates Bitcoin withdrawal order
- BOB โ Bitcoin: Standard Gateway offramp process completes the swap
Supported Chainsโ
The LayerZero integration supports 15+ major EVM chains including Ethereum, Base, Arbitrum, Avalanche, BSC, and more.
Get Quoteโ
Get a quote for cross-chain swaps via LayerZero:
import { LayerZeroGatewayClient, parseBtc } from '@gobob/bob-sdk';
import { bob } from 'viem/chains';
const client = new LayerZeroGatewayClient(bob.id);
// Bitcoin โ Base example
const onrampQuote = await client.getQuote({
fromChain: 'bitcoin',
fromToken: 'BTC',
toChain: 'base',
toToken: '0x0555E30da8f98308EdB960aa94C0Db47230d2B9c', // wBTC
fromUserAddress: 'bc1q...', // Bitcoin address
toUserAddress: '0x...', // EVM address on destination chain
amount: parseBtc("0.1"), // BTC
l0FeeBuffer: 500 // 5% LayerZero fee buffer (optional)
});
// Base โ Bitcoin example
const offrampQuote = await client.getQuote({
fromChain: 'base',
fromToken: '0x0555E30da8f98308EdB960aa94C0Db47230d2b9c', // wBTC
toChain: 'bitcoin',
toToken: 'BTC',
fromUserAddress: '0x...', // EVM address on origin chain
toUserAddress: 'bc1q...', // Bitcoin address
amount: 17000 // token amount in smallest unit
});
Destination Actions (Cross-Chain Calls)โ
LayerZero Gateway supports executing arbitrary calls on the destination chain after tokens arrive. This enables complex DeFi interactions like depositing into lending protocols, staking, or swapping tokens - all in a single cross-chain transaction.
Using destinationCallsโ
The destinationCalls parameter allows you to specify a series of calls to execute on the destination chain:
import { encodeFunctionData, erc20Abi } from 'viem';
// Example: Transfer tokens to a recipient on the destination chain
const transferCallData = encodeFunctionData({
abi: erc20Abi,
functionName: 'transfer',
args: ['0xEf7Ff7Fb24797656DF41616e807AB4016AE9dCD5', BigInt(1000000)],
});
const quote = await client.getQuote({
fromChain: 'bitcoin',
fromToken: 'BTC',
toChain: 'base',
toToken: '0x0555E30da8f98308EdB960aa94C0Db47230d2B9c', // wBTC
fromUserAddress: 'bc1q...',
toUserAddress: '0x...',
amount: parseBtc("0.1"),
destinationCalls: {
calls: [
{
target: '0x0555E30da8f98308EdB960aa94C0Db47230d2B9c', // wBTC token
callData: transferCallData,
value: BigInt(0), // Native value to send with call (if any)
},
],
leftoverRecipient: '0xEf7Ff7Fb24797656DF41616e807AB4016AE9dCD5', // Receives any leftover tokens
gasLimit: 300000, // Optional: gas limit for destination compose execution
},
});
destinationCalls Structureโ
interface DestinationCalls {
calls: DestinationCall[];
leftoverRecipient: Address;
gasLimit?: number; // Optional, defaults to 300000
}
interface DestinationCall {
target: Address; // Contract address to call
callData: Hex; // Encoded function call data
value: bigint; // Native value to send with call
}
How It Worksโ
- Token Arrival: Tokens arrive at the
MulticallComposercontract on the destination chain - Call Execution: The composer executes your specified calls sequentially
- Leftover Handling: Any tokens not spent by your calls are sent to
leftoverRecipient - Error Handling: If any call reverts, all tokens are sent to
leftoverRecipientas a safety mechanism
Important Notesโ
- Mutual Exclusivity: You cannot provide both
destinationCallsandmessage- use one or the other - Leftover Recipient: Always specify a
leftoverRecipientaddress to receive any unspent tokens - Gas Limit: The
gasLimitparameter controls gas allocated for the compose execution (default: 300000) - Call Validation: Calls cannot target EOAs (externally owned accounts) or the composer contract itself
- Token Spending: The composer ensures calls don't spend more tokens than received
Example: Deposit into Lending Protocolโ
import { encodeFunctionData, parseAbi } from 'viem';
const wbtcAddress = '0x0555E30da8f98308EdB960aa94C0Db47230d2B9c';
const lendingPoolAddress = '0x...'; // Your lending protocol
// Step 1: Approve lending pool to spend wBTC
const approveCallData = encodeFunctionData({
abi: erc20Abi,
functionName: 'approve',
args: [lendingPoolAddress, maxUint256],
});
// Step 2: Deposit wBTC into lending pool
const lendingAbi = parseAbi([
'function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode)',
]);
const depositCallData = encodeFunctionData({
abi: lendingAbi,
functionName: 'deposit',
args: [wbtcAddress, amount, userAddress, 0],
});
const quote = await client.getQuote({
// ... other params
destinationCalls: {
calls: [
{
target: wbtcAddress,
callData: approveCallData,
value: BigInt(0),
},
{
target: lendingPoolAddress,
callData: depositCallData,
value: BigInt(0),
},
],
leftoverRecipient: userAddress, // Receive any leftover tokens
gasLimit: 500000, // Higher gas limit for multiple calls
},
});
Execute Quoteโ
Execute the cross-chain swap:
import { createPublicClient, createWalletClient, http } from 'viem';
import { base } from 'viem/chains';
// Setup clients for the origin chain
const publicClient = createPublicClient({
chain: base, // Origin chain
transport: http()
});
const walletClient = createWalletClient({
chain: base,
transport: http(),
account: yourAccount
});
// Execute the quote
const txHash = await client.executeQuote({
quote,
walletClient,
publicClient,
btcSigner // Only required for Bitcoin โ EVM onramp
});
console.log('Transaction hash:', txHash);
Architecture & Smart Contractsโ
BOB Hub Architectureโ
All LayerZero operations route through BOB:
-
BOB Strategy Contract:
0x4572ce66cB33255B60a15e3c6cb2ef9c65A30ebC- Handles Bitcoin โ LayerZero bridging
- Swaps portion of wBTC to ETH for LayerZero fees
- Executes LayerZero
send()with proper parameters
-
Offramp Composer:
0xaffBF9ECC4a23adfFe887FB859654B8B780CCed0- Receives LayerZero โ BOB transfers
- Creates Gateway offramp orders for Bitcoin withdrawal
wBTC OFT Standardโ
LayerZero uses standardized wBTC OFT contracts across supported chains:
- Address:
0x0555e30da8f98308edb960aa94c0db47230d2b9c(most chains) - Exception: Optimism uses
0xc3f854b2970f8727d28527ece33176fac67fef48
MulticallComposer Contractโ
The MulticallComposer contract (0x814347a131B08679087F9A4842d493B1e788ea7a on all supported chains) handles destination actions on LayerZero chains:
- Receives tokens from LayerZero OFT transfers
- Executes user-specified calls on the destination chain
- Sends leftover tokens to the specified recipient
- Provides safety mechanisms to prevent token loss
Supported Chains: BOB, Base, Ethereum, Sonic
Reach out to the BOB Team if there is a chain which you would like us to add support for!