Lux Proposals
← All proposals
LP-0001Draftsecuritiescomplianceerc-1404erc-3643t-rex

LP-001: Digital Securities Standard

Abstract

This specification defines how Lux Network implements digital securities on-chain. A security token on Lux is a regulated ERC-20 with embedded compliance enforcement at the transfer layer. The on-chain token contract IS the cap table. The on-chain compliance registry IS the KYC/AML gate. Every transfer, every dividend payment, every corporate action is a verifiable on-chain transaction with an immutable audit trail.

Lux operates the full regulated stack: Alternative Trading System (ATS), Broker-Dealer (BD), and Transfer Agent (TA). The on-chain contracts are the execution layer for all three.

Motivation

Traditional securities infrastructure relies on:

Digital securities on Lux collapse the entire stack into on-chain primitives:

The result: 24/7 trading, instant settlement, automated compliance, and a single source of truth.

Standards Compatibility

ERC-1404: Simple Restricted Token

The base standard. Every SecurityToken implements ERC-1404, which adds two functions to ERC-20:


function detectTransferRestriction(address from, address to, uint256 value)
    external view returns (uint8 restrictionCode);

function messageForTransferRestriction(uint8 restrictionCode)
    external view returns (string memory message);

Callers check restrictions before submitting a transfer. Wallets and DEXs use this to display human-readable rejection reasons.

ERC-3643 (T-REX): Institutional Compliance

ERC-3643 defines the Token for Regulated EXchanges framework. Lux implements the core T-REX concepts through its modular compliance architecture:

| T-REX Concept | Lux Implementation |
|---|---|
| Identity Registry | ComplianceRegistry (whitelist + KYC status) |
| Identity Verification | Off-chain KYC via Hanzo IAM, on-chain attestation |
| Compliance Modules | IComplianceModule interface, pluggable into registry |
| Claim Topics | accreditationStatus field (0=none, 1=accredited, 2=QIB) |
| Trusted Issuers | COMPLIANCE_ROLE holders |

The ComplianceRegistry supports an ordered chain of IComplianceModule implementations. Each module checks a single rule. The registry iterates all modules; the first rejection stops the transfer.

Restriction Codes

Shared across all contracts in the securities module:

| Code | Constant | Meaning |
|------|----------|---------|
| 0 | SUCCESS | Transfer permitted |
| 1 | SENDER_NOT_WHITELISTED | Sender not in KYC whitelist |
| 2 | RECEIVER_NOT_WHITELISTED | Receiver not in KYC whitelist |
| 3 | SENDER_BLACKLISTED | Sender on sanctions/blacklist |
| 4 | RECEIVER_BLACKLISTED | Receiver on sanctions/blacklist |
| 5 | SENDER_LOCKED | Sender in lockup period |
| 6 | JURISDICTION_BLOCKED | Jurisdiction restriction |
| 7 | ACCREDITATION_REQUIRED | Accreditation check failed |
| 8-15 | Reserved | Future core codes |
| 16 | SENDER_NOT_ON_WHITELIST | Module: whitelist |
| 17 | RECEIVER_NOT_ON_WHITELIST | Module: whitelist |
| 18 | SENDER_LOCKUP_ACTIVE | Module: Rule 144 lockup |
| 19 | SENDER_JURISDICTION_BLOCKED | Module: jurisdiction |
| 20 | RECEIVER_JURISDICTION_BLOCKED | Module: jurisdiction |
| 21 | SENDER_JURISDICTION_UNSET | Module: jurisdiction unset |
| 22 | RECEIVER_JURISDICTION_UNSET | Module: jurisdiction unset |
| 32 | MAX_HOLDERS_REACHED | Transfer restriction engine |
| 33 | TRANSFER_AMOUNT_EXCEEDED | Transfer restriction engine |

Contract Architecture

Overview


securities/
  interfaces/
    IERC1404.sol            -- ERC-1404 (Simple Restricted Transfer)
    IST20.sol               -- ST-20 (verifyTransfer hook)
    IComplianceModule.sol   -- pluggable compliance interface
  compliance/
    ComplianceRegistry.sol  -- KYC/AML/accreditation registry (central gate)
    WhitelistModule.sol     -- whitelist-based transfer restriction
    LockupModule.sol        -- Rule 144 holding period enforcement
    JurisdictionModule.sol  -- country/jurisdiction restrictions (ISO 3166)
  token/
    SecurityToken.sol       -- base regulated ERC-20 (ERC-1404 + ST-20)
    RestrictedToken.sol     -- ERC-1404 with external restriction engine
    PartitionToken.sol      -- ERC-1400 partitioned security (tranches)
  registry/
    TransferRestriction.sol -- transfer restriction engine (max holders, amount caps)
    DocumentRegistry.sol    -- on-chain document storage (ERC-1643)
  corporate/
    DividendDistributor.sol -- on-chain dividend payments (any ERC-20)
    CorporateActions.sol    -- splits, mergers, forced transfers, seizure
  bridge/
    SecurityBridge.sol      -- cross-chain mint/burn/teleport

Source: github.com/luxfi/standard/contracts/securities/

SecurityToken

The base regulated ERC-20. Inherits ERC20, ERC20Burnable, ERC20Pausable, AccessControl. Implements both IERC1404 and IST20.

Key design decisions:


function _update(address from, address to, uint256 value) internal virtual override {
    if (from != address(0) && to != address(0)) {
        (bool allowed, uint8 code) = complianceRegistry.canTransfer(from, to, value);
        if (!allowed) revert TransferRestricted(code);
    }
    super._update(from, to, value);
}

This means compliance is enforced at the EVM level. No wrapper. No external call required by the user. Every transfer() and transferFrom() passes through compliance automatically.

ComplianceRegistry

Central KYC/AML/accreditation gate. Stores per-address state:

| Field | Type | Purpose |
|---|---|---|
| isWhitelisted | mapping(address => bool) | KYC-approved |
| isBlacklisted | mapping(address => bool) | Sanctions/blocked |
| lockupExpiry | mapping(address => uint256) | Unix timestamp, Rule 144 |
| jurisdiction | mapping(address => bytes2) | ISO 3166-1 alpha-2 code |
| accreditationStatus | mapping(address => uint8) | 0=none, 1=accredited, 2=QIB |

The canTransfer(from, to, amount) function runs:

1. Core checks: whitelist, blacklist, lockup

2. Pluggable module iteration: each IComplianceModule.checkTransfer() in order

3. First rejection stops the chain

Modules are added/removed by DEFAULT_ADMIN_ROLE. Order matters -- modules execute sequentially.

IComplianceModule


interface IComplianceModule {
    function checkTransfer(address from, address to, uint256 amount)
        external view returns (bool allowed, uint8 restrictionCode);
    function moduleName() external view returns (string memory);
}

Shipped modules:

| Module | Rule | Code |
|---|---|---|
| WhitelistModule | Sender and receiver must be on per-module whitelist | 16, 17 |
| LockupModule | Sender lockup timestamp must be in the past | 18 |
| JurisdictionModule | Sender/receiver jurisdiction must not be blocked | 19-22 |

Custom modules implement this interface. Examples: maximum daily transfer volume, investor count caps, cross-border restrictions.

JurisdictionModule

Enforces geographic restrictions per ISO 3166-1 alpha-2 country codes. Stored as bytes2 (e.g., "US", "GB", "KY").

Features:

LockupModule

Enforces SEC Rule 144 holding periods. Each address has a lockupExpiry Unix timestamp. If block.timestamp < lockupExpiry, the sender cannot transfer.

Typical lockup periods:

TransferRestriction

Per-token restriction engine:

DocumentRegistry

On-chain document storage per ERC-1643:

Required documents for SEC compliance:

DividendDistributor

Snapshot-based pull model for dividend payments:

1. Admin creates a dividend round, specifying payment token (any ERC-20, e.g., USDC) and total amount

2. Payment tokens are transferred to the contract at creation time

3. Holders claim pro-rata based on balance / totalSupply at the snapshot block

4. Unclaimed dividends can be reclaimed by admin after a period

Supports any ERC-20 as the payment token. USDC and LUX are the expected defaults.

CorporateActions

Regulatory-grade corporate actions:

All actions emit events with reason strings for audit trails. Requires CORPORATE_ACTION_ROLE.

SecurityBridge

Cross-chain mint/burn/teleport for security tokens. See LP-003 for full specification.

tZero Integration

Partnership

tZero (tzero.com) operates one of six SEC-registered digital Alternative Trading Systems in the US. Lux has a confirmed partnership for cross-listing digital securities.

Architecture


Lux Chain                          tZero ATS
-----------                        ---------
SecurityToken  <-- REST/Webhook --> tZero API
ComplianceRegistry                 tZero KYC
DividendDistributor                tZero Disbursements
SecurityBridge                     tZero Settlement

Webhook API

tZero integration uses REST + HMAC-SHA256 signed webhooks:

Outbound (Lux -> tZero):

Inbound (tZero -> Lux):

All webhook payloads are:

Compliance Data Sharing

KYC/AML status flows bidirectionally:

1. Investor KYCs on Lux (via Hanzo IAM) -> status synced to tZero via compliance sync API

2. Investor KYCs on tZero -> webhook pushes status to Lux, ComplianceRegistry.whitelistAdd() called

3. Sanctions screening: both systems run independent checks; either can block

Accreditation status mapping:

| Lux accreditationStatus | tZero Equivalent |
|---|---|
| 0 (none) | Unverified |
| 1 (accredited) | Accredited Investor (Rule 501) |
| 2 (QIB) | Qualified Institutional Buyer (Rule 144A) |

Settlement Bridging

When a trade executes on tZero:

1. tZero sends settlement webhook with trade details

2. Lux settlement service calls SecurityBridge.bridgeMint() or SecurityToken.transfer() depending on whether the recipient is on-chain

3. Compliance is enforced at the contract level regardless of trade origin

4. Settlement confirmation is sent back to tZero

The bridge operator for tZero settlement is an M-Chain MPC multisig (per LP-134; supersedes LP-5013). No single key can execute settlements.

Regulatory Framework

United States

SEC ATS Registration (Regulation ATS):

FINRA Broker-Dealer:

Section 17A Transfer Agent:

Exemptions:

Isle of Man (IOM)

Luxembourg

International Jurisdiction Framework

The JurisdictionModule contract uses ISO 3166-1 alpha-2 country codes for per-address jurisdiction tracking.

Configuration by offering type:

| Offering | Allowed Jurisdictions | Blocked Jurisdictions |
|---|---|---|
| Reg D 506(c) | US only (accredited) | All non-US |
| Reg S | Non-US | US |
| Reg A+ | US + international | OFAC sanctioned |
| Global STO | Per-token config | OFAC + country-specific |

OFAC sanctioned jurisdictions (blocked by default): CU, IR, KP, SY, RU (Crimea region via sub-code).

On-Chain Cap Table

The on-chain contracts collectively form the authoritative cap table. There is no separate off-chain database that is "the real" cap table -- the chain state is canonical.

Mapping

| Traditional Cap Table Element | On-Chain Implementation |
|---|---|
| Shareholder registry | SecurityToken.balanceOf(address) |
| KYC/AML status | ComplianceRegistry.isWhitelisted(address) + isBlacklisted(address) |
| Accreditation | ComplianceRegistry.accreditationStatus(address) |
| Rule 144 lockup | LockupModule.lockupExpiry(address) |
| Transfer restrictions | TransferRestriction.checkRestriction() |
| Offering documents | DocumentRegistry.getDocument(name) |
| Dividend payments | DividendDistributor.rounds(roundId) |
| Corporate actions | CorporateActions events |
| Jurisdiction | JurisdictionModule.accountJurisdiction(address) |
| Total outstanding | SecurityToken.totalSupply() |
| Authorized shares | Configurable cap via TransferRestriction or mint guard |

Go TA Engine

The lux/captable package provides the off-chain TA engine that reads chain state and provides SEC-compliant reporting:

| Package | Purpose |
|---|---|
| pkg/captable | Company, share class, entry CRUD |
| pkg/securities | Issuance, transfer, cancellation with immutable ledger |
| pkg/stakeholder | Investor/shareholder management, accreditation tracking |
| pkg/transfer | Rule 144, lockup periods, board approval checks |
| pkg/dividend | Dividend declaration, record date, distribution |
| pkg/corporate | Stock splits, mergers, reclassification |
| pkg/compliance | Form D, blue sky filings, Reg D compliance |
| pkg/document | Data rooms, access control, audit trails |
| pkg/tax | 1099-DIV, 1099-B, Schedule K-1 generation |

The TA engine indexes chain events and produces:

Three Pillars

The regulated digital securities stack has three licensed pillars, each mapping to on-chain and off-chain components.

Pillar 1: ATS (Alternative Trading System)

License: SEC Regulation ATS, FINRA membership

On-chain:

Off-chain:

Flow:


Investor -> lux/cex (off-chain order) -> SecurityToken.transfer() (on-chain settlement)
Investor -> DEX precompile + ComplianceHook (fully on-chain)

Both paths enforce identical compliance via ComplianceRegistry.

Pillar 2: BD (Broker-Dealer)

License: FINRA Broker-Dealer, SEC Section 15

On-chain:

Off-chain:

Settlement:

Pillar 3: TA (Transfer Agent)

License: SEC Section 17A

On-chain:

Off-chain:

The key insight: SecurityToken.balanceOf() IS the cap table. The Go TA engine is a read layer that indexes chain state and produces regulatory reports. It does not maintain a separate source of truth.

Deployment

Contract Deployment Order

1. ComplianceRegistry -- deploy first, grants COMPLIANCE_ROLE to admin

2. Compliance modules (WhitelistModule, LockupModule, JurisdictionModule) -- deploy and register with registry

3. SecurityToken -- deploy with registry address

4. TransferRestriction -- deploy, grant RESTRICTION_ADMIN_ROLE to token

5. DocumentRegistry -- deploy, upload offering documents

6. DividendDistributor -- deploy with security token address

7. CorporateActions -- deploy, grant MINTER_ROLE on token

8. SecurityBridge -- deploy, grant BRIDGE_ROLE to MPC multisig

Chain Deployment

Primary deployment: Lux C-Chain (EVM).

For L2 deployments (e.g., a regulated securities L2, per LP-018), deploy the same contracts on the L2 and use SecurityBridge for cross-chain transfers.

Role Matrix

| Role | Holder | Purpose |
|---|---|---|
| DEFAULT_ADMIN_ROLE | Issuer multisig | Grant/revoke all roles |
| MINTER_ROLE | Issuer + CorporateActions | Mint new tokens |
| PAUSER_ROLE | Issuer + compliance officer | Emergency pause |
| COMPLIANCE_ROLE | Compliance service | KYC whitelist updates |
| BRIDGE_ROLE | MPC multisig | Cross-chain operations |
| DIVIDEND_ADMIN_ROLE | Issuer | Create/reclaim dividends |
| CORPORATE_ACTION_ROLE | Issuer + legal | Forced transfers, seizure |
| DOCUMENT_ADMIN_ROLE | Issuer + legal | Document management |

Reference Links

| Resource | URL |
|---|---|
| Arca Labs ST-Contracts (original) | https://github.com/arcalabs/st-contracts |
| Lux Securities Contracts | https://github.com/luxfi/standard/contracts/securities/ |
| Lux Cap Table (Go TA engine) | https://github.com/luxfi/captable |
| ERC-1404 Specification | https://erc1404.org |
| ERC-3643 (T-REX) Specification | https://erc3643.org |
| tZero | https://tzero.com |
| Lux Compliance Service | https://github.com/luxfi/compliance |
| Lux Broker Service | https://github.com/luxfi/broker |
| Lux CEX Engine | https://github.com/luxfi/cex |
| Lux DEX Precompile (LP-9010) | https://github.com/luxfi/lps/LPs/lp-9010-dex-precompile.md |
| M-Chain MPC Custody (per LP-134; supersedes LP-5013) | https://github.com/luxfi/lps/LP-134-lux-chain-topology.md |
| Warp Messaging (LP-6022) | https://github.com/luxfi/lps/LPs/lp-6022 |

Security Considerations

1. Role separation: No single address should hold both MINTER_ROLE and COMPLIANCE_ROLE. The issuer mints; compliance officers manage the whitelist. Separate concerns.

2. Multisig for admin: DEFAULT_ADMIN_ROLE must be a multisig (Safe or MPC). A single EOA controlling the security token is a critical vulnerability.

3. Compliance bypass on mint/burn: By design, minting and burning bypass compliance. This is intentional -- the issuer must be able to issue and redeem. The MINTER_ROLE controls who can do this.

4. Nonce deduplication in bridge: SecurityBridge uses nonce tracking to prevent replay. The nonce is derived from sender + amount + chain + block. Bridge operators must verify cross-chain messages before executing mint/release.

5. Pausability: The token can be paused in emergencies. This halts all transfers. Use sparingly -- a paused security token blocks all trading.

6. Forced transfers: CorporateActions.forcedTransfer() bypasses compliance. This is required for regulatory seizure (court orders, sanctions). Access must be tightly controlled.

7. Secrets: All API keys, webhook secrets, and signing keys are stored in KMS (kms.hanzo.ai). Never in environment files. Never in source code. Never in plaintext.

Copyright

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

Licensed under the MIT License.