Liquidity is scattered across dozens of blockchains, and bridges between them must solve the trust problem without sacrificing speed. $50B is stuck in isolated pools — USDC on Arbitrum and on Optimism are different assets. Our approach is to build architectures that balance security, speed, and decentralization. Optimistic bridges, ZK-light client bridges, intent-based bridges — each option has its own trade-offs. We implement the one that fits your task and build bridges that handle millions of dollars daily. Order turnkey development — get a ready solution with audit and support.
Comparison of architectural models
| Model | Security | Speed | Decentralization | Complexity |
|---|---|---|---|---|
| Lock-and-mint | Medium (depends on bridge) | Fast | Low | Low |
| Liquidity Pool | High (native asset) | Fast (instant) | Medium | Medium |
| Intent-based | High (solver) | Instant | High (many solvers) | High |
Why protocol architecture is critical for cross-chain liquidity?
Lock-and-mint vs Liquidity Pool
Lock-and-mint (wrapped assets): tokens are locked on the source chain, wrapped copies are minted on the destination. Classic: wBTC (Bitcoin → Ethereum). Problem: the wrapped asset is a new token with counterparty risk on the bridge. If the bridge is hacked — wrapped tokens are useless. That's how $320M was lost in the Wormhole hack and $190M in the Nomad hack.
Liquidity Pool (native assets): a pool of native tokens is maintained on each chain (USDC on Arbitrum, USDC on Optimism). The user deposits into the pool on the source, withdraws a native token from the pool on the destination. This is the model of Stargate (LayerZero), Across Protocol, Hop Protocol. Advantage: the user gets real USDC, not wrapped. Disadvantage: liquidity is needed on every chain — a cold start problem.
Intent-based (solver model): the user declares an intention ("I want 1000 USDC on Optimism from my 1001 USDC on Arbitrum"), a solver immediately issues from its balance on the destination, later recovers its balance through a settlement mechanism. The model of Across Protocol (optimized) and UniswapX cross-chain. This gives an instant user experience: the user sees the funds on the destination within seconds, the solver's settlement happens later (through bundling and an official bridge).
Messaging layer: how does chain A learn about an event on chain B?
This is the fundamental problem. Options:
- Optimistic verification: the message is accepted as valid, there is a challenge window (30 min – 7 days). If no one challenges, it's considered final. Model: Nomad, Connext Amarok. Pro: relatively simple. Con: delay.
- Validator/Oracle set: a set of validators monitors the source chain and signs attestations of events. M-of-N multisig unlocks on the destination. Model: Wormhole (19 guardians), Multichain (MPC nodes), cBridge (SGN validators). Risk: centralized validator set — the main attack surface.
- ZK Light Client: the destination chain verifies a ZK proof of the source chain header. Trustless, but technically complex and expensive in gas. Models: zkBridge (Polyhedra), Succinct Labs, Herodotus. The technology is maturing in the current cycle.
- Native messaging (canonical): Arbitrum bridge, Optimism bridge — use the official L1↔L2 mechanism. Maximally secure, but a 7-day withdrawal delay (fraud proof window for Optimistic rollups).
LayerZero V2: Ultra Light Node (ULN). Two independent roles: DVN (Decentralized Verifier Network) verifies the header, Executor delivers the message. You can configure the DVN set to your security requirements. Stargate V2 is built on LayerZero V2.
Comparison of approaches
ZK Light Client is 100 times more secure than Optimistic bridges — trust in math instead of economics. But significantly more expensive in gas. For high-value transactions, choose ZK; for mass usage, choose Liquidity Pool with dynamic fees.
Deep dive: Stargate / LayerZero architecture
LayerZero is a messaging protocol, Stargate is a liquidity protocol built on top of it. We analyze their architecture as a reference implementation.
LayerZero V2: message flow
Source Chain Destination Chain
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ OApp (User Contract) │ │ OApp (User Contract) │
│ ↓ _lzSend() │ │ ↑ _lzReceive() │
│ Endpoint │ │ Endpoint │
│ ↓ emit PacketSent event │ │ ↑ lzReceive() │
│ │ │ │
│ DVN monitors event │ DVN signs │ DVN submits verification │
│ Executor monitors event ─────┼─────────────→ Executor calls lzReceive() │
└──────────────────────────────┘ └──────────────────────────────┘
Key insight of LayerZero V2: OApp (Omnichain Application) is your contract on each chain. _lzSend sends a message via the Endpoint. _lzReceive is the callback on the destination. Everything in between is the job of the DVN and Executor.
// OApp base contract (LayerZero V2)
import { OApp, Origin, MessagingFee } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
contract CrossChainLiquidityPool is OApp {
mapping(address => uint256) public deposits;
constructor(address _endpoint, address _owner) OApp(_endpoint, _owner) {}
// Initiating a cross-chain deposit
function depositAndBridge(
uint32 dstEid, // destination endpoint ID (chain)
address recipient,
uint256 amount,
bytes calldata extraOptions
) external payable {
// Accept tokens
IERC20(depositToken).safeTransferFrom(msg.sender, address(this), amount);
// Encode message
bytes memory message = abi.encode(recipient, amount);
// Calculate fee
MessagingFee memory fee = _quote(dstEid, message, extraOptions, false);
require(msg.value >= fee.nativeFee, "Insufficient fee");
// Send cross-chain message
_lzSend(
dstEid,
message,
extraOptions,
fee,
payable(msg.sender)
);
emit DepositBridged(msg.sender, dstEid, recipient, amount);
}
// Callback on destination chain
function _lzReceive(
Origin calldata origin,
bytes32 /*guid*/,
bytes calldata payload,
address /*executor*/,
bytes calldata /*extraData*/
) internal override {
// Verify source
require(
peers[origin.srcEid] == origin.sender,
"Unknown source"
);
(address recipient, uint256 amount) = abi.decode(payload, (address, uint256));
// Pay from pool on destination
require(poolBalance[depositToken] >= amount, "Insufficient pool");
poolBalance[depositToken] -= amount;
IERC20(depositToken).safeTransfer(recipient, amount);
emit BridgeReceived(origin.srcEid, recipient, amount);
}
}
Stargate V2: Hydra Pool and unified liquidity
Stargate V1 problem: the USDC pool on Arbitrum and the USDC pool on Optimism are separate. Imbalance: many withdrawals from Arbitrum, few incoming → pool is depleted.
Stargate V2 solution — Hydra Pool: a single global pool with credit mechanisms. Each chain has a credit from the global pool. Transfers are balanced globally, not only between chain pairs.
// Simplified credit-based pool model
contract StargatePool {
// Credits: how much we "owe" to other chain pools
mapping(uint32 => uint256) public credits; // dstEid => credit
uint256 public localBalance;
function sendTokens(
uint32 dstEid,
address to,
uint256 amountLD // Local Decimals
) external {
// Convert to Shared Decimals (unified precision)
uint256 amountSD = _toSD(amountLD);
require(localBalance >= amountSD, "Insufficient balance");
localBalance -= amountSD;
// Increase credit for destination (they will pay out)
credits[dstEid] += amountSD;
// Send message via LayerZero
_sendCrossChain(dstEid, abi.encode(to, amountSD, credits[dstEid]));
}
// Receive: destination pays out and updates credits
function _receiveTokens(uint32 srcEid, address to, uint256 amountSD) internal {
// Reduce debt to source
require(credits[srcEid] >= amountSD, "Insufficient credits");
credits[srcEid] -= amountSD;
localBalance += amountSD; // will be paid to user
IERC20(token).safeTransfer(to, _toLD(amountSD));
}
}
Shared Decimals — an important detail: different chains may have different ERC-20 precision. 6 decimals USDC on Ethereum, 6 on Arbitrum, but potentially different. Stargate normalizes to SD (Shared Decimals = 6) for inter-chain accounting.
Hydra Pool details
Hydra Pool uses a credit-based system: each chain has a credit limit based on total liquidity. On withdrawal, credit increases; on deposit, decreases. If credit exceeds the limit, fees increase to incentivize reverse flow.How does LayerZero V2 ensure secure message delivery?
Rebalancing mechanism
The problem of any liquidity bridge: flow imbalance. If everyone withdraws from chain A and deposits into chain B — the pool on A depletes, and on B it overflows.
contract RebalancingModule {
// Imbalance thresholds
uint256 public constant REBALANCE_THRESHOLD = 20; // 20% deviation
uint256 public constant TARGET_UTILIZATION = 80; // target utilization
function checkAndRebalance(uint32 srcEid, uint32 dstEid) external {
uint256 srcUtilization = getUtilization(srcEid); // % of pool used
uint256 dstUtilization = getUtilization(dstEid);
if (srcUtilization > TARGET_UTILIZATION + REBALANCE_THRESHOLD &&
dstUtilization < TARGET_UTILIZATION - REBALANCE_THRESHOLD) {
uint256 rebalanceAmount = calculateRebalanceAmount(srcEid, dstEid);
_initiateRebalance(srcEid, dstEid, rebalanceAmount);
}
}
// LPs receive rebalancing incentive for adding liquidity to deficit pools
function rebalancingFeeMultiplier(uint32 chainId) public view returns (uint256) {
uint256 utilization = getUtilization(chainId);
if (utilization > 90) return 200; // 2x fee for LP on deficit chain
if (utilization > 75) return 150;
return 100;
}
}
Fee mechanism for balancing
Dynamic fee: when pool utilization is high (>80%), the fee for bridging into that chain increases. This economically incentivizes transfers in the opposite direction and liquidity additions.
Security and audit
Our experience shows that bridge contracts are one of the most attacked categories in DeFi. We guarantee an external audit (mandatory two independent auditors) and include insurance against rare attacks.
Main attack vectors
Reentrancy through cross-chain callback: an attacker could initiate a recursive call via another chain before the first one completes.
Oracle/validator manipulation: if the validator set is small or centralized, an attack on the M-of-N threshold compromises the entire bridge. Wormhole hack: an exploit in signature verification allowed minting 120,000 wETH without backing.
Protections:
- Use proven messaging protocols (LayerZero V2, Wormhole, Axelar) instead of your own validator set
- Introduce rate limiting: maximum bridge amount per 1 hour/24 hours
- Emergency pause: multisig + timelock on critical operations
- Insurance fund: % of fees goes into an insurance fund
Replay attack
The same message should not be delivered twice. LayerZero protects via nonce: each OApp has an ordered nonce for each src/dst pair. A message with an unexpected nonce is rejected.
How to create a cross-chain protocol: step-by-step guide
- Choose architecture and messaging protocol.
- Write smart contracts in Solidity 0.8.x + Foundry.
- Integrate with LayerZero/Axelar.
- Deploy to testnet and perform cross-chain testing.
- Conduct audit (we recommend two audits).
- Deploy to mainnet and monitor.
Economic incentives for LPs
Attracting liquidity requires a well-designed economic model. Main mechanisms:
| Mechanism | Description |
|---|---|
| Bridge fees (LP share) | 0.01–0.06% of volume, distributed to LPs proportionally |
| Protocol token rewards | Emissions in governance token for LP |
| Rebalancing bonuses | Higher fee for liquidity in deficit pools |
| veToken voting | LPs vote to boost emission for their pool |
For a cold start: boosted rewards in the first 3–6 months from the protocol treasury.
What is included in protocol development
- Architectural documentation
- Smart contracts (core and auxiliary)
- Integration with chosen messaging protocol
- Frontend (wagmi + viem, multi-chain wallet)
- Security audit (external, two auditors)
- Deployment to testnet/mainnet
- Developer documentation
- Technical support for 3 months after launch
Our experience
We have implemented 10+ cross-chain bridges for DeFi protocols. 5 years in the blockchain development market. Total volume bridged through our contracts exceeds $500M. Contact us for a consultation — we will calculate timelines and cost individually.







