Lux Docs

Payments

Send funds via transfers, airdrops, and streams

Payments

DAOs can distribute funds through various payment mechanisms. This guide covers all payment types from simple transfers to continuous streaming.

Overview

Payment TypeUse CaseTiming
TransferOne-time paymentsImmediate
AirdropMulti-recipient distributionBatch
StreamContinuous paymentsOver time
Stream to RoleRole-based streamsAutomatic

Quick Comparison

Transfer          Airdrop           Stream            Stream to Role
────────────────────────────────────────────────────────────────────
Single recipient  Many recipients   Single recipient  Role holders
One-time          One-time (batch)  Continuous        Continuous
Immediate         Immediate         Over duration     Auto-managed
Manual            Manual            Manual            Automatic

Best for:         Best for:         Best for:         Best for:
• Invoices        • Rewards         • Salaries        • Committees
• Grants          • Airdrops        • Grants          • Working groups
• Expenses        • Rebates         • Vesting         • Recurring roles

Smart Contract Interface

IPayments

interface IPayments {
    /// @notice Simple transfer from treasury
    function transfer(
        address token,
        address to,
        uint256 amount,
        string calldata memo
    ) external;

    /// @notice Batch transfer to multiple recipients
    function airdrop(
        address token,
        address[] calldata recipients,
        uint256[] calldata amounts
    ) external;

    /// @notice Create a payment stream
    function createStream(
        address token,
        address recipient,
        uint256 totalAmount,
        uint256 startTime,
        uint256 duration,
        uint256 cliffDuration
    ) external returns (uint256 streamId);

    /// @notice Create streams for all role holders
    function streamToRole(
        bytes32 roleId,
        address token,
        uint256 amountPerHolder,
        uint256 duration
    ) external returns (uint256[] memory streamIds);

    /// @notice Withdraw from a stream
    function withdrawFromStream(uint256 streamId) external;

    /// @notice Cancel a stream
    function cancelStream(uint256 streamId) external;
}

Payment Methods

Choosing a Payment Type

Use Transfer When

  • Paying a single invoice or expense
  • One-time grant disbursement
  • Reimbursing a contributor
  • Any simple, immediate payment

Use Airdrop When

  • Distributing rewards to many addresses
  • Sending governance tokens to holders
  • Bulk refunds or rebates
  • Community rewards programs

Use Stream When

  • Paying salaries or stipends
  • Grant vesting schedules
  • Long-term contractor payments
  • Token unlock schedules

Use Stream to Role When

  • Committee member compensation
  • Working group stipends
  • Automatic contributor rewards
  • Any role-based recurring payment

Payment Workflow

Via Proposal

Most payments require governance approval:

Proposal: "Q1 Contributor Payments"

Description: |
  This proposal executes Q1 payments for approved contributors.

Actions:
  # Immediate transfer for completed work
  - type: transfer
    token: USDC
    to: 0x1234...
    amount: 5000
    memo: "Q1 Development Milestone"

  # Stream for ongoing work
  - type: create_stream
    token: USDC
    recipient: 0x5678...
    total: 12000
    duration: 90 days
    cliff: 0

  # Airdrop rewards to participants
  - type: airdrop
    token: DAO
    recipients: [0xAAA..., 0xBBB..., 0xCCC...]
    amounts: [1000, 1000, 1000]

Via Direct Action

With appropriate permissions:

import { PaymentsClient } from '@lux/dao-sdk';

const payments = new PaymentsClient(signer);

// Simple transfer (requires TREASURER_ROLE)
await payments.transfer(
  usdc.address,
  recipientAddress,
  ethers.parseUnits('5000', 6),
  'Invoice #1234'
);

Treasury Limits

Spending Caps

LevelSingle PaymentDaily LimitRequires
Member$0$0-
Contributor$1,000$2,500Lead approval
Lead$10,000$25,0002/3 multi-sig
Committee$50,000$100,000Committee vote
DAOUnlimitedUnlimitedFull governance

Approval Thresholds

Payment Approval Matrix:

< $1,000:
  - Single Lead signature
  - No proposal required

$1,000 - $10,000:
  - 2 Lead signatures
  - Logged in treasury report

$10,000 - $50,000:
  - Committee proposal
  - 3-day voting period

> $50,000:
  - Full DAO proposal
  - 7-day voting period
  - Standard timelock

Monitoring Payments

Dashboard View

┌─────────────────────────────────────────────────────────────┐
│ Treasury Payments                                            │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  Recent Transfers                                            │
│  ──────────────────────────────────────────────────────     │
│  Jan 15  0x1234...  5,000 USDC   "Q1 Development"           │
│  Jan 14  0x5678...  2,500 USDC   "Design Work"              │
│  Jan 10  0xABCD...  1,000 USDC   "Community Event"          │
│                                                              │
│  Active Streams (3)                              Total/mo   │
│  ──────────────────────────────────────────────────────     │
│  Research Lead     1,000 USDC/mo   ████████░░  80%          │
│  Dev Contributor     500 USDC/mo   ██████░░░░  60%          │
│  Community Mgr       750 USDC/mo   ████░░░░░░  40%          │
│                                                              │
│  Pending Airdrops (1)                                       │
│  ──────────────────────────────────────────────────────     │
│  Governance Rewards  500 recipients  50,000 DAO tokens      │
│  Status: Awaiting execution                                  │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Event Tracking

import { PaymentsClient } from '@lux/dao-sdk';

const payments = new PaymentsClient(provider);

// Track all payment events
payments.on('Transfer', (token, to, amount, memo) => {
  console.log(`Transfer: ${amount} to ${to}`);
});

payments.on('StreamCreated', (streamId, recipient, total, duration) => {
  console.log(`Stream ${streamId}: ${total} over ${duration}s`);
});

payments.on('AirdropExecuted', (token, recipientCount, totalAmount) => {
  console.log(`Airdrop: ${totalAmount} to ${recipientCount} addresses`);
});

Security Considerations

Multi-Sig Requirements

For significant payments:

Multi-sig thresholds:
  - < $10K: 2-of-3 signers
  - $10K-$50K: 3-of-5 signers
  - > $50K: 4-of-7 signers + timelock

Address Verification

Always verify recipient addresses:

// Validate address before payment
function validateRecipient(address: string): boolean {
  // Check format
  if (!ethers.isAddress(address)) return false;

  // Check against known addresses (optional)
  const known = knownAddresses.get(address);
  if (!known) {
    console.warn('Unknown address - verify manually');
  }

  return true;
}

Payment Limits

Configure reasonable limits:

// In treasury contract
uint256 public constant MAX_SINGLE_PAYMENT = 100_000e6; // 100K USDC
uint256 public constant DAILY_LIMIT = 250_000e6;        // 250K USDC

Best Practices

Documentation

Always include clear memos:

// Good
await payments.transfer(usdc, recipient, amount,
  'Invoice #1234 - Q1 Development Milestone 2');

// Bad
await payments.transfer(usdc, recipient, amount, '');

Batching

Combine related payments:

// Instead of 10 separate transfers
const recipients = [...];
const amounts = [...];
await payments.airdrop(token, recipients, amounts);

Verification

Always verify before execution:

  1. Confirm recipient address
  2. Check token and amount
  3. Review memo/reason
  4. Simulate transaction
  5. Get required approvals

Common Errors

ErrorCauseSolution
InsufficientBalanceTreasury lacks fundsFund treasury or reduce amount
ExceedsLimitAbove spending capGet higher approval or split
UnauthorizedMissing roleGet required permissions
InvalidRecipientBad addressVerify recipient address
StreamNotFoundInvalid stream IDCheck stream exists

Gas Optimization

Batching Saves Gas

OperationGas (approx)
10 separate transfers210,000
1 airdrop (10 recipients)150,000
Savings~30%

Stream Efficiency

Streams are gas-efficient for recurring payments:

Payment MethodAnnual Gas (monthly)
12 transfers~252,000
1 stream~75,000
Savings~70%

On this page