Lux Proposals
← All proposals
LP-0003Draftsecuritiesbridgecross-chainwarpteleport

LP-003: Cross-Chain Securities Bridge

Abstract

This specification defines the SecurityBridge contract and cross-chain protocol for moving security tokens between Lux chains. Security tokens can be bridged between the C-Chain, a tenant L2, Zoo EVM, and any Lux L1 / L2 (per LP-018). The bridge enforces compliance on both source and destination chains. Cross-listing with tZero uses the same bridge architecture for off-chain ATS settlement.

Motivation

Security tokens issued on one Lux chain need to trade on others:

Without a bridge, each chain would need its own token with its own compliance registry, and balances would diverge. The bridge maintains a single logical token supply across all chains.

Bridge Pattern

Lock/Mint (Source -> Destination)

Used when moving tokens from the chain where the token was originally deployed (the "home chain") to a remote chain.


Home Chain (C-Chain)              Remote Chain (Tenant L2)
--------------------              -------------------------
1. User calls lock()
   -> tokens transferred
      to SecurityBridge contract
   -> BridgeLock event emitted
                                  2. Relayer verifies the lock
                                     via Warp message
                                  3. Relayer calls bridgeMint()
                                     -> new tokens minted
                                        to user on remote chain
                                     -> BridgeMint event emitted

Burn/Release (Destination -> Source)

Used when moving tokens back to the home chain.


Remote Chain (Tenant L2)       Home Chain (C-Chain)
---------------------------       --------------------
1. User calls burn()
   -> tokens burned on
      remote chain
   -> BridgeBurn event emitted
                                  2. Relayer verifies the burn
                                     via Warp message
                                  3. Relayer calls bridgeRelease()
                                     -> locked tokens released
                                        to user on home chain
                                     -> BridgeRelease event emitted

Invariant

At all times:


HomeChain.SecurityBridge.lockedBalance + sum(RemoteChain[i].SecurityToken.totalSupply)
  == HomeChain.SecurityToken.totalSupply (at time of lock)

The bridge never creates or destroys net supply. Tokens are either locked on the home chain or minted on a remote chain. Never both.

Contract

The SecurityBridge contract (deployed per-token, per-chain):


contract SecurityBridge is AccessControl {
    bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE");

    SecurityToken public immutable TOKEN;
    mapping(bytes32 => bool) public processedNonces;

    // Source chain operations (user-callable)
    function lock(uint256 amount, uint256 destinationChainId, address destinationAddress) external;
    function burn(uint256 amount, uint256 destinationChainId) external;

    // Destination chain operations (bridge operator only)
    function bridgeMint(address recipient, uint256 amount, uint256 sourceChainId, bytes32 nonce) external;
    function bridgeRelease(address recipient, uint256 amount, uint256 sourceChainId, bytes32 nonce) external;
}

Nonce Deduplication

Every bridge operation generates a nonce:


bytes32 nonce = keccak256(abi.encodePacked(sender, amount, destinationChainId, block.timestamp, block.number));

The destination chain tracks processedNonces[nonce]. A nonce can only be processed once. This prevents replay attacks.

Role: BRIDGE_ROLE

The BRIDGE_ROLE authorizes bridgeMint() and bridgeRelease(). This role must be held by:

A single EOA must never hold BRIDGE_ROLE in production.

Warp Messaging

Protocol

Lux Warp Messaging (LP-6022) provides native cross-chain (L1 / L2) communication. The bridge uses Warp for lock/mint and burn/release verification.

Message Flow


Source Chain                    Lux P-Chain                   Destination Chain
------------                    -----------                   -----------------
1. SecurityBridge.lock()
   emits BridgeLock event

2. L1 / L2 validators sign
   Warp message containing:
   - sourceChainId
   - destinationChainId
   - sender
   - recipient
   - amount
   - nonce

                                3. Warp message aggregated
                                   (BLS signature threshold)

                                                              4. Relayer submits
                                                                 Warp message to
                                                                 destination chain

                                                              5. WarpMessenger precompile
                                                                 verifies BLS signature

                                                              6. SecurityBridge.bridgeMint()
                                                                 called with verified params

Warp Message Format


struct SecurityBridgeMessage {
    bytes32 messageType;     // keccak256("BRIDGE_LOCK") or keccak256("BRIDGE_BURN")
    uint256 sourceChainId;
    uint256 destinationChainId;
    address sender;
    address recipient;
    uint256 amount;
    bytes32 nonce;
    address tokenAddress;    // SecurityToken on source chain
}

Signature Threshold

Warp messages require a configurable BLS signature threshold from the source chain's validators. For security tokens:

Cross-Chain Flows

Zoo EVM <-> Tenant L2 <-> Lux C-Chain


                    Lux C-Chain (Home)
                    SecurityToken deployed here
                    SecurityBridge (lock/release)
                         |
                    Warp Messaging
                         |
              +----------+----------+
              |                     |
      Tenant L2             Zoo EVM
      SecurityToken            SecurityToken
      (bridge-minted)         (bridge-minted)
      SecurityBridge           SecurityBridge
      (burn/mint)              (burn/mint)
      ComplianceHook           ComplianceHook
      (DEX trading)            (marketplace)

C-Chain -> Tenant L2:

1. User locks 1000 ACME on C-Chain SecurityBridge

2. Warp message signed by C-Chain validators

3. Tenant L2 relayer verifies and calls bridgeMint(user, 1000, cChainId, nonce)

4. User now has 1000 ACME on Tenant L2, tradeable on DEX with ComplianceHook

Tenant L2 -> Zoo EVM:

1. User burns 500 ACME on Tenant L2 SecurityBridge (destination: Zoo EVM)

2. NOT a release back to C-Chain -- this is a hop. Implementation:

Direct chain-to-chain bridging (L1 ↔ L2 without C-Chain hop) is possible when both chains trust each other's validator set directly. This requires explicit opt-in via bridge configuration.

Chain IDs

| Chain | Chain ID | Purpose |
|---|---|---|
| Lux C-Chain | 96369 | Home chain for most security tokens |
| Tenant L2 (regulated EVM) | TBD | ATS trading, regulated DEX |
| Zoo EVM | TBD | NFT marketplace, DeSci |

Compliance on Bridge

Compliance is enforced at both ends:

Source chain (lock/burn):

Destination chain (mint/release):

Compliance registry synchronization:

tZero Cross-Listing Bridge

Architecture

tZero is an off-chain ATS. The "bridge" to tZero is not a blockchain bridge -- it is an API integration that uses the same lock/mint mental model.


Lux C-Chain                     tZero ATS
-----------                     ---------
SecurityToken                   tZero Security (off-chain)
SecurityBridge.lock()           tZero credits investor account
     |                               |
     +--- REST/Webhook API ----------+
     |                               |
SecurityBridge.bridgeRelease()  tZero debits investor account

Cross-Listing Flow

Lux -> tZero (investor wants to sell on tZero):

1. Investor locks tokens on Lux SecurityBridge (destination: tZero, identified by a reserved chainId)

2. Bridge event triggers webhook to tZero settlement API

3. tZero credits the investor's account with the corresponding security position

4. Investor can now sell on tZero ATS

tZero -> Lux (investor wants tokens on-chain):

1. Investor initiates withdrawal on tZero

2. tZero settlement API sends webhook to Lux bridge service

3. Bridge service (authorized with BRIDGE_ROLE via MPC) calls SecurityBridge.bridgeRelease()

4. Tokens released to investor's on-chain address

tZero Reserved Chain ID

tZero uses a reserved chain ID for bridge addressing:


tZero Chain ID: 0xTZERO (placeholder -- actual value assigned at integration time)

This is not a blockchain chain ID. It is a routing identifier that the bridge service uses to determine that the destination is tZero rather than another Lux chain.

Settlement Timing

| Direction | Latency | Notes |
|---|---|---|
| Lux -> tZero | < 5 minutes | Lock is instant; tZero credit after webhook processing |
| tZero -> Lux | < 5 minutes | tZero debit + webhook + bridgeRelease transaction |
| Lux -> Lux (cross-chain) | < 30 seconds | Warp message propagation + finality |

Webhook Security

All tZero webhooks use:


X-Signature: HMAC-SHA256(secret, timestamp + "." + body)
X-Timestamp: 1711100400
X-Idempotency-Key: uuid-v4

Bridge Operator

MPC Multisig

The bridge operator for production deployments is an M-Chain MPC multisig (per LP-134; supersedes LP-5013) hosting MPC ceremonies for bridge custody of external wallets (BTC, ETH, SOL, etc.):

Relayer Architecture


Warp Message (BLS signed)
        |
        v
+-------------------+
| Bridge Relayer     |
| (Go service)       |
|                    |
| 1. Verify Warp msg|
| 2. Decode params   |
| 3. Check compliance|
| 4. Submit to MPC   |
+-------------------+
        |
        v
+-------------------+
| M-Chain MPC        |
| (threshold sign)   |
|                    |
| 5. Sign bridgeMint |
|    transaction      |
+-------------------+
        |
        v
+-------------------+
| Destination Chain   |
| SecurityBridge      |
|                    |
| 6. bridgeMint()    |
+-------------------+

The relayer is a stateless Go service that:

1. Watches for Warp messages on source chains

2. Verifies BLS signature threshold

3. Checks compliance on destination chain (pre-flight)

4. Submits the mint/release request to the MPC signing cluster

5. Broadcasts the signed transaction to the destination chain

Emergency Procedures

Pause

Both the SecurityToken and SecurityBridge can be paused independently:

Stuck Funds

If tokens are locked on the home chain but the destination chain fails to mint:

1. The lock event and nonce are recorded on-chain

2. After a timeout (configurable, default 24 hours), admin can call a recovery function to release locked tokens back to the sender

3. Recovery requires DEFAULT_ADMIN_ROLE (multisig)

Chain Halt

If a destination chain halts:

1. Lock operations on the home chain continue to work (tokens accumulate in the bridge)

2. No mints occur on the halted chain

3. When the chain resumes, the relayer processes the backlog in order

4. Nonce deduplication prevents double-minting

Gas Costs

| Operation | Chain | Estimated Gas |
|---|---|---|
| lock() | Home chain | ~65,000 (transfer + event) |
| burn() | Remote chain | ~45,000 (burn + event) |
| bridgeMint() | Remote chain | ~55,000 (mint + nonce check + event) |
| bridgeRelease() | Home chain | ~50,000 (transfer + nonce check + event) |

Compliance checks in lock() add ~8,000-15,000 gas (via SecurityToken._update).

Security Considerations

1. Nonce replay: Each nonce can only be processed once. The nonce includes block.timestamp and block.number, making it unique per-block. Two locks in the same block from the same sender for the same amount produce different nonces due to different call positions.

2. Warp signature verification: The destination chain verifies the BLS aggregate signature against the source chain's registered validator set on the P-Chain. A compromised minority of validators cannot produce a valid Warp message (67% threshold minimum).

3. MPC key compromise: If the MPC signing threshold is compromised, the attacker can mint tokens on destination chains. Mitigation: per-asset key groups, HSM backing, quarterly rotation, real-time monitoring of bridge events.

4. Compliance desynchronization: If chain A whitelists a user and chain B has not synced yet, the user can lock on A but cannot trade on B. This is a liveness issue, not a safety issue -- compliance sync latency is the bottleneck. The compliance service targets < 30 second sync across chains.

5. Double-spend via reorg: If the source chain reorgs after a lock is processed, the destination chain has already minted. Mitigation: wait for finality before processing (Lux finality is 1ms, so reorgs are practically impossible under normal conditions).

6. Token supply audit: The bridge invariant (locked + remote supply = home supply) must be auditable. Both the home chain bridge balance and remote chain total supply are public on-chain state. An automated monitor verifies the invariant every block.

Reference

| Resource | Location |
|---|---|
| SecurityBridge contract | github.com/luxfi/standard/contracts/securities/bridge/SecurityBridge.sol |
| Warp Messaging 2.0 | lp-6022-warp-messaging-20-native-interchain-transfers.md |
| M-Chain MPC Custody (per LP-134; supersedes LP-5013) | LP-134-lux-chain-topology.md |
| Teleport Bridge Architecture | lp-6332-teleport-bridge-architecture-unified-cross-chain-protocol.md |
| LP-001 Digital Securities | LP-001-digital-securities.md |
| tZero API | https://tzero.com |

Copyright

Copyright (c) 2026 Lux Partners Limited. All rights reserved.

Licensed under the MIT License.