This is a demo running on testnets. Check the Docs for the complete setup guide to deploy on your own chain.

Documentation

Everything you need to deploy BlockBridge on your own chain

Product Overview

Deploy a production-ready cross-chain bridge to any EVM chain.

BlockBridge is a complete, white-label token bridge powered by Hyperlane, the permissionless interoperability framework. It ships with auditable smart contracts, a polished Next.js frontend, deployment scripts, and agent configuration — everything needed to connect your L1, L2, or L3 to any other EVM chain.

Smart ContractsNative, Collateral & Synthetic warp routes
Bridge UINext.js 14 + Tailwind + WalletConnect
Agent InfraValidator & Relayer configs included
Security HardenedPausable, reentrancy guard, transfer caps

What's Included

  • • Solidity contracts with 80+ Foundry tests (unit, integration, security, fork)
  • • Next.js 14 frontend with AppKit wallet connection and real-time fee quoting
  • • Shell deployment scripts for any EVM chain
  • • Docker-ready agent configurations for validators and relayers
  • • Comprehensive documentation (this page)

Quick Start

Prerequisites

Get Running

Install dependencies
# Download and unzip BlockBridge from web3.market, then:
cd blockbridge
pnpm install
Run contract tests
cd contracts
forge test
Start the frontend
cd bridge-ui
cp .env.example .env.local   # add your WalletConnect ID
pnpm dev
The demo is pre-configured for Sepolia ↔ BSC Testnet. To deploy on your own chains, continue to the next section.

Deploy to Your Chain

3a. Prerequisites

  • • Foundry installed (curl -L https://foundry.paradigm.xyz | bash)
  • • RPC URLs for both your origin and destination chains
  • • Deployer wallet with native gas tokens on both chains
  • • Hyperlane Mailbox address on each chain — check the Hyperlane Registry
If your chain doesn't have a Hyperlane Mailbox yet, you can deploy one using the Hyperlane CLI. This is required for custom/appchains.

3b. Deploy Contracts

Deploy the warp route contracts using forge create. Replace placeholders with your values.

HypNative (lock native token on origin)
forge create --json --broadcast \
  --rpc-url $ORIGIN_RPC \
  --private-key $DEPLOYER_PK \
  src/warp/BlockBridgeHypNative.sol:BlockBridgeHypNative \
  --constructor-args $MAILBOX_ORIGIN
HypERC20 (synthetic token on destination)
forge create --json --broadcast \
  --rpc-url $DEST_RPC \
  --private-key $DEPLOYER_PK \
  src/warp/BlockBridgeHypERC20.sol:BlockBridgeHypERC20 \
  --constructor-args 18 $MAILBOX_DEST "Token Name" "TKN"
HypERC20Collateral (lock ERC20 on origin)
forge create --json --broadcast \
  --rpc-url $ORIGIN_RPC \
  --private-key $DEPLOYER_PK \
  src/warp/BlockBridgeHypERC20Collateral.sol:BlockBridgeHypERC20Collateral \
  --constructor-args $ERC20_TOKEN_ADDRESS $MAILBOX_ORIGIN
Save all deployed contract addresses immediately. You will need them for router enrollment, frontend config, and verification.

3c. Enroll Remote Routers

Each warp contract must know about its counterpart on the remote chain. Call enrollRemoteRouter on both sides.

Enroll on origin (points to destination)
cast send $ORIGIN_CONTRACT \
  "enrollRemoteRouter(uint32,bytes32)" \
  $DEST_DOMAIN_ID \
  $(cast --to-bytes32 $DEST_CONTRACT) \
  --rpc-url $ORIGIN_RPC \
  --private-key $DEPLOYER_PK
Enroll on destination (points to origin)
cast send $DEST_CONTRACT \
  "enrollRemoteRouter(uint32,bytes32)" \
  $ORIGIN_DOMAIN_ID \
  $(cast --to-bytes32 $ORIGIN_CONTRACT) \
  --rpc-url $DEST_RPC \
  --private-key $DEPLOYER_PK
The domain ID is typically the chain ID (e.g., 1 for Ethereum, 42161 for Arbitrum). Check the Hyperlane registry for canonical domain IDs.

3d. Configure Security

Set Interchain Security Module (optional)
cast send $CONTRACT \
  "setInterchainSecurityModule(address)" \
  $ISM_ADDRESS \
  --rpc-url $RPC_URL \
  --private-key $DEPLOYER_PK
Set max transfer amount (HypNative only)
cast send $HYP_NATIVE \
  "setMaxTransferAmount(uint256)" \
  $(cast --to-wei 100) \
  --rpc-url $RPC_URL \
  --private-key $DEPLOYER_PK
Pause / Unpause
# Pause
cast send $CONTRACT "pause()" --rpc-url $RPC_URL --private-key $DEPLOYER_PK

# Unpause
cast send $CONTRACT "unpause()" --rpc-url $RPC_URL --private-key $DEPLOYER_PK

3e. Transfer Ownership

Once everything is configured, transfer ownership to a multisig (e.g., Gnosis Safe).

cast send $CONTRACT \
  "transferOwnership(address)" \
  $MULTISIG_ADDRESS \
  --rpc-url $RPC_URL \
  --private-key $DEPLOYER_PK
Ownership transfer is irreversible with a standard Ownable contract. Double-check the multisig address before executing.

3f. Verify on Block Explorer

forge verify-contract \
  $CONTRACT_ADDRESS \
  src/warp/BlockBridgeHypNative.sol:BlockBridgeHypNative \
  --chain-id $CHAIN_ID \
  --etherscan-api-key $ETHERSCAN_API_KEY \
  --constructor-args $(cast abi-encode "constructor(address)" $MAILBOX)

Configure the Frontend

After deploying contracts, update the frontend configuration to match your chains and tokens.

config/chains.ts

Add your chain configuration.

export const MY_CHAIN: ChainConfig = {
  id: 42161,                // Chain ID
  name: 'arbitrum',         // Internal name
  displayName: 'Arbitrum',  // Display name
  domainId: 42161,          // Hyperlane domain ID
  rpcUrl: process.env.NEXT_PUBLIC_RPC_ARBITRUM || 'https://arb1.arbitrum.io/rpc',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  blockExplorer: 'https://arbiscan.io',
  logoUrl: '/chains/arbitrum.svg',
  isTestnet: false,
};

config/tokens.ts

Add your token with contract addresses per chain.

export const MY_TOKEN: Token = {
  symbol: 'USDC',
  name: 'USD Coin',
  decimals: 6,
  addresses: {
    1: '0xA0b8...eB48',      // Ethereum
    42161: '0xaf88...3f2c',   // Arbitrum (synthetic)
  },
  isNative: false,
};

config/warpRoutes.ts

Add route entries for each direction.

{
  originChainId: 1,
  destinationChainId: 42161,
  originContract: '0x...',        // HypERC20Collateral on Ethereum
  destinationContract: '0x...',   // HypERC20 on Arbitrum
  tokenSymbol: 'USDC',
  type: 'collateral',
},
{
  originChainId: 42161,
  destinationChainId: 1,
  originContract: '0x...',        // HypERC20 on Arbitrum
  destinationContract: '0x...',   // HypERC20Collateral on Ethereum
  tokenSymbol: 'USDC',
  type: 'synthetic',
},

lib/wagmi/chains.ts

Define the chain for viem/wagmi.

import { defineChain } from 'viem';

export const myChain = defineChain({
  id: 42161,
  name: 'Arbitrum One',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { default: { http: ['https://arb1.arbitrum.io/rpc'] } },
  blockExplorers: { default: { name: 'Arbiscan', url: 'https://arbiscan.io' } },
});

lib/wagmi/config.ts & app/appkit-init.tsx

Add your chain to the WagmiAdapter networks array and AppKit networks.

Environment Variables

.env.local
NEXT_PUBLIC_WALLETCONNECT_ID=your_project_id
NEXT_PUBLIC_RPC_ARBITRUM=https://arb1.arbitrum.io/rpc

Validators & Relayers

Hyperlane uses a validator + relayer model for cross-chain messaging.

Validators

Watch the origin chain Mailbox for dispatched messages and sign merkle root checkpoints. Multiple validators form a multisig for security.

Relayers

Pick up signed messages and submit them to the destination chain Mailbox, which verifies them against the ISM before delivering to the warp route contract.

For supported testnets (Sepolia, BSC Testnet, etc.), Hyperlane runs public validator and relayer infrastructure. For custom chains or mainnet production, you must run your own.

Running Agents

Refer to the Hyperlane Agent documentation for full setup instructions. Key environment variables:

Validator
HYP_VALIDATOR_KEY=<private-key-or-aws-kms-id>
HYP_CHAINS_<CHAIN>_CONNECTION_URL=<rpc-url>
HYP_CHECKPOINTSYNCER_TYPE=localStorage
HYP_CHECKPOINTSYNCER_PATH=/tmp/checkpoints
Relayer
HYP_RELAYER_KEY=<private-key>
HYP_CHAINS_<ORIGIN>_CONNECTION_URL=<rpc-url>
HYP_CHAINS_<DEST>_CONNECTION_URL=<rpc-url>

Security Best Practices

Security Feature Matrix

FeatureHypNativeHypERC20HypERC20Collateral
Pausable&#10003;&#10003;&#10003;
ReentrancyGuard&#10003;&#8212;&#8212;
Transfer Caps&#10003;&#8212;&#8212;
Zero-Address Check&#10003;&#10003;&#10003;
Configurable ISM&#10003;&#10003;&#10003;

Multisig ISM

Configure a Multisig ISM for production. Testnet: 2-of-3 validators. Mainnet: 3-of-5 or higher threshold for economic security.

Key Management

  • • Use hardware wallets (Ledger/Trezor) for deployer keys
  • • Use AWS KMS or GCP Cloud HSM for validator signing keys
  • • Transfer contract ownership to a Gnosis Safe multisig
  • • Never store private keys in environment variables in production

Audit Recommendations

  • • Engage a professional security auditor before mainnet launch
  • • Run the full Foundry test suite: forge test -vvv
  • • Consider a bug bounty program for ongoing security

Mainnet Checklist

Contracts deployed on all target chains
Contracts verified on block explorers
Remote routers enrolled in both directions
Interchain Security Module configured (Multisig ISM)
Transfer caps set to appropriate limits
Contract ownership transferred to multisig
Validators running with secure key management
Relayer funded with gas tokens on all destination chains
Frontend config updated with mainnet addresses
End-to-end bridge transfer tested successfully
Security audit completed
Monitoring and alerting configured
Copy this checklist to your project management tool and assign owners to each item before your mainnet launch.

Customize the UI

globals.css — CSS Custom Properties

Colors are defined as HSL values. Edit these to change the entire color scheme.

:root {
  --background: 240 10% 3.9%;
  --foreground: 0 0% 98%;
  --primary: 217 91% 60%;
  --accent: 240 3.7% 15.9%;
  /* ... */
}

config/theme.ts — Hex Colors

Used for non-Tailwind contexts (e.g., charts, dynamic styles).

tailwind.config.ts

Maps CSS variables to Tailwind utility classes. Extend here for custom colors.

Branding

  • Logo & name: Edit components/layout/Header.tsx
  • Page title & meta: Edit app/layout.tsx metadata
  • AppKit theme: Edit app/appkit-init.tsx themeVariables
  • Chain logos: Add SVGs to public/chains/

Architecture Reference

Hyperlane Message Lifecycle

Dispatch

User calls transferRemote() on the origin warp route. Tokens are locked (native/collateral) or burned (synthetic). A message is dispatched to the Hyperlane Mailbox.

Validate

Validators observe the dispatched message on the origin chain and sign a merkle root checkpoint attesting to the message.

Relay

The relayer picks up the validated message and submits it (with validator signatures) to the destination Mailbox.

Deliver

The destination Mailbox verifies the message against the ISM, then calls handle() on the destination warp route, which mints or unlocks tokens to the recipient.

Warp Route Types

TypeOrigin ActionDestination ActionUse Case
NativeLock ETH/nativeMint syntheticBridge native gas token
CollateralLock ERC20Mint syntheticBridge existing ERC20
SyntheticBurn syntheticUnlock originalReturn to origin chain

Contract Security Model

All BlockBridge contracts inherit from Ownable (access control) + Pausable (emergency stop). HypNative adds ReentrancyGuard for safe ETH handling and configurable transfer caps.

Troubleshooting & FAQ

Common Errors

"No router enrolled for destination"

You forgot to call enrollRemoteRouter() on the origin contract. Run the enrollment command from section 3c for both directions.

"Contract is paused"

The contract owner has paused the bridge. The owner must call unpause() to re-enable transfers.

"Exceeds maximum transfer amount"

The transfer amount exceeds the configured cap on HypNative. The owner can increase it via setMaxTransferAmount() or set to 0 to disable the cap.

Message dispatched but not delivered

Check that: (1) the relayer is running and funded, (2) the ISM on the destination matches the validators signing checkpoints, (3) call delivered(messageId) on the destination Mailbox to verify status.

FAQ

How long does a bridge transfer take?

Typically 2-5 minutes. This depends on origin chain finality and relayer speed. The Hyperlane relayer automatically picks up and delivers messages.

What fees are involved?

You pay the Hyperlane protocol fee (quoted by quoteTransferRemote on the warp contract) plus the origin chain gas fee. The protocol fee covers validator signing and relayer delivery on the destination chain.

Where can I get testnet tokens?

Sepolia ETH from Google Cloud Web3 Faucet or Alchemy Faucet. BSC testnet BNB from the BNB Chain Faucet. HYPL tokens are minted during deployment.

Can I bridge in both directions?

Yes. Each warp route supports bidirectional transfers when both sides have enrolled remote routers.

Can I add more tokens later?

Yes. Deploy new warp route contract pairs, enroll routers, and add the token/route to the frontend config. No existing contracts need to change.

What happens if my transfer fails?

If the origin transaction reverts, your tokens are never locked/burned. If destination delivery fails (e.g., contract paused), the relayer will retry once the issue is resolved. Your tokens are safe.