Treasury
Protocol fee collection and distribution
Treasury
Cross-chain fee governance and distribution using Warp messaging.
Architecture Overview
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ LUX TREASURY ARCHITECTURE │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ C-CHAIN (FEE GOVERNANCE) │
│ ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│ │ FeeGov │ │
│ │ • Sets fee rate (0.1% floor - 5% cap) │ │
│ │ • Registers chains (P, X, A, B, C, D, T, G, Q, K, Z) │ │
│ │ • Broadcasts settings via Warp to all chains │ │
│ └─────────────────────────────────────────────────────────────────────────────────┘ │
│ │
│ OTHER CHAINS (FEE COLLECTION) │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │P-Chain │ │D-Chain │ │T-Chain │ │G-Chain │ │...etc │ │
│ │Collect │ │Collect │ │Collect │ │Collect │ │Collect │ │
│ └────┬───┘ └────┬───┘ └────┬───┘ └────┬───┘ └────┬───┘ │
│ │ │ │ │ │ │
│ └──────────┴──────────┴─────┬────┴──────────┘ │
│ │ Warp (bridge fees) │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│ │ Vault (C-Chain) │ │
│ │ • Receives fees via Warp proofs │ │
│ │ • Per-chain accounting │ │
│ │ • Replay protection │ │
│ └──────────────────────────────────┬──────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│ │ Router (C-Chain) │ │
│ │ • Distributes to recipients │ │
│ │ • Governance-controlled weights │ │
│ │ • Pull pattern claims │ │
│ └──────────────────────────────────┬──────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────┼─────────────────────────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Protocol │ │ DAO Treasury │ │ Validators │ │
│ │ (70%) │ │ (20%) │ │ (10%) │ │
│ │ │ │ │ │ │ │
│ │ → sLUX │ │ → Governance │ │ → P-Chain │ │
│ └─────────────┘ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────────────┘Core Contracts
| Contract | Description | Import |
|---|---|---|
| FeeGov | Fee rate governance | @luxfi/contracts/treasury/FeeGov.sol |
| Vault | Fee collection vault | @luxfi/contracts/treasury/Vault.sol |
| Router | Fee distribution | @luxfi/contracts/treasury/Router.sol |
| Collect | Per-chain collector | @luxfi/contracts/treasury/Collect.sol |
| ValidatorVault | Validator rewards | @luxfi/contracts/treasury/ValidatorVault.sol |
FeeGov
C-Chain governance for all chain fee rates:
import "@luxfi/contracts/treasury/FeeGov.sol";
FeeGov gov = FeeGov(FEE_GOV_ADDRESS);
// Set fee rate (0.5% = 50 basis points)
gov.set(50);
// Add chain for fee collection
gov.add(keccak256("D"));
// Broadcast settings to all chains via Warp
gov.broadcast();
// Check settings
(uint16 rate, uint16 floor, uint16 cap, uint32 version) = gov.settings();Fee Rate Limits
| Parameter | Value | Description |
|---|---|---|
| Default Rate | 0.3% (30 bp) | Initial fee rate |
| Floor | 0.1% (10 bp) | Minimum allowed rate |
| Cap | 5% (500 bp) | Maximum allowed rate |
Vault
Receives fees from all chains via Warp:
import "@luxfi/contracts/treasury/Vault.sol";
Vault vault = Vault(VAULT_ADDRESS);
// Relayer delivers Warp-proven fees
vault.receive_(chainId, amount, warpMessageId);
// Check per-chain accounting
(uint256 total, uint256 pending) = vault.stats(chainId);
// Global stats
uint256 allTimeTotal = vault.sum();
uint256 awaitingDistribution = vault.balance();Router
Distributes collected fees to recipients:
import "@luxfi/contracts/treasury/Router.sol";
Router router = Router(ROUTER_ADDRESS);
// Governance sets weights (basis points, sum to 10000)
address[] memory recipients = [protocolVault, daoTreasury, validatorVault];
uint256[] memory weights = [7000, 2000, 1000]; // 70%, 20%, 10%
router.setBatch(recipients, weights);
// Distribute fees from chains
bytes32[] memory chains = [CHAIN_P, CHAIN_D, CHAIN_T];
router.distribute(chains);
// Recipients claim (pull pattern)
router.claim(); // msg.sender claims their share
router.claimFor(recipient); // Anyone can claim for a recipientDistribution Weights
| Recipient | Weight | Description |
|---|---|---|
| Protocol Vault | 70% | sLUX stakers |
| DAO Treasury | 20% | Governance fund |
| Validator Vault | 10% | P-Chain validators |
Collect
Deployed on each chain to collect local fees:
import "@luxfi/contracts/treasury/Collect.sol";
Collect collect = Collect(COLLECT_ADDRESS);
// Protocols push fees
collect.push(feeAmount);
// Anyone can bridge collected fees to C-Chain Vault
bytes32 warpId = collect.bridge();
// Check stats
(uint256 total, uint256 pending, uint256 bridged, uint16 rate, uint32 version) = collect.stats();
// Calculate fee for an amount
uint256 fee = collect.fee(transactionAmount);Fee Calculation
// Fee = amount × rate / 10000
// At 0.3% rate: fee(1000 ether) = 3 etherValidatorVault
Bridges P-Chain validator rewards to C-Chain:
import "@luxfi/contracts/treasury/ValidatorVault.sol";
ValidatorVault vault = ValidatorVault(VALIDATOR_VAULT_ADDRESS);
// Receive rewards from P-Chain (via Warp)
vault.receiveRewards{value: rewardAmount}();
// Forward to LiquidLUX (exempt from performance fee)
vault.forwardRewardsToLiquidLUX();Cross-Chain Flow
1. FeeGov.broadcast() → Warp settings to all chains
2. Collect.sync(rate, version) ← Chain receives settings
3. Protocol.push(fee) → Local Collect contract
4. Collect.bridge() → Warp fees to C-Chain
5. Vault.receive_(chain, amt) ← Relayer delivers proof
6. Router.distribute(chains) → Split to recipients
7. Router.claim() ← Recipients pull fundsEvents
// FeeGov
event RateSet(uint16 rate, uint32 version);
event ChainAdded(bytes32 indexed chain);
event ChainRemoved(bytes32 indexed chain);
event Broadcast(uint256 chainCount);
// Vault
event Receive(bytes32 indexed chain, uint256 amount, bytes32 warpId);
event Flush(bytes32 indexed chain, uint256 amount);
// Router
event Weight(address indexed recipient, uint256 weight);
event Distribute(uint256 amount);
event Claim(address indexed recipient, uint256 amount);
// Collect
event Settings(uint16 rate, uint32 version);
event Fee(address indexed from, uint256 amount);
event Bridge(uint256 amount, bytes32 warpId);Security Considerations
- Warp Verification: All cross-chain messages verified via Warp proofs
- Replay Protection: Each Warp message ID can only be processed once
- Pull Pattern: Recipients claim funds (no unbounded loops)
- Version Checks: Stale settings rejected via version monotonicity
- Owner Controls: Rate changes require governance approval