Skip to main content

Overview

The PolygonBridgeFacet enables bridging of ETH and ERC20 tokens from Ethereum mainnet to Polygon PoS (Proof of Stake) using the official Polygon bridge infrastructure.

Contract Interface

Functions

startBridgeTokensViaPolygonBridge

Bridges tokens from Ethereum to Polygon PoS.
function startBridgeTokensViaPolygonBridge(
  BridgeData _bridgeData
) external payable
_bridgeData
BridgeData
Standard bridge data containing transaction details

swapAndStartBridgeTokensViaPolygonBridge

Performs a token swap on Ethereum before bridging to Polygon.
function swapAndStartBridgeTokensViaPolygonBridge(
  BridgeData _bridgeData,
  SwapData[] _swapData
) external payable
_bridgeData
BridgeData
Standard bridge data
_swapData
SwapData[]
Array of swap operations to execute before bridging

Usage Example

Bridging ETH to Polygon

import { PolygonBridgeFacet } from '@lifi/contract-types';

const polygonFacet = PolygonBridgeFacet__factory.connect(facetAddress, signer);

const bridgeData = {
  transactionId: ethers.utils.randomBytes(32),
  bridge: 'polygon',
  integrator: 'my-dapp',
  referrer: '0x0000000000000000000000000000000000000000',
  sendingAssetId: '0x0000000000000000000000000000000000000000', // Native ETH
  receiver: await signer.getAddress(),
  minAmount: ethers.utils.parseEther('1'),
  destinationChainId: 137, // Polygon PoS
  hasSourceSwaps: false,
  hasDestinationCall: false
};

const tx = await polygonFacet.startBridgeTokensViaPolygonBridge(
  bridgeData,
  { value: bridgeData.minAmount }
);

await tx.wait();

console.log('Bridging initiated. Tokens will arrive on Polygon in ~7-8 minutes.');

Bridging ERC20 Tokens

const bridgeData = {
  transactionId: ethers.utils.randomBytes(32),
  bridge: 'polygon',
  integrator: 'my-dapp',
  referrer: '0x0000000000000000000000000000000000000000',
  sendingAssetId: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum
  receiver: await signer.getAddress(),
  minAmount: ethers.utils.parseUnits('1000', 6),
  destinationChainId: 137,
  hasSourceSwaps: false,
  hasDestinationCall: false
};

// Approve USDC first
const usdc = new ethers.Contract(
  bridgeData.sendingAssetId,
  ['function approve(address spender, uint256 amount) returns (bool)'],
  signer
);

await usdc.approve(polygonFacet.address, bridgeData.minAmount);

// Bridge tokens
const tx = await polygonFacet.startBridgeTokensViaPolygonBridge(
  bridgeData,
  { value: 0 }
);

await tx.wait();

Swap and Bridge

const swapData = [{
  callTo: uniswapRouter,
  approveTo: uniswapRouter,
  sendingAssetId: daiAddress,
  receivingAssetId: usdcAddress,
  fromAmount: ethers.utils.parseUnits('1000', 18),
  callData: swapCalldata,
  requiresDeposit: true
}];

const bridgeData = {
  transactionId: ethers.utils.randomBytes(32),
  bridge: 'polygon',
  integrator: 'my-dapp',
  referrer: '0x0000000000000000000000000000000000000000',
  sendingAssetId: usdcAddress, // Will receive USDC after swap
  receiver: await signer.getAddress(),
  minAmount: ethers.utils.parseUnits('990', 6), // Min USDC expected
  destinationChainId: 137,
  hasSourceSwaps: true,
  hasDestinationCall: false
};

const tx = await polygonFacet.swapAndStartBridgeTokensViaPolygonBridge(
  bridgeData,
  swapData,
  { value: 0 }
);

await tx.wait();

Events

  • LiFiTransferStarted(BridgeData bridgeData) - Emitted when bridge transfer is initiated
  • LiFiTransferCompleted - Emitted when transfer completes
  • AssetSwapped - Emitted when using swapAndStart variant

Notes

  • This facet only supports bridging FROM Ethereum mainnet TO Polygon PoS
  • Bridging typically takes 7-8 minutes for checkpoint finality
  • The bridge uses the Plasma bridge by default for faster finality
  • For native ETH, the amount is sent as msg.value
  • For ERC20 tokens, approve the facet contract before calling
  • Token addresses on Polygon will be different from Ethereum (mapped tokens)

Bridge Times

  • Ethereum → Polygon: ~7-8 minutes (PoS bridge)
  • Polygon → Ethereum: ~3 hours (withdrawal requires checkpoint)

See Also

Build docs developers (and LLMs) love