Deployment Guide
Everything you need to deploy ProBridge on your own chains — contracts, frontend config, and production checklist.
Overview
How ProBridge works
ProBridge is a full-stack cross-chain bridge built on Hyperlane — a permissionless interoperability protocol. It includes Solidity contracts, a Next.js frontend, and a config system that lets you add any EVM chain without touching component code.
Smart Contracts
Solidity warp routes on both chains
Frontend
Next.js + wagmi + RainbowKit
Protocol
Hyperlane messaging + relayer
Bridge flow:
Requirements
What you need before deploying
node --versionforge --versiongit --versionInstall Foundry
curl -L https://foundry.paradigm.xyz | bash foundryup
Install frontend dependencies
cd probridge-ui npm install
You also need a WalletConnect Project ID (free at cloud.walletconnect.com) and a deployer wallet with gas on both chains.
Deploy Contracts
Using Remix IDE (recommended) or Foundry
Remix IDE is the easiest approach — no local setup needed. Open remix.ethereum.org, paste each contract file, set compiler to 0.8.24 + EVM Cancun, and deploy.
Deploy BlockBridgeIGP on the source chain
No constructor arguments needed. Copy the deployed address.
// Constructor: none // After deployment, save: // IGP_ADDRESS = "0x..."
Deploy BlockBridgeMultisigISM on the source chain
No constructor arguments needed.
// Constructor: none // After deployment, save: // ISM_ADDRESS = "0x..."
Deploy HypERC20Collateral on the source chain
This locks existing ERC20 tokens (e.g. USDC) on the source chain.
// Constructor args: // _mailbox: Hyperlane Mailbox address on source chain // _token: Address of the ERC20 you want to bridge // // Example (Base Sepolia USDC): // mailbox: 0x6966b0E55883d49BFB0b8E4AcEA2855b4C9Bf4e9 // token: 0x036CbD53842c5426634e7929541eC2318f3dCF7e
Deploy HypERC20 (synthetic) on the destination chain
This mints synthetic tokens on the destination chain when a bridge message arrives.
// Constructor args: // _mailbox: Hyperlane Mailbox on destination chain // _name: Token name (e.g. "ProBridge USDC") // _symbol: Token symbol (e.g. "pbUSDC") // _decimals: 6 for USDC // // Example (BNB Testnet): // mailbox: 0xF9F6F5646F478d5ab4e20B0F910C92F1CCC9Cc6D
Enroll remote routers (link the two contracts)
Call enrollRemoteRouter() on each contract so they trust messages from each other.
// On HypERC20Collateral (source chain):
// domain: destination chain ID (e.g. 97 for BNB Testnet)
// router: pad destination contract address to bytes32
// e.g. 0x000000000000000000000000{HypERC20_ADDRESS}
// On HypERC20 (destination chain):
// domain: source chain ID (e.g. 84532 for Base Sepolia)
// router: pad source contract address to bytes32
// e.g. 0x000000000000000000000000{HypERC20Collateral_ADDRESS}Both enrollments must be done or messages will be rejected. Pad the address with 24 leading zeros to convert from 20-byte address to 32-byte bytes32.
Configure Frontend
Update 3 config files with your deployed addresses
Add your contract addresses to contracts.config.ts
// config/contracts.config.ts
export const CONTRACTS_CONFIG: Record<number, ContractAddresses> = {
84532: { // Source chain ID
warpRoute: '0xYOUR_HYP_ERC20_COLLATERAL',
igp: '0xYOUR_IGP',
ism: '0xYOUR_ISM',
mailbox: '0xHYPERLANE_MAILBOX_SOURCE',
},
97: { // Destination chain ID
warpRoute: '0xYOUR_HYP_ERC20',
mailbox: '0xHYPERLANE_MAILBOX_DEST',
},
};Add your token to tokens.config.ts
// config/tokens.config.ts
export const TOKENS_CONFIG: TokenConfig[] = [
{
symbol: 'USDC',
name: 'USD Coin',
decimals: 6,
addresses: {
84532: '0xYOUR_TOKEN_ON_SOURCE', // original ERC20
97: '0xYOUR_SYNTHETIC_ON_DEST', // HypERC20 address
},
type: {
84532: 'collateral',
97: 'synthetic',
},
coingeckoId: 'usd-coin',
},
];Set your WalletConnect Project ID
# Create .env.local in the project root NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id_here
Run the frontend
npm run dev # Open http://localhost:3000
Add a New Chain
No component code needed — config only
ProBridge is designed so adding a chain requires editing config files only. No changes to UI components.
Deploy contracts on the new chain (same steps as above)
Make sure the new chain has a Hyperlane Mailbox. Check the Hyperlane registry for supported chains. For custom chains you'll need to deploy a Mailbox using the Hyperlane CLI.
Add chain to chains.config.ts
// config/chains.config.ts — add inside CHAINS_CONFIG array:
{
id: 42161, // Arbitrum One
name: 'Arbitrum One',
shortName: 'ARB',
label: 'Arbitrum Mainnet',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: [
'https://arb1.arbitrum.io/rpc',
'https://arbitrum-one-rpc.publicnode.com',
],
explorerUrl: 'https://arbiscan.io',
explorerTxPath: '/tx/',
color: '#28A0F0',
iconSvg: `<svg viewBox="0 0 32 32">...</svg>`,
},Add contract addresses to contracts.config.ts
42161: {
warpRoute: '0xYOUR_WARP_ROUTE_ON_ARBITRUM',
mailbox: '0xHYPERLANE_MAILBOX_ARBITRUM',
},Add token address on the new chain to tokens.config.ts
// Inside the USDC token entry:
addresses: {
84532: '0x036CbD...', // Base Sepolia
97: '0x779508...', // BNB Testnet
42161: '0xYOUR_USDC_OR_SYNTHETIC_ON_ARBITRUM', // ← add this
},
type: {
84532: 'collateral',
97: 'synthetic',
42161: 'collateral', // ← add this
},That's it — the chain selector, balance reader, progress tracker and history all pick up the new chain automatically.
Add a New Token
Bridge any ERC20 with a new warp route
Deploy warp route contracts for the new token
Deploy HypERC20Collateral on the source chain (pointing to your token), and HypERC20 on the destination chain. Enroll remote routers on both.
Add token entry to tokens.config.ts
{
symbol: 'WBTC',
name: 'Wrapped Bitcoin',
decimals: 8,
addresses: {
84532: '0xYOUR_WBTC_ON_SOURCE',
97: '0xYOUR_SYNTHETIC_WBTC_ON_DEST',
},
type: {
84532: 'collateral',
97: 'synthetic',
},
coingeckoId: 'wrapped-bitcoin',
iconId: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', // mainnet WBTC for icon
},The iconId field is used to load the token logo from the Trust Wallet CDN. Use the Ethereum mainnet address of the token for the best icon coverage.
Go to Production
Checklist before handling real value
Deploy to Vercel
npm install -g vercel vercel --prod
Hyperlane Mailbox addresses (mainnet)
| Chain | Chain ID | Mailbox Address |
|---|---|---|
| Ethereum | 1 | 0xc005dc82818d67AF737725bD4bf75435d065D239 |
| BNB Chain | 56 | 0x2971b9Aec44bE4eb673DF1B88cDB57b96eefe8a4 |
| Arbitrum | 42161 | 0x979Ca5202784112f4738403dBec5D0F3B9daabB9 |
| Optimism | 10 | 0xd4C1905BB1D26BC93DAC913e13CaCC278CdCC892 |
| Base | 8453 | 0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D |
| Polygon | 137 | 0x5d934f4e2f797775e53561bB72aca21ba36B96BB |
Full list of supported chains and Mailbox addresses: hyperlane-xyz/hyperlane-registry
Contract Reference
Key functions and security features
HypERC20Collateral
Deployed on the source chain. Locks existing ERC20 tokens and dispatches a Hyperlane message.
transferRemote(uint32 dest, bytes32 recipient, uint256 amount)Initiates a bridge transfer. Must send ETH for Hyperlane gas fee.
quoteFee(uint32 dest, bytes32 recipient, uint256 amount)Returns the required ETH fee to pay for gas on the destination chain.
enrollRemoteRouter(uint32 domain, bytes32 router)Owner only. Registers the destination contract as a trusted router.
pause() / unpause()Owner only. Emergency stop for all transfers.
HypERC20 (Synthetic)
Deployed on the destination chain. Mints tokens when a verified message arrives, burns them when bridging back.
handle(uint32 origin, bytes32 sender, bytes message)Called by Hyperlane Mailbox on message delivery. Mints tokens to recipient.
transferRemote(uint32 dest, bytes32 recipient, uint256 amount)Burns tokens and dispatches return message to source chain.
BlockBridgeIGP
Interchain Gas Paymaster. Collects ETH from users to pay for gas on the destination chain.
payForGas(bytes32 messageId, uint32 dest, uint256 gasAmount, address refund)Called internally during transferRemote() to pay for destination gas.
quoteGasPayment(uint32 dest, uint256 gasAmount)Returns ETH cost for a given gas amount on the destination chain.