mirror of
https://github.com/luxfi/dao.git
synced 2026-07-27 02:51:24 +00:00
feat: add wallet package, docs, LLM.md, and update submodule refs
- Add packages/wallet with Solana/EVM providers - Add comprehensive DAO governance documentation - Fix gitignore to cover nested node_modules - Update submodule refs
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
**/node_modules/
|
||||
CLAUDE.md
|
||||
+1
-1
Submodule api updated: bd625f1836...9cce58db9b
+1
-1
Submodule app updated: da76631000...f9858b7d06
+1
-1
Submodule contracts updated: d82de32acd...11f600c20b
@@ -0,0 +1,410 @@
|
||||
---
|
||||
title: Disabling Gasless Voting
|
||||
description: How to turn off gasless voting for your DAO
|
||||
---
|
||||
|
||||
# Disabling Gasless Voting
|
||||
|
||||
This guide covers how to disable gasless voting, either temporarily or permanently, and the implications for your DAO.
|
||||
|
||||
## When to Disable
|
||||
|
||||
### Temporary Disable
|
||||
|
||||
You might temporarily disable gasless voting for:
|
||||
|
||||
- **Maintenance** - Paymaster upgrades or migrations
|
||||
- **Budget Constraints** - Treasury needs reallocation
|
||||
- **Abuse Prevention** - Responding to spam or attacks
|
||||
- **Testing** - Troubleshooting voting issues
|
||||
|
||||
### Permanent Disable
|
||||
|
||||
Reasons to permanently disable:
|
||||
|
||||
- **Cost Reduction** - Gasless not economically viable
|
||||
- **Low Adoption** - Users prefer paying their own gas
|
||||
- **Migration** - Moving to different voting mechanism
|
||||
- **Security** - Concerns about paymaster vulnerabilities
|
||||
|
||||
## Disabling Process
|
||||
|
||||
### Step 1: Access Settings
|
||||
|
||||
1. Go to your DAO dashboard
|
||||
2. Navigate to **Settings** > **Gasless Voting**
|
||||
3. Locate the enable/disable toggle
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Gasless Voting Settings │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Status: ● Enabled │
|
||||
│ │
|
||||
│ Paymaster: 0x1234...5678 │
|
||||
│ Balance: 5.25 ETH │
|
||||
│ Total Votes: 1,234 sponsored │
|
||||
│ │
|
||||
│ [Disable Gasless Voting] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Choose Disable Type
|
||||
|
||||
Select temporary or permanent disable:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Disable Gasless Voting │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ○ Temporary Pause │
|
||||
│ Pause gas sponsorship but keep paymaster funded │
|
||||
│ Can re-enable instantly │
|
||||
│ │
|
||||
│ ○ Disable with Withdrawal │
|
||||
│ Disable and withdraw remaining paymaster funds │
|
||||
│ Requires re-setup to enable again │
|
||||
│ │
|
||||
│ ● Full Disable │
|
||||
│ Disable, withdraw funds, and remove paymaster │
|
||||
│ Complete removal of gasless infrastructure │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Handle Pending Operations
|
||||
|
||||
Check for in-flight operations:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Pending Operations │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ⚠ There are 3 pending gasless votes │
|
||||
│ │
|
||||
│ │ User │ Proposal │ Status │ Submitted │ │
|
||||
│ ├────────────────┼──────────┼───────────┼─────────────┤ │
|
||||
│ │ 0xABC...123 │ #42 │ Pending │ 2 min ago │ │
|
||||
│ │ 0xDEF...456 │ #42 │ Pending │ 1 min ago │ │
|
||||
│ │ 0xGHI...789 │ #43 │ Pending │ 30 sec ago │ │
|
||||
│ │
|
||||
│ Options: │
|
||||
│ ● Wait for pending operations to complete │
|
||||
│ ○ Force disable (pending operations will fail) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 4: Confirm Disable
|
||||
|
||||
Review impact and confirm:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Confirm Disable │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ You are about to disable gasless voting. │
|
||||
│ │
|
||||
│ Impact: │
|
||||
│ • Voters will need ETH to pay gas │
|
||||
│ • Participation may decrease │
|
||||
│ • Mobile/new users may have difficulty │
|
||||
│ │
|
||||
│ Reversible: Yes (can re-enable) │
|
||||
│ Paymaster Funds: 5.25 ETH (will be withdrawn) │
|
||||
│ Withdrawal To: DAO Treasury │
|
||||
│ │
|
||||
│ ⚠ Notify community before disabling │
|
||||
│ │
|
||||
│ [Cancel] [Confirm Disable] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Temporary Pause (Recommended First Step)
|
||||
|
||||
### Pause Without Withdrawal
|
||||
|
||||
Keep funds in place but stop sponsoring:
|
||||
|
||||
```yaml
|
||||
pause:
|
||||
type: temporary
|
||||
keep_funds: true
|
||||
duration: indefinite # or set time limit
|
||||
reason: "Maintenance window"
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Instant re-enable
|
||||
- No fund movement needed
|
||||
- Lower risk
|
||||
|
||||
### Pause via Contract
|
||||
|
||||
Directly pause the paymaster:
|
||||
|
||||
```solidity
|
||||
// Pause paymaster sponsorship
|
||||
IPaymaster paymaster = IPaymaster(paymasterAddress);
|
||||
paymaster.pause();
|
||||
|
||||
// Re-enable later
|
||||
paymaster.unpause();
|
||||
```
|
||||
|
||||
### Time-Limited Pause
|
||||
|
||||
Set automatic re-enable:
|
||||
|
||||
```yaml
|
||||
scheduled_pause:
|
||||
start: "2026-02-01T00:00:00Z"
|
||||
end: "2026-02-03T00:00:00Z"
|
||||
reason: "Planned maintenance"
|
||||
notify_users: true
|
||||
```
|
||||
|
||||
## Full Disable with Withdrawal
|
||||
|
||||
### Withdraw Paymaster Funds
|
||||
|
||||
1. Disable gasless voting
|
||||
2. Withdraw remaining funds
|
||||
3. Funds return to treasury or specified address
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Withdrawal Summary │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Paymaster Balance: 5.25 ETH │
|
||||
│ Reserved (pending): 0.05 ETH │
|
||||
│ Available: 5.20 ETH │
|
||||
│ │
|
||||
│ Withdraw To: DAO Treasury (0xTreas...ury) │
|
||||
│ │
|
||||
│ Transaction: 0xabc123... (pending) │
|
||||
│ │
|
||||
│ [View on Explorer] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Governance-Required Disable
|
||||
|
||||
For DAOs requiring governance approval:
|
||||
|
||||
```yaml
|
||||
proposal:
|
||||
title: "Disable Gasless Voting"
|
||||
type: governance_parameter
|
||||
actions:
|
||||
- action: disable_gasless
|
||||
- action: withdraw_paymaster
|
||||
amount: all
|
||||
destination: treasury
|
||||
rationale: |
|
||||
Due to budget constraints, we propose disabling gasless
|
||||
voting and reallocating the 5.25 ETH to the grants program.
|
||||
```
|
||||
|
||||
## Communication
|
||||
|
||||
### Notify Users Before Disabling
|
||||
|
||||
<Callout type="warning">
|
||||
Always communicate changes to your community before disabling gasless voting.
|
||||
</Callout>
|
||||
|
||||
**Announcement Template:**
|
||||
|
||||
```markdown
|
||||
## Gasless Voting Update
|
||||
|
||||
We will be disabling gasless voting on [DATE].
|
||||
|
||||
**Why:**
|
||||
[Reason for disabling]
|
||||
|
||||
**What this means:**
|
||||
- You will need ETH in your wallet to vote
|
||||
- Vote transactions will cost approximately $X
|
||||
- All other governance features remain the same
|
||||
|
||||
**Timeline:**
|
||||
- [Date]: Announcement
|
||||
- [Date]: Gasless disabled
|
||||
- [Date]: Review decision
|
||||
|
||||
**Questions?**
|
||||
Join the discussion in #governance
|
||||
```
|
||||
|
||||
### Update UI Messaging
|
||||
|
||||
Ensure the voting interface reflects the change:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Vote on Proposal #42 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Grant $50,000 to Research Committee │
|
||||
│ │
|
||||
│ Your Voting Power: 10,000 veLUX │
|
||||
│ │
|
||||
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ FOR │ │ AGAINST │ │ ABSTAIN │ │
|
||||
│ └────────────┘ └────────────┘ └────────────┘ │
|
||||
│ │
|
||||
│ ℹ Gas Required: ~$3.00 (0.001 ETH) │
|
||||
│ Your ETH Balance: 0.5 ETH ✓ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Re-Enabling Gasless Voting
|
||||
|
||||
### From Paused State
|
||||
|
||||
If you only paused (no withdrawal):
|
||||
|
||||
1. Go to **Settings** > **Gasless**
|
||||
2. Click **Resume Gasless Voting**
|
||||
3. Confirm
|
||||
|
||||
```solidity
|
||||
// Or via contract
|
||||
paymaster.unpause();
|
||||
```
|
||||
|
||||
### Full Re-Setup
|
||||
|
||||
If you withdrew funds or removed paymaster:
|
||||
|
||||
1. Follow the [Setup Guide](/docs/guide/gasless/setup)
|
||||
2. Deploy new paymaster (or reuse existing)
|
||||
3. Fund the paymaster
|
||||
4. Configure policies
|
||||
5. Enable gasless voting
|
||||
|
||||
## Impact Analysis
|
||||
|
||||
### Before Disabling, Consider:
|
||||
|
||||
```yaml
|
||||
impact_analysis:
|
||||
voter_participation:
|
||||
current_turnout: 45%
|
||||
estimated_after_disable: 30% # -15%
|
||||
affected_users: ~500 (no ETH balance)
|
||||
|
||||
cost_to_voters:
|
||||
avg_gas_per_vote: 0.003 ETH
|
||||
at_current_prices: ~$9/vote
|
||||
|
||||
alternatives:
|
||||
- provide_voting_eth_faucet
|
||||
- offer_vote_reimbursement
|
||||
- use_offchain_snapshot
|
||||
```
|
||||
|
||||
### Post-Disable Monitoring
|
||||
|
||||
Track metrics after disabling:
|
||||
|
||||
```yaml
|
||||
monitor:
|
||||
metrics:
|
||||
- voter_turnout
|
||||
- unique_voters
|
||||
- proposal_quorum_rate
|
||||
- user_complaints
|
||||
|
||||
comparison:
|
||||
period: 30 days before vs after
|
||||
alert_threshold: 20% drop in participation
|
||||
```
|
||||
|
||||
## Alternative Approaches
|
||||
|
||||
### Partial Gasless
|
||||
|
||||
Instead of full disable, limit gasless:
|
||||
|
||||
```yaml
|
||||
partial_gasless:
|
||||
eligibility:
|
||||
min_voting_power: 1000 veLUX # Raise threshold
|
||||
max_votes_per_proposal: 1
|
||||
rate_limit: 5 votes/week
|
||||
|
||||
cap:
|
||||
daily_budget: 0.5 ETH
|
||||
monthly_budget: 10 ETH
|
||||
```
|
||||
|
||||
### Vote Subsidies
|
||||
|
||||
Offer partial reimbursement instead:
|
||||
|
||||
```yaml
|
||||
vote_subsidy:
|
||||
enabled: true
|
||||
coverage: 50% # DAO pays half
|
||||
max_per_vote: 0.002 ETH
|
||||
monthly_cap: 5 ETH
|
||||
```
|
||||
|
||||
### Offchain Voting
|
||||
|
||||
Use Snapshot for signaling, onchain for execution:
|
||||
|
||||
```yaml
|
||||
hybrid_voting:
|
||||
signaling: snapshot (free)
|
||||
binding: onchain (gas required)
|
||||
threshold: constitutional proposals only
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
### Before Disabling
|
||||
|
||||
```yaml
|
||||
checklist:
|
||||
- [ ] Analyze participation impact
|
||||
- [ ] Check for pending operations
|
||||
- [ ] Plan fund withdrawal
|
||||
- [ ] Draft community announcement
|
||||
- [ ] Update documentation
|
||||
- [ ] Prepare UI changes
|
||||
```
|
||||
|
||||
### During Disable
|
||||
|
||||
```yaml
|
||||
checklist:
|
||||
- [ ] Wait for pending operations
|
||||
- [ ] Pause/disable paymaster
|
||||
- [ ] Withdraw funds (if applicable)
|
||||
- [ ] Verify disable successful
|
||||
- [ ] Publish announcement
|
||||
```
|
||||
|
||||
### After Disabling
|
||||
|
||||
```yaml
|
||||
checklist:
|
||||
- [ ] Monitor participation rates
|
||||
- [ ] Respond to user questions
|
||||
- [ ] Track support tickets
|
||||
- [ ] Review metrics weekly
|
||||
- [ ] Evaluate re-enabling if needed
|
||||
```
|
||||
@@ -0,0 +1,354 @@
|
||||
---
|
||||
title: Gasless Voting Overview
|
||||
description: Enable gas-free voting for DAO members
|
||||
---
|
||||
|
||||
# Gasless Voting Overview
|
||||
|
||||
Gasless voting allows DAO members to participate in governance without paying transaction fees. This guide explains how gasless voting works and its benefits.
|
||||
|
||||
## What is Gasless Voting?
|
||||
|
||||
Gasless voting uses account abstraction (EIP-4337) to sponsor gas fees for voters, removing the barrier of gas costs from governance participation.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Traditional Voting vs Gasless Voting │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Traditional: │
|
||||
│ User → Pay Gas → Submit Vote → Blockchain │
|
||||
│ │
|
||||
│ Gasless: │
|
||||
│ User → Sign Vote → Paymaster Pays Gas → Blockchain │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Key Benefits
|
||||
|
||||
| Benefit | Description |
|
||||
|---------|-------------|
|
||||
| **Zero Gas Cost** | Voters pay nothing to participate |
|
||||
| **Higher Turnout** | Remove financial barrier to voting |
|
||||
| **Better UX** | Simple one-click voting |
|
||||
| **Inclusive** | Enable participation regardless of ETH balance |
|
||||
| **Mobile-Friendly** | Vote from any device without gas management |
|
||||
|
||||
## How It Works
|
||||
|
||||
### EIP-4337 Account Abstraction
|
||||
|
||||
Gasless voting leverages EIP-4337, the account abstraction standard:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ EIP-4337 Architecture │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────┐ ┌───────────────┐ ┌─────────────────┐ │
|
||||
│ │ User │───►│ UserOperation │───►│ Bundler │ │
|
||||
│ │ Wallet │ │ (signed vote) │ │ │ │
|
||||
│ └─────────┘ └───────────────┘ └────────┬────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────┐ ┌───────────────┐ ┌─────────────────┐ │
|
||||
│ │ Vote │◄───│ EntryPoint │◄───│ Paymaster │ │
|
||||
│ │Recorded │ │ Contract │ │ (pays gas) │ │
|
||||
│ └─────────┘ └───────────────┘ └─────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Components
|
||||
|
||||
#### 1. UserOperation
|
||||
|
||||
A signed message containing the vote:
|
||||
|
||||
```yaml
|
||||
UserOperation:
|
||||
sender: voter_address
|
||||
callData: castVote(proposalId, support)
|
||||
signature: voter_signature
|
||||
# Gas fields handled by paymaster
|
||||
```
|
||||
|
||||
#### 2. Bundler
|
||||
|
||||
Aggregates UserOperations and submits to blockchain:
|
||||
|
||||
- Collects pending votes
|
||||
- Batches for efficiency
|
||||
- Submits to EntryPoint contract
|
||||
|
||||
#### 3. Paymaster
|
||||
|
||||
Sponsors gas fees on behalf of voters:
|
||||
|
||||
```yaml
|
||||
Paymaster:
|
||||
type: VerifyingPaymaster
|
||||
sponsor: dao_treasury
|
||||
policy: allow_governance_votes
|
||||
limit: max_gas_per_vote
|
||||
```
|
||||
|
||||
#### 4. EntryPoint
|
||||
|
||||
EIP-4337 singleton contract that:
|
||||
|
||||
- Validates UserOperations
|
||||
- Verifies paymaster approval
|
||||
- Executes vote transactions
|
||||
- Handles gas accounting
|
||||
|
||||
## Gasless Voting Flow
|
||||
|
||||
### Step-by-Step Process
|
||||
|
||||
```
|
||||
1. User clicks "Vote" on proposal
|
||||
└── No wallet popup for gas
|
||||
|
||||
2. Wallet prompts for signature
|
||||
└── Signs the vote intention (free)
|
||||
|
||||
3. Signed UserOperation sent to Bundler
|
||||
└── Vote queued for processing
|
||||
|
||||
4. Bundler submits to EntryPoint
|
||||
└── Paymaster confirms sponsorship
|
||||
|
||||
5. EntryPoint executes vote
|
||||
└── Gas paid by Paymaster
|
||||
|
||||
6. Vote recorded on-chain
|
||||
└── User notified of success
|
||||
```
|
||||
|
||||
### User Experience
|
||||
|
||||
From the voter's perspective:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Vote on Proposal #42 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Grant $50,000 to Research Committee │
|
||||
│ │
|
||||
│ Your Voting Power: 10,000 veLUX │
|
||||
│ │
|
||||
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ FOR │ │ AGAINST │ │ ABSTAIN │ │
|
||||
│ └────────────┘ └────────────┘ └────────────┘ │
|
||||
│ │
|
||||
│ ⚡ Gasless voting enabled │
|
||||
│ No ETH required to vote │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Eligibility and Policies
|
||||
|
||||
### Who Can Vote Gasless?
|
||||
|
||||
DAOs can configure eligibility:
|
||||
|
||||
```yaml
|
||||
gasless_policy:
|
||||
# Token-based eligibility
|
||||
min_voting_power: 100 veLUX
|
||||
|
||||
# Membership-based
|
||||
require_membership: true
|
||||
membership_tiers: [member, contributor, lead]
|
||||
|
||||
# Rate limiting
|
||||
votes_per_day: 10
|
||||
cooldown_between_votes: 1 minute
|
||||
```
|
||||
|
||||
### Supported Actions
|
||||
|
||||
Gasless transactions typically cover:
|
||||
|
||||
| Action | Gasless | Notes |
|
||||
|--------|---------|-------|
|
||||
| Cast vote | Yes | All proposal types |
|
||||
| Delegate | Yes | One-time setup |
|
||||
| Change delegation | Yes | Limited frequency |
|
||||
| Create proposal | No | Prevents spam |
|
||||
| Execute proposal | No | High gas cost |
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Replay Protection
|
||||
|
||||
Each UserOperation includes:
|
||||
|
||||
- Unique nonce per sender
|
||||
- Chain ID binding
|
||||
- Expiration timestamp
|
||||
|
||||
```yaml
|
||||
protection:
|
||||
nonce: auto_increment
|
||||
chainId: bound_to_chain
|
||||
validUntil: block_timestamp + 1_hour
|
||||
```
|
||||
|
||||
### Paymaster Verification
|
||||
|
||||
Paymaster validates before sponsoring:
|
||||
|
||||
```solidity
|
||||
function validatePaymasterUserOp(
|
||||
UserOperation calldata userOp,
|
||||
bytes32 userOpHash,
|
||||
uint256 maxCost
|
||||
) external returns (bytes memory context, uint256 validationData) {
|
||||
// Verify sender is eligible voter
|
||||
require(isEligibleVoter(userOp.sender), "Not eligible");
|
||||
|
||||
// Verify action is governance vote
|
||||
require(isGovernanceAction(userOp.callData), "Invalid action");
|
||||
|
||||
// Check rate limits
|
||||
require(!rateLimited(userOp.sender), "Rate limited");
|
||||
|
||||
// Check paymaster balance
|
||||
require(address(this).balance >= maxCost, "Insufficient funds");
|
||||
|
||||
return (abi.encode(userOp.sender), 0);
|
||||
}
|
||||
```
|
||||
|
||||
### Sybil Resistance
|
||||
|
||||
Prevent abuse through:
|
||||
|
||||
- Token-gated access
|
||||
- Rate limiting
|
||||
- Minimum voting power requirements
|
||||
- Historical participation requirements
|
||||
|
||||
## Cost Analysis
|
||||
|
||||
### Gas Costs
|
||||
|
||||
Typical gas usage for voting:
|
||||
|
||||
| Action | Gas Units | At 30 gwei |
|
||||
|--------|-----------|------------|
|
||||
| Simple vote | ~100,000 | ~$3.00 |
|
||||
| Delegate | ~80,000 | ~$2.40 |
|
||||
| Vote + delegate | ~150,000 | ~$4.50 |
|
||||
|
||||
### Paymaster Economics
|
||||
|
||||
```yaml
|
||||
economics:
|
||||
# Per-vote cost
|
||||
avg_gas_per_vote: 100,000
|
||||
gas_price: 30 gwei
|
||||
cost_per_vote: ~0.003 ETH (~$9)
|
||||
|
||||
# Monthly projections (1000 votes)
|
||||
monthly_votes: 1,000
|
||||
monthly_cost: ~3 ETH (~$9,000)
|
||||
|
||||
# Treasury sustainability
|
||||
funding_source: protocol_fees
|
||||
fee_allocation: 5%
|
||||
```
|
||||
|
||||
## Gasless Voting Dashboard
|
||||
|
||||
<Cards>
|
||||
<Card title="Setup Gasless" href="/docs/guide/gasless/setup" icon="settings">
|
||||
Configure gasless voting for your DAO
|
||||
</Card>
|
||||
<Card title="Paymaster" href="/docs/guide/gasless/paymaster" icon="credit-card">
|
||||
Manage paymaster funding
|
||||
</Card>
|
||||
<Card title="Disabling" href="/docs/guide/gasless/disabling" icon="x-circle">
|
||||
Turn off gasless voting
|
||||
</Card>
|
||||
<Card title="Using Gasless" href="/docs/guide/gasless/using" icon="zap">
|
||||
Voter guide for gasless voting
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## Comparison with Other Approaches
|
||||
|
||||
### Meta-Transactions
|
||||
|
||||
```yaml
|
||||
meta_transactions:
|
||||
pros:
|
||||
- Simpler implementation
|
||||
- Works with EOAs
|
||||
cons:
|
||||
- Requires relayer infrastructure
|
||||
- Custom per-contract implementation
|
||||
- Limited flexibility
|
||||
```
|
||||
|
||||
### Snapshot (Off-chain)
|
||||
|
||||
```yaml
|
||||
snapshot:
|
||||
pros:
|
||||
- Completely free
|
||||
- No blockchain interaction
|
||||
cons:
|
||||
- Votes not on-chain
|
||||
- Requires trusted execution
|
||||
- No automatic enforcement
|
||||
```
|
||||
|
||||
### EIP-4337 (Gasless Voting)
|
||||
|
||||
```yaml
|
||||
eip_4337:
|
||||
pros:
|
||||
- On-chain votes
|
||||
- Standardized approach
|
||||
- Flexible policies
|
||||
- Works with smart accounts
|
||||
cons:
|
||||
- Requires paymaster funding
|
||||
- More complex setup
|
||||
- Bundler dependency
|
||||
```
|
||||
|
||||
## Network Support
|
||||
|
||||
Gasless voting is available on:
|
||||
|
||||
| Network | EntryPoint | Status |
|
||||
|---------|------------|--------|
|
||||
| Ethereum | 0x5FF1...6197 | Active |
|
||||
| Arbitrum | 0x5FF1...6197 | Active |
|
||||
| Optimism | 0x5FF1...6197 | Active |
|
||||
| Base | 0x5FF1...6197 | Active |
|
||||
| Polygon | 0x5FF1...6197 | Active |
|
||||
| Lux | 0x5FF1...6197 | Active |
|
||||
|
||||
## Getting Started
|
||||
|
||||
### For DAO Admins
|
||||
|
||||
1. [Set up gasless voting](/docs/guide/gasless/setup)
|
||||
2. [Fund the paymaster](/docs/guide/gasless/paymaster)
|
||||
3. Configure eligibility policies
|
||||
4. Test with a sample proposal
|
||||
|
||||
### For Voters
|
||||
|
||||
1. [Learn how to vote gasless](/docs/guide/gasless/using)
|
||||
2. Connect your wallet
|
||||
3. Vote on proposals without gas
|
||||
4. Track your voting history
|
||||
@@ -0,0 +1,453 @@
|
||||
---
|
||||
title: Paymaster Management
|
||||
description: Fill and withdraw from the gasless voting paymaster
|
||||
---
|
||||
|
||||
# Paymaster Management
|
||||
|
||||
The paymaster is the account that sponsors gas fees for gasless voting. This guide covers funding, monitoring, and managing your paymaster balance.
|
||||
|
||||
## Understanding the Paymaster
|
||||
|
||||
### What is a Paymaster?
|
||||
|
||||
A paymaster is a smart contract that pays gas fees on behalf of users. In EIP-4337 account abstraction:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Paymaster Flow │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ [User] ──► Signs Vote (free) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ [Bundler] ──► Checks Paymaster │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ [Paymaster] ──► Validates & Approves │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ [EntryPoint] ──► Executes Vote │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ [Paymaster] ──► Gas Deducted from Balance │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Paymaster Balance
|
||||
|
||||
The paymaster holds ETH (or native token) to pay for gas:
|
||||
|
||||
```yaml
|
||||
paymaster:
|
||||
address: 0x1234...5678
|
||||
balance: 5.25 ETH
|
||||
deposited: 10.00 ETH
|
||||
spent: 4.75 ETH
|
||||
pending: 0.00 ETH # Reserved for in-flight operations
|
||||
```
|
||||
|
||||
## Viewing Paymaster Status
|
||||
|
||||
### Dashboard Overview
|
||||
|
||||
Access paymaster status from your DAO dashboard:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Paymaster Status │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Balance: 5.25 ETH │
|
||||
│ Status: ● Active │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Balance Health │ │
|
||||
│ │ ██████████████████░░░░░░░░ 52.5% │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Estimated Runway: │
|
||||
│ • ~1,750 votes at current gas prices │
|
||||
│ • ~5 weeks at current usage │
|
||||
│ │
|
||||
│ Today's Usage: 12 votes (0.036 ETH) │
|
||||
│ This Week: 84 votes (0.252 ETH) │
|
||||
│ This Month: 312 votes (0.936 ETH) │
|
||||
│ │
|
||||
│ [Deposit] [Withdraw] [View History] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Balance Alerts
|
||||
|
||||
Configure alerts for low balance:
|
||||
|
||||
```yaml
|
||||
alerts:
|
||||
warning:
|
||||
threshold: 1.0 ETH
|
||||
message: "Paymaster balance low"
|
||||
notify: [email, discord]
|
||||
|
||||
critical:
|
||||
threshold: 0.25 ETH
|
||||
message: "Paymaster critically low"
|
||||
notify: [email, discord, sms]
|
||||
action: pause_gasless # Optional auto-pause
|
||||
```
|
||||
|
||||
## Depositing Funds
|
||||
|
||||
### Manual Deposit
|
||||
|
||||
Add funds to the paymaster:
|
||||
|
||||
1. Go to **Settings** > **Gasless** > **Paymaster**
|
||||
2. Click **Deposit**
|
||||
3. Enter amount
|
||||
4. Confirm transaction
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Deposit to Paymaster │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Current Balance: 5.25 ETH │
|
||||
│ │
|
||||
│ Deposit Amount: [2.0 ] ETH │
|
||||
│ │
|
||||
│ [0.5 ETH] [1 ETH] [2 ETH] [5 ETH] │
|
||||
│ │
|
||||
│ New Balance: 7.25 ETH │
|
||||
│ │
|
||||
│ Source: │
|
||||
│ ● Connected Wallet (0x1234...5678) │
|
||||
│ ○ DAO Treasury (requires proposal) │
|
||||
│ │
|
||||
│ [Cancel] [Deposit] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Deposit via EntryPoint
|
||||
|
||||
Deposits go through the EIP-4337 EntryPoint contract:
|
||||
|
||||
```solidity
|
||||
// Deposit to paymaster via EntryPoint
|
||||
IEntryPoint entryPoint = IEntryPoint(0x5FF1...6197);
|
||||
entryPoint.depositTo{value: 2 ether}(paymasterAddress);
|
||||
```
|
||||
|
||||
### Treasury Deposit
|
||||
|
||||
Fund from DAO treasury:
|
||||
|
||||
**Option 1: Admin Action (if permitted)**
|
||||
|
||||
1. Admin initiates transfer from treasury
|
||||
2. Funds deposited to paymaster
|
||||
|
||||
**Option 2: Governance Proposal**
|
||||
|
||||
```yaml
|
||||
proposal:
|
||||
title: "Fund Gasless Paymaster"
|
||||
actions:
|
||||
- type: transfer
|
||||
from: treasury
|
||||
to: paymaster
|
||||
amount: 5 ETH
|
||||
rationale: "Maintain gasless voting for Q1 2026"
|
||||
```
|
||||
|
||||
### Auto-Refill
|
||||
|
||||
Configure automatic refills:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Auto-Refill Settings │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Auto-Refill: [● Enabled ○ Disabled] │
|
||||
│ │
|
||||
│ Trigger When: Balance falls below │
|
||||
│ [1.0 ] ETH │
|
||||
│ │
|
||||
│ Refill Amount: [3.0 ] ETH │
|
||||
│ │
|
||||
│ Monthly Cap: [10.0 ] ETH │
|
||||
│ │
|
||||
│ Source: [DAO Treasury ▼] │
|
||||
│ │
|
||||
│ Approval: │
|
||||
│ ○ Automatic (no proposal needed) │
|
||||
│ ● Requires admin approval │
|
||||
│ ○ Requires governance proposal │
|
||||
│ │
|
||||
│ [Save Settings] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Withdrawing Funds
|
||||
|
||||
### When to Withdraw
|
||||
|
||||
You may need to withdraw funds:
|
||||
|
||||
- Migrating to new paymaster
|
||||
- Reallocating treasury funds
|
||||
- Disabling gasless voting
|
||||
- Emergency fund recovery
|
||||
|
||||
### Withdrawal Process
|
||||
|
||||
1. Go to **Settings** > **Gasless** > **Paymaster**
|
||||
2. Click **Withdraw**
|
||||
3. Enter amount or select "Withdraw All"
|
||||
4. Confirm transaction
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Withdraw from Paymaster │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Current Balance: 5.25 ETH │
|
||||
│ Pending Operations: 0.05 ETH (reserved) │
|
||||
│ Available: 5.20 ETH │
|
||||
│ │
|
||||
│ Withdraw Amount: [5.20 ] ETH │
|
||||
│ │
|
||||
│ [25%] [50%] [75%] [MAX] │
|
||||
│ │
|
||||
│ Destination: [0x1234...5678 ] │
|
||||
│ ○ Connected Wallet │
|
||||
│ ● DAO Treasury │
|
||||
│ ○ Custom Address │
|
||||
│ │
|
||||
│ ⚠ Warning: Withdrawing all funds will disable gasless │
|
||||
│ voting until refunded. │
|
||||
│ │
|
||||
│ [Cancel] [Withdraw] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Withdrawal via Contract
|
||||
|
||||
Direct contract interaction:
|
||||
|
||||
```solidity
|
||||
// Paymaster owner withdraws funds
|
||||
IPaymaster paymaster = IPaymaster(paymasterAddress);
|
||||
paymaster.withdrawTo(recipient, amount);
|
||||
```
|
||||
|
||||
<Callout type="warning">
|
||||
Only the paymaster owner can withdraw funds. Ensure proper access control.
|
||||
</Callout>
|
||||
|
||||
### Governance-Required Withdrawal
|
||||
|
||||
For DAOs requiring governance approval:
|
||||
|
||||
```yaml
|
||||
proposal:
|
||||
title: "Withdraw Paymaster Funds"
|
||||
type: treasury_withdrawal
|
||||
actions:
|
||||
- type: paymaster_withdraw
|
||||
amount: 5 ETH
|
||||
destination: treasury
|
||||
rationale: "Reallocate unused gasless funds to grants"
|
||||
```
|
||||
|
||||
## Monitoring Usage
|
||||
|
||||
### Usage Analytics
|
||||
|
||||
Track how funds are being used:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Paymaster Analytics │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Period: Last 30 Days │
|
||||
│ │
|
||||
│ Total Sponsored: 312 votes │
|
||||
│ Total Gas Spent: 0.936 ETH │
|
||||
│ Average per Vote: 0.003 ETH │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Daily Usage (ETH) │ │
|
||||
│ │ │ │
|
||||
│ │ ▄ │ │
|
||||
│ │ ▄ █ ▄ ▄ │ │
|
||||
│ │ █ █ ▄ █ ▄ ▄ ▄ ▄ █ │ │
|
||||
│ │ ▄ █ █ ▄ █ █ █ ▄ ▄ █ ▄ █ ▄ ▄ █ █ ▄ │ │
|
||||
│ │ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ │ │
|
||||
│ │ ───────────────────────────────── │ │
|
||||
│ │ 1 5 10 15 20 25 30 │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Top Users: │
|
||||
│ 1. 0xABC...123 - 45 votes (0.135 ETH) │
|
||||
│ 2. 0xDEF...456 - 38 votes (0.114 ETH) │
|
||||
│ 3. 0xGHI...789 - 32 votes (0.096 ETH) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Cost Breakdown
|
||||
|
||||
Understand where gas is going:
|
||||
|
||||
```yaml
|
||||
cost_breakdown:
|
||||
by_action:
|
||||
cast_vote: 85%
|
||||
cast_vote_with_reason: 10%
|
||||
delegate: 5%
|
||||
|
||||
by_proposal_type:
|
||||
standard: 60%
|
||||
constitutional: 25%
|
||||
emergency: 15%
|
||||
|
||||
by_gas_price:
|
||||
low_traffic: 40% # < 30 gwei
|
||||
normal: 45% # 30-60 gwei
|
||||
high_traffic: 15% # > 60 gwei
|
||||
```
|
||||
|
||||
### Estimating Runway
|
||||
|
||||
Calculate how long funds will last:
|
||||
|
||||
```yaml
|
||||
runway_calculation:
|
||||
current_balance: 5.25 ETH
|
||||
avg_daily_spend: 0.03 ETH
|
||||
estimated_days: 175
|
||||
|
||||
scenarios:
|
||||
low_activity: # 10 votes/day
|
||||
daily_cost: 0.03 ETH
|
||||
runway: 175 days
|
||||
|
||||
normal_activity: # 25 votes/day
|
||||
daily_cost: 0.075 ETH
|
||||
runway: 70 days
|
||||
|
||||
high_activity: # 50 votes/day
|
||||
daily_cost: 0.15 ETH
|
||||
runway: 35 days
|
||||
```
|
||||
|
||||
## Paymaster Security
|
||||
|
||||
### Access Control
|
||||
|
||||
Secure your paymaster:
|
||||
|
||||
```yaml
|
||||
access_control:
|
||||
owner: dao_multisig
|
||||
admin: dao_admin_role
|
||||
|
||||
permissions:
|
||||
deposit: [owner, admin, anyone]
|
||||
withdraw: [owner]
|
||||
pause: [owner, admin]
|
||||
update_policy: [owner]
|
||||
```
|
||||
|
||||
### Spending Limits
|
||||
|
||||
Prevent runaway spending:
|
||||
|
||||
```yaml
|
||||
spending_limits:
|
||||
per_user:
|
||||
daily: 0.1 ETH
|
||||
weekly: 0.5 ETH
|
||||
monthly: 2.0 ETH
|
||||
|
||||
global:
|
||||
daily: 5 ETH
|
||||
weekly: 20 ETH
|
||||
monthly: 50 ETH
|
||||
```
|
||||
|
||||
### Emergency Pause
|
||||
|
||||
Pause sponsorship in emergencies:
|
||||
|
||||
1. Go to **Settings** > **Gasless**
|
||||
2. Click **Emergency Pause**
|
||||
3. Confirm action
|
||||
|
||||
```solidity
|
||||
// Or via contract
|
||||
paymaster.pause();
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
| Issue | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| Deposit not showing | Transaction pending | Wait for confirmation |
|
||||
| Cannot withdraw | Funds reserved | Wait for pending operations |
|
||||
| Balance incorrect | Sync delay | Refresh dashboard |
|
||||
| Auto-refill failed | Treasury insufficient | Add treasury funds |
|
||||
|
||||
### Verifying Paymaster Balance
|
||||
|
||||
Check balance directly on-chain:
|
||||
|
||||
```javascript
|
||||
const entryPoint = new ethers.Contract(
|
||||
"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
|
||||
entryPointAbi,
|
||||
provider
|
||||
);
|
||||
|
||||
const balance = await entryPoint.balanceOf(paymasterAddress);
|
||||
console.log("Paymaster balance:", ethers.utils.formatEther(balance));
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Do
|
||||
|
||||
- Maintain 2-4 weeks runway minimum
|
||||
- Set up low-balance alerts
|
||||
- Monitor usage patterns
|
||||
- Use auto-refill for consistent funding
|
||||
- Keep withdrawal access secure
|
||||
|
||||
### Don't
|
||||
|
||||
- Let balance reach zero
|
||||
- Ignore usage spikes
|
||||
- Give withdrawal access broadly
|
||||
- Rely solely on manual refills
|
||||
- Forget to pause before migration
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Disabling Gasless" href="/docs/guide/gasless/disabling" icon="x-circle">
|
||||
Turn off gasless voting
|
||||
</Card>
|
||||
<Card title="Using Gasless" href="/docs/guide/gasless/using" icon="zap">
|
||||
Voter experience guide
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,446 @@
|
||||
---
|
||||
title: Setting Up Gasless Voting
|
||||
description: Configure gasless voting for your DAO
|
||||
---
|
||||
|
||||
# Setting Up Gasless Voting
|
||||
|
||||
This guide walks DAO administrators through enabling and configuring gasless voting using EIP-4337 account abstraction.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before setting up gasless voting:
|
||||
|
||||
- **Admin Role** - DAO admin or governance permissions
|
||||
- **Treasury Funds** - ETH/native token for paymaster
|
||||
- **Governance Contracts** - Deployed Governor or voting contract
|
||||
- **Network Support** - Chain with EIP-4337 support
|
||||
|
||||
## Setup Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Gasless Voting Setup Steps │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. Enable Gasless Feature │
|
||||
│ └── Toggle in DAO settings │
|
||||
│ │
|
||||
│ 2. Deploy Paymaster │
|
||||
│ └── Create paymaster contract │
|
||||
│ │
|
||||
│ 3. Configure Policies │
|
||||
│ └── Set eligibility rules │
|
||||
│ │
|
||||
│ 4. Fund Paymaster │
|
||||
│ └── Deposit ETH for gas sponsorship │
|
||||
│ │
|
||||
│ 5. Test and Launch │
|
||||
│ └── Verify with test vote │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Step 1: Enable Gasless Feature
|
||||
|
||||
### Navigate to Settings
|
||||
|
||||
1. Go to your DAO dashboard
|
||||
2. Click **Settings** in the sidebar
|
||||
3. Select **Gasless Voting** tab
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ DAO Settings │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ [General] [Governance] [Treasury] [Staking] [Gasless] │
|
||||
│ ^^^^^^^^ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Enable the Feature
|
||||
|
||||
Toggle gasless voting on:
|
||||
|
||||
```yaml
|
||||
gasless_voting:
|
||||
enabled: true
|
||||
network: ethereum # or your chain
|
||||
```
|
||||
|
||||
## Step 2: Deploy Paymaster
|
||||
|
||||
### Option A: Use Platform Paymaster
|
||||
|
||||
Use the built-in managed paymaster:
|
||||
|
||||
1. Click **Use Platform Paymaster**
|
||||
2. Review terms and fees
|
||||
3. Confirm setup
|
||||
|
||||
```yaml
|
||||
platform_paymaster:
|
||||
type: managed
|
||||
fee: 1% of sponsored gas
|
||||
min_deposit: 0.1 ETH
|
||||
auto_refill: optional
|
||||
```
|
||||
|
||||
### Option B: Deploy Custom Paymaster
|
||||
|
||||
Deploy your own paymaster contract:
|
||||
|
||||
1. Click **Deploy Custom Paymaster**
|
||||
2. Choose paymaster type:
|
||||
|
||||
```yaml
|
||||
paymaster_types:
|
||||
- verifying: Standard signature-based
|
||||
- token: Accept ERC-20 for gas
|
||||
- whitelist: Explicit allowlist
|
||||
```
|
||||
|
||||
3. Configure parameters:
|
||||
|
||||
```solidity
|
||||
// Example VerifyingPaymaster constructor
|
||||
constructor(
|
||||
IEntryPoint _entryPoint,
|
||||
address _verifyingSigner
|
||||
) BasePaymaster(_entryPoint) {
|
||||
verifyingSigner = _verifyingSigner;
|
||||
}
|
||||
```
|
||||
|
||||
4. Deploy and verify contract
|
||||
|
||||
### Paymaster Contract Addresses
|
||||
|
||||
Reference EntryPoint addresses:
|
||||
|
||||
| Network | EntryPoint v0.6 | EntryPoint v0.7 |
|
||||
|---------|-----------------|-----------------|
|
||||
| Ethereum | 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 | 0x0000000071727De22E5E9d8BAf0edAc6f37da032 |
|
||||
| Arbitrum | 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 | 0x0000000071727De22E5E9d8BAf0edAc6f37da032 |
|
||||
| Optimism | 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 | 0x0000000071727De22E5E9d8BAf0edAc6f37da032 |
|
||||
| Lux | 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 | 0x0000000071727De22E5E9d8BAf0edAc6f37da032 |
|
||||
|
||||
## Step 3: Configure Policies
|
||||
|
||||
### Eligibility Rules
|
||||
|
||||
Define who can use gasless voting:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Gasless Eligibility │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Minimum Voting Power: │
|
||||
│ [100 ] veLUX │
|
||||
│ │
|
||||
│ Membership Required: │
|
||||
│ [● Yes ○ No] │
|
||||
│ │
|
||||
│ Allowed Tiers: │
|
||||
│ [☑] Member │
|
||||
│ [☑] Contributor │
|
||||
│ [☑] Lead │
|
||||
│ [☑] Admin │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
Prevent abuse with rate limits:
|
||||
|
||||
```yaml
|
||||
rate_limits:
|
||||
# Per-user limits
|
||||
votes_per_day: 20
|
||||
votes_per_proposal: 1
|
||||
cooldown_seconds: 60
|
||||
|
||||
# Global limits
|
||||
total_votes_per_hour: 1000
|
||||
max_gas_per_day: 10 ETH
|
||||
```
|
||||
|
||||
### Sponsored Actions
|
||||
|
||||
Choose which actions are gasless:
|
||||
|
||||
```yaml
|
||||
sponsored_actions:
|
||||
# Core governance
|
||||
cast_vote: true
|
||||
cast_vote_with_reason: true
|
||||
cast_vote_by_sig: true
|
||||
|
||||
# Delegation
|
||||
delegate: true
|
||||
delegate_by_sig: true
|
||||
|
||||
# Not sponsored (prevent spam)
|
||||
propose: false
|
||||
execute: false
|
||||
cancel: false
|
||||
```
|
||||
|
||||
### Gas Limits
|
||||
|
||||
Set maximum gas per operation:
|
||||
|
||||
```yaml
|
||||
gas_limits:
|
||||
cast_vote:
|
||||
max_gas: 150000
|
||||
max_priority_fee: 2 gwei
|
||||
max_fee: 100 gwei
|
||||
|
||||
delegate:
|
||||
max_gas: 100000
|
||||
max_priority_fee: 2 gwei
|
||||
max_fee: 100 gwei
|
||||
```
|
||||
|
||||
## Step 4: Fund Paymaster
|
||||
|
||||
### Initial Deposit
|
||||
|
||||
Fund the paymaster with ETH:
|
||||
|
||||
1. Go to **Gasless** > **Paymaster Balance**
|
||||
2. Click **Deposit**
|
||||
3. Enter amount (minimum 0.1 ETH recommended)
|
||||
4. Confirm transaction
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Fund Paymaster │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Current Balance: 0.00 ETH │
|
||||
│ Recommended: 1.00 ETH (for ~300 votes) │
|
||||
│ │
|
||||
│ Deposit Amount: [1.0 ] ETH │
|
||||
│ │
|
||||
│ Estimated Coverage: │
|
||||
│ • ~300 votes at current gas prices │
|
||||
│ • ~2 weeks of normal activity │
|
||||
│ │
|
||||
│ [Cancel] [Deposit] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Auto-Refill (Optional)
|
||||
|
||||
Set up automatic refills from treasury:
|
||||
|
||||
```yaml
|
||||
auto_refill:
|
||||
enabled: true
|
||||
trigger_balance: 0.5 ETH
|
||||
refill_amount: 2.0 ETH
|
||||
max_refill_per_month: 10 ETH
|
||||
source: dao_treasury
|
||||
requires_approval: false # or true for governance vote
|
||||
```
|
||||
|
||||
## Step 5: Test and Launch
|
||||
|
||||
### Test Vote
|
||||
|
||||
Before going live, test with a sample vote:
|
||||
|
||||
1. Create a test proposal (or use testnet)
|
||||
2. Connect as an eligible voter
|
||||
3. Attempt gasless vote
|
||||
4. Verify:
|
||||
- Vote recorded correctly
|
||||
- Gas paid by paymaster
|
||||
- No errors in process
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Test Results │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ✓ UserOperation created successfully │
|
||||
│ ✓ Paymaster validated sponsorship │
|
||||
│ ✓ Bundler accepted UserOperation │
|
||||
│ ✓ Vote executed on-chain │
|
||||
│ ✓ Gas paid: 0.003 ETH from paymaster │
|
||||
│ │
|
||||
│ Status: Ready for production │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Launch Checklist
|
||||
|
||||
```yaml
|
||||
pre_launch:
|
||||
- [ ] Paymaster deployed and verified
|
||||
- [ ] Policies configured
|
||||
- [ ] Paymaster funded
|
||||
- [ ] Test vote successful
|
||||
- [ ] Documentation updated
|
||||
|
||||
launch:
|
||||
- [ ] Enable for all users
|
||||
- [ ] Announce to community
|
||||
- [ ] Monitor first votes
|
||||
- [ ] Support ready
|
||||
|
||||
post_launch:
|
||||
- [ ] Track usage metrics
|
||||
- [ ] Monitor paymaster balance
|
||||
- [ ] Gather feedback
|
||||
- [ ] Adjust policies if needed
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Custom Verification Logic
|
||||
|
||||
Implement custom eligibility checks:
|
||||
|
||||
```solidity
|
||||
contract CustomPaymaster is BasePaymaster {
|
||||
IGovernanceToken public governanceToken;
|
||||
uint256 public minVotingPower;
|
||||
|
||||
function _validatePaymasterUserOp(
|
||||
UserOperation calldata userOp,
|
||||
bytes32 userOpHash,
|
||||
uint256 maxCost
|
||||
) internal override returns (bytes memory context, uint256 validationData) {
|
||||
// Check minimum voting power
|
||||
uint256 votingPower = governanceToken.getVotes(userOp.sender);
|
||||
require(votingPower >= minVotingPower, "Insufficient voting power");
|
||||
|
||||
// Check if action is governance vote
|
||||
bytes4 selector = bytes4(userOp.callData[:4]);
|
||||
require(
|
||||
selector == IGovernor.castVote.selector ||
|
||||
selector == IGovernor.castVoteWithReason.selector,
|
||||
"Invalid action"
|
||||
);
|
||||
|
||||
return ("", 0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-Paymaster Setup
|
||||
|
||||
Use different paymasters for different actions:
|
||||
|
||||
```yaml
|
||||
paymasters:
|
||||
governance:
|
||||
address: 0xAAA...
|
||||
actions: [cast_vote, delegate]
|
||||
priority: 1
|
||||
|
||||
grants:
|
||||
address: 0xBBB...
|
||||
actions: [claim_grant]
|
||||
priority: 2
|
||||
|
||||
fallback:
|
||||
enabled: false # Require explicit paymaster
|
||||
```
|
||||
|
||||
### Bundler Configuration
|
||||
|
||||
Configure bundler settings:
|
||||
|
||||
```yaml
|
||||
bundler:
|
||||
# Primary bundler
|
||||
primary:
|
||||
url: https://bundler.example.com
|
||||
api_key: ${BUNDLER_API_KEY}
|
||||
|
||||
# Fallback bundlers
|
||||
fallback:
|
||||
- url: https://backup1.example.com
|
||||
- url: https://backup2.example.com
|
||||
|
||||
# Settings
|
||||
max_fee_per_gas: 100 gwei
|
||||
max_priority_fee: 2 gwei
|
||||
timeout_ms: 30000
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Dashboard Metrics
|
||||
|
||||
Track gasless voting health:
|
||||
|
||||
```yaml
|
||||
metrics:
|
||||
- paymaster_balance
|
||||
- votes_sponsored_today
|
||||
- average_gas_per_vote
|
||||
- failed_sponsorships
|
||||
- unique_voters
|
||||
```
|
||||
|
||||
### Alerts
|
||||
|
||||
Set up alerts for issues:
|
||||
|
||||
```yaml
|
||||
alerts:
|
||||
low_balance:
|
||||
threshold: 0.5 ETH
|
||||
notify: [admin_email, discord_webhook]
|
||||
|
||||
high_usage:
|
||||
threshold: 100 votes/hour
|
||||
notify: [admin_email]
|
||||
|
||||
failures:
|
||||
threshold: 5 failures/hour
|
||||
notify: [admin_email, pagerduty]
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
| Issue | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| "Paymaster validation failed" | Eligibility not met | Check voter requirements |
|
||||
| "Insufficient paymaster balance" | Low funds | Deposit more ETH |
|
||||
| "UserOperation reverted" | Invalid calldata | Verify action format |
|
||||
| "Bundler rejected" | Gas price too low | Increase gas settings |
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable verbose logging:
|
||||
|
||||
```yaml
|
||||
debug:
|
||||
enabled: true
|
||||
log_level: debug
|
||||
log_user_operations: true
|
||||
log_paymaster_validation: true
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Paymaster Management" href="/docs/guide/gasless/paymaster" icon="credit-card">
|
||||
Manage paymaster funds
|
||||
</Card>
|
||||
<Card title="Disabling Gasless" href="/docs/guide/gasless/disabling" icon="x-circle">
|
||||
Turn off gasless voting
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,436 @@
|
||||
---
|
||||
title: Using Gasless Voting
|
||||
description: How to vote without paying gas fees
|
||||
---
|
||||
|
||||
# Using Gasless Voting
|
||||
|
||||
Gasless voting lets you participate in DAO governance without paying transaction fees. This guide explains how to use this feature as a voter.
|
||||
|
||||
## What is Gasless Voting?
|
||||
|
||||
With gasless voting:
|
||||
|
||||
- **You sign** a message with your vote
|
||||
- **The DAO pays** the transaction fee
|
||||
- **Your vote** is recorded on-chain
|
||||
|
||||
No ETH required in your wallet to vote.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Traditional vs Gasless Voting │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Traditional Voting: │
|
||||
│ 1. Click Vote │
|
||||
│ 2. Approve gas fee ($3-10) │
|
||||
│ 3. Wait for confirmation │
|
||||
│ 4. Vote recorded │
|
||||
│ │
|
||||
│ Gasless Voting: │
|
||||
│ 1. Click Vote │
|
||||
│ 2. Sign message (free) │
|
||||
│ 3. Wait for confirmation │
|
||||
│ 4. Vote recorded │
|
||||
│ │
|
||||
│ You save: $3-10 per vote │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Checking Eligibility
|
||||
|
||||
### Am I Eligible?
|
||||
|
||||
Gasless voting may have requirements:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Your Gasless Voting Status │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ✓ Gasless voting available for you │
|
||||
│ │
|
||||
│ Requirements Met: │
|
||||
│ ✓ Minimum voting power (100+ veLUX) │
|
||||
│ ✓ DAO membership active │
|
||||
│ ✓ Not rate limited │
|
||||
│ │
|
||||
│ Your Voting Power: 5,000 veLUX │
|
||||
│ Gasless Votes Today: 2 of 20 allowed │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Common Requirements
|
||||
|
||||
| Requirement | Typical Threshold |
|
||||
|-------------|-------------------|
|
||||
| Minimum voting power | 100+ tokens |
|
||||
| Membership status | Active member |
|
||||
| Rate limit | 10-20 votes/day |
|
||||
| Cooldown | 1 minute between votes |
|
||||
|
||||
### If You're Not Eligible
|
||||
|
||||
If gasless isn't available, you'll see:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Gasless Voting Not Available │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ✗ You don't meet the requirements for gasless voting │
|
||||
│ │
|
||||
│ Missing: │
|
||||
│ ✗ Minimum voting power (you have 50, need 100 veLUX) │
|
||||
│ │
|
||||
│ Options: │
|
||||
│ • Stake more tokens to reach 100 veLUX │
|
||||
│ • Vote with gas (costs ~$3) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## How to Vote Gasless
|
||||
|
||||
### Step 1: Find a Proposal
|
||||
|
||||
1. Go to **Governance** > **Proposals**
|
||||
2. Select an active proposal
|
||||
3. Review the proposal details
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Proposal #42: Grant $50,000 to Research Committee │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Status: Active - Voting Open │
|
||||
│ Ends: 3 days, 4 hours │
|
||||
│ │
|
||||
│ Current Results: │
|
||||
│ For: ████████████████████░░░░ 68% │
|
||||
│ Against: ████████░░░░░░░░░░░░░░░░ 32% │
|
||||
│ │
|
||||
│ Quorum: ██████████████░░░░░░░░░░ 65% reached │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Choose Your Vote
|
||||
|
||||
Select For, Against, or Abstain:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Cast Your Vote │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Your Voting Power: 5,000 veLUX │
|
||||
│ │
|
||||
│ ┌────────────────┐ │
|
||||
│ │ ● FOR │ ← Selected │
|
||||
│ └────────────────┘ │
|
||||
│ ┌────────────────┐ │
|
||||
│ │ ○ AGAINST │ │
|
||||
│ └────────────────┘ │
|
||||
│ ┌────────────────┐ │
|
||||
│ │ ○ ABSTAIN │ │
|
||||
│ └────────────────┘ │
|
||||
│ │
|
||||
│ Add reason (optional): │
|
||||
│ [This initiative aligns with our research goals... ] │
|
||||
│ │
|
||||
│ ⚡ Gasless voting enabled - No gas fee required │
|
||||
│ │
|
||||
│ [Submit Vote] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Sign the Vote
|
||||
|
||||
Click Submit and sign in your wallet:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ MetaMask - Sign Message │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ dao.example.com requests your signature │
|
||||
│ │
|
||||
│ Message: │
|
||||
│ ───────────────────────────────── │
|
||||
│ Cast vote on Proposal #42 │
|
||||
│ Vote: For │
|
||||
│ Reason: This initiative aligns with our research goals │
|
||||
│ ───────────────────────────────── │
|
||||
│ │
|
||||
│ This will not cost any gas fees. │
|
||||
│ Your vote will be recorded on-chain. │
|
||||
│ │
|
||||
│ [Reject] [Sign] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
<Callout type="info">
|
||||
Signing is free - you're only approving your vote, not paying for a transaction.
|
||||
</Callout>
|
||||
|
||||
### Step 4: Wait for Confirmation
|
||||
|
||||
Your vote is submitted to the bundler:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Vote Submitted │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ⟳ Processing your vote... │
|
||||
│ │
|
||||
│ Status: Pending │
|
||||
│ Estimated time: 15-60 seconds │
|
||||
│ │
|
||||
│ What's happening: │
|
||||
│ 1. ✓ Vote signed │
|
||||
│ 2. ✓ Submitted to bundler │
|
||||
│ 3. ⟳ Waiting for on-chain confirmation │
|
||||
│ 4. ○ Vote recorded │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 5: Vote Confirmed
|
||||
|
||||
Once confirmed, you'll see:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Vote Recorded! │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ✓ Your vote has been recorded on-chain │
|
||||
│ │
|
||||
│ Proposal: #42 - Grant to Research Committee │
|
||||
│ Your Vote: FOR │
|
||||
│ Voting Power: 5,000 veLUX │
|
||||
│ Gas Paid: $0.00 (sponsored) │
|
||||
│ │
|
||||
│ Transaction: 0xabc123... │
|
||||
│ [View on Explorer] │
|
||||
│ │
|
||||
│ Thank you for participating in governance! │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Delegating Gaslessly
|
||||
|
||||
You can also delegate your voting power without gas:
|
||||
|
||||
### Step 1: Go to Delegation
|
||||
|
||||
1. Navigate to **Governance** > **Delegation**
|
||||
2. Click **Delegate Votes**
|
||||
|
||||
### Step 2: Choose Delegate
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Delegate Your Voting Power │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Your Voting Power: 5,000 veLUX │
|
||||
│ Currently Delegated To: Self │
|
||||
│ │
|
||||
│ Delegate To: │
|
||||
│ [0xABC...123 ] │
|
||||
│ │
|
||||
│ Or choose from active delegates: │
|
||||
│ ┌────────────────────────────────────────────────────┐ │
|
||||
│ │ alice.eth │ 50,000 veLUX │ 95% participation│ │
|
||||
│ │ bob.eth │ 30,000 veLUX │ 88% participation│ │
|
||||
│ │ research.eth │ 25,000 veLUX │ 100% participation│ │
|
||||
│ └────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ⚡ Gasless delegation enabled │
|
||||
│ │
|
||||
│ [Cancel] [Delegate] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Sign and Confirm
|
||||
|
||||
Same process as voting - sign the message for free.
|
||||
|
||||
## Changing Your Vote
|
||||
|
||||
Most DAOs allow changing votes before the voting period ends:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Your Current Vote │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Proposal #42 │
|
||||
│ Your Vote: FOR (5,000 veLUX) │
|
||||
│ Cast: 2 days ago │
|
||||
│ │
|
||||
│ Voting ends in: 1 day, 4 hours │
|
||||
│ │
|
||||
│ [Change Vote] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
<Callout type="warning">
|
||||
Changing your vote uses one of your daily gasless vote allowances.
|
||||
</Callout>
|
||||
|
||||
## Rate Limits
|
||||
|
||||
### Understanding Limits
|
||||
|
||||
DAOs may limit gasless votes to prevent abuse:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Your Gasless Voting Limits │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Daily Votes: 5 / 20 used │
|
||||
│ ████░░░░░░░░░░░░░░░░ 25% │
|
||||
│ │
|
||||
│ Resets in: 8 hours │
|
||||
│ │
|
||||
│ Cooldown: None (ready to vote) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### If Rate Limited
|
||||
|
||||
If you've hit your limit:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Rate Limit Reached │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ You've used all 20 gasless votes today. │
|
||||
│ │
|
||||
│ Options: │
|
||||
│ • Wait until limit resets (8 hours) │
|
||||
│ • Vote with gas (~$3) │
|
||||
│ │
|
||||
│ [Vote with Gas] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Viewing Vote History
|
||||
|
||||
Track your voting activity:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ My Voting History │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ │ Proposal │ Vote │ Power │ Method │ Date │
|
||||
│ ├───────────────────┼─────────┼────────┼──────────┼────────│
|
||||
│ │ #42 Research Grant│ For │ 5,000 │ Gasless │ Today │
|
||||
│ │ #41 Treasury Alloc│ Against │ 5,000 │ Gasless │ 3d ago │
|
||||
│ │ #40 Parameter Upd │ For │ 4,500 │ Gasless │ 1w ago │
|
||||
│ │ #39 Committee Elec│ Abstain │ 4,500 │ Regular │ 2w ago │
|
||||
│ │
|
||||
│ Total Votes: 45 │
|
||||
│ Gasless Votes: 42 (93%) │
|
||||
│ Gas Saved: ~$126 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
| Issue | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| "Gasless not available" | Don't meet requirements | Check eligibility requirements |
|
||||
| Signature rejected | Wallet issue | Try reconnecting wallet |
|
||||
| Vote not confirming | Network congestion | Wait or retry |
|
||||
| "Rate limited" | Too many votes | Wait for reset |
|
||||
|
||||
### Vote Stuck "Pending"
|
||||
|
||||
If your vote is stuck:
|
||||
|
||||
1. **Wait** - Bundlers may batch transactions (up to 2 minutes)
|
||||
2. **Check Status** - View in your voting history
|
||||
3. **Retry** - If failed, try voting again
|
||||
4. **Fallback** - Vote with gas as backup
|
||||
|
||||
### Wrong Vote Recorded
|
||||
|
||||
If your vote appears incorrect:
|
||||
|
||||
1. Verify on block explorer
|
||||
2. Check if you can change vote
|
||||
3. Contact DAO support if persistent issue
|
||||
|
||||
## FAQ
|
||||
|
||||
### Is gasless voting secure?
|
||||
|
||||
Yes. Your vote is:
|
||||
- Signed by your wallet (only you can create it)
|
||||
- Recorded on-chain (tamper-proof)
|
||||
- Verified by smart contracts (can't be spoofed)
|
||||
|
||||
### Why do I need to sign?
|
||||
|
||||
Signing proves you authorized the vote. Without your signature, no one can vote on your behalf.
|
||||
|
||||
### Does the DAO see my private key?
|
||||
|
||||
No. Signing uses your private key locally - only the signature leaves your device.
|
||||
|
||||
### Can I use gasless on mobile?
|
||||
|
||||
Yes, if your mobile wallet supports message signing (most do).
|
||||
|
||||
### What if gasless is disabled mid-vote?
|
||||
|
||||
Your pending vote will still process. Future votes will require gas.
|
||||
|
||||
### Is there a limit to gasless votes?
|
||||
|
||||
Yes, typically 10-20 per day to prevent abuse. Check your DAO's specific limits.
|
||||
|
||||
## Tips for Best Experience
|
||||
|
||||
### Do
|
||||
|
||||
- Check eligibility before important votes
|
||||
- Sign promptly when wallet prompts
|
||||
- Monitor vote confirmation
|
||||
- Keep some ETH as backup
|
||||
|
||||
### Don't
|
||||
|
||||
- Close browser during voting
|
||||
- Spam vote attempts
|
||||
- Ignore rate limits
|
||||
- Assume all DAOs have gasless
|
||||
|
||||
## Need Help?
|
||||
|
||||
If you encounter issues:
|
||||
|
||||
1. Check the [FAQ](/docs/faq)
|
||||
2. Visit the DAO's Discord support channel
|
||||
3. Contact DAO admins
|
||||
@@ -0,0 +1,472 @@
|
||||
---
|
||||
title: Fund Clawback
|
||||
description: Recall funds from child node treasuries
|
||||
---
|
||||
|
||||
# Fund Clawback
|
||||
|
||||
Parent DAOs can recall (clawback) funds from child node treasuries. This mechanism ensures ultimate control over delegated resources while respecting the autonomy of sub-DAOs.
|
||||
|
||||
## Overview
|
||||
|
||||
Clawback allows parent DAOs to:
|
||||
|
||||
- Recall unused or misallocated funds
|
||||
- Recover assets during node dissolution
|
||||
- Respond to emergencies
|
||||
- Rebalance treasury allocations
|
||||
|
||||
## When to Use Clawback
|
||||
|
||||
### Appropriate Uses
|
||||
|
||||
- **Node dissolution** - Returning funds when closing a sub-DAO
|
||||
- **Budget reallocation** - Moving unused funds to higher priorities
|
||||
- **Emergency recovery** - Security incident response
|
||||
- **Charter violation** - Funds used outside mandate
|
||||
- **Period end** - Returning unspent quarterly allocation
|
||||
|
||||
### Not Appropriate
|
||||
|
||||
- Punitive action without governance
|
||||
- Overriding legitimate child decisions
|
||||
- Routine budget adjustments (use transfers)
|
||||
- Political disputes
|
||||
|
||||
<Callout type="warning">
|
||||
Clawback is a significant action that can disrupt child operations. Always follow proper governance and provide adequate notice.
|
||||
</Callout>
|
||||
|
||||
## Clawback Process
|
||||
|
||||
### Timelock Delay
|
||||
|
||||
Most configurations include a clawback delay:
|
||||
|
||||
```
|
||||
Parent initiates Delay period Execution
|
||||
clawback (3-7 days) (funds recalled)
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
────●───────────────────●────────────────●────►
|
||||
│ │ │
|
||||
│ │ │
|
||||
└───── Child can ───┘ │
|
||||
respond or │
|
||||
appeal │
|
||||
│
|
||||
Funds transfer to
|
||||
parent treasury
|
||||
```
|
||||
|
||||
### Delay Rationale
|
||||
|
||||
| Delay | Use Case |
|
||||
|-------|----------|
|
||||
| 0 days | Emergency reserve (parent-controlled) |
|
||||
| 1 day | Operational funds (tight oversight) |
|
||||
| 3 days | Standard committees |
|
||||
| 7 days | Autonomous sub-DAOs |
|
||||
| 14 days | High-autonomy entities |
|
||||
|
||||
## Clawback Methods
|
||||
|
||||
### Method 1: Via UI
|
||||
|
||||
1. Navigate to **Organization** > **Hierarchy**
|
||||
2. Select the child node
|
||||
3. Click **"Clawback Funds"**
|
||||
4. Configure the clawback
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Clawback Funds: Research Committee │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Child Treasury Balances: │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ USDC 75,000.00 │ │
|
||||
│ │ ETH 12.5 │ │
|
||||
│ │ DAO 500,000 │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Token to recall: [USDC ▼] │
|
||||
│ │
|
||||
│ Amount: [50,000 ] │
|
||||
│ │
|
||||
│ Reason (required): │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Q4 budget underspent - reallocating to Grants │ │
|
||||
│ │ Committee for year-end programs. │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ⏱️ Timelock: 3 days (per child configuration) │
|
||||
│ │
|
||||
│ [ Cancel ] [ Initiate Clawback ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Method 2: Via Proposal
|
||||
|
||||
Recommended for significant clawbacks:
|
||||
|
||||
```yaml
|
||||
Proposal: "Recall Unspent Q4 Budget from Research Committee"
|
||||
|
||||
Description: |
|
||||
The Research Committee has $50,000 USDC remaining from
|
||||
their Q4 budget. This proposal recalls those funds for
|
||||
reallocation to the Grants Committee.
|
||||
|
||||
## Rationale
|
||||
- Research Committee spent $50K of $100K Q4 allocation
|
||||
- Grants Committee has backlog of approved applications
|
||||
- Fiscal year ends in 30 days
|
||||
|
||||
## Impact
|
||||
- Research Committee retains $25K for ongoing projects
|
||||
- $50K reallocated to high-priority grants
|
||||
|
||||
## Timeline
|
||||
- 3-day clawback delay per committee charter
|
||||
- Reallocation within 7 days of execution
|
||||
|
||||
Actions:
|
||||
- type: clawback
|
||||
childId: 42
|
||||
token: USDC
|
||||
amount: 50000000000 # 50K USDC (6 decimals)
|
||||
reason: "Q4 budget reallocation"
|
||||
|
||||
- type: transfer
|
||||
to: grants_committee
|
||||
token: USDC
|
||||
amount: 50000000000
|
||||
```
|
||||
|
||||
### Method 3: Via SDK
|
||||
|
||||
```typescript
|
||||
import { HierarchyClient } from '@lux/dao-sdk';
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
const hierarchy = new HierarchyClient(signer);
|
||||
|
||||
// Initiate clawback
|
||||
const tx = await hierarchy.clawback(
|
||||
childId,
|
||||
usdcAddress,
|
||||
ethers.parseUnits('50000', 6), // 50K USDC
|
||||
'Q4 budget reallocation'
|
||||
);
|
||||
|
||||
const receipt = await tx.wait();
|
||||
const clawbackId = receipt.events[0].args.clawbackId;
|
||||
|
||||
console.log(`Clawback initiated: ${clawbackId}`);
|
||||
console.log(`Executes after: ${await hierarchy.clawbackExecutionTime(clawbackId)}`);
|
||||
```
|
||||
|
||||
## Smart Contract Interface
|
||||
|
||||
```solidity
|
||||
interface IHierarchy {
|
||||
/// @notice Emitted when clawback is initiated
|
||||
event ClawbackInitiated(
|
||||
uint256 indexed clawbackId,
|
||||
uint256 indexed childId,
|
||||
address token,
|
||||
uint256 amount,
|
||||
string reason,
|
||||
uint256 executeAfter
|
||||
);
|
||||
|
||||
/// @notice Emitted when clawback is executed
|
||||
event ClawbackExecuted(
|
||||
uint256 indexed clawbackId,
|
||||
uint256 indexed childId,
|
||||
address token,
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
/// @notice Emitted when clawback is cancelled
|
||||
event ClawbackCancelled(
|
||||
uint256 indexed clawbackId,
|
||||
string reason
|
||||
);
|
||||
|
||||
/// @notice Initiates a clawback with timelock
|
||||
/// @param childId Child node to recall from
|
||||
/// @param token Token address (address(0) for native)
|
||||
/// @param amount Amount to recall
|
||||
/// @param reason Documented reason
|
||||
/// @return clawbackId Unique identifier for this clawback
|
||||
function clawback(
|
||||
uint256 childId,
|
||||
address token,
|
||||
uint256 amount,
|
||||
string calldata reason
|
||||
) external returns (uint256 clawbackId);
|
||||
|
||||
/// @notice Executes a clawback after timelock
|
||||
/// @param clawbackId The clawback to execute
|
||||
function executeClawback(uint256 clawbackId) external;
|
||||
|
||||
/// @notice Cancels a pending clawback
|
||||
/// @param clawbackId The clawback to cancel
|
||||
/// @param reason Why it was cancelled
|
||||
function cancelClawback(
|
||||
uint256 clawbackId,
|
||||
string calldata reason
|
||||
) external;
|
||||
|
||||
/// @notice Returns clawback details
|
||||
function getClawback(uint256 clawbackId) external view returns (
|
||||
uint256 childId,
|
||||
address token,
|
||||
uint256 amount,
|
||||
string memory reason,
|
||||
uint256 executeAfter,
|
||||
bool executed,
|
||||
bool cancelled
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Clawback Lifecycle
|
||||
|
||||
### States
|
||||
|
||||
```
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ Pending │────▶│ Ready │────▶│ Executed │
|
||||
└──────────┘ └──────────┘ └──────────┘
|
||||
│ │
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────┐ ┌──────────┐
|
||||
│Cancelled │ │ Expired │
|
||||
└──────────┘ └──────────┘
|
||||
```
|
||||
|
||||
| State | Description |
|
||||
|-------|-------------|
|
||||
| Pending | Initiated, waiting for timelock |
|
||||
| Ready | Timelock passed, can be executed |
|
||||
| Executed | Funds transferred to parent |
|
||||
| Cancelled | Clawback cancelled before execution |
|
||||
| Expired | Not executed within grace period |
|
||||
|
||||
### Execution Window
|
||||
|
||||
After timelock, there's a window to execute:
|
||||
|
||||
```typescript
|
||||
const clawback = await hierarchy.getClawback(clawbackId);
|
||||
|
||||
// Can execute between these times
|
||||
const canExecuteAfter = clawback.executeAfter;
|
||||
const mustExecuteBefore = clawback.executeAfter + EXECUTION_WINDOW;
|
||||
|
||||
if (block.timestamp > mustExecuteBefore) {
|
||||
// Clawback expired, must reinitiate
|
||||
}
|
||||
```
|
||||
|
||||
## Child Response Options
|
||||
|
||||
When a clawback is initiated, the child can:
|
||||
|
||||
### 1. Accept and Prepare
|
||||
|
||||
```typescript
|
||||
// Child prepares for reduced budget
|
||||
await childTreasury.adjustBudgets(reducedAmount);
|
||||
```
|
||||
|
||||
### 2. Request Cancellation
|
||||
|
||||
Appeal to parent governance:
|
||||
|
||||
```yaml
|
||||
Proposal: "Cancel Clawback - Active Projects Need Funds"
|
||||
|
||||
Description: |
|
||||
The pending clawback of $50K would disrupt three active
|
||||
research projects. We request cancellation.
|
||||
|
||||
## Affected Projects
|
||||
1. Privacy Research - $20K committed
|
||||
2. Scalability Study - $15K committed
|
||||
3. Interop Analysis - $10K committed
|
||||
|
||||
## Alternative
|
||||
We propose returning $25K and retaining $25K for
|
||||
project completion.
|
||||
```
|
||||
|
||||
### 3. Emergency Use
|
||||
|
||||
If funds are legitimately needed:
|
||||
|
||||
```typescript
|
||||
// Child spends funds before execution
|
||||
// (only if within mandate - improper use is misconduct)
|
||||
await childTreasury.transfer(
|
||||
projectAddress,
|
||||
usdcAddress,
|
||||
amount,
|
||||
'Committed project funding'
|
||||
);
|
||||
```
|
||||
|
||||
## Cancelling a Clawback
|
||||
|
||||
### Via UI
|
||||
|
||||
1. Navigate to pending clawbacks
|
||||
2. Select the clawback
|
||||
3. Click **"Cancel Clawback"**
|
||||
4. Provide reason
|
||||
|
||||
### Via Proposal
|
||||
|
||||
```yaml
|
||||
Proposal: "Cancel Research Committee Clawback"
|
||||
|
||||
Description: |
|
||||
After reviewing the Research Committee's response, we
|
||||
agree to cancel the clawback and allow completion of
|
||||
current projects.
|
||||
|
||||
Actions:
|
||||
- type: cancel_clawback
|
||||
clawbackId: 123
|
||||
reason: "Active projects need completion funding"
|
||||
```
|
||||
|
||||
### Via SDK
|
||||
|
||||
```typescript
|
||||
await hierarchy.cancelClawback(
|
||||
clawbackId,
|
||||
'Projects need completion - agreed with child committee'
|
||||
);
|
||||
```
|
||||
|
||||
## Emergency Clawback
|
||||
|
||||
For urgent situations (security breach, misconduct):
|
||||
|
||||
```typescript
|
||||
// Emergency clawback bypasses normal timelock
|
||||
// Requires GUARDIAN_ROLE
|
||||
await hierarchy.emergencyClawback(
|
||||
childId,
|
||||
tokenAddress,
|
||||
amount,
|
||||
'Security incident - unauthorized access detected'
|
||||
);
|
||||
```
|
||||
|
||||
<Callout type="error">
|
||||
Emergency clawback should only be used for genuine emergencies. Misuse undermines trust in the hierarchy.
|
||||
</Callout>
|
||||
|
||||
## Clawback All Funds
|
||||
|
||||
For node dissolution:
|
||||
|
||||
```typescript
|
||||
// Recall all tokens from child treasury
|
||||
const balances = await hierarchy.getChildBalances(childId);
|
||||
|
||||
for (const balance of balances) {
|
||||
if (balance.amount > 0) {
|
||||
await hierarchy.clawback(
|
||||
childId,
|
||||
balance.token,
|
||||
balance.amount,
|
||||
'Node dissolution - returning all funds'
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Monitoring Clawbacks
|
||||
|
||||
### Dashboard View
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Pending Clawbacks │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ID Child Amount Executes Status │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ 123 Research Committee 50K USDC in 2 days Pending │
|
||||
│ 124 Regional Chapter 10K USDC in 5 days Pending │
|
||||
│ │
|
||||
│ [View Details] [Cancel] [Execute When Ready] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Event Monitoring
|
||||
|
||||
```typescript
|
||||
hierarchy.on('ClawbackInitiated', (id, childId, token, amount, reason) => {
|
||||
console.log(`Clawback ${id}: ${amount} from child ${childId}`);
|
||||
notifyChildAdmin(childId, 'clawback_initiated', { amount, reason });
|
||||
});
|
||||
|
||||
hierarchy.on('ClawbackExecuted', (id, childId, token, amount) => {
|
||||
console.log(`Clawback ${id} executed: ${amount} returned to parent`);
|
||||
});
|
||||
|
||||
hierarchy.on('ClawbackCancelled', (id, reason) => {
|
||||
console.log(`Clawback ${id} cancelled: ${reason}`);
|
||||
});
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Before Initiating
|
||||
|
||||
1. **Communicate** - Inform child leadership in advance
|
||||
2. **Document** - Clear rationale in the reason field
|
||||
3. **Consider alternatives** - Is clawback the right approach?
|
||||
4. **Verify amounts** - Check child treasury balances
|
||||
|
||||
### During Timelock
|
||||
|
||||
1. **Monitor** - Watch for child response
|
||||
2. **Be available** - Respond to questions/appeals
|
||||
3. **Review** - Reconsider if new information emerges
|
||||
|
||||
### After Execution
|
||||
|
||||
1. **Confirm receipt** - Verify funds in parent treasury
|
||||
2. **Reallocate** - Use funds as intended
|
||||
3. **Document** - Record in governance records
|
||||
4. **Follow up** - Address any child concerns
|
||||
|
||||
## Access Control
|
||||
|
||||
| Action | Required Permission |
|
||||
|--------|---------------------|
|
||||
| Initiate clawback | `ADMIN_ROLE` on parent |
|
||||
| Execute clawback | Any (after timelock) |
|
||||
| Cancel clawback | `ADMIN_ROLE` on parent |
|
||||
| Emergency clawback | `GUARDIAN_ROLE` |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `Unauthorized` | Missing admin role | Get proper permissions |
|
||||
| `ClawbackDisabled` | Config disables clawback | Cannot clawback this child |
|
||||
| `InsufficientBalance` | Child doesn't have funds | Reduce amount |
|
||||
| `TimelockNotPassed` | Too early to execute | Wait for timelock |
|
||||
| `ClawbackExpired` | Execution window passed | Reinitiate clawback |
|
||||
@@ -0,0 +1,343 @@
|
||||
---
|
||||
title: Freezing a Node
|
||||
description: Temporarily halt child node operations
|
||||
---
|
||||
|
||||
# Freezing a Node
|
||||
|
||||
Parent DAOs can freeze child nodes to temporarily halt all operations. This is a powerful oversight mechanism for emergencies or misconduct.
|
||||
|
||||
## Overview
|
||||
|
||||
When a node is frozen:
|
||||
|
||||
- All proposals are paused
|
||||
- Treasury transfers blocked
|
||||
- Voting halted
|
||||
- Administrative functions disabled
|
||||
|
||||
The node remains frozen until explicitly unfrozen by the parent.
|
||||
|
||||
## When to Freeze
|
||||
|
||||
### Appropriate Uses
|
||||
|
||||
- **Security breach** - Suspected compromise of node admin
|
||||
- **Misconduct** - Violation of charter or DAO policies
|
||||
- **Emergency** - Urgent situation requiring immediate halt
|
||||
- **Audit** - Temporary pause during investigation
|
||||
- **Transition** - Restructuring or leadership change
|
||||
|
||||
### Not Appropriate
|
||||
|
||||
- Policy disagreements (use governance instead)
|
||||
- Performance issues (address through regular channels)
|
||||
- Punitive action without cause
|
||||
- Avoiding legitimate proposals
|
||||
|
||||
<Callout type="warning">
|
||||
Freezing is a serious action. Use only when necessary and document the rationale clearly.
|
||||
</Callout>
|
||||
|
||||
## Freeze Methods
|
||||
|
||||
### Method 1: Via UI (Admin)
|
||||
|
||||
If you have admin role on the parent:
|
||||
|
||||
1. Navigate to **Organization** > **Hierarchy**
|
||||
2. Select the child node
|
||||
3. Click **"Freeze Node"**
|
||||
4. Confirm the action
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Freeze Node: Research Committee │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ⚠️ This will immediately halt all operations │
|
||||
│ │
|
||||
│ Effects: │
|
||||
│ • All active proposals paused │
|
||||
│ • Treasury transfers blocked │
|
||||
│ • New proposals cannot be created │
|
||||
│ • Voting on pending items halted │
|
||||
│ │
|
||||
│ Reason (required): │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Security concern - investigating unauthorized │ │
|
||||
│ │ access to committee admin wallet. │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ [ Cancel ] [ Freeze Node ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Method 2: Via Proposal
|
||||
|
||||
For non-emergency situations or when admin prefers governance:
|
||||
|
||||
```yaml
|
||||
Proposal: "Freeze Research Committee Pending Audit"
|
||||
|
||||
Description: |
|
||||
This proposal freezes the Research Committee while an
|
||||
audit of recent grant disbursements is conducted.
|
||||
|
||||
## Rationale
|
||||
Concerns have been raised about several recent grants
|
||||
that may not align with the committee charter.
|
||||
|
||||
## Duration
|
||||
Expected freeze: 2 weeks pending audit results
|
||||
|
||||
## Next Steps
|
||||
1. Audit committee reviews transactions
|
||||
2. Findings presented to parent DAO
|
||||
3. Unfreeze proposal if cleared
|
||||
4. Corrective action if issues found
|
||||
|
||||
Actions:
|
||||
- type: freeze
|
||||
childId: 42
|
||||
reason: "Audit of grant disbursements"
|
||||
```
|
||||
|
||||
### Method 3: Via SDK
|
||||
|
||||
```typescript
|
||||
import { HierarchyClient } from '@lux/dao-sdk';
|
||||
|
||||
const hierarchy = new HierarchyClient(signer);
|
||||
|
||||
// Freeze a child node
|
||||
const tx = await hierarchy.freeze(
|
||||
childId,
|
||||
'Security concern - investigating unauthorized access'
|
||||
);
|
||||
|
||||
await tx.wait();
|
||||
console.log('Node frozen');
|
||||
|
||||
// Check freeze status
|
||||
const isFrozen = await hierarchy.isFrozen(childId);
|
||||
console.log(`Frozen: ${isFrozen}`);
|
||||
```
|
||||
|
||||
## Smart Contract Interface
|
||||
|
||||
```solidity
|
||||
interface IHierarchy {
|
||||
/// @notice Emitted when a node is frozen
|
||||
event NodeFrozen(
|
||||
uint256 indexed nodeId,
|
||||
address indexed freezer,
|
||||
string reason,
|
||||
uint256 timestamp
|
||||
);
|
||||
|
||||
/// @notice Emitted when a node is unfrozen
|
||||
event NodeUnfrozen(
|
||||
uint256 indexed nodeId,
|
||||
address indexed unfreezer,
|
||||
uint256 timestamp
|
||||
);
|
||||
|
||||
/// @notice Freezes a child node
|
||||
/// @param childId The child node to freeze
|
||||
/// @param reason Documented reason for freezing
|
||||
function freeze(uint256 childId, string calldata reason) external;
|
||||
|
||||
/// @notice Unfreezes a previously frozen child
|
||||
/// @param childId The child node to unfreeze
|
||||
function unfreeze(uint256 childId) external;
|
||||
|
||||
/// @notice Returns true if node is frozen
|
||||
function isFrozen(uint256 nodeId) external view returns (bool);
|
||||
|
||||
/// @notice Returns freeze info for a node
|
||||
function freezeInfo(uint256 nodeId) external view returns (
|
||||
bool frozen,
|
||||
address frozenBy,
|
||||
uint256 frozenAt,
|
||||
string memory reason
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Effects of Freezing
|
||||
|
||||
### Immediate Effects
|
||||
|
||||
| Operation | Status | Details |
|
||||
|-----------|--------|---------|
|
||||
| Proposals | Paused | Cannot create new, voting halted |
|
||||
| Treasury | Blocked | All transfers disabled |
|
||||
| Roles | Locked | Cannot add/remove members |
|
||||
| Settings | Locked | Configuration changes blocked |
|
||||
| Children | Unaffected | Sub-nodes continue (unless cascaded) |
|
||||
|
||||
### What Still Works
|
||||
|
||||
- Read-only operations (viewing proposals, balances)
|
||||
- Parent administrative functions
|
||||
- Event logging
|
||||
- Emergency contacts
|
||||
|
||||
### Cascade Option
|
||||
|
||||
Optionally freeze all descendants:
|
||||
|
||||
```typescript
|
||||
// Freeze node and all children
|
||||
await hierarchy.freezeCascade(childId, 'Parent freeze - cascade');
|
||||
```
|
||||
|
||||
## Unfreezing a Node
|
||||
|
||||
### Via UI
|
||||
|
||||
1. Navigate to frozen node
|
||||
2. Click **"Unfreeze Node"**
|
||||
3. Confirm the action
|
||||
|
||||
### Via Proposal
|
||||
|
||||
```yaml
|
||||
Proposal: "Unfreeze Research Committee - Audit Complete"
|
||||
|
||||
Description: |
|
||||
The audit has been completed with no issues found.
|
||||
This proposal unfreezes the Research Committee.
|
||||
|
||||
## Audit Results
|
||||
- All 15 grants reviewed
|
||||
- No policy violations found
|
||||
- Recommendations for improved documentation
|
||||
|
||||
Actions:
|
||||
- type: unfreeze
|
||||
childId: 42
|
||||
```
|
||||
|
||||
### Via SDK
|
||||
|
||||
```typescript
|
||||
const tx = await hierarchy.unfreeze(childId);
|
||||
await tx.wait();
|
||||
console.log('Node unfrozen');
|
||||
```
|
||||
|
||||
## Freeze Duration
|
||||
|
||||
### Recommended Limits
|
||||
|
||||
| Situation | Duration | Action |
|
||||
|-----------|----------|--------|
|
||||
| Security investigation | 1-2 weeks | Unfreeze or escalate |
|
||||
| Audit | 2-4 weeks | Unfreeze or restructure |
|
||||
| Misconduct | Until resolved | May lead to dissolution |
|
||||
| Emergency | 24-72 hours | Quick resolution required |
|
||||
|
||||
### Automatic Unfreeze (Optional)
|
||||
|
||||
Some implementations support time-limited freezes:
|
||||
|
||||
```typescript
|
||||
// Freeze for 7 days
|
||||
await hierarchy.freezeWithExpiry(
|
||||
childId,
|
||||
'Temporary pause for review',
|
||||
7 * 24 * 60 * 60 // 7 days in seconds
|
||||
);
|
||||
```
|
||||
|
||||
## Monitoring Frozen Nodes
|
||||
|
||||
### Dashboard View
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Organization Hierarchy │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ▼ Root DAO │
|
||||
│ │ │
|
||||
│ ├── Treasury Committee ● Active │
|
||||
│ │ │
|
||||
│ ├── Research Committee ⏸ Frozen (3 days) │
|
||||
│ │ └── Reason: Audit of grant disbursements │
|
||||
│ │ │
|
||||
│ └── Grants Committee ● Active │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Event Monitoring
|
||||
|
||||
```typescript
|
||||
// Listen for freeze events
|
||||
hierarchy.on('NodeFrozen', (nodeId, freezer, reason, timestamp) => {
|
||||
console.log(`Node ${nodeId} frozen by ${freezer}`);
|
||||
console.log(`Reason: ${reason}`);
|
||||
|
||||
// Alert stakeholders
|
||||
notifyAdmin(nodeId, 'frozen', reason);
|
||||
});
|
||||
|
||||
hierarchy.on('NodeUnfrozen', (nodeId, unfreezer, timestamp) => {
|
||||
console.log(`Node ${nodeId} unfrozen by ${unfreezer}`);
|
||||
});
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Before Freezing
|
||||
|
||||
1. **Document the reason** - Clear, specific rationale
|
||||
2. **Notify stakeholders** - Inform child node admins
|
||||
3. **Set expectations** - Timeline and next steps
|
||||
4. **Prepare resolution path** - How to unfreeze
|
||||
|
||||
### During Freeze
|
||||
|
||||
1. **Regular updates** - Keep affected parties informed
|
||||
2. **Active investigation** - Work toward resolution
|
||||
3. **Time limit** - Don't leave frozen indefinitely
|
||||
4. **Escalate if needed** - Involve higher governance
|
||||
|
||||
### After Unfreezing
|
||||
|
||||
1. **Post-mortem** - Document lessons learned
|
||||
2. **Process improvements** - Prevent recurrence
|
||||
3. **Communicate resolution** - Public transparency
|
||||
4. **Monitor closely** - Ensure normal operation
|
||||
|
||||
## Access Control
|
||||
|
||||
| Action | Required Permission |
|
||||
|--------|---------------------|
|
||||
| Freeze | `ADMIN_ROLE` on parent |
|
||||
| Unfreeze | `ADMIN_ROLE` on parent |
|
||||
| View freeze status | Any (public) |
|
||||
| Emergency freeze | `GUARDIAN_ROLE` |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Cannot Freeze
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `Unauthorized` | Missing admin role | Get proper permissions |
|
||||
| `NotChild` | Node is not a child | Check hierarchy |
|
||||
| `AlreadyFrozen` | Already frozen | No action needed |
|
||||
| `FreezeDisabled` | Config disables freeze | Update child config |
|
||||
|
||||
### Cannot Unfreeze
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `Unauthorized` | Missing admin role | Get proper permissions |
|
||||
| `NotFrozen` | Node is not frozen | No action needed |
|
||||
| `TimelockActive` | Waiting period | Wait for timelock |
|
||||
@@ -0,0 +1,290 @@
|
||||
---
|
||||
title: Project Hierarchy
|
||||
description: Create and manage sub-DAOs with parent-child relationships
|
||||
---
|
||||
|
||||
# Project Hierarchy
|
||||
|
||||
DAOs can create sub-organizations (child nodes) to delegate authority, organize working groups, and manage specialized functions while maintaining oversight from the parent.
|
||||
|
||||
## Overview
|
||||
|
||||
The hierarchy system enables:
|
||||
|
||||
- **Delegation** - Parent DAOs delegate specific responsibilities to sub-DAOs
|
||||
- **Autonomy** - Child nodes operate independently within defined boundaries
|
||||
- **Oversight** - Parent retains control mechanisms (freeze, clawback)
|
||||
- **Scalability** - Large organizations decompose into manageable units
|
||||
|
||||
## Hierarchy Structure
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Root DAO │
|
||||
│ (Top-level) │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌────────────────┼────────────────┐
|
||||
│ │ │
|
||||
┌───────▼──────┐ ┌───────▼──────┐ ┌───────▼──────┐
|
||||
│ Treasury │ │ Grants │ │ Research │
|
||||
│ Committee │ │ Committee │ │ Committee │
|
||||
└───────┬──────┘ └───────┬──────┘ └──────────────┘
|
||||
│ │
|
||||
┌───────▼──────┐ ┌───────▼──────┐
|
||||
│ Audit │ │ Regional │
|
||||
│ Working Grp │ │ Chapter │
|
||||
└──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Parent-Child Relationships
|
||||
|
||||
| Aspect | Parent | Child |
|
||||
|--------|--------|-------|
|
||||
| Creation | Creates child nodes | Created by parent |
|
||||
| Funding | Allocates budget | Receives allocation |
|
||||
| Governance | Sets boundaries | Operates within limits |
|
||||
| Control | Can freeze/clawback | Subject to parent rules |
|
||||
| Proposals | Can override child | Escalates major decisions |
|
||||
|
||||
### Node Types
|
||||
|
||||
**Root DAO**
|
||||
- Top-level governance entity
|
||||
- No parent (fully sovereign)
|
||||
- Controls all descendant nodes
|
||||
|
||||
**Committee**
|
||||
- Specialized working group
|
||||
- Has defined scope and budget
|
||||
- Reports to parent
|
||||
|
||||
**Working Group**
|
||||
- Temporary or permanent team
|
||||
- Task-specific mandate
|
||||
- Minimal bureaucracy
|
||||
|
||||
**Regional Chapter**
|
||||
- Geographic organization
|
||||
- Local autonomy
|
||||
- Coordinates with siblings
|
||||
|
||||
## Smart Contract Interface
|
||||
|
||||
### IHierarchy
|
||||
|
||||
```solidity
|
||||
interface IHierarchy {
|
||||
/// @notice Creates a new child node under the caller's DAO
|
||||
/// @param name Display name for the child
|
||||
/// @param admin Initial admin address
|
||||
/// @param config Governance configuration
|
||||
/// @return childId The ID of the created child node
|
||||
function createChild(
|
||||
string calldata name,
|
||||
address admin,
|
||||
NodeConfig calldata config
|
||||
) external returns (uint256 childId);
|
||||
|
||||
/// @notice Freezes a child node, halting all operations
|
||||
/// @param childId The child to freeze
|
||||
function freeze(uint256 childId) external;
|
||||
|
||||
/// @notice Unfreezes a previously frozen child
|
||||
/// @param childId The child to unfreeze
|
||||
function unfreeze(uint256 childId) external;
|
||||
|
||||
/// @notice Recalls funds from a child node to parent treasury
|
||||
/// @param childId The child to recall from
|
||||
/// @param token Token address (address(0) for native)
|
||||
/// @param amount Amount to recall
|
||||
function clawback(
|
||||
uint256 childId,
|
||||
address token,
|
||||
uint256 amount
|
||||
) external;
|
||||
|
||||
/// @notice Returns the parent of a node
|
||||
function parent(uint256 nodeId) external view returns (uint256);
|
||||
|
||||
/// @notice Returns all children of a node
|
||||
function children(uint256 nodeId) external view returns (uint256[] memory);
|
||||
|
||||
/// @notice Returns true if node is frozen
|
||||
function isFrozen(uint256 nodeId) external view returns (bool);
|
||||
}
|
||||
```
|
||||
|
||||
### NodeConfig
|
||||
|
||||
```solidity
|
||||
struct NodeConfig {
|
||||
// Governance
|
||||
uint256 votingPeriod; // Duration of voting in seconds
|
||||
uint256 quorum; // Minimum participation required
|
||||
uint256 threshold; // Approval threshold (basis points)
|
||||
|
||||
// Permissions
|
||||
bool canCreateChildren; // Can this node create sub-nodes
|
||||
bool canTransferExternal; // Can transfer outside hierarchy
|
||||
uint256 spendingLimit; // Max single transaction (0 = unlimited)
|
||||
|
||||
// Control
|
||||
bool parentCanFreeze; // Parent can freeze this node
|
||||
bool parentCanClawback; // Parent can recall funds
|
||||
uint256 clawbackDelay; // Delay before clawback executes
|
||||
}
|
||||
```
|
||||
|
||||
## Hierarchy Operations
|
||||
|
||||
<Cards>
|
||||
<Card title="Create Sub-DAO" href="/docs/guide/hierarchy/node-creation" icon="plus-circle">
|
||||
Spawn child nodes for delegation
|
||||
</Card>
|
||||
<Card title="Freeze Node" href="/docs/guide/hierarchy/freezing" icon="pause-circle">
|
||||
Temporarily halt child operations
|
||||
</Card>
|
||||
<Card title="Clawback Funds" href="/docs/guide/hierarchy/clawback" icon="rotate-ccw">
|
||||
Recall funds from child treasury
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Grants Program
|
||||
|
||||
```yaml
|
||||
Structure:
|
||||
- Grants Committee (parent)
|
||||
- Review Panel (evaluates applications)
|
||||
- Disbursement (handles payments)
|
||||
- Monitoring (tracks outcomes)
|
||||
|
||||
Delegation:
|
||||
- Committee approves grants > $10K
|
||||
- Review Panel handles < $10K
|
||||
- Disbursement executes all payments
|
||||
```
|
||||
|
||||
### Regional Organization
|
||||
|
||||
```yaml
|
||||
Structure:
|
||||
- Global DAO (parent)
|
||||
- North America Chapter
|
||||
- Europe Chapter
|
||||
- Asia-Pacific Chapter
|
||||
|
||||
Autonomy:
|
||||
- Local events and community
|
||||
- Regional partnerships
|
||||
- Local treasury management
|
||||
|
||||
Coordination:
|
||||
- Global initiatives
|
||||
- Cross-regional projects
|
||||
- Shared resources
|
||||
```
|
||||
|
||||
### Treasury Management
|
||||
|
||||
```yaml
|
||||
Structure:
|
||||
- Treasury DAO (parent)
|
||||
- Investment Committee
|
||||
- Operations Budget
|
||||
- Emergency Reserve
|
||||
|
||||
Controls:
|
||||
- Investment: 30-day clawback delay
|
||||
- Operations: No clawback (autonomous)
|
||||
- Reserve: Instant clawback (parent-controlled)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Do
|
||||
|
||||
- Define clear mandates for each child
|
||||
- Set appropriate spending limits
|
||||
- Document escalation procedures
|
||||
- Regular oversight and reporting
|
||||
- Test governance before funding
|
||||
|
||||
### Don't
|
||||
|
||||
- Create overly deep hierarchies (3 levels max recommended)
|
||||
- Give children unlimited spending
|
||||
- Disable all parent controls
|
||||
- Create duplicate responsibilities
|
||||
- Neglect monitoring
|
||||
|
||||
## Security Considerations
|
||||
|
||||
<Callout type="warning">
|
||||
Parent control mechanisms are powerful. Ensure proper governance before enabling freeze and clawback capabilities.
|
||||
</Callout>
|
||||
|
||||
### Access Control
|
||||
|
||||
| Action | Required Permission |
|
||||
|--------|---------------------|
|
||||
| Create child | `ADMIN_ROLE` on parent |
|
||||
| Freeze child | `ADMIN_ROLE` on parent |
|
||||
| Clawback | Proposal + timelock |
|
||||
| Unfreeze | `ADMIN_ROLE` on parent |
|
||||
|
||||
### Risk Mitigation
|
||||
|
||||
1. **Multi-sig for parent admin** - Prevent single-point failures
|
||||
2. **Timelock on clawback** - Give child time to respond
|
||||
3. **Clear termination criteria** - Define when freeze/clawback is appropriate
|
||||
4. **Audit trail** - Log all hierarchy operations
|
||||
|
||||
## Integration Examples
|
||||
|
||||
### Creating a Committee via Proposal
|
||||
|
||||
```yaml
|
||||
Proposal: "Create Research Committee"
|
||||
|
||||
Actions:
|
||||
- type: create_child
|
||||
name: "Research Committee"
|
||||
admin: 0x1234...
|
||||
config:
|
||||
votingPeriod: 604800 # 7 days
|
||||
quorum: 1000000 # 1M tokens
|
||||
threshold: 5000 # 50%
|
||||
canCreateChildren: false
|
||||
canTransferExternal: true
|
||||
spendingLimit: 50000000000 # $50K USDC
|
||||
parentCanFreeze: true
|
||||
parentCanClawback: true
|
||||
clawbackDelay: 259200 # 3 days
|
||||
|
||||
- type: transfer
|
||||
to: research_committee
|
||||
amount: 100000
|
||||
token: USDC
|
||||
```
|
||||
|
||||
### Querying Hierarchy
|
||||
|
||||
```typescript
|
||||
import { HierarchyClient } from '@lux/dao-sdk';
|
||||
|
||||
const hierarchy = new HierarchyClient(provider);
|
||||
|
||||
// Get all children of root DAO
|
||||
const children = await hierarchy.children(ROOT_DAO_ID);
|
||||
|
||||
// Check if node is frozen
|
||||
const frozen = await hierarchy.isFrozen(childId);
|
||||
|
||||
// Get parent chain to root
|
||||
const ancestors = await hierarchy.getAncestors(nodeId);
|
||||
```
|
||||
@@ -0,0 +1,398 @@
|
||||
---
|
||||
title: Creating Sub-DAOs
|
||||
description: How to create child nodes and delegate authority
|
||||
---
|
||||
|
||||
# Creating Sub-DAOs
|
||||
|
||||
Sub-DAOs (child nodes) allow parent organizations to delegate specific functions while maintaining oversight. This guide covers creating and configuring child nodes.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before creating a sub-DAO:
|
||||
|
||||
- Admin role on parent DAO
|
||||
- Clear mandate and scope defined
|
||||
- Initial funding approved
|
||||
- Admin address ready
|
||||
|
||||
## Creation Methods
|
||||
|
||||
### Method 1: Via UI
|
||||
|
||||
#### Step 1: Navigate to Hierarchy
|
||||
|
||||
1. Go to your DAO dashboard
|
||||
2. Click **"Organization"** in the sidebar
|
||||
3. Click **"Create Sub-DAO"**
|
||||
|
||||
#### Step 2: Configure Basic Info
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Create Sub-DAO │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Name: [Research Committee ] │
|
||||
│ │
|
||||
│ Description: [Funds and coordinates research ] │
|
||||
│ [initiatives across the ecosystem ] │
|
||||
│ │
|
||||
│ Admin: [0x1234...5678 ] │
|
||||
│ │
|
||||
│ Type: ( ) Committee │
|
||||
│ (•) Working Group │
|
||||
│ ( ) Regional Chapter │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Step 3: Set Governance Parameters
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Governance Settings │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Voting Period: [7 ] days │
|
||||
│ │
|
||||
│ Quorum: [1,000,000] tokens (10% of supply) │
|
||||
│ │
|
||||
│ Approval: [50 ] % │
|
||||
│ │
|
||||
│ Proposal Threshold: [10,000] tokens to create │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ ℹ️ Lower thresholds = more proposals │ │
|
||||
│ │ Higher quorum = stronger mandate │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Step 4: Configure Permissions
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Permissions │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ [✓] Can create child nodes │
|
||||
│ └── Allow this sub-DAO to create its own children │
|
||||
│ │
|
||||
│ [✓] Can transfer externally │
|
||||
│ └── Send funds outside the hierarchy │
|
||||
│ │
|
||||
│ Spending Limit: [$50,000] per transaction │
|
||||
│ └── 0 = unlimited │
|
||||
│ │
|
||||
│ ────────────────────────────────────────────────────── │
|
||||
│ Parent Controls │
|
||||
│ ────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ [✓] Parent can freeze │
|
||||
│ └── Allow parent to halt operations │
|
||||
│ │
|
||||
│ [✓] Parent can clawback │
|
||||
│ └── Allow parent to recall funds │
|
||||
│ │
|
||||
│ Clawback Delay: [3 ] days │
|
||||
│ └── Notice period before funds recalled │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Step 5: Initial Funding (Optional)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Initial Funding │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ [✓] Fund on creation │
|
||||
│ │
|
||||
│ Token: [USDC ▼] │
|
||||
│ Amount: [100,000 ] │
|
||||
│ │
|
||||
│ Available in parent treasury: 500,000 USDC │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ + Add another token │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Step 6: Review and Submit
|
||||
|
||||
1. Click **"Preview"** to review configuration
|
||||
2. Verify all settings are correct
|
||||
3. Click **"Create Sub-DAO"**
|
||||
4. Sign the transaction
|
||||
|
||||
### Method 2: Via Proposal
|
||||
|
||||
For larger organizations, creation should go through governance:
|
||||
|
||||
```yaml
|
||||
Proposal: "Create Research Committee Sub-DAO"
|
||||
|
||||
Description: |
|
||||
This proposal creates a Research Committee to coordinate
|
||||
and fund research initiatives.
|
||||
|
||||
## Mandate
|
||||
- Evaluate research proposals
|
||||
- Fund approved projects up to $50K
|
||||
- Track research outcomes
|
||||
- Report quarterly to parent
|
||||
|
||||
## Budget
|
||||
Initial funding: $100,000 USDC
|
||||
Quarterly allocation: $25,000 USDC
|
||||
|
||||
## Leadership
|
||||
Initial Admin: research-lead.eth (0x1234...)
|
||||
|
||||
Actions:
|
||||
- type: create_child
|
||||
name: "Research Committee"
|
||||
admin: "0x1234..."
|
||||
config:
|
||||
votingPeriod: 604800
|
||||
quorum: 1000000
|
||||
threshold: 5000
|
||||
canCreateChildren: false
|
||||
canTransferExternal: true
|
||||
spendingLimit: 50000000000
|
||||
parentCanFreeze: true
|
||||
parentCanClawback: true
|
||||
clawbackDelay: 259200
|
||||
|
||||
- type: transfer
|
||||
to: ${newChild}
|
||||
amount: 100000
|
||||
token: USDC
|
||||
```
|
||||
|
||||
### Method 3: Via SDK
|
||||
|
||||
```typescript
|
||||
import { HierarchyClient, NodeConfig } from '@lux/dao-sdk';
|
||||
|
||||
const hierarchy = new HierarchyClient(signer);
|
||||
|
||||
// Configure the child node
|
||||
const config: NodeConfig = {
|
||||
votingPeriod: 7 * 24 * 60 * 60, // 7 days
|
||||
quorum: ethers.parseUnits('1000000', 18),
|
||||
threshold: 5000, // 50% in basis points
|
||||
canCreateChildren: false,
|
||||
canTransferExternal: true,
|
||||
spendingLimit: ethers.parseUnits('50000', 6), // 50K USDC
|
||||
parentCanFreeze: true,
|
||||
parentCanClawback: true,
|
||||
clawbackDelay: 3 * 24 * 60 * 60, // 3 days
|
||||
};
|
||||
|
||||
// Create the child
|
||||
const tx = await hierarchy.createChild(
|
||||
'Research Committee',
|
||||
'0x1234...admin',
|
||||
config
|
||||
);
|
||||
|
||||
const receipt = await tx.wait();
|
||||
const childId = receipt.events[0].args.childId;
|
||||
|
||||
console.log(`Created child node: ${childId}`);
|
||||
```
|
||||
|
||||
## Configuration Reference
|
||||
|
||||
### Governance Parameters
|
||||
|
||||
| Parameter | Description | Recommended |
|
||||
|-----------|-------------|-------------|
|
||||
| `votingPeriod` | Duration of voting | 3-14 days |
|
||||
| `quorum` | Minimum participation | 5-20% of supply |
|
||||
| `threshold` | Approval percentage | 50-67% |
|
||||
| `proposalThreshold` | Tokens to propose | 0.1-1% of supply |
|
||||
|
||||
### Permission Flags
|
||||
|
||||
| Flag | Default | Description |
|
||||
|------|---------|-------------|
|
||||
| `canCreateChildren` | false | Create nested sub-DAOs |
|
||||
| `canTransferExternal` | true | Send funds outside hierarchy |
|
||||
| `spendingLimit` | 0 | Max per-transaction (0 = unlimited) |
|
||||
|
||||
### Parent Controls
|
||||
|
||||
| Control | Default | Description |
|
||||
|---------|---------|-------------|
|
||||
| `parentCanFreeze` | true | Parent can halt operations |
|
||||
| `parentCanClawback` | true | Parent can recall funds |
|
||||
| `clawbackDelay` | 3 days | Notice before clawback |
|
||||
|
||||
## Post-Creation Setup
|
||||
|
||||
After creating a sub-DAO:
|
||||
|
||||
### 1. Configure Roles
|
||||
|
||||
```yaml
|
||||
Roles to create:
|
||||
- Admin: Full management (multi-sig recommended)
|
||||
- Lead: Create proposals, manage budget
|
||||
- Member: Vote, participate
|
||||
- Observer: Read-only access
|
||||
```
|
||||
|
||||
### 2. Set Up Committees
|
||||
|
||||
If the sub-DAO will have its own working groups:
|
||||
|
||||
```yaml
|
||||
Working Groups:
|
||||
- Review Panel
|
||||
- Evaluates incoming proposals
|
||||
- 3-5 members
|
||||
- Operations
|
||||
- Handles day-to-day
|
||||
- 2-3 members
|
||||
```
|
||||
|
||||
### 3. Document Mandate
|
||||
|
||||
Create a charter document:
|
||||
|
||||
```markdown
|
||||
# Research Committee Charter
|
||||
|
||||
## Purpose
|
||||
Fund and coordinate ecosystem research.
|
||||
|
||||
## Scope
|
||||
- Academic research partnerships
|
||||
- Technical research grants
|
||||
- Industry analysis
|
||||
|
||||
## Out of Scope
|
||||
- Product development
|
||||
- Marketing research
|
||||
- Operational expenses
|
||||
|
||||
## Budget
|
||||
- Quarterly allocation: $25,000
|
||||
- Single grant limit: $50,000
|
||||
- Emergency reserve: $10,000
|
||||
|
||||
## Governance
|
||||
- Voting period: 7 days
|
||||
- Quorum: 10%
|
||||
- Approval: 50%
|
||||
|
||||
## Reporting
|
||||
- Monthly activity report
|
||||
- Quarterly budget review
|
||||
- Annual impact assessment
|
||||
```
|
||||
|
||||
### 4. Fund the Treasury
|
||||
|
||||
Transfer initial operating funds:
|
||||
|
||||
```typescript
|
||||
// From parent DAO
|
||||
await treasury.transfer(
|
||||
childAddress,
|
||||
usdc.address,
|
||||
ethers.parseUnits('100000', 6),
|
||||
'Initial Research Committee funding'
|
||||
);
|
||||
```
|
||||
|
||||
## Common Configurations
|
||||
|
||||
### Autonomous Committee
|
||||
|
||||
High autonomy, minimal parent control:
|
||||
|
||||
```typescript
|
||||
const autonomousConfig: NodeConfig = {
|
||||
votingPeriod: 604800,
|
||||
quorum: ethers.parseUnits('500000', 18),
|
||||
threshold: 5000,
|
||||
canCreateChildren: true,
|
||||
canTransferExternal: true,
|
||||
spendingLimit: 0, // Unlimited
|
||||
parentCanFreeze: false, // Cannot freeze
|
||||
parentCanClawback: false, // Cannot clawback
|
||||
clawbackDelay: 0,
|
||||
};
|
||||
```
|
||||
|
||||
### Controlled Working Group
|
||||
|
||||
Limited autonomy, strong oversight:
|
||||
|
||||
```typescript
|
||||
const controlledConfig: NodeConfig = {
|
||||
votingPeriod: 259200, // 3 days
|
||||
quorum: ethers.parseUnits('100000', 18),
|
||||
threshold: 5000,
|
||||
canCreateChildren: false,
|
||||
canTransferExternal: false, // Internal only
|
||||
spendingLimit: ethers.parseUnits('10000', 6),
|
||||
parentCanFreeze: true,
|
||||
parentCanClawback: true,
|
||||
clawbackDelay: 86400, // 1 day
|
||||
};
|
||||
```
|
||||
|
||||
### Regional Chapter
|
||||
|
||||
Balanced autonomy with coordination:
|
||||
|
||||
```typescript
|
||||
const chapterConfig: NodeConfig = {
|
||||
votingPeriod: 604800,
|
||||
quorum: ethers.parseUnits('200000', 18),
|
||||
threshold: 5000,
|
||||
canCreateChildren: true, // Can create local groups
|
||||
canTransferExternal: true,
|
||||
spendingLimit: ethers.parseUnits('25000', 6),
|
||||
parentCanFreeze: true,
|
||||
parentCanClawback: true,
|
||||
clawbackDelay: 604800, // 7 days notice
|
||||
};
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Creation Failed
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `Unauthorized` | Missing admin role | Get admin permission |
|
||||
| `InvalidConfig` | Bad parameters | Check config values |
|
||||
| `InsufficientFunds` | Not enough for initial funding | Reduce or skip funding |
|
||||
| `MaxDepthExceeded` | Too many hierarchy levels | Create at higher level |
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Child not visible in UI:**
|
||||
- Wait for transaction confirmation
|
||||
- Refresh the page
|
||||
- Check the transaction succeeded
|
||||
|
||||
**Cannot transfer funds:**
|
||||
- Verify child has treasury address
|
||||
- Check spending limits
|
||||
- Confirm transfer is within scope
|
||||
|
||||
**Governance not working:**
|
||||
- Verify token distribution
|
||||
- Check quorum settings
|
||||
- Ensure voting period started
|
||||
@@ -0,0 +1,129 @@
|
||||
---
|
||||
title: User Guide
|
||||
description: Complete guide to participating in DAO governance
|
||||
---
|
||||
|
||||
# User Guide
|
||||
|
||||
This comprehensive guide covers everything you need to participate in DAO governance, from basic concepts to advanced features.
|
||||
|
||||
## Getting Started
|
||||
|
||||
<Steps>
|
||||
<Step title="Connect Your Wallet">
|
||||
Connect a supported wallet like MetaMask, WalletConnect, or a hardware wallet.
|
||||
</Step>
|
||||
<Step title="Acquire Governance Tokens">
|
||||
Purchase or earn tokens through bonding, staking, or community participation.
|
||||
</Step>
|
||||
<Step title="Lock for Voting Power">
|
||||
Lock tokens to receive vote-escrowed tokens with voting power.
|
||||
</Step>
|
||||
<Step title="Participate">
|
||||
Vote on proposals, join committees, and contribute to governance.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Guide Sections
|
||||
|
||||
### Fundamentals
|
||||
|
||||
<Cards>
|
||||
<Card title="Getting Started" href="/docs/guide/getting-started" icon="play">
|
||||
Learn the basics and set up your account
|
||||
</Card>
|
||||
<Card title="Governance Types" href="/docs/guide/getting-started/governance-types" icon="git-branch">
|
||||
Understand different governance models
|
||||
</Card>
|
||||
<Card title="Creating a Project" href="/docs/guide/getting-started/creating-committee" icon="plus-circle">
|
||||
Set up your first DAO or committee
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### Proposals & Voting
|
||||
|
||||
<Cards>
|
||||
<Card title="Creating Proposals" href="/docs/guide/resolutions" icon="file-plus">
|
||||
Submit governance proposals
|
||||
</Card>
|
||||
<Card title="Voting" href="/docs/guide/voting" icon="check-square">
|
||||
Cast votes and participate in decisions
|
||||
</Card>
|
||||
<Card title="Delegation" href="/docs/guide/voting/delegation" icon="users">
|
||||
Delegate your voting power
|
||||
</Card>
|
||||
<Card title="Execution" href="/docs/guide/voting/execution" icon="play-circle">
|
||||
Execute passed proposals
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### Organization
|
||||
|
||||
<Cards>
|
||||
<Card title="Roles" href="/docs/guide/roles" icon="shield">
|
||||
Create and manage roles
|
||||
</Card>
|
||||
<Card title="Treasury" href="/docs/guide/treasury" icon="vault">
|
||||
Manage community funds
|
||||
</Card>
|
||||
<Card title="Hierarchy" href="/docs/guide/hierarchy" icon="git-merge">
|
||||
Sub-DAOs and working groups
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### Payments & Finance
|
||||
|
||||
<Cards>
|
||||
<Card title="Payments" href="/docs/guide/payments" icon="send">
|
||||
Airdrops, streams, and transfers
|
||||
</Card>
|
||||
<Card title="Staking" href="/docs/guide/staking" icon="lock">
|
||||
Stake tokens for rewards
|
||||
</Card>
|
||||
<Card title="Distributions" href="/docs/guide/distributions" icon="pie-chart">
|
||||
Asset distribution splits
|
||||
</Card>
|
||||
<Card title="Token Sales" href="/docs/guide/token-sales" icon="trending-up">
|
||||
Conduct token sales
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### Advanced
|
||||
|
||||
<Cards>
|
||||
<Card title="Gasless Voting" href="/docs/guide/gasless" icon="zap">
|
||||
Vote without gas fees
|
||||
</Card>
|
||||
<Card title="Multisig" href="/docs/guide/multisig" icon="key">
|
||||
Multi-signature operations
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Proposal Lifecycle
|
||||
|
||||
| Stage | Duration | Description |
|
||||
|-------|----------|-------------|
|
||||
| Draft | 7 days | Community feedback period |
|
||||
| Review | 3 days | Formal review before voting |
|
||||
| Voting | 7 days | Active voting period |
|
||||
| Timelock | 1-14 days | Delay before execution |
|
||||
| Execution | - | Proposal effects applied |
|
||||
|
||||
### Voting Thresholds
|
||||
|
||||
| Type | Quorum | Approval | Timelock |
|
||||
|------|--------|----------|----------|
|
||||
| Standard | 1M tokens | 50% | 3 days |
|
||||
| Constitutional | 5M tokens | 67% | 14 days |
|
||||
| Emergency | 500K tokens | 75% | None |
|
||||
|
||||
### Role Permissions
|
||||
|
||||
| Level | Spending | Requires |
|
||||
|-------|----------|----------|
|
||||
| Member | $0 | Join committee |
|
||||
| Contributor | <$1K | Lead approval |
|
||||
| Lead | <$10K | 2/3 signatures |
|
||||
| Admin | >$10K | Full vote |
|
||||
@@ -0,0 +1,404 @@
|
||||
---
|
||||
title: Multisig Operations
|
||||
description: Sign and manage multi-signature proposals
|
||||
---
|
||||
|
||||
# Multisig Operations
|
||||
|
||||
Multi-signature (multisig) wallets require multiple parties to approve transactions before execution. This guide covers how to sign proposals and manage multisig operations.
|
||||
|
||||
## Overview
|
||||
|
||||
Multisig adds an extra layer of security by requiring `M-of-N` signatures:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Multisig Flow │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Propose │───▶│ Sign │───▶│ Threshold│───▶│ Execute │ │
|
||||
│ │ │ │ (M/N) │ │ Met │ │ │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
│ │
|
||||
│ Example: 3-of-5 multisig │
|
||||
│ - 5 total signers │
|
||||
│ - 3 signatures required to execute │
|
||||
│ - Any 3 of the 5 can approve │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Multisig Types
|
||||
|
||||
### Treasury Multisig
|
||||
|
||||
Controls treasury funds and large transfers:
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------|
|
||||
| Signers | 5 |
|
||||
| Threshold | 3-of-5 |
|
||||
| Use | Treasury transfers > $10K |
|
||||
| Timelock | 24 hours |
|
||||
|
||||
### Operations Multisig
|
||||
|
||||
For day-to-day operational transactions:
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------|
|
||||
| Signers | 3 |
|
||||
| Threshold | 2-of-3 |
|
||||
| Use | Small transfers, routine ops |
|
||||
| Timelock | None |
|
||||
|
||||
### Emergency Multisig
|
||||
|
||||
For urgent security actions:
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------|
|
||||
| Signers | 7 |
|
||||
| Threshold | 4-of-7 |
|
||||
| Use | Pause contracts, emergency actions |
|
||||
| Timelock | None |
|
||||
|
||||
## Signing a Proposal
|
||||
|
||||
### Step 1: View Pending Proposals
|
||||
|
||||
Navigate to **Governance > Multisig** to see proposals awaiting your signature:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Pending Signatures │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ #MS-42: Transfer 50,000 USDC to Grants Committee │ │
|
||||
│ │ │ │
|
||||
│ │ Status: Awaiting Signatures (2/3) │ │
|
||||
│ │ Submitted: 2 hours ago by 0x1234...abcd │ │
|
||||
│ │ Expires: in 5 days │ │
|
||||
│ │ │ │
|
||||
│ │ Signers: │ │
|
||||
│ │ ✓ 0x1234...abcd (Proposer) │ │
|
||||
│ │ ✓ 0x5678...efgh │ │
|
||||
│ │ ○ 0x9abc...ijkl (You) │ │
|
||||
│ │ │ │
|
||||
│ │ [View Details] [Sign] │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Review Proposal Details
|
||||
|
||||
Before signing, carefully review:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Proposal #MS-42 Details │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Type: Treasury Transfer │
|
||||
│ Amount: 50,000 USDC │
|
||||
│ Recipient: 0xGRANTS...COMMITTEE │
|
||||
│ │
|
||||
│ ───────────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ Transaction Details: │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Contract: 0xTREASURY...ADDRESS │ │
|
||||
│ │ Function: transfer(address,uint256) │ │
|
||||
│ │ Parameters: │ │
|
||||
│ │ - to: 0xGRANTS...COMMITTEE │ │
|
||||
│ │ - amount: 50000000000 (50,000 USDC) │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Simulation Result: ✓ Success │
|
||||
│ Gas Estimate: 150,000 │
|
||||
│ │
|
||||
│ Associated Governance Proposal: #42 (Passed) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
<Callout type="warning">
|
||||
**Always verify transaction details before signing.** Check:
|
||||
- Correct recipient address
|
||||
- Correct amount and token
|
||||
- Transaction simulation succeeded
|
||||
- Associated governance approval (if required)
|
||||
</Callout>
|
||||
|
||||
### Step 3: Sign the Transaction
|
||||
|
||||
1. Click **Sign**
|
||||
2. Review the signature request in your wallet
|
||||
3. Confirm the signature
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Sign Proposal │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ You are signing: │
|
||||
│ Proposal #MS-42: Transfer 50,000 USDC │
|
||||
│ │
|
||||
│ This signature: │
|
||||
│ - Does NOT execute the transaction │
|
||||
│ - Adds your approval to the proposal │
|
||||
│ - Is required for threshold to be met │
|
||||
│ │
|
||||
│ Current Signatures: 2/3 │
|
||||
│ After Your Signature: 3/3 (Ready to Execute) │
|
||||
│ │
|
||||
│ [Cancel] [Sign Proposal] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 4: Execution
|
||||
|
||||
Once the threshold is met, anyone can execute:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Proposal Ready for Execution │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ #MS-42: Transfer 50,000 USDC │
|
||||
│ │
|
||||
│ Status: ✓ Threshold Met (3/3 signatures) │
|
||||
│ │
|
||||
│ Signers: │
|
||||
│ ✓ 0x1234...abcd - Signed 2 hours ago │
|
||||
│ ✓ 0x5678...efgh - Signed 1 hour ago │
|
||||
│ ✓ 0x9abc...ijkl - Signed just now │
|
||||
│ │
|
||||
│ Timelock: None │
|
||||
│ │
|
||||
│ [Execute Transaction] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Creating a Multisig Proposal
|
||||
|
||||
### Requirements
|
||||
|
||||
To create a multisig proposal, you must be:
|
||||
- An authorized signer on the multisig
|
||||
- Or have a passed governance proposal requiring multisig execution
|
||||
|
||||
### Step 1: Initiate Proposal
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Create Multisig Proposal │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Multisig: Treasury (3-of-5) │
|
||||
│ │
|
||||
│ Transaction Type: │
|
||||
│ ┌─────┐ ┌─────────┐ ┌────────┐ ┌──────────┐ │
|
||||
│ │Token│ │ ETH │ │Contract│ │ Custom │ │
|
||||
│ │Trans│ │ Transfer│ │ Call │ │ Data │ │
|
||||
│ └─────┘ └─────────┘ └────────┘ └──────────┘ │
|
||||
│ │
|
||||
│ Token Transfer Details: │
|
||||
│ Token: [USDC ▼] │
|
||||
│ Amount: [50000_____] │
|
||||
│ Recipient: [0x_________] │
|
||||
│ │
|
||||
│ Governance Reference (optional): │
|
||||
│ [Proposal #42 ▼] │
|
||||
│ │
|
||||
│ Note: │
|
||||
│ [Q1 Grants Committee funding per governance vote___] │
|
||||
│ │
|
||||
│ [Cancel] [Create Proposal] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Simulate Transaction
|
||||
|
||||
Before creating, the system simulates the transaction:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Transaction Simulation │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ✓ Simulation Successful │
|
||||
│ │
|
||||
│ State Changes: │
|
||||
│ - Treasury USDC Balance: 500,000 → 450,000 (-50,000) │
|
||||
│ - Grants USDC Balance: 0 → 50,000 (+50,000) │
|
||||
│ │
|
||||
│ Events Emitted: │
|
||||
│ - Transfer(treasury, grants, 50000000000) │
|
||||
│ │
|
||||
│ Gas Estimate: 150,000 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Submit and Sign
|
||||
|
||||
The proposal is created with your signature as the first approval.
|
||||
|
||||
## Managing Signers
|
||||
|
||||
### Viewing Signers
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Treasury Multisig (3-of-5) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Signers: │
|
||||
│ │
|
||||
│ │ Address │ Name │ Added │ Signatures │ │
|
||||
│ │─────────────────│───────────│────────────│────────────│ │
|
||||
│ │ 0x1234...abcd │ Alice │ Jan 2025 │ 42 │ │
|
||||
│ │ 0x5678...efgh │ Bob │ Jan 2025 │ 38 │ │
|
||||
│ │ 0x9abc...ijkl │ Carol │ Feb 2025 │ 35 │ │
|
||||
│ │ 0xdef0...mnop │ Dave │ Mar 2025 │ 29 │ │
|
||||
│ │ 0x1357...qrst │ Eve │ Apr 2025 │ 22 │ │
|
||||
│ │
|
||||
│ Configuration: │
|
||||
│ - Threshold: 3 signatures required │
|
||||
│ - Total Signers: 5 │
|
||||
│ - Change Threshold: Requires governance vote │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Adding/Removing Signers
|
||||
|
||||
Signer changes require governance approval:
|
||||
|
||||
1. Submit governance proposal to add/remove signer
|
||||
2. Community votes on proposal
|
||||
3. If passed, multisig configuration updated after timelock
|
||||
|
||||
<Callout type="info">
|
||||
Changing multisig signers is a significant governance action. Proposals typically require higher quorum and longer discussion periods.
|
||||
</Callout>
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### For Signers
|
||||
|
||||
1. **Verify Everything**
|
||||
- Check recipient addresses character by character
|
||||
- Verify amounts match governance approvals
|
||||
- Review transaction simulation results
|
||||
|
||||
2. **Use Hardware Wallets**
|
||||
- Store signing keys on hardware wallets
|
||||
- Never expose private keys
|
||||
- Enable all security features
|
||||
|
||||
3. **Communicate Securely**
|
||||
- Coordinate with other signers through secure channels
|
||||
- Verify urgent requests through multiple channels
|
||||
- Be suspicious of unusual or rushed requests
|
||||
|
||||
4. **Maintain Availability**
|
||||
- Respond to signing requests promptly
|
||||
- Notify team if you'll be unavailable
|
||||
- Have backup plans for extended absences
|
||||
|
||||
### For the DAO
|
||||
|
||||
1. **Signer Distribution**
|
||||
- Geographic distribution
|
||||
- Organizational distribution
|
||||
- Timezone coverage
|
||||
|
||||
2. **Regular Audits**
|
||||
- Review signer list quarterly
|
||||
- Remove inactive signers
|
||||
- Verify signer key security
|
||||
|
||||
3. **Emergency Procedures**
|
||||
- Document key recovery processes
|
||||
- Define emergency contact chains
|
||||
- Regular drills and tests
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Signature Invalid"
|
||||
|
||||
**Causes:**
|
||||
- Signed with wrong address
|
||||
- Transaction data changed since signing
|
||||
- Signature expired
|
||||
|
||||
**Solutions:**
|
||||
- Verify connected wallet matches signer address
|
||||
- Re-sign the proposal
|
||||
- Check proposal hasn't been modified
|
||||
|
||||
### "Threshold Not Met"
|
||||
|
||||
**Causes:**
|
||||
- Not enough signers have signed
|
||||
- Signatures expired
|
||||
- Signer removed after signing
|
||||
|
||||
**Solutions:**
|
||||
- Contact remaining signers
|
||||
- Check signature expiration
|
||||
- Verify current signer list
|
||||
|
||||
### "Execution Failed"
|
||||
|
||||
**Causes:**
|
||||
- Contract state changed since simulation
|
||||
- Insufficient gas
|
||||
- External dependency failed
|
||||
|
||||
**Solutions:**
|
||||
- Re-simulate transaction
|
||||
- Increase gas limit
|
||||
- Check external contract states
|
||||
- Create new proposal if needed
|
||||
|
||||
## Integration with Governance
|
||||
|
||||
Multisig operations typically follow governance approval:
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Governance Proposal Multisig Execution │
|
||||
│ ───────────────────────────── ────────────────────────── │
|
||||
│ │
|
||||
│ 1. Proposal Created 4. MS Proposal Created │
|
||||
│ 2. Community Votes 5. Signers Review │
|
||||
│ 3. Proposal Passes 6. Collect Signatures │
|
||||
│ │ 7. Execute Transaction │
|
||||
│ └───────────────────────────────▶ │
|
||||
│ │
|
||||
└────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Token Setup" href="/docs/guide/token-setup" icon="coins">
|
||||
Configure tokens for your multisig project
|
||||
</Card>
|
||||
<Card title="Settings" href="/docs/guide/settings" icon="settings">
|
||||
Manage project settings
|
||||
</Card>
|
||||
<Card title="Treasury" href="/docs/guide/treasury" icon="vault">
|
||||
Treasury management guide
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,512 @@
|
||||
---
|
||||
title: Airdrops
|
||||
description: Distribute tokens to multiple addresses at once
|
||||
---
|
||||
|
||||
# Airdrops
|
||||
|
||||
Airdrops enable efficient distribution of tokens to many recipients in a single transaction. Use airdrops for rewards, governance token distribution, and bulk payments.
|
||||
|
||||
## Overview
|
||||
|
||||
Airdrops are ideal for:
|
||||
|
||||
- Governance token distribution
|
||||
- Community rewards
|
||||
- Retroactive compensation
|
||||
- Bulk refunds
|
||||
- Loyalty programs
|
||||
|
||||
## Creating an Airdrop
|
||||
|
||||
### Via UI
|
||||
|
||||
1. Navigate to **Treasury** > **Payments**
|
||||
2. Click **"New Airdrop"**
|
||||
3. Configure recipients and amounts
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ New Airdrop │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Token: [DAO ▼] │
|
||||
│ │
|
||||
│ Distribution Method: │
|
||||
│ (•) Equal amounts │
|
||||
│ ( ) Custom amounts │
|
||||
│ ( ) Import CSV │
|
||||
│ │
|
||||
│ Amount per recipient: [1,000 ] │
|
||||
│ │
|
||||
│ Recipients: │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ 0x1234...5678 ✓ │ │
|
||||
│ │ 0xABCD...EFGH ✓ │ │
|
||||
│ │ 0x9876...5432 ✓ │ │
|
||||
│ │ contributor.eth ✓ │ │
|
||||
│ │ │ │
|
||||
│ │ + Add address │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Recipients: 4 │
|
||||
│ Total: 4,000 DAO tokens │
|
||||
│ Treasury Balance: 500,000 DAO │
|
||||
│ │
|
||||
│ [ Cancel ] [ Create Airdrop ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Custom Amounts
|
||||
|
||||
For variable distribution:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Custom Airdrop Amounts │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Address Amount │
|
||||
│ ────────────────────────────────────────────────────── │
|
||||
│ 0x1234...5678 2,500 │
|
||||
│ 0xABCD...EFGH 1,500 │
|
||||
│ 0x9876...5432 1,000 │
|
||||
│ contributor.eth 500 │
|
||||
│ │
|
||||
│ Total: 5,500 DAO tokens │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Import from CSV
|
||||
|
||||
For large distributions:
|
||||
|
||||
```csv
|
||||
address,amount
|
||||
0x1234567890123456789012345678901234567890,2500
|
||||
0xABCDEF1234567890ABCDEF1234567890ABCDEF12,1500
|
||||
0x9876543210987654321098765432109876543210,1000
|
||||
contributor.eth,500
|
||||
```
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Import Recipients │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ 📄 Drop CSV file here │ │
|
||||
│ │ or click to browse │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ CSV Format: │
|
||||
│ address,amount │
|
||||
│ 0x1234...,1000 │
|
||||
│ │
|
||||
│ [Download Template] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Via Proposal
|
||||
|
||||
```yaml
|
||||
Proposal: "Q1 Community Rewards Airdrop"
|
||||
|
||||
Description: |
|
||||
This proposal distributes governance tokens to Q1 contributors.
|
||||
|
||||
## Criteria
|
||||
- Minimum 10 forum posts
|
||||
- At least 1 accepted proposal
|
||||
- Active governance participation
|
||||
|
||||
## Distribution
|
||||
- 50 recipients
|
||||
- 50,000 DAO tokens total
|
||||
- Average: 1,000 tokens per recipient
|
||||
|
||||
Actions:
|
||||
- type: airdrop
|
||||
token: DAO
|
||||
recipients:
|
||||
- 0x1234...
|
||||
- 0x5678...
|
||||
- 0xABCD...
|
||||
# ... more addresses
|
||||
amounts:
|
||||
- 2500000000000000000000 # 2,500 DAO
|
||||
- 1500000000000000000000 # 1,500 DAO
|
||||
- 1000000000000000000000 # 1,000 DAO
|
||||
# ... matching amounts
|
||||
```
|
||||
|
||||
### Via SDK
|
||||
|
||||
```typescript
|
||||
import { PaymentsClient } from '@lux/dao-sdk';
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
const payments = new PaymentsClient(signer);
|
||||
|
||||
// Define recipients and amounts
|
||||
const recipients = [
|
||||
'0x1234...5678',
|
||||
'0xABCD...EFGH',
|
||||
'0x9876...5432',
|
||||
];
|
||||
|
||||
const amounts = [
|
||||
ethers.parseUnits('2500', 18), // 2,500 tokens
|
||||
ethers.parseUnits('1500', 18), // 1,500 tokens
|
||||
ethers.parseUnits('1000', 18), // 1,000 tokens
|
||||
];
|
||||
|
||||
// Execute airdrop
|
||||
const tx = await payments.airdrop(
|
||||
daoTokenAddress,
|
||||
recipients,
|
||||
amounts
|
||||
);
|
||||
|
||||
await tx.wait();
|
||||
console.log(`Airdropped to ${recipients.length} addresses`);
|
||||
```
|
||||
|
||||
## Smart Contract Interface
|
||||
|
||||
```solidity
|
||||
interface IPayments {
|
||||
/// @notice Emitted on airdrop
|
||||
event Airdrop(
|
||||
address indexed token,
|
||||
uint256 recipientCount,
|
||||
uint256 totalAmount,
|
||||
bytes32 merkleRoot // For verification
|
||||
);
|
||||
|
||||
/// @notice Distribute tokens to multiple recipients
|
||||
/// @param token Token to distribute
|
||||
/// @param recipients Array of recipient addresses
|
||||
/// @param amounts Array of amounts (must match recipients length)
|
||||
function airdrop(
|
||||
address token,
|
||||
address[] calldata recipients,
|
||||
uint256[] calldata amounts
|
||||
) external;
|
||||
|
||||
/// @notice Equal distribution to all recipients
|
||||
/// @param token Token to distribute
|
||||
/// @param recipients Array of recipient addresses
|
||||
/// @param amountEach Amount each recipient receives
|
||||
function airdropEqual(
|
||||
address token,
|
||||
address[] calldata recipients,
|
||||
uint256 amountEach
|
||||
) external;
|
||||
}
|
||||
```
|
||||
|
||||
## Merkle Airdrops
|
||||
|
||||
For very large distributions (1000+ recipients), use Merkle proofs:
|
||||
|
||||
### Setup
|
||||
|
||||
```typescript
|
||||
import { StandardMerkleTree } from '@openzeppelin/merkle-tree';
|
||||
|
||||
// Build merkle tree
|
||||
const values = recipients.map((addr, i) => [addr, amounts[i].toString()]);
|
||||
const tree = StandardMerkleTree.of(values, ['address', 'uint256']);
|
||||
|
||||
// Get root for contract
|
||||
const merkleRoot = tree.root;
|
||||
console.log('Merkle Root:', merkleRoot);
|
||||
|
||||
// Generate proofs
|
||||
for (const [i, v] of tree.entries()) {
|
||||
const proof = tree.getProof(i);
|
||||
console.log(`${v[0]}: ${JSON.stringify(proof)}`);
|
||||
}
|
||||
```
|
||||
|
||||
### Contract
|
||||
|
||||
```solidity
|
||||
interface IMerkleAirdrop {
|
||||
/// @notice Initialize airdrop with merkle root
|
||||
function createMerkleAirdrop(
|
||||
address token,
|
||||
uint256 totalAmount,
|
||||
bytes32 merkleRoot,
|
||||
uint256 expiresAt
|
||||
) external returns (uint256 airdropId);
|
||||
|
||||
/// @notice Claim tokens with merkle proof
|
||||
function claim(
|
||||
uint256 airdropId,
|
||||
address recipient,
|
||||
uint256 amount,
|
||||
bytes32[] calldata proof
|
||||
) external;
|
||||
|
||||
/// @notice Check if address has claimed
|
||||
function hasClaimed(uint256 airdropId, address recipient)
|
||||
external view returns (bool);
|
||||
}
|
||||
```
|
||||
|
||||
### Claim UI
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Claim Airdrop │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 🎉 You're eligible for the Q1 Rewards Airdrop! │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ 1,500 DAO │ │
|
||||
│ │ tokens available │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Connected: 0x1234...5678 │
|
||||
│ Status: Unclaimed │
|
||||
│ Expires: March 31, 2026 │
|
||||
│ │
|
||||
│ [ Claim Tokens ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Airdrop Strategies
|
||||
|
||||
### Retroactive Rewards
|
||||
|
||||
Reward past contributors:
|
||||
|
||||
```yaml
|
||||
Criteria:
|
||||
- Governance participation (weighted)
|
||||
- Forum activity (weighted)
|
||||
- Development contributions (weighted)
|
||||
- Community building (weighted)
|
||||
|
||||
Calculation:
|
||||
score = (proposals_voted * 10) +
|
||||
(forum_posts * 2) +
|
||||
(PRs_merged * 50) +
|
||||
(events_organized * 100)
|
||||
|
||||
tokens = min(score * 10, max_per_user)
|
||||
```
|
||||
|
||||
### Proportional Distribution
|
||||
|
||||
Based on holdings or activity:
|
||||
|
||||
```typescript
|
||||
// Proportional to token holdings
|
||||
const totalSupply = await token.totalSupply();
|
||||
const airdropPool = ethers.parseUnits('100000', 18);
|
||||
|
||||
const amounts = await Promise.all(
|
||||
recipients.map(async (addr) => {
|
||||
const balance = await token.balanceOf(addr);
|
||||
return (balance * airdropPool) / totalSupply;
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
### Tiered Distribution
|
||||
|
||||
Based on levels or tiers:
|
||||
|
||||
```typescript
|
||||
const tiers = {
|
||||
gold: ethers.parseUnits('5000', 18),
|
||||
silver: ethers.parseUnits('2500', 18),
|
||||
bronze: ethers.parseUnits('1000', 18),
|
||||
};
|
||||
|
||||
const amounts = recipients.map((addr) => {
|
||||
const tier = getUserTier(addr);
|
||||
return tiers[tier];
|
||||
});
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
### Pre-Airdrop Checks
|
||||
|
||||
```typescript
|
||||
async function verifyAirdrop(
|
||||
token: string,
|
||||
recipients: string[],
|
||||
amounts: bigint[]
|
||||
): Promise<void> {
|
||||
// Validate arrays match
|
||||
if (recipients.length !== amounts.length) {
|
||||
throw new Error('Recipients and amounts must match');
|
||||
}
|
||||
|
||||
// Check for duplicates
|
||||
const unique = new Set(recipients);
|
||||
if (unique.size !== recipients.length) {
|
||||
throw new Error('Duplicate recipients found');
|
||||
}
|
||||
|
||||
// Validate addresses
|
||||
for (const addr of recipients) {
|
||||
if (!ethers.isAddress(addr)) {
|
||||
throw new Error(`Invalid address: ${addr}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Check total amount
|
||||
const total = amounts.reduce((a, b) => a + b, 0n);
|
||||
const balance = await treasury.balance(token);
|
||||
if (total > balance) {
|
||||
throw new Error(`Insufficient balance: need ${total}, have ${balance}`);
|
||||
}
|
||||
|
||||
console.log('Airdrop verified:');
|
||||
console.log(` Recipients: ${recipients.length}`);
|
||||
console.log(` Total: ${ethers.formatUnits(total, 18)}`);
|
||||
}
|
||||
```
|
||||
|
||||
### Post-Airdrop Verification
|
||||
|
||||
```typescript
|
||||
// Verify all recipients received tokens
|
||||
const receipt = await tx.wait();
|
||||
|
||||
for (let i = 0; i < recipients.length; i++) {
|
||||
const balance = await token.balanceOf(recipients[i]);
|
||||
console.log(`${recipients[i]}: ${ethers.formatUnits(balance, 18)}`);
|
||||
}
|
||||
```
|
||||
|
||||
## Gas Optimization
|
||||
|
||||
### Batch Size Limits
|
||||
|
||||
Large airdrops may exceed gas limits:
|
||||
|
||||
```typescript
|
||||
const BATCH_SIZE = 200; // Adjust based on gas limits
|
||||
|
||||
async function batchAirdrop(
|
||||
token: string,
|
||||
recipients: string[],
|
||||
amounts: bigint[]
|
||||
): Promise<void> {
|
||||
for (let i = 0; i < recipients.length; i += BATCH_SIZE) {
|
||||
const batchRecipients = recipients.slice(i, i + BATCH_SIZE);
|
||||
const batchAmounts = amounts.slice(i, i + BATCH_SIZE);
|
||||
|
||||
const tx = await payments.airdrop(token, batchRecipients, batchAmounts);
|
||||
await tx.wait();
|
||||
|
||||
console.log(`Batch ${i / BATCH_SIZE + 1} complete`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Gas Estimates
|
||||
|
||||
| Recipients | Estimated Gas | Estimated Cost (at 30 gwei) |
|
||||
|------------|--------------|----------------------------|
|
||||
| 10 | ~150,000 | ~$3 |
|
||||
| 50 | ~400,000 | ~$8 |
|
||||
| 100 | ~700,000 | ~$14 |
|
||||
| 200 | ~1,200,000 | ~$24 |
|
||||
| 500+ | Use Merkle | Varies |
|
||||
|
||||
## Airdrop Expiry
|
||||
|
||||
For unclaimed airdrops:
|
||||
|
||||
```typescript
|
||||
// Create airdrop with expiry
|
||||
const expiresAt = Math.floor(Date.now() / 1000) + 90 * 24 * 60 * 60; // 90 days
|
||||
|
||||
await payments.createMerkleAirdrop(
|
||||
token,
|
||||
totalAmount,
|
||||
merkleRoot,
|
||||
expiresAt
|
||||
);
|
||||
|
||||
// Reclaim expired funds
|
||||
await payments.reclaimExpiredAirdrop(airdropId);
|
||||
```
|
||||
|
||||
## Common Errors
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `ArrayLengthMismatch` | Recipients/amounts don't match | Fix array lengths |
|
||||
| `DuplicateRecipient` | Same address twice | Remove duplicates |
|
||||
| `InsufficientBalance` | Not enough tokens | Fund treasury |
|
||||
| `GasLimitExceeded` | Too many recipients | Use batches or Merkle |
|
||||
| `InvalidProof` | Bad Merkle proof | Regenerate proof |
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Address Validation
|
||||
|
||||
```typescript
|
||||
// Filter invalid addresses
|
||||
const validRecipients = recipients.filter((addr) => {
|
||||
// Valid format
|
||||
if (!ethers.isAddress(addr)) return false;
|
||||
|
||||
// Not zero address
|
||||
if (addr === ethers.ZeroAddress) return false;
|
||||
|
||||
// Not contract (optional)
|
||||
// if (await provider.getCode(addr) !== '0x') return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
```
|
||||
|
||||
### Sybil Resistance
|
||||
|
||||
For community airdrops:
|
||||
|
||||
```yaml
|
||||
Anti-sybil measures:
|
||||
- Minimum account age
|
||||
- Minimum activity threshold
|
||||
- Identity verification (optional)
|
||||
- Cross-reference with known Sybil lists
|
||||
- Quadratic distribution (sqrt of activity)
|
||||
```
|
||||
|
||||
## Event Monitoring
|
||||
|
||||
```typescript
|
||||
// Track airdrop events
|
||||
payments.on('Airdrop', (token, count, total, merkleRoot) => {
|
||||
console.log(`Airdrop: ${count} recipients, ${total} tokens`);
|
||||
|
||||
// Log for reporting
|
||||
recordAirdrop({
|
||||
token,
|
||||
recipientCount: count,
|
||||
totalAmount: total,
|
||||
merkleRoot,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,374 @@
|
||||
---
|
||||
title: Payments
|
||||
description: 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 Type | Use Case | Timing |
|
||||
|--------------|----------|--------|
|
||||
| [Transfer](/docs/guide/payments/transfer) | One-time payments | Immediate |
|
||||
| [Airdrop](/docs/guide/payments/airdrop) | Multi-recipient distribution | Batch |
|
||||
| [Stream](/docs/guide/payments/stream) | Continuous payments | Over time |
|
||||
| [Stream to Role](/docs/guide/payments/stream-to-role) | Role-based streams | Automatic |
|
||||
|
||||
## 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
|
||||
|
||||
```solidity
|
||||
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
|
||||
|
||||
<Cards>
|
||||
<Card title="Transfer" href="/docs/guide/payments/transfer" icon="send">
|
||||
One-time payments to single recipient
|
||||
</Card>
|
||||
<Card title="Airdrop" href="/docs/guide/payments/airdrop" icon="users">
|
||||
Distribute to multiple addresses at once
|
||||
</Card>
|
||||
<Card title="Stream" href="/docs/guide/payments/stream" icon="clock">
|
||||
Continuous payments over time (Sablier-style)
|
||||
</Card>
|
||||
<Card title="Stream to Role" href="/docs/guide/payments/stream-to-role" icon="shield">
|
||||
Automatic streams to role holders
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## 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:
|
||||
|
||||
```yaml
|
||||
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:
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
| Level | Single Payment | Daily Limit | Requires |
|
||||
|-------|----------------|-------------|----------|
|
||||
| Member | $0 | $0 | - |
|
||||
| Contributor | $1,000 | $2,500 | Lead approval |
|
||||
| Lead | $10,000 | $25,000 | 2/3 multi-sig |
|
||||
| Committee | $50,000 | $100,000 | Committee vote |
|
||||
| DAO | Unlimited | Unlimited | Full governance |
|
||||
|
||||
### Approval Thresholds
|
||||
|
||||
```yaml
|
||||
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
|
||||
|
||||
```typescript
|
||||
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:
|
||||
|
||||
```yaml
|
||||
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:
|
||||
|
||||
```typescript
|
||||
// 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:
|
||||
|
||||
```solidity
|
||||
// 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:
|
||||
|
||||
```typescript
|
||||
// Good
|
||||
await payments.transfer(usdc, recipient, amount,
|
||||
'Invoice #1234 - Q1 Development Milestone 2');
|
||||
|
||||
// Bad
|
||||
await payments.transfer(usdc, recipient, amount, '');
|
||||
```
|
||||
|
||||
### Batching
|
||||
|
||||
Combine related payments:
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `InsufficientBalance` | Treasury lacks funds | Fund treasury or reduce amount |
|
||||
| `ExceedsLimit` | Above spending cap | Get higher approval or split |
|
||||
| `Unauthorized` | Missing role | Get required permissions |
|
||||
| `InvalidRecipient` | Bad address | Verify recipient address |
|
||||
| `StreamNotFound` | Invalid stream ID | Check stream exists |
|
||||
|
||||
## Gas Optimization
|
||||
|
||||
### Batching Saves Gas
|
||||
|
||||
| Operation | Gas (approx) |
|
||||
|-----------|--------------|
|
||||
| 10 separate transfers | 210,000 |
|
||||
| 1 airdrop (10 recipients) | 150,000 |
|
||||
| Savings | ~30% |
|
||||
|
||||
### Stream Efficiency
|
||||
|
||||
Streams are gas-efficient for recurring payments:
|
||||
|
||||
| Payment Method | Annual Gas (monthly) |
|
||||
|----------------|---------------------|
|
||||
| 12 transfers | ~252,000 |
|
||||
| 1 stream | ~75,000 |
|
||||
| Savings | ~70% |
|
||||
@@ -0,0 +1,486 @@
|
||||
---
|
||||
title: Stream to Role
|
||||
description: Automatic payment streams for role holders
|
||||
---
|
||||
|
||||
# Stream to Role
|
||||
|
||||
Stream to Role automatically creates and manages payment streams for all holders of a specific role. When members join or leave a role, their streams are automatically created or cancelled.
|
||||
|
||||
## Overview
|
||||
|
||||
Instead of manually managing individual streams:
|
||||
|
||||
```
|
||||
Traditional: Stream to Role:
|
||||
───────────────────────── ─────────────────────────
|
||||
Create stream for Alice Set: Committee Members
|
||||
Create stream for Bob → $1,000/month each
|
||||
Create stream for Carol Alice joins → stream created
|
||||
Alice leaves → cancel stream Bob leaves → stream cancelled
|
||||
Dave joins → create stream Carol joins → stream created
|
||||
...manual for every change ...automatic forever
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Automatic management** - Streams created/cancelled on role changes
|
||||
- **Consistent compensation** - All role holders receive same rate
|
||||
- **Reduced governance overhead** - One proposal covers all members
|
||||
- **Real-time updates** - Changes take effect immediately
|
||||
- **Audit trail** - All stream events logged
|
||||
|
||||
## Creating a Role Stream
|
||||
|
||||
### Via UI
|
||||
|
||||
1. Navigate to **Treasury** > **Payments**
|
||||
2. Click **"Stream to Role"**
|
||||
3. Configure the role stream
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Create Role Stream │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Role: [Committee Member ▼] │
|
||||
│ │
|
||||
│ Current Holders: 5 │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ • 0x1234...5678 (alice.eth) │ │
|
||||
│ │ • 0xABCD...EFGH (bob.eth) │ │
|
||||
│ │ • 0x9876...5432 (carol.eth) │ │
|
||||
│ │ • 0xDEF0...1234 (dave.eth) │ │
|
||||
│ │ • 0x5555...6666 (eve.eth) │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Token: [USDC ▼] │
|
||||
│ │
|
||||
│ Amount per holder: [1,000 ] │
|
||||
│ Per: [Month ▼] │
|
||||
│ ≈ $32.88/day per holder │
|
||||
│ │
|
||||
│ Duration: [12 ] months │
|
||||
│ │
|
||||
│ ────────────────────────────────────────────────────── │
|
||||
│ Budget Impact │
|
||||
│ ────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ Current monthly: $5,000 (5 holders × $1,000) │
|
||||
│ Annual maximum: $60,000 │
|
||||
│ Treasury balance: 125,000 USDC │
|
||||
│ │
|
||||
│ ⚠️ Budget will scale with role membership │
|
||||
│ │
|
||||
│ [ Cancel ] [ Create Role Stream ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Via Proposal
|
||||
|
||||
```yaml
|
||||
Proposal: "Committee Member Compensation Streams"
|
||||
|
||||
Description: |
|
||||
This proposal establishes automatic payment streams for all
|
||||
Research Committee members.
|
||||
|
||||
## Terms
|
||||
- Rate: $1,000 USDC per member per month
|
||||
- Duration: 12 months
|
||||
- Applies to: All current and future committee members
|
||||
|
||||
## Current Members (5)
|
||||
- alice.eth
|
||||
- bob.eth
|
||||
- carol.eth
|
||||
- dave.eth
|
||||
- eve.eth
|
||||
|
||||
## Budget Impact
|
||||
- Current: $5,000/month ($60,000/year)
|
||||
- Maximum (10 members): $10,000/month ($120,000/year)
|
||||
|
||||
Actions:
|
||||
- type: stream_to_role
|
||||
roleId: COMMITTEE_MEMBER_ROLE
|
||||
token: USDC
|
||||
amountPerHolder: 1000000000 # 1K USDC/month (6 decimals)
|
||||
duration: 31536000 # 12 months in seconds
|
||||
```
|
||||
|
||||
### Via SDK
|
||||
|
||||
```typescript
|
||||
import { RoleStreamsClient } from '@lux/dao-sdk';
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
const roleStreams = new RoleStreamsClient(signer);
|
||||
|
||||
// Create streams for all role holders
|
||||
const tx = await roleStreams.streamToRole({
|
||||
roleId: ethers.keccak256(ethers.toUtf8Bytes('COMMITTEE_MEMBER')),
|
||||
token: usdcAddress,
|
||||
amountPerHolder: ethers.parseUnits('1000', 6), // Per month
|
||||
duration: 365 * 24 * 60 * 60, // 12 months
|
||||
});
|
||||
|
||||
const receipt = await tx.wait();
|
||||
const streamIds = receipt.events
|
||||
.filter(e => e.event === 'StreamCreated')
|
||||
.map(e => e.args.streamId);
|
||||
|
||||
console.log(`Created ${streamIds.length} streams`);
|
||||
```
|
||||
|
||||
## Smart Contract Interface
|
||||
|
||||
```solidity
|
||||
interface IRoleStreams {
|
||||
struct RoleStream {
|
||||
bytes32 roleId;
|
||||
address token;
|
||||
uint256 amountPerHolder;
|
||||
uint256 duration;
|
||||
uint256 startTime;
|
||||
bool active;
|
||||
}
|
||||
|
||||
/// @notice Emitted when role stream configured
|
||||
event RoleStreamCreated(
|
||||
uint256 indexed roleStreamId,
|
||||
bytes32 indexed roleId,
|
||||
address token,
|
||||
uint256 amountPerHolder,
|
||||
uint256 duration
|
||||
);
|
||||
|
||||
/// @notice Emitted when member stream created
|
||||
event MemberStreamCreated(
|
||||
uint256 indexed roleStreamId,
|
||||
address indexed member,
|
||||
uint256 streamId
|
||||
);
|
||||
|
||||
/// @notice Emitted when member stream cancelled
|
||||
event MemberStreamCancelled(
|
||||
uint256 indexed roleStreamId,
|
||||
address indexed member,
|
||||
uint256 streamId
|
||||
);
|
||||
|
||||
/// @notice Create streams for all role holders
|
||||
function streamToRole(
|
||||
bytes32 roleId,
|
||||
address token,
|
||||
uint256 amountPerHolder,
|
||||
uint256 duration
|
||||
) external returns (uint256 roleStreamId);
|
||||
|
||||
/// @notice Update amount for future streams
|
||||
function updateRoleStreamAmount(
|
||||
uint256 roleStreamId,
|
||||
uint256 newAmount
|
||||
) external;
|
||||
|
||||
/// @notice Pause role stream (no new streams created)
|
||||
function pauseRoleStream(uint256 roleStreamId) external;
|
||||
|
||||
/// @notice Cancel all streams for a role
|
||||
function cancelRoleStream(uint256 roleStreamId) external;
|
||||
|
||||
/// @notice Get all active streams for a role
|
||||
function getRoleStreams(bytes32 roleId)
|
||||
external view returns (uint256[] memory streamIds);
|
||||
}
|
||||
```
|
||||
|
||||
## Automatic Management
|
||||
|
||||
### When Members Join
|
||||
|
||||
When a new member is granted the role:
|
||||
|
||||
```
|
||||
1. Role granted to new address
|
||||
2. System detects role change
|
||||
3. New stream automatically created
|
||||
4. Stream starts immediately
|
||||
5. Event logged
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Example: Grant role and stream created automatically
|
||||
await accessControl.grantRole(COMMITTEE_ROLE, newMemberAddress);
|
||||
// Stream created in same transaction via hook
|
||||
```
|
||||
|
||||
### When Members Leave
|
||||
|
||||
When a member's role is revoked:
|
||||
|
||||
```
|
||||
1. Role revoked from address
|
||||
2. System detects role change
|
||||
3. Stream cancelled
|
||||
4. Earned funds sent to member
|
||||
5. Remaining funds returned to treasury
|
||||
6. Event logged
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Example: Revoke role and stream cancelled automatically
|
||||
await accessControl.revokeRole(COMMITTEE_ROLE, leavingMemberAddress);
|
||||
// Stream cancelled, funds settled in same transaction
|
||||
```
|
||||
|
||||
## Role Stream Management
|
||||
|
||||
### Dashboard View
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Role Streams │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Committee Members Active ● │
|
||||
│ ────────────────────────────────────────────────────── │
|
||||
│ Rate: $1,000 USDC/month per holder │
|
||||
│ Duration: 12 months │
|
||||
│ Active holders: 5 │
|
||||
│ Monthly cost: $5,000 │
|
||||
│ │
|
||||
│ Member Streams: │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ alice.eth ████████░░░░ 67% Withdrawn: $8,000 │ │
|
||||
│ │ bob.eth ████████░░░░ 67% Withdrawn: $6,500 │ │
|
||||
│ │ carol.eth ██████░░░░░░ 50% Withdrawn: $4,000 │ │
|
||||
│ │ dave.eth ████░░░░░░░░ 33% Withdrawn: $2,000 │ │
|
||||
│ │ eve.eth ██░░░░░░░░░░ 17% Withdrawn: $500 │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ [ Update Rate ] [ Pause ] [ Cancel All ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Updating Rate
|
||||
|
||||
Adjust compensation for future periods:
|
||||
|
||||
```yaml
|
||||
Proposal: "Increase Committee Member Compensation"
|
||||
|
||||
Description: |
|
||||
Increase monthly rate from $1,000 to $1,500 USDC.
|
||||
Takes effect for all new stream periods.
|
||||
|
||||
Actions:
|
||||
- type: update_role_stream_amount
|
||||
roleStreamId: 1
|
||||
newAmount: 1500000000 # 1.5K USDC
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Via SDK
|
||||
await roleStreams.updateRoleStreamAmount(
|
||||
roleStreamId,
|
||||
ethers.parseUnits('1500', 6)
|
||||
);
|
||||
```
|
||||
|
||||
### Pausing Streams
|
||||
|
||||
Temporarily stop new streams:
|
||||
|
||||
```typescript
|
||||
// Pause role stream
|
||||
await roleStreams.pauseRoleStream(roleStreamId);
|
||||
|
||||
// Existing streams continue, no new streams created on role grant
|
||||
// Resume later:
|
||||
await roleStreams.resumeRoleStream(roleStreamId);
|
||||
```
|
||||
|
||||
### Cancelling All Streams
|
||||
|
||||
End all streams for a role:
|
||||
|
||||
```yaml
|
||||
Proposal: "Discontinue Committee Compensation"
|
||||
|
||||
Description: |
|
||||
This proposal cancels all committee member streams.
|
||||
All earned funds will be settled to members.
|
||||
|
||||
Actions:
|
||||
- type: cancel_role_stream
|
||||
roleStreamId: 1
|
||||
```
|
||||
|
||||
## Multi-Role Compensation
|
||||
|
||||
Create different streams for different roles:
|
||||
|
||||
```yaml
|
||||
Role Compensation Structure:
|
||||
|
||||
Lead (1 holder):
|
||||
- $5,000 USDC/month
|
||||
- $50,000 DAO tokens/year (vesting)
|
||||
|
||||
Senior Member (3 holders):
|
||||
- $3,000 USDC/month
|
||||
- $20,000 DAO tokens/year (vesting)
|
||||
|
||||
Member (5 holders):
|
||||
- $1,000 USDC/month
|
||||
- $10,000 DAO tokens/year (vesting)
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Create multiple role streams
|
||||
const roles = [
|
||||
{ role: 'LEAD', usdcPerMonth: 5000, daoPerYear: 50000 },
|
||||
{ role: 'SENIOR_MEMBER', usdcPerMonth: 3000, daoPerYear: 20000 },
|
||||
{ role: 'MEMBER', usdcPerMonth: 1000, daoPerYear: 10000 },
|
||||
];
|
||||
|
||||
for (const { role, usdcPerMonth, daoPerYear } of roles) {
|
||||
const roleId = ethers.keccak256(ethers.toUtf8Bytes(role));
|
||||
|
||||
// USDC monthly stream
|
||||
await roleStreams.streamToRole({
|
||||
roleId,
|
||||
token: usdcAddress,
|
||||
amountPerHolder: ethers.parseUnits(String(usdcPerMonth), 6),
|
||||
duration: 30 * 24 * 60 * 60, // Monthly
|
||||
});
|
||||
|
||||
// DAO token annual vesting
|
||||
await roleStreams.streamToRole({
|
||||
roleId,
|
||||
token: daoTokenAddress,
|
||||
amountPerHolder: ethers.parseUnits(String(daoPerYear), 18),
|
||||
duration: 365 * 24 * 60 * 60, // Annual
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Budget Management
|
||||
|
||||
### Budget Caps
|
||||
|
||||
Set maximum budget for a role stream:
|
||||
|
||||
```solidity
|
||||
interface IRoleStreams {
|
||||
/// @notice Set maximum monthly budget for role
|
||||
function setRoleBudgetCap(
|
||||
uint256 roleStreamId,
|
||||
uint256 maxMonthlyBudget
|
||||
) external;
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Cap at 10 members worth ($10K/month)
|
||||
await roleStreams.setRoleBudgetCap(
|
||||
roleStreamId,
|
||||
ethers.parseUnits('10000', 6)
|
||||
);
|
||||
|
||||
// If role exceeds cap, new members don't get streams
|
||||
// until others leave
|
||||
```
|
||||
|
||||
### Budget Forecasting
|
||||
|
||||
```typescript
|
||||
// Calculate budget impact
|
||||
const currentHolders = await accessControl.getRoleMemberCount(roleId);
|
||||
const monthlyRate = ethers.parseUnits('1000', 6);
|
||||
|
||||
const monthly = monthlyRate * BigInt(currentHolders);
|
||||
const annual = monthly * 12n;
|
||||
|
||||
console.log(`Current monthly: $${ethers.formatUnits(monthly, 6)}`);
|
||||
console.log(`Annual projection: $${ethers.formatUnits(annual, 6)}`);
|
||||
```
|
||||
|
||||
## Withdrawal for Members
|
||||
|
||||
Role stream recipients withdraw same as regular streams:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Your Committee Compensation │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Role: Committee Member │
|
||||
│ Rate: $1,000 USDC/month │
|
||||
│ │
|
||||
│ Current Period: │
|
||||
│ ●═══════════════════●░░░░░░░░░░░░░░░░░░░░░░░░░░░░░● │
|
||||
│ Jan 1 Today Jan 31 │
|
||||
│ │
|
||||
│ Earned this period: $666.67 │
|
||||
│ Available to withdraw: $666.67 │
|
||||
│ │
|
||||
│ Total withdrawn (all time): $8,000.00 │
|
||||
│ │
|
||||
│ [ Withdraw $666.67 ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Events and Monitoring
|
||||
|
||||
```typescript
|
||||
// Monitor role stream events
|
||||
roleStreams.on('RoleStreamCreated', (id, roleId, token, amount, duration) => {
|
||||
console.log(`Role stream ${id} created for role ${roleId}`);
|
||||
});
|
||||
|
||||
roleStreams.on('MemberStreamCreated', (roleStreamId, member, streamId) => {
|
||||
console.log(`Member ${member} joined, stream ${streamId} created`);
|
||||
});
|
||||
|
||||
roleStreams.on('MemberStreamCancelled', (roleStreamId, member, streamId) => {
|
||||
console.log(`Member ${member} left, stream ${streamId} cancelled`);
|
||||
});
|
||||
```
|
||||
|
||||
## Common Errors
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `RoleNotFound` | Invalid role ID | Check role exists |
|
||||
| `NoRoleHolders` | Role has no members | Add members first |
|
||||
| `BudgetCapExceeded` | Max budget reached | Increase cap or wait |
|
||||
| `RoleStreamPaused` | Stream is paused | Resume stream |
|
||||
| `Unauthorized` | Missing permission | Get ADMIN_ROLE |
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Role Design
|
||||
|
||||
- Keep roles focused and well-defined
|
||||
- Document role responsibilities
|
||||
- Set appropriate member limits
|
||||
- Review membership regularly
|
||||
|
||||
### Compensation Design
|
||||
|
||||
- Align rates with responsibilities
|
||||
- Include token component for alignment
|
||||
- Set reasonable budget caps
|
||||
- Plan for growth
|
||||
|
||||
### Governance
|
||||
|
||||
- Require proposals for rate changes
|
||||
- Log all membership changes
|
||||
- Regular budget reviews
|
||||
- Clear off-boarding process
|
||||
@@ -0,0 +1,510 @@
|
||||
---
|
||||
title: Payment Streams
|
||||
description: Continuous payments over time using Sablier-style streams
|
||||
---
|
||||
|
||||
# Payment Streams
|
||||
|
||||
Streams provide continuous, real-time payments where tokens flow from treasury to recipient every second. This is ideal for salaries, vesting, and long-term grants.
|
||||
|
||||
## Overview
|
||||
|
||||
Instead of lump-sum payments:
|
||||
|
||||
```
|
||||
Traditional: ●────────────────────────────────────────●
|
||||
Jan 1 Dec 31
|
||||
$60,000 paid
|
||||
|
||||
Stream: ●═══════════════════════════════════════●
|
||||
Jan 1 Dec 31
|
||||
$164.38/day flowing continuously
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Cash flow management** - Recipients access funds as earned
|
||||
- **Reduced counterparty risk** - Cancel anytime, only earned funds transferred
|
||||
- **Automation** - No manual monthly payments
|
||||
- **Transparency** - Real-time visibility into payment status
|
||||
- **Flexibility** - Cliffs, linear, or custom curves
|
||||
|
||||
## Creating a Stream
|
||||
|
||||
### Via UI
|
||||
|
||||
1. Navigate to **Treasury** > **Payments**
|
||||
2. Click **"New Stream"**
|
||||
3. Configure stream parameters
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Create Payment Stream │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Recipient: [0x1234...5678 ] │
|
||||
│ ENS: developer.eth ✓ │
|
||||
│ │
|
||||
│ Token: [USDC ▼] │
|
||||
│ │
|
||||
│ Total Amount: [60,000 ] │
|
||||
│ │
|
||||
│ Duration: [12 ] months │
|
||||
│ ≈ 365 days │
|
||||
│ │
|
||||
│ Cliff: [1 ] month │
|
||||
│ No withdrawals until cliff completes │
|
||||
│ │
|
||||
│ Start: (•) Immediately │
|
||||
│ ( ) Custom date: [ ] │
|
||||
│ │
|
||||
│ ────────────────────────────────────────────────────── │
|
||||
│ Stream Preview │
|
||||
│ ────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ ●══════════════════════════════════════════════════● │
|
||||
│ │◄─ cliff ─►│◄───────── vesting ─────────────────►│ │
|
||||
│ Jan 1 Feb 1 Dec 31 │
|
||||
│ $0 $5,000 $60,000 │
|
||||
│ │
|
||||
│ Rate: $164.38/day ($5,000/month) │
|
||||
│ │
|
||||
│ [ Cancel ] [ Create Stream ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Via Proposal
|
||||
|
||||
```yaml
|
||||
Proposal: "Create Development Contractor Stream"
|
||||
|
||||
Description: |
|
||||
This proposal creates a 12-month payment stream for our
|
||||
lead developer contractor.
|
||||
|
||||
## Terms
|
||||
- Total: $60,000 USDC
|
||||
- Duration: 12 months
|
||||
- Cliff: 1 month
|
||||
- Start: Upon execution
|
||||
|
||||
## Milestones
|
||||
Monthly deliverables tracked in development roadmap.
|
||||
|
||||
## Cancellation
|
||||
Stream can be cancelled by DAO vote if deliverables not met.
|
||||
|
||||
Actions:
|
||||
- type: create_stream
|
||||
token: USDC
|
||||
recipient: 0x1234...5678
|
||||
totalAmount: 60000000000 # 60K USDC (6 decimals)
|
||||
startTime: 0 # Immediately on execution
|
||||
duration: 31536000 # 365 days in seconds
|
||||
cliffDuration: 2592000 # 30 days in seconds
|
||||
```
|
||||
|
||||
### Via SDK
|
||||
|
||||
```typescript
|
||||
import { StreamsClient } from '@lux/dao-sdk';
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
const streams = new StreamsClient(signer);
|
||||
|
||||
// Create a 12-month stream with 1-month cliff
|
||||
const tx = await streams.createStream({
|
||||
token: usdcAddress,
|
||||
recipient: '0x1234...5678',
|
||||
totalAmount: ethers.parseUnits('60000', 6),
|
||||
startTime: Math.floor(Date.now() / 1000),
|
||||
duration: 365 * 24 * 60 * 60, // 365 days
|
||||
cliffDuration: 30 * 24 * 60 * 60, // 30 days
|
||||
});
|
||||
|
||||
const receipt = await tx.wait();
|
||||
const streamId = receipt.events[0].args.streamId;
|
||||
|
||||
console.log(`Created stream: ${streamId}`);
|
||||
```
|
||||
|
||||
## Smart Contract Interface
|
||||
|
||||
```solidity
|
||||
interface IStreams {
|
||||
struct Stream {
|
||||
address sender;
|
||||
address recipient;
|
||||
address token;
|
||||
uint256 totalAmount;
|
||||
uint256 startTime;
|
||||
uint256 endTime;
|
||||
uint256 cliffTime;
|
||||
uint256 withdrawn;
|
||||
bool cancelled;
|
||||
}
|
||||
|
||||
/// @notice Emitted when stream created
|
||||
event StreamCreated(
|
||||
uint256 indexed streamId,
|
||||
address indexed sender,
|
||||
address indexed recipient,
|
||||
address token,
|
||||
uint256 totalAmount,
|
||||
uint256 startTime,
|
||||
uint256 endTime,
|
||||
uint256 cliffTime
|
||||
);
|
||||
|
||||
/// @notice Emitted on withdrawal
|
||||
event Withdrawal(
|
||||
uint256 indexed streamId,
|
||||
address indexed recipient,
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
/// @notice Emitted when stream cancelled
|
||||
event StreamCancelled(
|
||||
uint256 indexed streamId,
|
||||
uint256 recipientAmount,
|
||||
uint256 senderAmount
|
||||
);
|
||||
|
||||
/// @notice Create a new payment stream
|
||||
function createStream(
|
||||
address token,
|
||||
address recipient,
|
||||
uint256 totalAmount,
|
||||
uint256 startTime,
|
||||
uint256 duration,
|
||||
uint256 cliffDuration
|
||||
) external returns (uint256 streamId);
|
||||
|
||||
/// @notice Withdraw available funds from stream
|
||||
function withdraw(uint256 streamId) external;
|
||||
|
||||
/// @notice Cancel stream (sender only)
|
||||
function cancel(uint256 streamId) external;
|
||||
|
||||
/// @notice Get withdrawable amount
|
||||
function withdrawable(uint256 streamId) external view returns (uint256);
|
||||
|
||||
/// @notice Get stream details
|
||||
function getStream(uint256 streamId) external view returns (Stream memory);
|
||||
}
|
||||
```
|
||||
|
||||
## Stream Types
|
||||
|
||||
### Linear Stream
|
||||
|
||||
Constant rate throughout duration:
|
||||
|
||||
```
|
||||
Amount
|
||||
^
|
||||
│ ●
|
||||
│ ●────
|
||||
│ ●────
|
||||
│ ●────
|
||||
│ ●────
|
||||
│ ●────
|
||||
│●────
|
||||
└──────────────────────────────► Time
|
||||
```
|
||||
|
||||
### Linear with Cliff
|
||||
|
||||
No withdrawals until cliff, then linear:
|
||||
|
||||
```
|
||||
Amount
|
||||
^
|
||||
│ ●
|
||||
│ ●────
|
||||
│ ●────
|
||||
│ ●────
|
||||
│ ●────
|
||||
│ ●────
|
||||
│ │
|
||||
●─────┘cliff
|
||||
└──────────────────────────────► Time
|
||||
```
|
||||
|
||||
### Exponential (Advanced)
|
||||
|
||||
Custom curves for vesting schedules:
|
||||
|
||||
```
|
||||
Amount
|
||||
^
|
||||
│ ●
|
||||
│ ●
|
||||
│ ●
|
||||
│ ●
|
||||
│ ●
|
||||
│ ●
|
||||
│ ●
|
||||
│ ●
|
||||
│ ●
|
||||
│ ●
|
||||
│●
|
||||
└──────────────────────────────► Time
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Exponential stream (if supported)
|
||||
await streams.createExponentialStream({
|
||||
token: tokenAddress,
|
||||
recipient: recipientAddress,
|
||||
totalAmount: amount,
|
||||
duration: 365 * 24 * 60 * 60,
|
||||
exponent: 2, // Quadratic curve
|
||||
});
|
||||
```
|
||||
|
||||
## Withdrawing from Streams
|
||||
|
||||
### Recipient Withdrawal
|
||||
|
||||
Recipients can withdraw earned funds anytime:
|
||||
|
||||
```typescript
|
||||
// Check withdrawable amount
|
||||
const available = await streams.withdrawable(streamId);
|
||||
console.log(`Withdrawable: ${ethers.formatUnits(available, 6)} USDC`);
|
||||
|
||||
// Withdraw all available
|
||||
const tx = await streams.withdraw(streamId);
|
||||
await tx.wait();
|
||||
```
|
||||
|
||||
### Withdrawal UI
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Your Streams │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Stream #42: Development Contract │
|
||||
│ ────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ ●═══════════════════●░░░░░░░░░░░░░░░░░░░░░░░░░░░░░● │
|
||||
│ Jan 1 Now Dec 31 │
|
||||
│ │
|
||||
│ Progress: 25% (91 days of 365) │
|
||||
│ Earned: $15,000.00 USDC │
|
||||
│ Withdrawn: $10,000.00 USDC │
|
||||
│ Available: $5,000.00 USDC │
|
||||
│ │
|
||||
│ Rate: $164.38/day │
|
||||
│ │
|
||||
│ [ Withdraw $5,000 ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Cancelling Streams
|
||||
|
||||
### When to Cancel
|
||||
|
||||
- Contractor leaves early
|
||||
- Deliverables not met
|
||||
- Budget reallocation needed
|
||||
- Mutual agreement
|
||||
|
||||
### Cancellation Process
|
||||
|
||||
On cancellation:
|
||||
1. Recipient receives all earned (vested) funds
|
||||
2. Remaining funds return to treasury
|
||||
3. Stream marked as cancelled
|
||||
|
||||
```typescript
|
||||
// Cancel a stream
|
||||
const tx = await streams.cancel(streamId);
|
||||
const receipt = await tx.wait();
|
||||
|
||||
// Check settlement
|
||||
const event = receipt.events.find(e => e.event === 'StreamCancelled');
|
||||
console.log(`Recipient received: ${event.args.recipientAmount}`);
|
||||
console.log(`Returned to treasury: ${event.args.senderAmount}`);
|
||||
```
|
||||
|
||||
### Cancellation via Proposal
|
||||
|
||||
```yaml
|
||||
Proposal: "Cancel Stream #42 - Contractor Departure"
|
||||
|
||||
Description: |
|
||||
The contractor has given notice and will depart on March 15.
|
||||
This proposal cancels the stream, settling earned funds.
|
||||
|
||||
## Settlement
|
||||
- Earned (75 days): $12,329.00 USDC → Recipient
|
||||
- Remaining: $47,671.00 USDC → Treasury
|
||||
|
||||
Actions:
|
||||
- type: cancel_stream
|
||||
streamId: 42
|
||||
```
|
||||
|
||||
## Stream Management
|
||||
|
||||
### Viewing Active Streams
|
||||
|
||||
```typescript
|
||||
// Get all streams for treasury
|
||||
const activeStreams = await streams.getActiveStreams(treasuryAddress);
|
||||
|
||||
for (const stream of activeStreams) {
|
||||
const withdrawable = await streams.withdrawable(stream.id);
|
||||
console.log({
|
||||
id: stream.id,
|
||||
recipient: stream.recipient,
|
||||
total: ethers.formatUnits(stream.totalAmount, 6),
|
||||
withdrawn: ethers.formatUnits(stream.withdrawn, 6),
|
||||
available: ethers.formatUnits(withdrawable, 6),
|
||||
progress: `${Math.round((Date.now() / 1000 - stream.startTime) / (stream.endTime - stream.startTime) * 100)}%`
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Stream Dashboard
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Active Streams │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ID Recipient Total Withdrawn Progress │
|
||||
│ ────────────────────────────────────────────────────── │
|
||||
│ 42 0x1234...developer 60K USDC 15K USDC ████░░ 25% │
|
||||
│ 43 0x5678...designer 24K USDC 8K USDC ████░░ 33% │
|
||||
│ 44 0xABCD...community 12K USDC 0 ██░░░░ 10% │
|
||||
│ │
|
||||
│ Total Committed: 96,000 USDC │
|
||||
│ Total Withdrawn: 23,000 USDC │
|
||||
│ Total Remaining: 73,000 USDC │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Advanced Patterns
|
||||
|
||||
### Multi-Stream Compensation
|
||||
|
||||
Create multiple streams for complex packages:
|
||||
|
||||
```yaml
|
||||
Actions:
|
||||
# Base salary
|
||||
- type: create_stream
|
||||
token: USDC
|
||||
recipient: 0x1234...
|
||||
totalAmount: 60000000000
|
||||
duration: 31536000
|
||||
cliffDuration: 0
|
||||
|
||||
# Token vesting
|
||||
- type: create_stream
|
||||
token: DAO
|
||||
recipient: 0x1234...
|
||||
totalAmount: 10000000000000000000000
|
||||
duration: 94608000 # 3 years
|
||||
cliffDuration: 31536000 # 1 year cliff
|
||||
```
|
||||
|
||||
### Milestone-Based Streams
|
||||
|
||||
Combine streams with milestone approvals:
|
||||
|
||||
```typescript
|
||||
// Create stream segments for each milestone
|
||||
const milestones = [
|
||||
{ amount: 10000, duration: 90 * 24 * 60 * 60 }, // Q1
|
||||
{ amount: 15000, duration: 90 * 24 * 60 * 60 }, // Q2
|
||||
{ amount: 20000, duration: 90 * 24 * 60 * 60 }, // Q3
|
||||
{ amount: 15000, duration: 90 * 24 * 60 * 60 }, // Q4
|
||||
];
|
||||
|
||||
// Approve each milestone via separate proposals
|
||||
// Stream for next milestone created upon approval
|
||||
```
|
||||
|
||||
### Refueling Streams
|
||||
|
||||
Top up streams without creating new ones:
|
||||
|
||||
```typescript
|
||||
// If supported by implementation
|
||||
await streams.topUp(streamId, additionalAmount);
|
||||
```
|
||||
|
||||
## Calculating Stream Amounts
|
||||
|
||||
### Daily Rate
|
||||
|
||||
```typescript
|
||||
const dailyRate = totalAmount / durationDays;
|
||||
// $60,000 / 365 = $164.38/day
|
||||
```
|
||||
|
||||
### Monthly Equivalent
|
||||
|
||||
```typescript
|
||||
const monthlyRate = totalAmount / (duration / (30 * 24 * 60 * 60));
|
||||
// $60,000 / 12 = $5,000/month
|
||||
```
|
||||
|
||||
### At Any Point
|
||||
|
||||
```typescript
|
||||
function streamedAmount(stream: Stream, timestamp: number): bigint {
|
||||
if (timestamp < stream.cliffTime) return 0n;
|
||||
if (timestamp >= stream.endTime) return stream.totalAmount;
|
||||
|
||||
const elapsed = timestamp - stream.startTime;
|
||||
const duration = stream.endTime - stream.startTime;
|
||||
|
||||
return (stream.totalAmount * BigInt(elapsed)) / BigInt(duration);
|
||||
}
|
||||
```
|
||||
|
||||
## Common Errors
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `StreamNotFound` | Invalid stream ID | Check stream exists |
|
||||
| `CliffNotReached` | Before cliff | Wait for cliff |
|
||||
| `NothingToWithdraw` | Already withdrawn | Wait for more to vest |
|
||||
| `StreamCancelled` | Already cancelled | Cannot interact |
|
||||
| `Unauthorized` | Not sender/recipient | Check permissions |
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Setting Duration
|
||||
|
||||
| Payment Type | Typical Duration |
|
||||
|--------------|------------------|
|
||||
| Trial period | 1-3 months |
|
||||
| Project work | 3-6 months |
|
||||
| Annual contract | 12 months |
|
||||
| Token vesting | 2-4 years |
|
||||
|
||||
### Setting Cliffs
|
||||
|
||||
| Scenario | Cliff Recommendation |
|
||||
|----------|---------------------|
|
||||
| New contractor | 1 month |
|
||||
| Proven contributor | None |
|
||||
| Token grant | 6-12 months |
|
||||
| Founder vesting | 1 year |
|
||||
|
||||
### Monitoring
|
||||
|
||||
- Track stream progress weekly
|
||||
- Review upcoming stream expirations
|
||||
- Plan renewals in advance
|
||||
- Document cancellation reasons
|
||||
@@ -0,0 +1,434 @@
|
||||
---
|
||||
title: Transfers
|
||||
description: Send one-time payments from treasury
|
||||
---
|
||||
|
||||
# Transfers
|
||||
|
||||
Transfers are the simplest form of payment - sending tokens from the DAO treasury to a single recipient.
|
||||
|
||||
## Overview
|
||||
|
||||
Use transfers for:
|
||||
|
||||
- Invoice payments
|
||||
- Grant disbursements
|
||||
- Expense reimbursements
|
||||
- One-time rewards
|
||||
- Any immediate, single-recipient payment
|
||||
|
||||
## Creating a Transfer
|
||||
|
||||
### Via UI
|
||||
|
||||
1. Navigate to **Treasury** > **Payments**
|
||||
2. Click **"New Transfer"**
|
||||
3. Fill in transfer details
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ New Transfer │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Token: [USDC ▼] │
|
||||
│ │
|
||||
│ Recipient: [0x1234...5678 ] │
|
||||
│ ENS: contributor.eth ✓ │
|
||||
│ │
|
||||
│ Amount: [5,000 ] │
|
||||
│ ≈ $5,000.00 USD │
|
||||
│ │
|
||||
│ Memo: [Invoice #1234 - Q1 Development ] │
|
||||
│ [Milestone completion ] │
|
||||
│ │
|
||||
│ Treasury Balance: 125,000 USDC │
|
||||
│ │
|
||||
│ [ Cancel ] [ Create Transfer ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Via Proposal
|
||||
|
||||
For amounts requiring governance approval:
|
||||
|
||||
```yaml
|
||||
Proposal: "Pay Development Invoice #1234"
|
||||
|
||||
Description: |
|
||||
This proposal pays Invoice #1234 for Q1 development work.
|
||||
|
||||
## Work Completed
|
||||
- Feature A implementation
|
||||
- Bug fixes (12 issues)
|
||||
- Documentation updates
|
||||
|
||||
## Invoice Details
|
||||
- Vendor: Development Team
|
||||
- Invoice: #1234
|
||||
- Amount: $5,000 USDC
|
||||
- Due: January 31, 2026
|
||||
|
||||
Actions:
|
||||
- type: transfer
|
||||
token: USDC
|
||||
to: 0x1234...5678
|
||||
amount: 5000000000 # 5K USDC (6 decimals)
|
||||
memo: "Invoice #1234 - Q1 Development Milestone"
|
||||
```
|
||||
|
||||
### Via SDK
|
||||
|
||||
```typescript
|
||||
import { TreasuryClient } from '@lux/dao-sdk';
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
const treasury = new TreasuryClient(signer);
|
||||
|
||||
// Simple transfer
|
||||
const tx = await treasury.transfer(
|
||||
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
|
||||
'0x1234...5678', // Recipient
|
||||
ethers.parseUnits('5000', 6), // Amount
|
||||
'Invoice #1234 - Q1 Development Milestone' // Memo
|
||||
);
|
||||
|
||||
await tx.wait();
|
||||
console.log('Transfer complete');
|
||||
```
|
||||
|
||||
## Smart Contract Interface
|
||||
|
||||
```solidity
|
||||
interface ITreasury {
|
||||
/// @notice Emitted on transfer
|
||||
event Transfer(
|
||||
address indexed token,
|
||||
address indexed to,
|
||||
uint256 amount,
|
||||
string memo,
|
||||
address indexed executor
|
||||
);
|
||||
|
||||
/// @notice Transfer tokens from treasury
|
||||
/// @param token Token address (address(0) for native)
|
||||
/// @param to Recipient address
|
||||
/// @param amount Amount to transfer
|
||||
/// @param memo Description of payment
|
||||
function transfer(
|
||||
address token,
|
||||
address to,
|
||||
uint256 amount,
|
||||
string calldata memo
|
||||
) external;
|
||||
|
||||
/// @notice Get treasury balance
|
||||
function balance(address token) external view returns (uint256);
|
||||
}
|
||||
```
|
||||
|
||||
## Transfer with Native Token
|
||||
|
||||
For ETH or native chain token:
|
||||
|
||||
```typescript
|
||||
// Transfer native token (ETH)
|
||||
await treasury.transfer(
|
||||
ethers.ZeroAddress, // Use zero address for native
|
||||
recipientAddress,
|
||||
ethers.parseEther('1.5'),
|
||||
'Infrastructure costs reimbursement'
|
||||
);
|
||||
```
|
||||
|
||||
## Approval Workflows
|
||||
|
||||
### Direct Transfer (Small Amounts)
|
||||
|
||||
For amounts within role spending limits:
|
||||
|
||||
```
|
||||
Contributor → Lead Approval → Transfer
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Check if amount is within direct transfer limit
|
||||
const limit = await treasury.spendingLimit(signerAddress);
|
||||
if (amount <= limit) {
|
||||
await treasury.transfer(token, to, amount, memo);
|
||||
} else {
|
||||
console.log('Amount exceeds limit - create proposal');
|
||||
}
|
||||
```
|
||||
|
||||
### Proposal-Based Transfer (Large Amounts)
|
||||
|
||||
For amounts requiring governance:
|
||||
|
||||
```
|
||||
Proposer → Voting → Timelock → Execution
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Proposal flow
|
||||
1. Submit proposal with transfer action
|
||||
2. Community votes (7 days)
|
||||
3. If passed, enters timelock (3 days)
|
||||
4. Anyone can execute after timelock
|
||||
```
|
||||
|
||||
### Multi-Sig Transfer (Emergency/Fast)
|
||||
|
||||
For urgent payments with multi-sig:
|
||||
|
||||
```
|
||||
Signer 1 → Signer 2 → Signer 3 → Transfer
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Using Safe multi-sig
|
||||
const safeTx = await safe.createTransaction({
|
||||
to: treasury.address,
|
||||
data: treasury.interface.encodeFunctionData('transfer', [
|
||||
token, recipient, amount, memo
|
||||
]),
|
||||
value: 0
|
||||
});
|
||||
|
||||
// Collect signatures
|
||||
await safe.signTransaction(safeTx); // Signer 1
|
||||
// ... other signers ...
|
||||
|
||||
// Execute when threshold met
|
||||
await safe.executeTransaction(safeTx);
|
||||
```
|
||||
|
||||
## Scheduled Transfers
|
||||
|
||||
For future-dated payments:
|
||||
|
||||
```typescript
|
||||
// Schedule transfer for specific time
|
||||
const futureTime = Math.floor(Date.now() / 1000) + 7 * 24 * 60 * 60; // 7 days
|
||||
|
||||
await treasury.scheduleTransfer(
|
||||
token,
|
||||
recipient,
|
||||
amount,
|
||||
memo,
|
||||
futureTime
|
||||
);
|
||||
```
|
||||
|
||||
Or via proposal with custom execution time:
|
||||
|
||||
```yaml
|
||||
Proposal: "Scheduled Payment - Q2 Start"
|
||||
|
||||
Actions:
|
||||
- type: transfer
|
||||
token: USDC
|
||||
to: 0x1234...
|
||||
amount: 25000000000
|
||||
memo: "Q2 Budget Release"
|
||||
executeAfter: 1712188800 # April 1, 2026
|
||||
```
|
||||
|
||||
## Recurring Transfers
|
||||
|
||||
For regular payments, consider:
|
||||
|
||||
1. **Streams** - Continuous payment over time
|
||||
2. **Scheduled Proposals** - Quarterly bulk approvals
|
||||
3. **Role-Based Streams** - Automatic for role holders
|
||||
|
||||
Example quarterly approval:
|
||||
|
||||
```yaml
|
||||
Proposal: "Q2 Contributor Payments"
|
||||
|
||||
Description: |
|
||||
Pre-approved monthly payments for Q2 contributors.
|
||||
|
||||
Actions:
|
||||
# April
|
||||
- type: scheduled_transfer
|
||||
token: USDC
|
||||
to: 0xAAA...
|
||||
amount: 5000000000
|
||||
executeAfter: 1712188800
|
||||
|
||||
# May
|
||||
- type: scheduled_transfer
|
||||
token: USDC
|
||||
to: 0xAAA...
|
||||
amount: 5000000000
|
||||
executeAfter: 1714780800
|
||||
|
||||
# June
|
||||
- type: scheduled_transfer
|
||||
token: USDC
|
||||
to: 0xAAA...
|
||||
amount: 5000000000
|
||||
executeAfter: 1717459200
|
||||
```
|
||||
|
||||
## Transfer Verification
|
||||
|
||||
### Pre-Transfer Checks
|
||||
|
||||
```typescript
|
||||
async function verifyTransfer(
|
||||
token: string,
|
||||
to: string,
|
||||
amount: bigint
|
||||
): Promise<boolean> {
|
||||
// 1. Verify recipient address
|
||||
if (!ethers.isAddress(to)) {
|
||||
throw new Error('Invalid recipient address');
|
||||
}
|
||||
|
||||
// 2. Check treasury balance
|
||||
const balance = await treasury.balance(token);
|
||||
if (balance < amount) {
|
||||
throw new Error('Insufficient treasury balance');
|
||||
}
|
||||
|
||||
// 3. Check spending limits
|
||||
const limit = await treasury.spendingLimit(signer.address);
|
||||
if (amount > limit) {
|
||||
throw new Error('Amount exceeds spending limit');
|
||||
}
|
||||
|
||||
// 4. Verify recipient is not blacklisted
|
||||
const isBlocked = await treasury.isBlocked(to);
|
||||
if (isBlocked) {
|
||||
throw new Error('Recipient is blocked');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### Post-Transfer Verification
|
||||
|
||||
```typescript
|
||||
// Verify transfer completed
|
||||
const receipt = await tx.wait();
|
||||
|
||||
// Check event
|
||||
const event = receipt.logs.find(
|
||||
log => log.topics[0] === treasury.interface.getEvent('Transfer').topicHash
|
||||
);
|
||||
|
||||
if (event) {
|
||||
const decoded = treasury.interface.decodeEventLog('Transfer', event.data, event.topics);
|
||||
console.log(`Transferred ${decoded.amount} to ${decoded.to}`);
|
||||
}
|
||||
|
||||
// Verify balances changed
|
||||
const newBalance = await treasury.balance(token);
|
||||
console.log(`Treasury balance: ${newBalance}`);
|
||||
```
|
||||
|
||||
## Memo Best Practices
|
||||
|
||||
Include useful information in memos:
|
||||
|
||||
```typescript
|
||||
// Good memos
|
||||
'Invoice #1234 - Q1 Development Milestone 2'
|
||||
'Grant #56 - Research Project Phase 1'
|
||||
'Reimbursement - ETHDenver travel (Alice)'
|
||||
'Bounty - Bug #789 critical fix'
|
||||
|
||||
// Bad memos
|
||||
'' // Empty
|
||||
'payment' // Too vague
|
||||
'asdf' // Meaningless
|
||||
```
|
||||
|
||||
## Handling Errors
|
||||
|
||||
### Common Errors
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `InsufficientBalance` | Treasury lacks funds | Fund treasury first |
|
||||
| `ExceedsSpendingLimit` | Above your limit | Get approval or use proposal |
|
||||
| `InvalidRecipient` | Bad address format | Verify address |
|
||||
| `RecipientBlocked` | Blocked address | Contact admin |
|
||||
| `TransferFailed` | Token transfer reverted | Check token contract |
|
||||
|
||||
### Error Handling
|
||||
|
||||
```typescript
|
||||
try {
|
||||
await treasury.transfer(token, to, amount, memo);
|
||||
} catch (error) {
|
||||
if (error.message.includes('InsufficientBalance')) {
|
||||
console.error('Treasury needs funding');
|
||||
} else if (error.message.includes('ExceedsSpendingLimit')) {
|
||||
console.error('Create a proposal for this amount');
|
||||
} else {
|
||||
console.error('Transfer failed:', error.message);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Transfer Events
|
||||
|
||||
Track transfers for reporting:
|
||||
|
||||
```typescript
|
||||
// Historical transfers
|
||||
const filter = treasury.filters.Transfer();
|
||||
const events = await treasury.queryFilter(filter, fromBlock, toBlock);
|
||||
|
||||
for (const event of events) {
|
||||
console.log({
|
||||
token: event.args.token,
|
||||
to: event.args.to,
|
||||
amount: event.args.amount.toString(),
|
||||
memo: event.args.memo,
|
||||
executor: event.args.executor,
|
||||
block: event.blockNumber
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Multi-Token Transfers
|
||||
|
||||
Send multiple tokens in one proposal:
|
||||
|
||||
```yaml
|
||||
Proposal: "Contributor Compensation Package"
|
||||
|
||||
Actions:
|
||||
# USDC payment
|
||||
- type: transfer
|
||||
token: USDC
|
||||
to: 0x1234...
|
||||
amount: 5000000000
|
||||
memo: "Monthly stipend"
|
||||
|
||||
# Governance tokens
|
||||
- type: transfer
|
||||
token: DAO
|
||||
to: 0x1234...
|
||||
amount: 10000000000000000000000 # 10K tokens
|
||||
memo: "Performance bonus"
|
||||
```
|
||||
|
||||
## Security Checklist
|
||||
|
||||
Before executing a transfer:
|
||||
|
||||
- [ ] Verify recipient address (check twice)
|
||||
- [ ] Confirm token is correct
|
||||
- [ ] Validate amount (check decimals)
|
||||
- [ ] Review memo for accuracy
|
||||
- [ ] Ensure sufficient balance
|
||||
- [ ] Check spending limits
|
||||
- [ ] Get required approvals
|
||||
- [ ] Simulate transaction first
|
||||
@@ -0,0 +1,302 @@
|
||||
---
|
||||
title: Action-Based Proposals
|
||||
description: Create proposals with executable on-chain actions
|
||||
---
|
||||
|
||||
# Action-Based Proposals
|
||||
|
||||
Action-based proposals contain specific on-chain transactions that execute automatically when the proposal passes and timelock completes.
|
||||
|
||||
## Overview
|
||||
|
||||
When you create an action-based proposal, you're defining exact transactions that will run on the blockchain. This provides:
|
||||
|
||||
- **Transparency** - Everyone can see exactly what will happen
|
||||
- **Automation** - No manual intervention required
|
||||
- **Trustless Execution** - Code executes as written
|
||||
|
||||
## Common Action Types
|
||||
|
||||
### Treasury Transfer
|
||||
|
||||
Send tokens from the DAO treasury to a recipient.
|
||||
|
||||
```yaml
|
||||
Action: Transfer
|
||||
To: 0x1234...5678
|
||||
Amount: 10,000 USDC
|
||||
Memo: "Q1 Development Grant"
|
||||
```
|
||||
|
||||
**UI Steps:**
|
||||
1. Select "Transfer" action
|
||||
2. Choose token from treasury
|
||||
3. Enter recipient address
|
||||
4. Enter amount
|
||||
5. Add optional memo
|
||||
|
||||
### Parameter Update
|
||||
|
||||
Change a protocol parameter.
|
||||
|
||||
```yaml
|
||||
Action: Update Parameter
|
||||
Contract: Governor
|
||||
Parameter: votingPeriod
|
||||
Old Value: 7 days
|
||||
New Value: 5 days
|
||||
```
|
||||
|
||||
**Configurable Parameters:**
|
||||
- Voting period
|
||||
- Quorum threshold
|
||||
- Proposal threshold
|
||||
- Timelock delay
|
||||
|
||||
### Role Management
|
||||
|
||||
Add or remove role members.
|
||||
|
||||
```yaml
|
||||
Action: Grant Role
|
||||
Role: Committee Lead
|
||||
Address: 0xABCD...
|
||||
Permissions: [create_proposal, manage_budget]
|
||||
```
|
||||
|
||||
**Role Actions:**
|
||||
- Grant role to address
|
||||
- Revoke role from address
|
||||
- Create new role
|
||||
- Update role permissions
|
||||
|
||||
### Contract Upgrade
|
||||
|
||||
Upgrade a protocol contract (if upgradeable).
|
||||
|
||||
```yaml
|
||||
Action: Upgrade Contract
|
||||
Proxy: 0x1111...
|
||||
New Implementation: 0x2222...
|
||||
Initialize: initializeV2()
|
||||
```
|
||||
|
||||
<Callout type="warning">
|
||||
Contract upgrades are high-risk operations. Ensure thorough testing and auditing before proposing.
|
||||
</Callout>
|
||||
|
||||
## Creating an Action-Based Proposal
|
||||
|
||||
### Step 1: Select Action Type
|
||||
|
||||
From the proposal creation screen:
|
||||
|
||||
1. Click "Action Based"
|
||||
2. Choose action category:
|
||||
- Treasury
|
||||
- Governance
|
||||
- Roles
|
||||
- Custom
|
||||
|
||||
### Step 2: Configure Action
|
||||
|
||||
**For Treasury Transfer:**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Transfer from Treasury │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Token: [USDC ▼] │
|
||||
│ │
|
||||
│ Recipient: [0x1234...5678 ] │
|
||||
│ │
|
||||
│ Amount: [50,000 ] │
|
||||
│ │
|
||||
│ Available: 125,000 USDC │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ + Add Another Transfer │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Add Multiple Actions
|
||||
|
||||
You can chain multiple actions in a single proposal:
|
||||
|
||||
```yaml
|
||||
actions:
|
||||
# Action 1: Fund the grant program
|
||||
- type: transfer
|
||||
to: grant_multisig
|
||||
amount: 40000
|
||||
token: USDC
|
||||
|
||||
# Action 2: Fund administration
|
||||
- type: transfer
|
||||
to: admin_wallet
|
||||
amount: 5000
|
||||
token: USDC
|
||||
|
||||
# Action 3: Update grant limit
|
||||
- type: parameter
|
||||
contract: grants
|
||||
function: setMaxGrant
|
||||
args: [10000]
|
||||
```
|
||||
|
||||
### Step 4: Simulate Execution
|
||||
|
||||
Before submitting, simulate the proposal:
|
||||
|
||||
1. Click "Simulate"
|
||||
2. Review expected state changes
|
||||
3. Verify no errors
|
||||
4. Check gas estimates
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Simulation Results │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ✓ Action 1: Transfer 40,000 USDC to 0x1234... │
|
||||
│ • Treasury balance: 125,000 → 85,000 USDC │
|
||||
│ • Recipient balance: 0 → 40,000 USDC │
|
||||
│ │
|
||||
│ ✓ Action 2: Transfer 5,000 USDC to 0x5678... │
|
||||
│ • Treasury balance: 85,000 → 80,000 USDC │
|
||||
│ │
|
||||
│ ✓ Action 3: Update maxGrant parameter │
|
||||
│ • Old value: 5,000 │
|
||||
│ • New value: 10,000 │
|
||||
│ │
|
||||
│ Estimated gas: 245,000 │
|
||||
│ Status: ✓ All actions valid │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 5: Add Description
|
||||
|
||||
Write a clear description explaining:
|
||||
|
||||
```markdown
|
||||
## Summary
|
||||
This proposal funds the Q1 2026 Research Grant Program.
|
||||
|
||||
## Actions
|
||||
1. Transfer $40,000 USDC to grant multisig (0x1234...)
|
||||
2. Transfer $5,000 USDC to admin wallet (0x5678...)
|
||||
3. Increase maximum individual grant from $5K to $10K
|
||||
|
||||
## Rationale
|
||||
The Research Committee received 15 qualified applications totaling
|
||||
$120,000 in requests. This funding allows us to support the top
|
||||
applicants while increasing flexibility for exceptional proposals.
|
||||
|
||||
## Budget
|
||||
- Grant awards: $40,000
|
||||
- Administration: $5,000
|
||||
- Total: $45,000
|
||||
|
||||
## Success Metrics
|
||||
- Fund at least 5 grants
|
||||
- Publish research summaries within 6 months
|
||||
- 80% completion rate
|
||||
```
|
||||
|
||||
### Step 6: Submit
|
||||
|
||||
1. Review all actions
|
||||
2. Click "Submit Proposal"
|
||||
3. Confirm in wallet
|
||||
4. Pay gas fee
|
||||
|
||||
## Execution Details
|
||||
|
||||
When a proposal passes:
|
||||
|
||||
1. **Timelock starts** - 3-14 days depending on type
|
||||
2. **Queue** - Actions queued for execution
|
||||
3. **Execution window** - Anyone can trigger execution
|
||||
4. **On-chain** - Transactions execute atomically
|
||||
|
||||
### Atomic Execution
|
||||
|
||||
All actions in a proposal execute together:
|
||||
- If any action fails, all revert
|
||||
- No partial execution
|
||||
- Guaranteed consistency
|
||||
|
||||
### Who Can Execute?
|
||||
|
||||
After timelock expires:
|
||||
- Any wallet can call `execute()`
|
||||
- No special permissions required
|
||||
- Gas paid by executor
|
||||
- Often automated by keepers
|
||||
|
||||
## Advanced Actions
|
||||
|
||||
### Batch Transfers
|
||||
|
||||
Send to multiple recipients:
|
||||
|
||||
```yaml
|
||||
- type: batch_transfer
|
||||
token: USDC
|
||||
transfers:
|
||||
- to: 0xAAA...
|
||||
amount: 10000
|
||||
- to: 0xBBB...
|
||||
amount: 15000
|
||||
- to: 0xCCC...
|
||||
amount: 25000
|
||||
```
|
||||
|
||||
### Streaming Payments
|
||||
|
||||
Set up Sablier streams:
|
||||
|
||||
```yaml
|
||||
- type: create_stream
|
||||
recipient: 0x1234...
|
||||
token: USDC
|
||||
total: 60000
|
||||
duration: 365 days
|
||||
cliff: 30 days
|
||||
```
|
||||
|
||||
### Cross-Chain Actions
|
||||
|
||||
Execute on other chains (if supported):
|
||||
|
||||
```yaml
|
||||
- type: cross_chain
|
||||
target_chain: arbitrum
|
||||
action:
|
||||
type: transfer
|
||||
to: 0x1234...
|
||||
amount: 10000
|
||||
token: USDC
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Errors
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| Insufficient balance | Treasury lacks funds | Reduce amount or fund treasury |
|
||||
| Invalid recipient | Bad address format | Verify address |
|
||||
| Simulation failed | Action would revert | Check parameters |
|
||||
| Gas estimation failed | Complex transaction | Simplify or split |
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
1. **Check token balance** - Ensure treasury has sufficient funds
|
||||
2. **Verify addresses** - Double-check all recipient addresses
|
||||
3. **Test on testnet** - Try actions on testnet first
|
||||
4. **Review permissions** - Ensure DAO has required permissions
|
||||
@@ -0,0 +1,318 @@
|
||||
---
|
||||
title: From Scratch Proposals
|
||||
description: Build custom proposals with any combination of actions
|
||||
---
|
||||
|
||||
# From Scratch Proposals
|
||||
|
||||
From Scratch proposals give you complete flexibility to create custom governance actions. Use this when templates don't cover your needs.
|
||||
|
||||
## When to Use
|
||||
|
||||
- Complex multi-step operations
|
||||
- Custom contract interactions
|
||||
- Novel governance actions
|
||||
- Combining different action types
|
||||
|
||||
## Creating a From Scratch Proposal
|
||||
|
||||
### Step 1: Start New Proposal
|
||||
|
||||
1. Navigate to Proposals → New Proposal
|
||||
2. Select "From Scratch"
|
||||
|
||||
### Step 2: Add Title and Description
|
||||
|
||||
```yaml
|
||||
Title: "Comprehensive Q1 Operations Package"
|
||||
|
||||
Description: |
|
||||
This proposal combines multiple operational needs into a single
|
||||
governance action for efficiency.
|
||||
|
||||
## Components
|
||||
1. Treasury rebalancing
|
||||
2. New role creation
|
||||
3. Parameter updates
|
||||
4. Grant disbursements
|
||||
```
|
||||
|
||||
### Step 3: Build Action List
|
||||
|
||||
Click "Add Action" to build your proposal:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Proposal Actions │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. [Transfer] 50,000 USDC → Research Committee [×] │
|
||||
│ 2. [Transfer] 30,000 USDC → Culture Committee [×] │
|
||||
│ 3. [Contract] updateQuorum(2000000) [×] │
|
||||
│ 4. [Role] Create "Grant Reviewer" role [×] │
|
||||
│ │
|
||||
│ [+ Add Action] │
|
||||
│ │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ Execution Order: Sequential (1 → 2 → 3 → 4) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 4: Configure Each Action
|
||||
|
||||
**Action Configuration Panel:**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Configure Action │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Type: [Custom Contract Call ▼] │
|
||||
│ │
|
||||
│ Target Contract: │
|
||||
│ [0x1234567890abcdef1234567890abcdef12345678 ] │
|
||||
│ │
|
||||
│ Function: │
|
||||
│ [updateQuorum(uint256) ] │
|
||||
│ │
|
||||
│ Parameters: │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ uint256 newQuorum: [2000000 ] │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Value (ETH): [0 ] │
|
||||
│ │
|
||||
│ [Validate] [Add to Proposal] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 5: Reorder Actions
|
||||
|
||||
Drag and drop to change execution order:
|
||||
|
||||
```
|
||||
Actions execute in order. Earlier actions affect later ones.
|
||||
|
||||
Example:
|
||||
1. First, transfer funds TO the multisig
|
||||
2. Then, the multisig can USE those funds
|
||||
|
||||
Not:
|
||||
1. Multisig tries to use funds (FAILS - no balance)
|
||||
2. Transfer funds (too late)
|
||||
```
|
||||
|
||||
### Step 6: Add ABI (if needed)
|
||||
|
||||
For custom contracts, paste the ABI:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"name": "updateQuorum",
|
||||
"type": "function",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "newQuorum",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"outputs": []
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Step 7: Simulate and Submit
|
||||
|
||||
1. Click "Simulate All Actions"
|
||||
2. Review state changes
|
||||
3. Fix any errors
|
||||
4. Submit proposal
|
||||
|
||||
## Complex Examples
|
||||
|
||||
### Example 1: Treasury Rebalancing
|
||||
|
||||
Swap tokens and reallocate:
|
||||
|
||||
```yaml
|
||||
actions:
|
||||
# Step 1: Swap ETH to stablecoins
|
||||
- type: contract_call
|
||||
target: uniswap_router
|
||||
function: swapExactETHForTokens
|
||||
args:
|
||||
- 95000000 # minOut (95 USDC per ETH)
|
||||
- ["WETH", "USDC"]
|
||||
- treasury
|
||||
- deadline
|
||||
value: 10 ETH
|
||||
|
||||
# Step 2: Deposit to yield strategy
|
||||
- type: contract_call
|
||||
target: aave_pool
|
||||
function: deposit
|
||||
args:
|
||||
- USDC
|
||||
- 500000000000 # 500K USDC
|
||||
- treasury
|
||||
- 0
|
||||
|
||||
# Step 3: Update allocation record
|
||||
- type: contract_call
|
||||
target: treasury_tracker
|
||||
function: recordAllocation
|
||||
args:
|
||||
- "aave_usdc"
|
||||
- 500000000000
|
||||
```
|
||||
|
||||
### Example 2: Committee Setup
|
||||
|
||||
Create a new committee with all configurations:
|
||||
|
||||
```yaml
|
||||
actions:
|
||||
# Step 1: Deploy committee Safe
|
||||
- type: contract_call
|
||||
target: safe_factory
|
||||
function: createProxy
|
||||
args:
|
||||
- safe_singleton
|
||||
- setup_data
|
||||
|
||||
# Step 2: Create committee role
|
||||
- type: contract_call
|
||||
target: roles_registry
|
||||
function: createRole
|
||||
args:
|
||||
- "Infrastructure Committee"
|
||||
- ["create_proposal", "manage_treasury", "approve_grants"]
|
||||
|
||||
# Step 3: Assign initial members
|
||||
- type: contract_call
|
||||
target: roles_registry
|
||||
function: grantRole
|
||||
args:
|
||||
- infrastructure_role_id
|
||||
- [member1, member2, member3]
|
||||
|
||||
# Step 4: Fund the committee
|
||||
- type: transfer
|
||||
to: new_committee_safe
|
||||
amount: 100000
|
||||
token: USDC
|
||||
|
||||
# Step 5: Set budget limits
|
||||
- type: contract_call
|
||||
target: treasury_controller
|
||||
function: setCommitteeBudget
|
||||
args:
|
||||
- new_committee_safe
|
||||
- 12 # 12% of WT
|
||||
- 12000 # $12K monthly
|
||||
```
|
||||
|
||||
### Example 3: Emergency Response
|
||||
|
||||
Quick action package for incidents:
|
||||
|
||||
```yaml
|
||||
actions:
|
||||
# Step 1: Pause affected contracts
|
||||
- type: contract_call
|
||||
target: bond_depository
|
||||
function: pause
|
||||
args: []
|
||||
|
||||
# Step 2: Emergency withdrawal
|
||||
- type: contract_call
|
||||
target: treasury
|
||||
function: emergencyWithdraw
|
||||
args:
|
||||
- emergency_multisig
|
||||
- affected_tokens
|
||||
|
||||
# Step 3: Notify downstream
|
||||
- type: contract_call
|
||||
target: notification_registry
|
||||
function: broadcastAlert
|
||||
args:
|
||||
- "SECURITY_INCIDENT"
|
||||
- incident_hash
|
||||
```
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Conditional Logic
|
||||
|
||||
Use helper contracts for conditions:
|
||||
|
||||
```yaml
|
||||
- type: contract_call
|
||||
target: conditional_executor
|
||||
function: executeIf
|
||||
args:
|
||||
- condition_contract
|
||||
- "checkBalance(address,uint256)"
|
||||
- [treasury, 100000]
|
||||
- action_calldata
|
||||
```
|
||||
|
||||
### Batching with Multicall
|
||||
|
||||
Execute many calls efficiently:
|
||||
|
||||
```yaml
|
||||
- type: contract_call
|
||||
target: multicall3
|
||||
function: aggregate3
|
||||
args:
|
||||
- [
|
||||
{ target: contract1, calldata: data1 },
|
||||
{ target: contract2, calldata: data2 },
|
||||
{ target: contract3, calldata: data3 }
|
||||
]
|
||||
```
|
||||
|
||||
### Time-Delayed Actions
|
||||
|
||||
Schedule future execution:
|
||||
|
||||
```yaml
|
||||
- type: contract_call
|
||||
target: timelock_controller
|
||||
function: schedule
|
||||
args:
|
||||
- target
|
||||
- value
|
||||
- calldata
|
||||
- predecessor
|
||||
- salt
|
||||
- delay # Execute after this delay
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Planning
|
||||
|
||||
1. **Map dependencies** - Understand action order
|
||||
2. **Calculate gas** - Complex proposals cost more
|
||||
3. **Test thoroughly** - Use testnets
|
||||
4. **Document clearly** - Explain each action
|
||||
|
||||
### Safety
|
||||
|
||||
1. **Validate addresses** - Triple-check all targets
|
||||
2. **Use checksums** - Prevent typos
|
||||
3. **Simulate first** - Never skip simulation
|
||||
4. **Review ABI** - Ensure correct function signatures
|
||||
|
||||
### Communication
|
||||
|
||||
1. **Detailed descriptions** - Explain every action
|
||||
2. **Technical appendix** - Include raw calldata
|
||||
3. **Risk assessment** - Note potential issues
|
||||
4. **Rollback plan** - How to reverse if needed
|
||||
@@ -0,0 +1,237 @@
|
||||
---
|
||||
title: Creating a Proposal
|
||||
description: How to submit governance proposals
|
||||
---
|
||||
|
||||
# Creating a Proposal
|
||||
|
||||
Proposals (also called Resolutions) are the primary mechanism for governance decisions. This guide covers all proposal types and the creation process.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before creating a proposal:
|
||||
|
||||
- Minimum token requirement (typically 10K voting tokens)
|
||||
- Connected wallet with sufficient balance
|
||||
- Clear understanding of what you're proposing
|
||||
- Community discussion (recommended)
|
||||
|
||||
## Proposal Types
|
||||
|
||||
### Action-Based Proposal
|
||||
|
||||
Executable on-chain actions that take effect automatically when passed.
|
||||
|
||||
<Cards>
|
||||
<Card title="Action-Based" href="/docs/guide/resolutions/action-based" icon="zap">
|
||||
Treasury transfers, parameter changes, contract calls
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
**Examples:**
|
||||
- Transfer funds to a recipient
|
||||
- Update protocol parameters
|
||||
- Upgrade contracts
|
||||
- Add/remove committee members
|
||||
|
||||
### From Scratch Proposal
|
||||
|
||||
Custom proposals for complex or unique situations.
|
||||
|
||||
<Cards>
|
||||
<Card title="From Scratch" href="/docs/guide/resolutions/from-scratch" icon="edit">
|
||||
Build custom proposals with any combination of actions
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
**Examples:**
|
||||
- Multi-step treasury operations
|
||||
- Complex contract interactions
|
||||
- Conditional executions
|
||||
|
||||
### Template Proposal
|
||||
|
||||
Pre-built templates for common governance actions.
|
||||
|
||||
<Cards>
|
||||
<Card title="Templates" href="/docs/guide/resolutions/templates" icon="copy">
|
||||
Use pre-configured proposal templates
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
**Available Templates:**
|
||||
- Grant disbursement
|
||||
- Committee budget allocation
|
||||
- Role creation
|
||||
- Parameter adjustment
|
||||
|
||||
### dApp Explorer Proposal
|
||||
|
||||
Create proposals by interacting with external dApps.
|
||||
|
||||
<Cards>
|
||||
<Card title="dApp Explorer" href="/docs/guide/resolutions/dapp-explorer" icon="globe">
|
||||
Propose transactions from any dApp
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
**Supported Actions:**
|
||||
- DEX swaps
|
||||
- Lending deposits
|
||||
- NFT operations
|
||||
- Any contract interaction
|
||||
|
||||
## Creating a Proposal
|
||||
|
||||
### Step 1: Navigate to Proposals
|
||||
|
||||
1. Go to your DAO dashboard
|
||||
2. Click **"Proposals"** in the sidebar
|
||||
3. Click **"New Proposal"**
|
||||
|
||||
### Step 2: Choose Proposal Type
|
||||
|
||||
Select the type that fits your needs:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Create New Proposal │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Action │ │ From │ │ Template │ │
|
||||
│ │ Based │ │ Scratch │ │ │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────┐ │
|
||||
│ │ dApp │ │
|
||||
│ │ Explorer │ │
|
||||
│ └──────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Fill in Details
|
||||
|
||||
**Required Fields:**
|
||||
|
||||
```yaml
|
||||
Title: "Fund Research Grant Program Q1 2026"
|
||||
|
||||
Description: |
|
||||
This proposal allocates $50,000 from the Research Committee
|
||||
treasury to fund the Q1 2026 grant program.
|
||||
|
||||
## Rationale
|
||||
The Research Committee has received 15 qualified applications...
|
||||
|
||||
## Budget Breakdown
|
||||
- Grant awards: $40,000
|
||||
- Administration: $5,000
|
||||
- Review panel: $5,000
|
||||
|
||||
Actions:
|
||||
- type: transfer
|
||||
to: 0x...
|
||||
amount: 50000
|
||||
token: USDC
|
||||
```
|
||||
|
||||
### Step 4: Add Actions
|
||||
|
||||
For action-based proposals, specify what happens on execution:
|
||||
|
||||
**Transfer Action:**
|
||||
```yaml
|
||||
- type: transfer
|
||||
recipient: 0x1234...
|
||||
amount: 50000
|
||||
token: USDC
|
||||
description: "Q1 Grant Funding"
|
||||
```
|
||||
|
||||
**Contract Call Action:**
|
||||
```yaml
|
||||
- type: contract_call
|
||||
target: 0x5678...
|
||||
function: "updateParameter"
|
||||
args: ["maxSupply", "1000000"]
|
||||
```
|
||||
|
||||
**Multi-action:**
|
||||
```yaml
|
||||
actions:
|
||||
- type: transfer
|
||||
recipient: 0xAAA...
|
||||
amount: 25000
|
||||
token: USDC
|
||||
- type: transfer
|
||||
recipient: 0xBBB...
|
||||
amount: 25000
|
||||
token: USDC
|
||||
```
|
||||
|
||||
### Step 5: Preview and Submit
|
||||
|
||||
1. Click **"Preview"** to review
|
||||
2. Verify all actions are correct
|
||||
3. Click **"Submit Proposal"**
|
||||
4. Sign the transaction
|
||||
|
||||
## After Submission
|
||||
|
||||
### Review Period (3 days)
|
||||
|
||||
- Community can review and comment
|
||||
- No voting yet
|
||||
- Author can provide clarifications
|
||||
- Cannot modify proposal
|
||||
|
||||
### Voting Period (7 days)
|
||||
|
||||
- Token holders vote For/Against/Abstain
|
||||
- Track progress on proposal page
|
||||
- Engage with community questions
|
||||
|
||||
### Post-Voting
|
||||
|
||||
**If Passed:**
|
||||
- Enters timelock queue
|
||||
- After timelock, can be executed
|
||||
- See [Executing a Proposal](/docs/guide/voting/execution)
|
||||
|
||||
**If Failed:**
|
||||
- Can resubmit after 30 days
|
||||
- Consider community feedback
|
||||
- Modify and try again
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Do
|
||||
|
||||
- ✅ Discuss in forum first
|
||||
- ✅ Provide clear rationale
|
||||
- ✅ Include detailed budget
|
||||
- ✅ Set realistic timelines
|
||||
- ✅ Respond to questions
|
||||
|
||||
### Don't
|
||||
|
||||
- ❌ Submit without discussion
|
||||
- ❌ Be vague about intentions
|
||||
- ❌ Request excessive funding
|
||||
- ❌ Ignore community feedback
|
||||
- ❌ Rush the process
|
||||
|
||||
## Proposal Checklist
|
||||
|
||||
Before submitting:
|
||||
|
||||
- [ ] Clear, descriptive title
|
||||
- [ ] Detailed description with rationale
|
||||
- [ ] Specific, verifiable actions
|
||||
- [ ] Budget breakdown (if applicable)
|
||||
- [ ] Success metrics defined
|
||||
- [ ] Community discussion completed
|
||||
- [ ] Reviewed by committee (if applicable)
|
||||
- [ ] Wallet connected with required tokens
|
||||
@@ -0,0 +1,295 @@
|
||||
---
|
||||
title: Template Proposals
|
||||
description: Use pre-built proposal templates for common actions
|
||||
---
|
||||
|
||||
# Template Proposals
|
||||
|
||||
Templates provide pre-configured proposal structures for common governance actions. Fill in the blanks and submit.
|
||||
|
||||
## Available Templates
|
||||
|
||||
### Grant Disbursement
|
||||
|
||||
Fund approved grants with proper documentation.
|
||||
|
||||
```yaml
|
||||
Template: grant_disbursement
|
||||
Fields:
|
||||
- recipient: address
|
||||
- amount: uint256
|
||||
- token: address
|
||||
- grant_id: string
|
||||
- milestone: string
|
||||
```
|
||||
|
||||
**Use when:**
|
||||
- Paying approved grant recipients
|
||||
- Milestone-based funding
|
||||
- Research or development grants
|
||||
|
||||
### Committee Budget Allocation
|
||||
|
||||
Allocate quarterly budget to committees.
|
||||
|
||||
```yaml
|
||||
Template: committee_budget
|
||||
Fields:
|
||||
- committee: address
|
||||
- quarter: string
|
||||
- allocation: uint256
|
||||
- breakdown: string[]
|
||||
```
|
||||
|
||||
**Use when:**
|
||||
- Quarterly budget cycles
|
||||
- Committee funding requests
|
||||
- Budget adjustments
|
||||
|
||||
### Role Creation
|
||||
|
||||
Create new roles with permissions.
|
||||
|
||||
```yaml
|
||||
Template: create_role
|
||||
Fields:
|
||||
- name: string
|
||||
- permissions: string[]
|
||||
- initial_members: address[]
|
||||
- budget_limit: uint256
|
||||
```
|
||||
|
||||
**Use when:**
|
||||
- New working groups
|
||||
- Committee positions
|
||||
- Contributor roles
|
||||
|
||||
### Parameter Adjustment
|
||||
|
||||
Update governance parameters.
|
||||
|
||||
```yaml
|
||||
Template: parameter_change
|
||||
Fields:
|
||||
- parameter: string
|
||||
- current_value: uint256
|
||||
- new_value: uint256
|
||||
- rationale: string
|
||||
```
|
||||
|
||||
**Use when:**
|
||||
- Voting period changes
|
||||
- Quorum adjustments
|
||||
- Fee modifications
|
||||
|
||||
### Emergency Action
|
||||
|
||||
Quick response actions with expedited process.
|
||||
|
||||
```yaml
|
||||
Template: emergency
|
||||
Fields:
|
||||
- action_type: string
|
||||
- affected_contracts: address[]
|
||||
- mitigation_steps: string
|
||||
- requires_guardian: boolean
|
||||
```
|
||||
|
||||
**Use when:**
|
||||
- Security incidents
|
||||
- Critical bugs
|
||||
- Market emergencies
|
||||
|
||||
## Using Templates
|
||||
|
||||
### Step 1: Select Template
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Choose a Template │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 📋 Grant Disbursement [Use] │
|
||||
│ Fund approved grants │
|
||||
│ │
|
||||
│ 💰 Committee Budget [Use] │
|
||||
│ Allocate quarterly budget │
|
||||
│ │
|
||||
│ 👤 Role Creation [Use] │
|
||||
│ Create new roles with permissions │
|
||||
│ │
|
||||
│ ⚙️ Parameter Adjustment [Use] │
|
||||
│ Update governance parameters │
|
||||
│ │
|
||||
│ 🚨 Emergency Action [Use] │
|
||||
│ Quick response for incidents │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Fill Template Fields
|
||||
|
||||
**Example: Grant Disbursement**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Grant Disbursement │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Grant ID: │
|
||||
│ [GR-2026-042 ] │
|
||||
│ │
|
||||
│ Recipient Address: │
|
||||
│ [0x1234567890abcdef1234567890abcdef12345678 ] │
|
||||
│ │
|
||||
│ Amount: │
|
||||
│ [15,000 ] [USDC ▼] │
|
||||
│ │
|
||||
│ Milestone: │
|
||||
│ [Milestone 2: MVP Completion ] │
|
||||
│ │
|
||||
│ ──────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ Supporting Documents: │
|
||||
│ [📎 milestone_report.pdf ] │
|
||||
│ [📎 demo_video.mp4 ] │
|
||||
│ │
|
||||
│ Committee Approval: │
|
||||
│ [Research Committee - Vote #RC-2026-018 ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Auto-Generated Description
|
||||
|
||||
Templates generate formatted descriptions:
|
||||
|
||||
```markdown
|
||||
# Grant Disbursement: GR-2026-042
|
||||
|
||||
## Summary
|
||||
Disbursement of $15,000 USDC to grant recipient for Milestone 2 completion.
|
||||
|
||||
## Details
|
||||
- **Grant ID:** GR-2026-042
|
||||
- **Recipient:** 0x1234...5678
|
||||
- **Amount:** 15,000 USDC
|
||||
- **Milestone:** Milestone 2: MVP Completion
|
||||
|
||||
## Verification
|
||||
- Committee Approval: Research Committee Vote #RC-2026-018
|
||||
- Milestone Report: [IPFS Link]
|
||||
- Demo: [IPFS Link]
|
||||
|
||||
## Actions
|
||||
1. Transfer 15,000 USDC from Treasury to 0x1234...5678
|
||||
2. Update grant status in registry
|
||||
```
|
||||
|
||||
### Step 4: Review and Submit
|
||||
|
||||
1. Review auto-generated content
|
||||
2. Add any custom notes
|
||||
3. Verify all fields
|
||||
4. Submit proposal
|
||||
|
||||
## Custom Templates
|
||||
|
||||
### Creating Organization Templates
|
||||
|
||||
Committees can create custom templates:
|
||||
|
||||
```yaml
|
||||
# custom_template.yaml
|
||||
name: "Research Fellowship"
|
||||
description: "Fund research fellowships"
|
||||
category: "Grants"
|
||||
|
||||
fields:
|
||||
- name: fellow_name
|
||||
type: string
|
||||
required: true
|
||||
|
||||
- name: institution
|
||||
type: string
|
||||
required: true
|
||||
|
||||
- name: research_topic
|
||||
type: string
|
||||
required: true
|
||||
|
||||
- name: duration_months
|
||||
type: number
|
||||
min: 3
|
||||
max: 24
|
||||
|
||||
- name: monthly_stipend
|
||||
type: number
|
||||
token: USDC
|
||||
|
||||
actions:
|
||||
- type: create_stream
|
||||
recipient: "{{fellow_address}}"
|
||||
total: "{{monthly_stipend * duration_months}}"
|
||||
duration: "{{duration_months}} months"
|
||||
|
||||
- type: register
|
||||
contract: fellowship_registry
|
||||
data:
|
||||
fellow: "{{fellow_name}}"
|
||||
institution: "{{institution}}"
|
||||
topic: "{{research_topic}}"
|
||||
```
|
||||
|
||||
### Submitting Custom Templates
|
||||
|
||||
1. Draft template in YAML format
|
||||
2. Submit template proposal
|
||||
3. Committee review
|
||||
4. If approved, template becomes available
|
||||
|
||||
## Template Best Practices
|
||||
|
||||
### For Template Users
|
||||
|
||||
- ✅ Verify all fields before submission
|
||||
- ✅ Attach supporting documentation
|
||||
- ✅ Reference approval votes
|
||||
- ✅ Use appropriate template
|
||||
|
||||
### For Template Creators
|
||||
|
||||
- ✅ Clear field descriptions
|
||||
- ✅ Sensible defaults
|
||||
- ✅ Input validation
|
||||
- ✅ Comprehensive auto-description
|
||||
- ✅ Proper error messages
|
||||
|
||||
## Template Library
|
||||
|
||||
### Finance Templates
|
||||
|
||||
| Template | Description |
|
||||
|----------|-------------|
|
||||
| grant_disbursement | Pay approved grants |
|
||||
| committee_budget | Quarterly allocations |
|
||||
| stream_payment | Create payment streams |
|
||||
| batch_transfer | Multiple transfers |
|
||||
|
||||
### Governance Templates
|
||||
|
||||
| Template | Description |
|
||||
|----------|-------------|
|
||||
| create_role | New role with permissions |
|
||||
| update_role | Modify existing role |
|
||||
| remove_role | Revoke role |
|
||||
| parameter_change | Update parameters |
|
||||
|
||||
### Operations Templates
|
||||
|
||||
| Template | Description |
|
||||
|----------|-------------|
|
||||
| create_subdao | New Sub-DAO |
|
||||
| working_group | New working group |
|
||||
| committee_election | Run election |
|
||||
| emergency_action | Quick response |
|
||||
@@ -0,0 +1,353 @@
|
||||
---
|
||||
title: General Settings
|
||||
description: Configure basic project information and branding
|
||||
---
|
||||
|
||||
# General Settings
|
||||
|
||||
General settings control your project's identity, branding, and basic configuration. These settings are typically visible to all users and define how your DAO appears publicly.
|
||||
|
||||
## Project Identity
|
||||
|
||||
### Project Name
|
||||
|
||||
The display name for your DAO or governance project.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Project Name │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Name: [My DAO Project___________________________] │
|
||||
│ │
|
||||
│ Requirements: │
|
||||
│ - 3-50 characters │
|
||||
│ - Alphanumeric and spaces │
|
||||
│ - No special characters except hyphens │
|
||||
│ │
|
||||
│ This name appears in: │
|
||||
│ - Navigation and headers │
|
||||
│ - Proposal listings │
|
||||
│ - External integrations │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
A brief description of your project's purpose and mission.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Description │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ A decentralized governance platform enabling community- │ │
|
||||
│ │ driven decision-making for protocol development and │ │
|
||||
│ │ treasury management. │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Character count: 156/500 │
|
||||
│ │
|
||||
│ Tips: │
|
||||
│ - Be clear and concise │
|
||||
│ - Explain the DAO's purpose │
|
||||
│ - Avoid jargon │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Logo and Branding
|
||||
|
||||
Upload your project's visual identity.
|
||||
|
||||
| Asset | Specifications | Use |
|
||||
|-------|----------------|-----|
|
||||
| Logo | 256x256px, PNG/SVG | Headers, listings |
|
||||
| Icon | 64x64px, PNG | Favicons, compact views |
|
||||
| Banner | 1200x400px, PNG/JPG | Project pages |
|
||||
| Primary Color | Hex code | UI accents |
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Branding │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Logo Icon Banner │
|
||||
│ ┌─────────────┐ ┌───────┐ ┌────────────┐ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ [Logo] │ │ [Icon]│ │ [Banner] │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ └─────────────┘ └───────┘ └────────────┘ │
|
||||
│ [Upload] [Upload] [Upload] │
|
||||
│ │
|
||||
│ Primary Color: [#3B82F6_] ████ │
|
||||
│ Secondary Color: [#1E40AF_] ████ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## External Links
|
||||
|
||||
### Website and Social
|
||||
|
||||
Connect your external presence:
|
||||
|
||||
| Link Type | Example | Required |
|
||||
|-----------|---------|----------|
|
||||
| Website | https://dao.example.com | Yes |
|
||||
| Documentation | https://docs.example.com | Recommended |
|
||||
| Forum | https://forum.example.com | Recommended |
|
||||
| Discord | https://discord.gg/example | Recommended |
|
||||
| Twitter | @example | Recommended |
|
||||
| GitHub | https://github.com/example | Optional |
|
||||
| Blog | https://blog.example.com | Optional |
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ External Links │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Website: [https://dao.example.com_______] ✓ Verified │
|
||||
│ Documentation: [https://docs.example.com______] ✓ Verified │
|
||||
│ Forum: [https://forum.example.com_____] ✓ Verified │
|
||||
│ Discord: [https://discord.gg/example____] ✓ Verified │
|
||||
│ Twitter: [@example______________________] ✓ Verified │
|
||||
│ GitHub: [https://github.com/example____] ○ Optional │
|
||||
│ │
|
||||
│ [+ Add Custom Link] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Custom Links
|
||||
|
||||
Add additional links specific to your project:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Custom Links │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ │ Label │ URL │ Actions │ │
|
||||
│ │────────────────│──────────────────────────────│─────────│ │
|
||||
│ │ Whitepaper │ https://example.com/white... │ [Edit] │ │
|
||||
│ │ Bug Bounty │ https://immunefi.com/bounty │ [Edit] │ │
|
||||
│ │ Brand Assets │ https://example.com/brand │ [Edit] │ │
|
||||
│ │
|
||||
│ [+ Add Link] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Contact Information
|
||||
|
||||
### Support Contact
|
||||
|
||||
Configure how users can reach your team:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Contact Information │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Support Email: [support@example.com_________] │
|
||||
│ │
|
||||
│ Support Options: │
|
||||
│ ☑ Discord Support Channel │
|
||||
│ ☑ Email Support │
|
||||
│ ☐ Telegram Support │
|
||||
│ ☐ In-app Chat │
|
||||
│ │
|
||||
│ Response Time: [24 hours ▼] │
|
||||
│ │
|
||||
│ Support Hours: │
|
||||
│ ○ 24/7 (automated + human) │
|
||||
│ ● Business hours (9-5 UTC) │
|
||||
│ ○ Community-driven │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Display Settings
|
||||
|
||||
### Language and Localization
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Localization │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Primary Language: [English ▼] │
|
||||
│ │
|
||||
│ Additional Languages: │
|
||||
│ ☑ Spanish │
|
||||
│ ☑ Chinese (Simplified) │
|
||||
│ ☐ Chinese (Traditional) │
|
||||
│ ☑ Japanese │
|
||||
│ ☐ Korean │
|
||||
│ ☑ Portuguese │
|
||||
│ ☑ French │
|
||||
│ ☐ German │
|
||||
│ ☐ Russian │
|
||||
│ ☐ Arabic │
|
||||
│ ☐ Persian │
|
||||
│ │
|
||||
│ Timezone Display: [User's local time ▼] │
|
||||
│ Date Format: [YYYY-MM-DD ▼] │
|
||||
│ Number Format: [1,234.56 ▼] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### UI Preferences
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ UI Preferences │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Theme: │
|
||||
│ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │ Light │ │ ●Dark │ │ System │ │
|
||||
│ └────────┘ └────────┘ └────────┘ │
|
||||
│ │
|
||||
│ Layout: │
|
||||
│ ○ Compact - Dense information display │
|
||||
│ ● Standard - Balanced spacing │
|
||||
│ ○ Spacious - More whitespace │
|
||||
│ │
|
||||
│ Dashboard Widgets: │
|
||||
│ ☑ Active Proposals │
|
||||
│ ☑ Voting Power │
|
||||
│ ☑ Treasury Balance │
|
||||
│ ☐ Recent Activity │
|
||||
│ ☑ Delegation Status │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Notifications
|
||||
|
||||
### Default Notification Preferences
|
||||
|
||||
Set default notification settings for new members:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Notification Defaults │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ │ Event │ Email │ Push │ Discord │ │
|
||||
│ │──────────────────────────│───────│──────│─────────│ │
|
||||
│ │ New Proposal Created │ ☑ │ ☑ │ ☑ │ │
|
||||
│ │ Voting Starts │ ☑ │ ☑ │ ☑ │ │
|
||||
│ │ Voting Ends (Reminder) │ ☑ │ ☑ │ ☑ │ │
|
||||
│ │ Proposal Passed │ ☐ │ ☐ │ ☑ │ │
|
||||
│ │ Proposal Executed │ ☐ │ ☐ │ ☑ │ │
|
||||
│ │ Delegation Received │ ☑ │ ☐ │ ☐ │ │
|
||||
│ │ Treasury Activity │ ☐ │ ☐ │ ☑ │ │
|
||||
│ │
|
||||
│ Note: Users can customize their own preferences │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Privacy Settings
|
||||
|
||||
### Data Collection
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Privacy Settings │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Analytics: │
|
||||
│ ☑ Basic usage analytics (page views, feature usage) │
|
||||
│ ☐ Advanced analytics (user journeys, cohort analysis) │
|
||||
│ │
|
||||
│ Public Information: │
|
||||
│ ☑ Show all voting history publicly │
|
||||
│ ☑ Show delegation relationships │
|
||||
│ ☐ Show individual balances │
|
||||
│ │
|
||||
│ Member Directory: │
|
||||
│ ○ Public - Anyone can see members │
|
||||
│ ● Members Only - Only members see each other │
|
||||
│ ○ Hidden - No member directory │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Saving Changes
|
||||
|
||||
### Immediate Changes
|
||||
|
||||
Changes to these settings take effect immediately:
|
||||
|
||||
- Project name and description
|
||||
- Logo and branding
|
||||
- External links
|
||||
- Contact information
|
||||
- Display preferences
|
||||
- Notification defaults
|
||||
|
||||
### Confirmation Required
|
||||
|
||||
Some changes require confirmation:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Confirm Changes │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ You are about to change: │
|
||||
│ │
|
||||
│ - Project Name: "Old Name" → "New Name" │
|
||||
│ - Primary Color: #3B82F6 → #10B981 │
|
||||
│ │
|
||||
│ These changes will be visible to all users immediately. │
|
||||
│ │
|
||||
│ [Cancel] [Confirm Changes] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Branding Consistency
|
||||
|
||||
- Use consistent colors and logos across all platforms
|
||||
- Ensure logo is readable at small sizes
|
||||
- Test color contrast for accessibility
|
||||
- Keep descriptions clear and up-to-date
|
||||
|
||||
### Link Management
|
||||
|
||||
- Regularly verify all links work
|
||||
- Update links when URLs change
|
||||
- Use permanent/stable URLs when possible
|
||||
- Include relevant context with custom links
|
||||
|
||||
### Communication
|
||||
|
||||
- Keep contact information current
|
||||
- Set realistic response time expectations
|
||||
- Document support procedures
|
||||
- Monitor all listed channels
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Governance Settings" href="/docs/guide/settings/governance" icon="vote">
|
||||
Configure voting parameters
|
||||
</Card>
|
||||
<Card title="Token Setup" href="/docs/guide/token-setup" icon="coins">
|
||||
Set up project tokens
|
||||
</Card>
|
||||
<Card title="Access Control" href="/docs/guide/roles" icon="shield">
|
||||
Manage roles and permissions
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,470 @@
|
||||
---
|
||||
title: Governance Settings
|
||||
description: Configure voting periods, thresholds, and governance parameters
|
||||
---
|
||||
|
||||
# Governance Settings
|
||||
|
||||
Governance settings control how proposals are created, voted on, and executed. These settings define the rules that govern your DAO's decision-making process.
|
||||
|
||||
<Callout type="warning">
|
||||
Most governance settings require a governance proposal to change. Modifications affect all future proposals and should be carefully considered.
|
||||
</Callout>
|
||||
|
||||
## Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Governance Settings │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Proposal Lifecycle │
|
||||
│ ───────────────── │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Creation │───▶│ Voting │───▶│ Timelock │───▶│Execution │ │
|
||||
│ │Threshold │ │ Period │ │ Delay │ │ │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
│ 100K tokens 7 days 3 days Immediate │
|
||||
│ │
|
||||
│ Vote Requirements │
|
||||
│ ───────────────── │
|
||||
│ Quorum: 1,000,000 tokens (participation minimum) │
|
||||
│ Approval: >50% For votes (standard proposals) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Proposal Settings
|
||||
|
||||
### Proposal Threshold
|
||||
|
||||
The minimum voting power required to create a proposal.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Proposal Threshold │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Current Value: 100,000 veTOKEN │
|
||||
│ │
|
||||
│ New Value: [100000________] veTOKEN │
|
||||
│ │
|
||||
│ │ Threshold │ % of Supply │ Effect │ │
|
||||
│ │───────────│─────────────│──────────────────────────────│ │
|
||||
│ │ 10,000 │ 0.1% │ Very accessible │ │
|
||||
│ │ 100,000 │ 1% │ Moderate barrier (current) │ │
|
||||
│ │ 500,000 │ 5% │ Significant barrier │ │
|
||||
│ │ 1,000,000 │ 10% │ High barrier │ │
|
||||
│ │
|
||||
│ ⚠ Requires governance vote to change │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Considerations:**
|
||||
- **Too low**: Spam proposals, cluttered governance
|
||||
- **Too high**: Limits participation, centralizes power
|
||||
- **Balance**: Allow engaged members to propose while preventing noise
|
||||
|
||||
### Proposal Deposit
|
||||
|
||||
Optional deposit required when creating proposals.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Proposal Deposit │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ☑ Require deposit to create proposals │
|
||||
│ │
|
||||
│ Deposit Amount: [1000______] TOKEN │
|
||||
│ │
|
||||
│ Deposit Return: │
|
||||
│ ● Returned if proposal passes OR reaches quorum │
|
||||
│ ○ Returned only if proposal passes │
|
||||
│ ○ Never returned (fee-based) │
|
||||
│ │
|
||||
│ Slash Conditions: │
|
||||
│ ☑ Proposal fails to reach quorum │
|
||||
│ ☐ Proposal is defeated │
|
||||
│ ☐ Proposal is vetoed │
|
||||
│ │
|
||||
│ Slashed deposits go to: [Treasury ▼] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Voting Settings
|
||||
|
||||
### Voting Period
|
||||
|
||||
How long the voting window remains open.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Voting Period │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Current Value: 7 days │
|
||||
│ │
|
||||
│ New Value: [7___] days │
|
||||
│ │
|
||||
│ │ Duration │ Blocks (~) │ Trade-off │ │
|
||||
│ │──────────│────────────│───────────────────────────────│ │
|
||||
│ │ 3 days │ ~21,600 │ Fast decisions, less input │ │
|
||||
│ │ 7 days │ ~50,400 │ Balanced (recommended) │ │
|
||||
│ │ 14 days │ ~100,800 │ Maximum input, slow execution │ │
|
||||
│ │
|
||||
│ Note: Voting period is measured in blocks for precision │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Voting Delay
|
||||
|
||||
Optional delay between proposal creation and voting start.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Voting Delay │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ☑ Enable voting delay │
|
||||
│ │
|
||||
│ Delay Duration: [1___] days │
|
||||
│ │
|
||||
│ Purpose: │
|
||||
│ - Allows community to prepare before voting starts │
|
||||
│ - Prevents snapshot manipulation │
|
||||
│ - Enables token accumulation before snapshot │
|
||||
│ │
|
||||
│ Timeline with delay: │
|
||||
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │Create │─▶│ Delay │─▶│ Voting │─▶│Timelock│ │
|
||||
│ │ │ │ 1 day │ │ 7 days │ │ 3 days │ │
|
||||
│ └────────┘ └────────┘ └────────┘ └────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Quorum Settings
|
||||
|
||||
Minimum participation required for a valid vote.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Quorum Settings │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Quorum Type: │
|
||||
│ ● Fixed Amount │
|
||||
│ ○ Percentage of Supply │
|
||||
│ ○ Percentage of Locked Supply │
|
||||
│ │
|
||||
│ Quorum Value: [1000000_____] veTOKEN │
|
||||
│ │
|
||||
│ │ Type │ Standard │ Constitutional │ Emergency │ │
|
||||
│ │────────────│──────────│────────────────│───────────│ │
|
||||
│ │ Quorum │ 1M │ 5M │ 500K │ │
|
||||
│ │ % Supply │ 10% │ 50% │ 5% │ │
|
||||
│ │
|
||||
│ Quorum includes: │
|
||||
│ ☑ For votes │
|
||||
│ ☑ Against votes │
|
||||
│ ☑ Abstain votes │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Approval Threshold
|
||||
|
||||
Percentage of For votes required to pass.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Approval Threshold │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Standard Proposals: │
|
||||
│ Approval Required: [50__]% + 1 │
|
||||
│ (Simple majority) │
|
||||
│ │
|
||||
│ Constitutional Proposals: │
|
||||
│ Approval Required: [67__]% │
|
||||
│ (Supermajority) │
|
||||
│ │
|
||||
│ Emergency Proposals: │
|
||||
│ Approval Required: [75__]% │
|
||||
│ (High consensus) │
|
||||
│ │
|
||||
│ Calculation: │
|
||||
│ Approval % = For / (For + Against) × 100 │
|
||||
│ (Abstain votes excluded from calculation) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Timelock Settings
|
||||
|
||||
### Timelock Delay
|
||||
|
||||
Mandatory waiting period before execution.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Timelock Settings │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ │ Proposal Type │ Timelock │ Purpose │ │
|
||||
│ │──────────────────│──────────│────────────────────────────│ │
|
||||
│ │ Standard │ 3 days │ Community review │ │
|
||||
│ │ Constitutional │ 14 days │ Extended review │ │
|
||||
│ │ Emergency │ 0 days │ Immediate action │ │
|
||||
│ │
|
||||
│ Standard Timelock: [3___] days │
|
||||
│ Constitutional Timelock: [14__] days │
|
||||
│ │
|
||||
│ Grace Period: [7___] days │
|
||||
│ (Time to execute after timelock expires) │
|
||||
│ │
|
||||
│ ⚠ If not executed within grace period, proposal expires │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Cancellation Rules
|
||||
|
||||
Who can cancel pending proposals.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Cancellation Rules │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Proposals can be cancelled by: │
|
||||
│ ☑ Proposer (before voting ends) │
|
||||
│ ☑ Guardian/Admin (any time before execution) │
|
||||
│ ☐ Governance vote (during timelock) │
|
||||
│ │
|
||||
│ Guardian Address: [0x1234...abcd] │
|
||||
│ │
|
||||
│ Auto-cancel conditions: │
|
||||
│ ☑ Proposer's voting power drops below threshold │
|
||||
│ ☐ Quorum not met at end of voting │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Proposal Types
|
||||
|
||||
### Standard Proposals
|
||||
|
||||
Default proposal type for routine governance.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Standard Proposal Settings │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Allowed Actions: │
|
||||
│ ☑ Treasury transfers (< $100,000) │
|
||||
│ ☑ Role assignments │
|
||||
│ ☑ Parameter updates (within range) │
|
||||
│ ☑ External contract calls │
|
||||
│ │
|
||||
│ Settings: │
|
||||
│ - Proposal Threshold: 100,000 veTOKEN │
|
||||
│ - Voting Period: 7 days │
|
||||
│ - Quorum: 1,000,000 veTOKEN │
|
||||
│ - Approval: >50% │
|
||||
│ - Timelock: 3 days │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Constitutional Proposals
|
||||
|
||||
For significant protocol changes.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Constitutional Proposal Settings │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Required for: │
|
||||
│ ☑ Contract upgrades │
|
||||
│ ☑ Governance parameter changes │
|
||||
│ ☑ Treasury transfers > $100,000 │
|
||||
│ ☑ Adding/removing signers │
|
||||
│ │
|
||||
│ Settings: │
|
||||
│ - Proposal Threshold: 500,000 veTOKEN │
|
||||
│ - Voting Period: 14 days │
|
||||
│ - Quorum: 5,000,000 veTOKEN │
|
||||
│ - Approval: >66.7% │
|
||||
│ - Timelock: 14 days │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Emergency Proposals
|
||||
|
||||
For urgent security actions.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Emergency Proposal Settings │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ⚠ Emergency proposals bypass normal timelock │
|
||||
│ │
|
||||
│ Allowed for: │
|
||||
│ ☑ Pausing contracts │
|
||||
│ ☑ Revoking compromised permissions │
|
||||
│ ☐ Treasury transfers │
|
||||
│ ☐ Contract upgrades │
|
||||
│ │
|
||||
│ Settings: │
|
||||
│ - Proposal Threshold: 500,000 veTOKEN │
|
||||
│ - Voting Period: 3 days │
|
||||
│ - Quorum: 500,000 veTOKEN │
|
||||
│ - Approval: >75% │
|
||||
│ - Timelock: 0 days (immediate) │
|
||||
│ │
|
||||
│ Requires Guardian approval: ☑ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Vote Counting
|
||||
|
||||
### Counting Method
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Vote Counting Method │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Method: │
|
||||
│ ● Simple Voting (For/Against/Abstain) │
|
||||
│ ○ Ranked Choice │
|
||||
│ ○ Quadratic Voting │
|
||||
│ ○ Conviction Voting │
|
||||
│ │
|
||||
│ Abstain Handling: │
|
||||
│ ● Count toward quorum only │
|
||||
│ ○ Count as neutral vote │
|
||||
│ ○ Exclude entirely │
|
||||
│ │
|
||||
│ Tie Breaking: │
|
||||
│ ● Proposal fails on tie │
|
||||
│ ○ Guardian decides │
|
||||
│ ○ Extended voting period │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Snapshot Timing
|
||||
|
||||
When voting power is calculated.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Snapshot Settings │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Snapshot Block: │
|
||||
│ ● At proposal creation │
|
||||
│ ○ At voting start (after delay) │
|
||||
│ ○ Custom block height │
|
||||
│ │
|
||||
│ Implications: │
|
||||
│ - Voting power is locked at snapshot │
|
||||
│ - Token transfers after snapshot don't affect vote │
|
||||
│ - Prevents vote buying during active proposals │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Changing Settings
|
||||
|
||||
### Governance-Required Changes
|
||||
|
||||
To modify governance settings:
|
||||
|
||||
1. **Create Proposal**: Submit a constitutional proposal
|
||||
2. **Discussion Period**: Allow community review
|
||||
3. **Voting**: Token holders vote on changes
|
||||
4. **Timelock**: Changes queue for execution
|
||||
5. **Execution**: New settings take effect
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Propose Governance Change │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ This change requires a governance proposal. │
|
||||
│ │
|
||||
│ Proposed Change: │
|
||||
│ - Setting: Voting Period │
|
||||
│ - Current: 7 days │
|
||||
│ - Proposed: 10 days │
|
||||
│ │
|
||||
│ Proposal Type: Constitutional │
|
||||
│ Expected Timeline: ~30 days │
|
||||
│ │
|
||||
│ [Cancel] [Create Proposal] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
<Callout type="info">
|
||||
**Best Practice**: Make incremental changes to governance parameters. Large changes may have unintended consequences.
|
||||
</Callout>
|
||||
|
||||
## Recommended Configurations
|
||||
|
||||
### Conservative (High Security)
|
||||
|
||||
```
|
||||
Proposal Threshold: 500,000 tokens (5%)
|
||||
Voting Period: 14 days
|
||||
Quorum: 20% of supply
|
||||
Approval: 67%
|
||||
Timelock: 14 days
|
||||
```
|
||||
|
||||
### Balanced (Recommended)
|
||||
|
||||
```
|
||||
Proposal Threshold: 100,000 tokens (1%)
|
||||
Voting Period: 7 days
|
||||
Quorum: 10% of supply
|
||||
Approval: 50%+1
|
||||
Timelock: 3 days
|
||||
```
|
||||
|
||||
### Agile (Fast Decisions)
|
||||
|
||||
```
|
||||
Proposal Threshold: 10,000 tokens (0.1%)
|
||||
Voting Period: 3 days
|
||||
Quorum: 5% of supply
|
||||
Approval: 50%+1
|
||||
Timelock: 1 day
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="General Settings" href="/docs/guide/settings/general" icon="settings">
|
||||
Configure basic project information
|
||||
</Card>
|
||||
<Card title="Voting Guide" href="/docs/guide/voting" icon="vote">
|
||||
Learn about the voting process
|
||||
</Card>
|
||||
<Card title="Creating Proposals" href="/docs/guide/resolutions" icon="file-plus">
|
||||
Submit governance proposals
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,249 @@
|
||||
---
|
||||
title: Project Settings
|
||||
description: Configure and manage your DAO project settings
|
||||
---
|
||||
|
||||
# Project Settings
|
||||
|
||||
This guide covers how to configure and manage settings for your DAO project. Settings control governance parameters, token configurations, access permissions, and more.
|
||||
|
||||
## Overview
|
||||
|
||||
Project settings are organized into categories:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Settings Overview │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ General │ │ Governance │ │ Tokens │ │
|
||||
│ │ Settings │ │ Settings │ │ Settings │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Access │ │ Treasury │ │ Integrations│ │
|
||||
│ │ Control │ │ Settings │ │ │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Settings Categories
|
||||
|
||||
<Cards>
|
||||
<Card title="General Settings" href="/docs/guide/settings/general" icon="settings">
|
||||
Project name, description, links, and branding
|
||||
</Card>
|
||||
<Card title="Governance Settings" href="/docs/guide/settings/governance" icon="vote">
|
||||
Voting periods, thresholds, and quorum requirements
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## Accessing Settings
|
||||
|
||||
### Admin Access
|
||||
|
||||
To modify settings, you need admin permissions:
|
||||
|
||||
1. Navigate to **Project > Settings**
|
||||
2. Select the category you want to modify
|
||||
3. Make changes and save
|
||||
4. Changes may require governance approval
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Project Settings [Admin Required] │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Navigation │ │
|
||||
│ │ │ │
|
||||
│ │ ▸ General │ │
|
||||
│ │ ▸ Governance │ │
|
||||
│ │ ▸ Tokens │ │
|
||||
│ │ ▸ Access Control │ │
|
||||
│ │ ▸ Treasury │ │
|
||||
│ │ ▸ Integrations │ │
|
||||
│ │ ▸ Advanced │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Select a category to view and modify settings │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Permission Levels
|
||||
|
||||
| Level | Can View | Can Modify | Requires Vote |
|
||||
|-------|----------|------------|---------------|
|
||||
| Member | Yes | No | N/A |
|
||||
| Contributor | Yes | Limited | No |
|
||||
| Admin | Yes | Yes | Some settings |
|
||||
| Owner | Yes | Yes | Critical settings |
|
||||
|
||||
## Settings Change Process
|
||||
|
||||
### Immediate Changes
|
||||
|
||||
Some settings can be changed immediately by admins:
|
||||
|
||||
- Project name and description
|
||||
- External links
|
||||
- Notification preferences
|
||||
- Display settings
|
||||
|
||||
### Governance-Required Changes
|
||||
|
||||
Critical settings require governance approval:
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Settings Change Flow │
|
||||
│ ─────────────────── │
|
||||
│ │
|
||||
│ 1. Admin proposes change │
|
||||
│ 2. System creates governance proposal │
|
||||
│ 3. Token holders vote │
|
||||
│ 4. If passed, change enters timelock │
|
||||
│ 5. After timelock, change is applied │
|
||||
│ │
|
||||
│ Timeline: 7-14 days typical │
|
||||
│ │
|
||||
└────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Settings requiring governance:
|
||||
|
||||
- Voting period changes
|
||||
- Quorum threshold changes
|
||||
- Token configurations
|
||||
- Access control modifications
|
||||
- Treasury parameters
|
||||
|
||||
## Settings Summary
|
||||
|
||||
### General Settings
|
||||
|
||||
| Setting | Description | Requires Vote |
|
||||
|---------|-------------|---------------|
|
||||
| Project Name | Display name | No |
|
||||
| Description | Project description | No |
|
||||
| Logo | Project logo/avatar | No |
|
||||
| Links | Website, social links | No |
|
||||
| Contact | Support email | No |
|
||||
|
||||
### Governance Settings
|
||||
|
||||
| Setting | Description | Requires Vote |
|
||||
|---------|-------------|---------------|
|
||||
| Voting Period | How long votes are open | Yes |
|
||||
| Timelock Delay | Delay before execution | Yes |
|
||||
| Proposal Threshold | Tokens needed to propose | Yes |
|
||||
| Quorum | Minimum participation | Yes |
|
||||
|
||||
### Token Settings
|
||||
|
||||
| Setting | Description | Requires Vote |
|
||||
|---------|-------------|---------------|
|
||||
| Governance Token | Token used for voting | Yes |
|
||||
| Lock Parameters | Min/max lock durations | Yes |
|
||||
| Multipliers | Time-based multipliers | Yes |
|
||||
|
||||
### Treasury Settings
|
||||
|
||||
| Setting | Description | Requires Vote |
|
||||
|---------|-------------|---------------|
|
||||
| Spending Limits | Per-transaction limits | Yes |
|
||||
| Approved Tokens | Tokens treasury can hold | Yes |
|
||||
| Reserve Requirements | Minimum reserves | Yes |
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Before Changing Settings
|
||||
|
||||
1. **Understand Impact**
|
||||
- How will this affect governance?
|
||||
- Are there unintended consequences?
|
||||
- Have similar changes been made elsewhere?
|
||||
|
||||
2. **Communicate**
|
||||
- Discuss changes in forum/Discord
|
||||
- Gather community feedback
|
||||
- Build consensus before proposing
|
||||
|
||||
3. **Test First**
|
||||
- Use testnet when possible
|
||||
- Simulate changes
|
||||
- Review with other admins
|
||||
|
||||
### Making Changes
|
||||
|
||||
1. **Document Rationale**
|
||||
- Why is this change needed?
|
||||
- What problem does it solve?
|
||||
- What alternatives were considered?
|
||||
|
||||
2. **Propose Conservatively**
|
||||
- Make incremental changes
|
||||
- Avoid changing multiple settings at once
|
||||
- Allow time to observe effects
|
||||
|
||||
3. **Monitor After**
|
||||
- Watch for unexpected behavior
|
||||
- Gather feedback
|
||||
- Be ready to adjust
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Permission Denied"
|
||||
|
||||
**Causes:**
|
||||
- Insufficient role permissions
|
||||
- Settings require governance vote
|
||||
- Connected with wrong wallet
|
||||
|
||||
**Solutions:**
|
||||
- Verify your role level
|
||||
- Check if setting requires proposal
|
||||
- Connect with admin wallet
|
||||
|
||||
### "Change Not Applied"
|
||||
|
||||
**Causes:**
|
||||
- Change pending governance vote
|
||||
- In timelock queue
|
||||
- Transaction failed
|
||||
|
||||
**Solutions:**
|
||||
- Check proposal status
|
||||
- Wait for timelock to expire
|
||||
- Retry the transaction
|
||||
|
||||
### "Invalid Value"
|
||||
|
||||
**Causes:**
|
||||
- Value out of allowed range
|
||||
- Incorrect format
|
||||
- Conflicts with other settings
|
||||
|
||||
**Solutions:**
|
||||
- Check allowed ranges
|
||||
- Use correct format (numbers, addresses, etc.)
|
||||
- Resolve conflicts with related settings
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="General Settings" href="/docs/guide/settings/general" icon="settings">
|
||||
Configure basic project information
|
||||
</Card>
|
||||
<Card title="Governance Settings" href="/docs/guide/settings/governance" icon="vote">
|
||||
Set voting parameters and thresholds
|
||||
</Card>
|
||||
<Card title="Multisig" href="/docs/guide/multisig" icon="key">
|
||||
Multi-signature operations
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,448 @@
|
||||
---
|
||||
title: Managing Distributions
|
||||
description: Configure and manage token holder distributions
|
||||
---
|
||||
|
||||
# Managing Distributions
|
||||
|
||||
Distributions allow DAOs to share rewards, revenue, and other assets with stakers and token holders. This guide covers setting up and managing distribution mechanisms.
|
||||
|
||||
## Distribution Types
|
||||
|
||||
### Reward Distributions
|
||||
|
||||
Regular rewards for staking participation:
|
||||
|
||||
```yaml
|
||||
Type: Staking Rewards
|
||||
Frequency: Weekly
|
||||
Source: Protocol Revenue
|
||||
Recipients: All stakers
|
||||
Calculation: Pro-rata by stake weight
|
||||
```
|
||||
|
||||
### Revenue Sharing
|
||||
|
||||
Share protocol income with token holders:
|
||||
|
||||
```yaml
|
||||
Type: Revenue Share
|
||||
Frequency: Monthly
|
||||
Source: Fee collection
|
||||
Recipients: veToken holders
|
||||
Calculation: Pro-rata by voting power
|
||||
```
|
||||
|
||||
### One-Time Airdrops
|
||||
|
||||
Distribute tokens for specific events:
|
||||
|
||||
```yaml
|
||||
Type: Airdrop
|
||||
Frequency: One-time
|
||||
Source: Treasury allocation
|
||||
Recipients: Snapshot of holders
|
||||
Calculation: Custom criteria
|
||||
```
|
||||
|
||||
### Dividend Distributions
|
||||
|
||||
Periodic profit sharing:
|
||||
|
||||
```yaml
|
||||
Type: Dividend
|
||||
Frequency: Quarterly
|
||||
Source: Net protocol profit
|
||||
Recipients: Token holders
|
||||
Calculation: Per-token basis
|
||||
```
|
||||
|
||||
## Setting Up Distributions
|
||||
|
||||
### Step 1: Create Distribution Pool
|
||||
|
||||
1. Navigate to **DAO Settings** > **Distributions**
|
||||
2. Click **Create Pool**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Create Distribution Pool │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Name: [Staking Rewards Pool ] │
|
||||
│ │
|
||||
│ Token: [LUX ▼] │
|
||||
│ │
|
||||
│ Recipients: [○ All token holders │
|
||||
│ ● Stakers only │
|
||||
│ ○ veToken holders │
|
||||
│ ○ Custom list ] │
|
||||
│ │
|
||||
│ Distribution: [○ Pro-rata by balance │
|
||||
│ ● Pro-rata by stake weight │
|
||||
│ ○ Equal split │
|
||||
│ ○ Custom formula ] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Configure Distribution Schedule
|
||||
|
||||
Set up automatic distributions:
|
||||
|
||||
```yaml
|
||||
schedule:
|
||||
frequency: weekly
|
||||
day: Monday
|
||||
time: 00:00 UTC
|
||||
|
||||
# Or use block-based
|
||||
block_interval: 50400 # ~weekly on ETH
|
||||
|
||||
# Minimum distribution threshold
|
||||
min_amount: 1000 LUX
|
||||
```
|
||||
|
||||
### Step 3: Fund the Pool
|
||||
|
||||
Add tokens to the distribution pool:
|
||||
|
||||
**Manual Funding:**
|
||||
1. Go to pool dashboard
|
||||
2. Click **Add Funds**
|
||||
3. Enter amount and confirm
|
||||
|
||||
**Automatic Funding:**
|
||||
```yaml
|
||||
auto_fund:
|
||||
enabled: true
|
||||
source: protocol_fees
|
||||
percentage: 50%
|
||||
frequency: daily
|
||||
```
|
||||
|
||||
### Step 4: Configure Recipient Criteria
|
||||
|
||||
Define who receives distributions:
|
||||
|
||||
```yaml
|
||||
recipients:
|
||||
type: stakers
|
||||
|
||||
filters:
|
||||
min_stake: 100 LUX
|
||||
min_lock_time: 7 days
|
||||
active_only: true
|
||||
|
||||
exclusions:
|
||||
- treasury_address
|
||||
- team_vesting_contracts
|
||||
|
||||
snapshot:
|
||||
type: block_based
|
||||
block: distribution_block - 1
|
||||
```
|
||||
|
||||
## Distribution Calculations
|
||||
|
||||
### Pro-Rata by Balance
|
||||
|
||||
Standard distribution based on token balance:
|
||||
|
||||
```
|
||||
User Share = (User Balance / Total Supply) × Distribution Amount
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Total Distribution: 10,000 LUX
|
||||
User Balance: 1,000 LUX
|
||||
Total Supply: 100,000 LUX
|
||||
|
||||
User Share = (1,000 / 100,000) × 10,000 = 100 LUX
|
||||
```
|
||||
|
||||
### Pro-Rata by Stake Weight
|
||||
|
||||
Weighted by lock duration:
|
||||
|
||||
```
|
||||
User Share = (User Stake × Lock Multiplier / Total Weighted Stake) × Distribution Amount
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Total Distribution: 10,000 LUX
|
||||
User Stake: 1,000 LUX (locked 180 days, 2x multiplier)
|
||||
User Weight: 2,000 weighted LUX
|
||||
Total Weighted Stake: 200,000 weighted LUX
|
||||
|
||||
User Share = (2,000 / 200,000) × 10,000 = 100 LUX
|
||||
```
|
||||
|
||||
### Time-Weighted Average
|
||||
|
||||
Rewards based on staking duration within period:
|
||||
|
||||
```
|
||||
User Share = (User Days Staked / Total Stake-Days) × Distribution Amount
|
||||
```
|
||||
|
||||
### Custom Formulas
|
||||
|
||||
Create custom distribution logic:
|
||||
|
||||
```solidity
|
||||
function calculateShare(
|
||||
address user,
|
||||
uint256 totalDistribution
|
||||
) external view returns (uint256) {
|
||||
uint256 stake = stakingContract.balanceOf(user);
|
||||
uint256 lockTime = stakingContract.lockTime(user);
|
||||
uint256 boost = nftContract.getBoost(user);
|
||||
|
||||
uint256 weight = stake * lockTime * boost / 1e18;
|
||||
uint256 totalWeight = getTotalWeight();
|
||||
|
||||
return (weight * totalDistribution) / totalWeight;
|
||||
}
|
||||
```
|
||||
|
||||
## Managing Active Distributions
|
||||
|
||||
### Distribution Dashboard
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Distribution Dashboard │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Active Pools: 3 │
|
||||
│ Total Distributed (30d): 125,000 LUX │
|
||||
│ Unique Recipients: 2,456 │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Pool Name │ Balance │ Next Dist │ APY │ │
|
||||
│ ├────────────────────┼────────────┼───────────┼───────┤ │
|
||||
│ │ Staking Rewards │ 50,000 LUX │ 3 days │ 12.5% │ │
|
||||
│ │ Revenue Share │ 25,000 USDC│ 12 days │ 5.2% │ │
|
||||
│ │ LP Incentives │ 30,000 LUX │ 5 days │ 45.0% │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Monitoring Distributions
|
||||
|
||||
Track distribution health:
|
||||
|
||||
```yaml
|
||||
metrics:
|
||||
- pool_balance
|
||||
- distribution_rate
|
||||
- recipient_count
|
||||
- average_claim_size
|
||||
- unclaimed_amount
|
||||
- runway_days
|
||||
```
|
||||
|
||||
### Adjusting Parameters
|
||||
|
||||
Modify distribution settings via governance:
|
||||
|
||||
1. Create parameter change proposal
|
||||
2. Specify new values:
|
||||
|
||||
```yaml
|
||||
proposal:
|
||||
type: parameter_change
|
||||
target: staking_rewards_pool
|
||||
changes:
|
||||
- param: distribution_rate
|
||||
old: 10000 LUX/week
|
||||
new: 15000 LUX/week
|
||||
- param: min_stake
|
||||
old: 100 LUX
|
||||
new: 50 LUX
|
||||
```
|
||||
|
||||
## Claiming Distributions
|
||||
|
||||
### Automatic Claims
|
||||
|
||||
Enable auto-claim for users:
|
||||
|
||||
```yaml
|
||||
auto_claim:
|
||||
enabled: true
|
||||
threshold: 10 LUX # Min amount to trigger
|
||||
gas_limit: 100000
|
||||
gas_price_cap: 50 gwei
|
||||
```
|
||||
|
||||
### Manual Claims
|
||||
|
||||
Users claim through dashboard:
|
||||
|
||||
1. Go to **My Staking** > **Rewards**
|
||||
2. View pending rewards
|
||||
3. Click **Claim** or **Compound**
|
||||
|
||||
### Batch Claims
|
||||
|
||||
Claim from multiple pools:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Claim Rewards │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ☑ Staking Rewards 125.50 LUX │
|
||||
│ ☑ Revenue Share 45.20 USDC │
|
||||
│ ☑ LP Incentives 89.00 LUX │
|
||||
│ ☐ Governance Rewards 0.00 LUX │
|
||||
│ │
|
||||
│ ──────────────────────────────────── │
|
||||
│ Total: 214.50 LUX + 45.20 USDC │
|
||||
│ │
|
||||
│ [Claim All] [Claim Selected] [Compound LUX] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Distribution History
|
||||
|
||||
### View Past Distributions
|
||||
|
||||
Access historical data:
|
||||
|
||||
```yaml
|
||||
history:
|
||||
period: last_90_days
|
||||
|
||||
distributions:
|
||||
- date: 2026-01-20
|
||||
pool: staking_rewards
|
||||
amount: 10,000 LUX
|
||||
recipients: 1,234
|
||||
avg_reward: 8.1 LUX
|
||||
|
||||
- date: 2026-01-13
|
||||
pool: staking_rewards
|
||||
amount: 10,000 LUX
|
||||
recipients: 1,198
|
||||
avg_reward: 8.3 LUX
|
||||
```
|
||||
|
||||
### Export Data
|
||||
|
||||
Export distribution records:
|
||||
|
||||
- CSV format for accounting
|
||||
- JSON for integrations
|
||||
- On-chain verification links
|
||||
|
||||
## Advanced Distribution Patterns
|
||||
|
||||
### Merkle Distributions
|
||||
|
||||
Efficient distribution for large recipient lists:
|
||||
|
||||
```yaml
|
||||
merkle_distribution:
|
||||
root: 0xabc123...
|
||||
total_amount: 1,000,000 LUX
|
||||
recipients: 50,000
|
||||
proof_url: ipfs://Qm...
|
||||
|
||||
# Users claim with Merkle proof
|
||||
claim_window: 90 days
|
||||
unclaimed_return: treasury
|
||||
```
|
||||
|
||||
### Streaming Distributions
|
||||
|
||||
Continuous reward streaming:
|
||||
|
||||
```yaml
|
||||
stream:
|
||||
type: sablier
|
||||
total: 100,000 LUX
|
||||
duration: 365 days
|
||||
cliff: 0
|
||||
recipients:
|
||||
- address: 0x123...
|
||||
share: 50%
|
||||
- address: 0x456...
|
||||
share: 50%
|
||||
```
|
||||
|
||||
### Conditional Distributions
|
||||
|
||||
Distribute based on conditions:
|
||||
|
||||
```yaml
|
||||
conditional:
|
||||
trigger: tvl > 10_000_000 USD
|
||||
|
||||
distribution:
|
||||
pool: milestone_rewards
|
||||
amount: 50,000 LUX
|
||||
recipients: stakers
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
| Issue | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| No rewards shown | Below minimum stake | Increase stake amount |
|
||||
| Distribution delayed | Low gas prices | Increase gas budget |
|
||||
| Wrong amount | Snapshot timing | Check snapshot block |
|
||||
| Failed claim | Insufficient gas | Increase gas limit |
|
||||
|
||||
### Emergency Actions
|
||||
|
||||
If distribution issues occur:
|
||||
|
||||
1. **Pause distributions** - Stop automatic payouts
|
||||
2. **Investigate** - Review logs and calculations
|
||||
3. **Fix** - Correct any configuration errors
|
||||
4. **Resume** - Re-enable after verification
|
||||
|
||||
```yaml
|
||||
emergency:
|
||||
pause_distributions: true
|
||||
notify_admins: true
|
||||
snapshot_state: true
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Do
|
||||
|
||||
- Set sustainable reward rates
|
||||
- Monitor pool balances
|
||||
- Communicate distribution schedules
|
||||
- Test distributions on testnet
|
||||
- Maintain adequate runway
|
||||
|
||||
### Don't
|
||||
|
||||
- Promise unsustainable APYs
|
||||
- Change schedules without notice
|
||||
- Exclude legitimate participants
|
||||
- Let pools run empty
|
||||
- Ignore unclaimed token buildup
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Using Staking" href="/docs/guide/staking/using-staking" icon="lock">
|
||||
Token holder staking guide
|
||||
</Card>
|
||||
<Card title="Treasury" href="/docs/guide/treasury" icon="vault">
|
||||
Manage distribution funding
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,209 @@
|
||||
---
|
||||
title: Staking Overview
|
||||
description: Stake tokens to earn rewards and participate in governance
|
||||
---
|
||||
|
||||
# Staking Overview
|
||||
|
||||
Staking allows token holders to lock their tokens in exchange for rewards, enhanced voting power, and governance participation. This guide covers the staking system and its benefits.
|
||||
|
||||
## What is Staking?
|
||||
|
||||
Staking is the process of locking tokens in a smart contract to:
|
||||
|
||||
- **Earn Rewards** - Receive a share of protocol revenue or inflation
|
||||
- **Gain Voting Power** - Lock tokens for vote-escrowed governance tokens
|
||||
- **Support the Network** - Contribute to protocol security and decentralization
|
||||
- **Access Benefits** - Unlock premium features or reduced fees
|
||||
|
||||
## How Staking Works
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Staking Flow │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ [Deposit Tokens] ──► [Staking Contract] ──► [Receive veTokens]
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ [Accumulate Rewards] │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ [Claim Rewards] or [Compound] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Staking Mechanics
|
||||
|
||||
1. **Deposit** - Lock tokens for a chosen duration
|
||||
2. **Receive veTokens** - Get vote-escrowed tokens representing your stake
|
||||
3. **Earn Rewards** - Accumulate rewards over time
|
||||
4. **Participate** - Vote on proposals with your veTokens
|
||||
5. **Withdraw** - Unlock tokens after the lock period ends
|
||||
|
||||
## Staking Models
|
||||
|
||||
### Fixed Lock Period
|
||||
|
||||
Lock tokens for a predetermined duration with fixed rewards.
|
||||
|
||||
| Lock Period | APY Boost | Early Exit |
|
||||
|-------------|-----------|------------|
|
||||
| 30 days | 1.0x | 10% penalty |
|
||||
| 90 days | 1.5x | 15% penalty |
|
||||
| 180 days | 2.0x | 20% penalty |
|
||||
| 365 days | 3.0x | 25% penalty |
|
||||
|
||||
### Flexible Staking
|
||||
|
||||
No lock period with instant withdrawal capability.
|
||||
|
||||
- Lower rewards than locked staking
|
||||
- Instant liquidity
|
||||
- Good for short-term participants
|
||||
|
||||
### Vote-Escrow (veToken) Model
|
||||
|
||||
Lock tokens to receive voting power that decays over time.
|
||||
|
||||
```yaml
|
||||
Lock Duration: 4 years maximum
|
||||
Voting Power: Linear decay to 0 at unlock
|
||||
Rewards: Proportional to voting power
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Lock 1,000 tokens for 4 years → 1,000 veTokens
|
||||
After 2 years → 500 veTokens remaining
|
||||
After 4 years → 0 veTokens (tokens unlocked)
|
||||
```
|
||||
|
||||
## Benefits of Staking
|
||||
|
||||
### For Token Holders
|
||||
|
||||
- **Passive Income** - Earn rewards without active trading
|
||||
- **Governance Rights** - Vote on protocol decisions
|
||||
- **Fee Discounts** - Reduced fees on protocol services
|
||||
- **Priority Access** - Early access to new features
|
||||
|
||||
### For DAOs
|
||||
|
||||
- **Reduced Circulating Supply** - Less sell pressure
|
||||
- **Aligned Incentives** - Long-term holder commitment
|
||||
- **Governance Participation** - Active voter base
|
||||
- **Treasury Revenue** - Staking fees to treasury
|
||||
|
||||
## Reward Sources
|
||||
|
||||
Staking rewards can come from multiple sources:
|
||||
|
||||
### Protocol Revenue
|
||||
|
||||
```yaml
|
||||
Sources:
|
||||
- Trading fees: 50% to stakers
|
||||
- Lending interest: 30% to stakers
|
||||
- NFT royalties: 25% to stakers
|
||||
- Service fees: Variable
|
||||
```
|
||||
|
||||
### Inflation
|
||||
|
||||
```yaml
|
||||
Annual Emission: 5% of total supply
|
||||
Distribution:
|
||||
- Stakers: 80%
|
||||
- Treasury: 15%
|
||||
- Development: 5%
|
||||
```
|
||||
|
||||
### External Incentives
|
||||
|
||||
Partner protocols may provide additional rewards:
|
||||
|
||||
- Liquidity mining programs
|
||||
- Ecosystem grants
|
||||
- Partnership distributions
|
||||
|
||||
## Staking Dashboard
|
||||
|
||||
<Cards>
|
||||
<Card title="Setup Staking" href="/docs/guide/staking/setup" icon="settings">
|
||||
Configure staking for your DAO
|
||||
</Card>
|
||||
<Card title="Distributions" href="/docs/guide/staking/distributions" icon="pie-chart">
|
||||
Manage reward distributions
|
||||
</Card>
|
||||
<Card title="Using Staking" href="/docs/guide/staking/using-staking" icon="lock">
|
||||
Guide for token holders
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## Quick Stats Example
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Staking Overview │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Total Staked: 45,000,000 LUX (45% of supply) │
|
||||
│ Current APY: 12.5% │
|
||||
│ Total Stakers: 8,234 │
|
||||
│ Rewards Paid: 2,500,000 LUX │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Lock Distribution │ │
|
||||
│ │ ████████████████████░░░░ 30 days: 20% │ │
|
||||
│ │ ██████████████░░░░░░░░░░ 90 days: 35% │ │
|
||||
│ │ ██████████░░░░░░░░░░░░░░ 180 days: 25% │ │
|
||||
│ │ ████████░░░░░░░░░░░░░░░░ 365 days: 20% │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
<Callout type="warning">
|
||||
Before staking, understand the risks:
|
||||
</Callout>
|
||||
|
||||
### Smart Contract Risk
|
||||
|
||||
- Contracts are audited but not risk-free
|
||||
- Funds are locked for the duration
|
||||
- Upgrades require governance approval
|
||||
|
||||
### Impermanent Loss
|
||||
|
||||
For liquidity staking:
|
||||
- Token price changes may affect value
|
||||
- Consider price volatility before staking
|
||||
|
||||
### Slashing Risk
|
||||
|
||||
Some staking systems include slashing for:
|
||||
- Malicious behavior
|
||||
- Downtime (for validator staking)
|
||||
- Protocol violations
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. **Governance Tokens** - Acquire tokens to stake
|
||||
2. **Connected Wallet** - MetaMask, WalletConnect, etc.
|
||||
3. **Gas for Transactions** - ETH/native token for fees
|
||||
|
||||
### First Steps
|
||||
|
||||
1. Navigate to the staking page
|
||||
2. Choose lock duration
|
||||
3. Enter amount to stake
|
||||
4. Review and confirm transaction
|
||||
5. Start earning rewards
|
||||
|
||||
See [Using Staking](/docs/guide/staking/using-staking) for detailed instructions.
|
||||
@@ -0,0 +1,364 @@
|
||||
---
|
||||
title: Setting Up Staking
|
||||
description: Configure staking for your DAO
|
||||
---
|
||||
|
||||
# Setting Up Staking
|
||||
|
||||
This guide covers how DAO administrators can set up and configure staking for their organization.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before setting up staking, ensure you have:
|
||||
|
||||
- **Admin Role** - DAO admin or governance permissions
|
||||
- **Token Contract** - Deployed ERC-20 governance token
|
||||
- **Treasury Funds** - Initial rewards allocation
|
||||
- **Governance Approval** - If required by your DAO
|
||||
|
||||
## Staking Configuration
|
||||
|
||||
### Step 1: Navigate to Staking Settings
|
||||
|
||||
1. Go to your DAO dashboard
|
||||
2. Click **Settings** in the sidebar
|
||||
3. Select **Staking** tab
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ DAO Settings │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ [General] [Governance] [Treasury] [Staking] [Gasless] │
|
||||
│ ^^^^^^^^ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Enable Staking
|
||||
|
||||
Toggle staking on and select your model:
|
||||
|
||||
```yaml
|
||||
Staking Enabled: true
|
||||
Staking Model: vote_escrow # Options: fixed, flexible, vote_escrow
|
||||
```
|
||||
|
||||
**Model Comparison:**
|
||||
|
||||
| Model | Lock Required | Voting Power | Best For |
|
||||
|-------|--------------|--------------|----------|
|
||||
| Fixed | Yes (preset periods) | Static | Predictable rewards |
|
||||
| Flexible | No | Static | Liquidity preference |
|
||||
| Vote-Escrow | Yes (variable) | Decaying | Long-term alignment |
|
||||
|
||||
### Step 3: Configure Lock Periods
|
||||
|
||||
For fixed or vote-escrow models, define lock periods:
|
||||
|
||||
```yaml
|
||||
lock_periods:
|
||||
- duration: 30 days
|
||||
multiplier: 1.0
|
||||
early_exit_penalty: 10%
|
||||
|
||||
- duration: 90 days
|
||||
multiplier: 1.5
|
||||
early_exit_penalty: 15%
|
||||
|
||||
- duration: 180 days
|
||||
multiplier: 2.0
|
||||
early_exit_penalty: 20%
|
||||
|
||||
- duration: 365 days
|
||||
multiplier: 3.0
|
||||
early_exit_penalty: 25%
|
||||
|
||||
- duration: 730 days # 2 years
|
||||
multiplier: 4.0
|
||||
early_exit_penalty: 30%
|
||||
```
|
||||
|
||||
### Step 4: Set Reward Parameters
|
||||
|
||||
Configure how rewards are distributed:
|
||||
|
||||
```yaml
|
||||
rewards:
|
||||
source: protocol_revenue # Options: inflation, revenue, hybrid
|
||||
|
||||
# For inflation model
|
||||
inflation:
|
||||
annual_rate: 5%
|
||||
distribution:
|
||||
stakers: 80%
|
||||
treasury: 15%
|
||||
development: 5%
|
||||
|
||||
# For revenue model
|
||||
revenue:
|
||||
fee_share: 50% # % of protocol fees to stakers
|
||||
|
||||
# Distribution frequency
|
||||
distribution_interval: weekly # daily, weekly, monthly
|
||||
```
|
||||
|
||||
### Step 5: Configure Minimum Stakes
|
||||
|
||||
Set minimum amounts to prevent dust attacks:
|
||||
|
||||
```yaml
|
||||
minimums:
|
||||
stake_amount: 100 LUX
|
||||
lock_duration: 7 days
|
||||
claim_amount: 1 LUX
|
||||
```
|
||||
|
||||
### Step 6: Enable/Disable Features
|
||||
|
||||
Toggle optional features:
|
||||
|
||||
```yaml
|
||||
features:
|
||||
compound_rewards: true # Auto-compound option
|
||||
partial_unstake: false # Allow partial withdrawals
|
||||
delegate_stake: true # Delegate voting power
|
||||
early_exit: true # Allow early exit with penalty
|
||||
boost_nft: false # NFT-based APY boosts
|
||||
```
|
||||
|
||||
## Deploying Staking Contracts
|
||||
|
||||
If your DAO doesn't have staking contracts yet:
|
||||
|
||||
### Option 1: Use Built-in Templates
|
||||
|
||||
1. Click **Deploy Staking Contract**
|
||||
2. Select template:
|
||||
- Simple Staking
|
||||
- Vote-Escrow (veToken)
|
||||
- Gauge System
|
||||
3. Configure parameters
|
||||
4. Submit deployment proposal
|
||||
5. Execute after approval
|
||||
|
||||
### Option 2: Connect Existing Contract
|
||||
|
||||
```yaml
|
||||
contract_address: 0x1234...5678
|
||||
abi: [...] # Contract ABI
|
||||
methods:
|
||||
stake: stake(uint256)
|
||||
unstake: withdraw(uint256)
|
||||
claim: claimReward()
|
||||
balance: balanceOf(address)
|
||||
```
|
||||
|
||||
## Reward Fund Setup
|
||||
|
||||
### Initial Funding
|
||||
|
||||
Allocate rewards from treasury:
|
||||
|
||||
1. Go to **Treasury** > **Allocations**
|
||||
2. Create new allocation:
|
||||
|
||||
```yaml
|
||||
allocation:
|
||||
name: "Staking Rewards Q1 2026"
|
||||
amount: 1,000,000 LUX
|
||||
destination: staking_rewards_pool
|
||||
schedule: monthly
|
||||
duration: 3 months
|
||||
```
|
||||
|
||||
### Ongoing Funding
|
||||
|
||||
Set up automatic funding from revenue:
|
||||
|
||||
```yaml
|
||||
auto_fund:
|
||||
enabled: true
|
||||
source: protocol_fees
|
||||
percentage: 50%
|
||||
frequency: weekly
|
||||
cap: 100,000 LUX per week
|
||||
```
|
||||
|
||||
## Governance Integration
|
||||
|
||||
### Voting Power
|
||||
|
||||
Configure how staking affects voting:
|
||||
|
||||
```yaml
|
||||
voting_power:
|
||||
base: 1 # 1 token = 1 vote base
|
||||
staking_multiplier: true
|
||||
lock_bonus:
|
||||
30_days: 1.1x
|
||||
90_days: 1.25x
|
||||
180_days: 1.5x
|
||||
365_days: 2.0x
|
||||
```
|
||||
|
||||
### Proposal Thresholds
|
||||
|
||||
Staked tokens count toward proposal thresholds:
|
||||
|
||||
```yaml
|
||||
proposal_threshold:
|
||||
create: 10,000 veTokens
|
||||
vote: 1 veToken
|
||||
quorum: 1,000,000 veTokens
|
||||
```
|
||||
|
||||
## Testing Your Setup
|
||||
|
||||
Before going live:
|
||||
|
||||
### 1. Testnet Deployment
|
||||
|
||||
Deploy to testnet first:
|
||||
|
||||
```bash
|
||||
# Deploy staking contract to testnet
|
||||
forge script script/DeployStaking.s.sol --rpc-url $TESTNET_RPC --broadcast
|
||||
```
|
||||
|
||||
### 2. Verify Configuration
|
||||
|
||||
```yaml
|
||||
checklist:
|
||||
- [ ] Lock periods configured correctly
|
||||
- [ ] Reward rates are sustainable
|
||||
- [ ] Minimum stakes prevent dust
|
||||
- [ ] Early exit penalties are reasonable
|
||||
- [ ] Voting power integration works
|
||||
- [ ] Claiming rewards functions
|
||||
- [ ] Compounding works (if enabled)
|
||||
```
|
||||
|
||||
### 3. UI Preview
|
||||
|
||||
Test the staking interface:
|
||||
|
||||
1. Connect test wallet
|
||||
2. Stake test tokens
|
||||
3. Verify lock period
|
||||
4. Wait for rewards accrual
|
||||
5. Test claiming
|
||||
6. Test unstaking
|
||||
|
||||
## Launch Checklist
|
||||
|
||||
```yaml
|
||||
pre_launch:
|
||||
- [ ] Contracts deployed and verified
|
||||
- [ ] Initial rewards funded
|
||||
- [ ] Documentation published
|
||||
- [ ] UI tested thoroughly
|
||||
- [ ] Audit completed (recommended)
|
||||
|
||||
launch:
|
||||
- [ ] Announce staking launch
|
||||
- [ ] Monitor first stakes
|
||||
- [ ] Support ready for questions
|
||||
- [ ] Emergency pause available
|
||||
|
||||
post_launch:
|
||||
- [ ] Monitor TVL growth
|
||||
- [ ] Track APY sustainability
|
||||
- [ ] Gather user feedback
|
||||
- [ ] Adjust parameters if needed
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Low Participation
|
||||
|
||||
**Symptoms:** Few stakers, low TVL
|
||||
|
||||
**Solutions:**
|
||||
- Increase reward rates
|
||||
- Add lock bonuses
|
||||
- Reduce minimum stake
|
||||
- Improve UI/UX
|
||||
|
||||
### Unsustainable APY
|
||||
|
||||
**Symptoms:** Rewards depleting too fast
|
||||
|
||||
**Solutions:**
|
||||
- Reduce emission rate
|
||||
- Cap maximum stake per user
|
||||
- Add more revenue sources
|
||||
- Adjust reward schedule
|
||||
|
||||
### Voting Power Concentration
|
||||
|
||||
**Symptoms:** Few large stakers dominate
|
||||
|
||||
**Solutions:**
|
||||
- Implement quadratic voting
|
||||
- Cap maximum voting power
|
||||
- Add delegation incentives
|
||||
- Time-weight voting power
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Gauge System
|
||||
|
||||
For protocols with multiple pools:
|
||||
|
||||
```yaml
|
||||
gauges:
|
||||
enabled: true
|
||||
pools:
|
||||
- name: "Core Staking"
|
||||
weight: 60%
|
||||
min_weight: 40%
|
||||
|
||||
- name: "LP Staking"
|
||||
weight: 30%
|
||||
min_weight: 10%
|
||||
|
||||
- name: "NFT Staking"
|
||||
weight: 10%
|
||||
min_weight: 5%
|
||||
|
||||
voting:
|
||||
frequency: weekly
|
||||
min_weight_change: 1%
|
||||
```
|
||||
|
||||
### Boost System
|
||||
|
||||
NFT or threshold-based boosts:
|
||||
|
||||
```yaml
|
||||
boosts:
|
||||
nft_boost:
|
||||
enabled: true
|
||||
contract: 0xABC...
|
||||
max_boost: 1.5x
|
||||
|
||||
tier_boost:
|
||||
enabled: true
|
||||
tiers:
|
||||
- min_stake: 10,000 LUX
|
||||
boost: 1.1x
|
||||
- min_stake: 100,000 LUX
|
||||
boost: 1.25x
|
||||
- min_stake: 1,000,000 LUX
|
||||
boost: 1.5x
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Distributions" href="/docs/guide/staking/distributions" icon="pie-chart">
|
||||
Set up reward distributions
|
||||
</Card>
|
||||
<Card title="Using Staking" href="/docs/guide/staking/using-staking" icon="lock">
|
||||
Token holder guide
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,429 @@
|
||||
---
|
||||
title: Using Staking
|
||||
description: How to stake tokens and earn rewards as a token holder
|
||||
---
|
||||
|
||||
# Using Staking
|
||||
|
||||
This guide explains how token holders can stake their tokens, earn rewards, and participate in governance through the staking system.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before staking, you'll need:
|
||||
|
||||
1. **Governance Tokens** - LUX or your DAO's token
|
||||
2. **Connected Wallet** - MetaMask, WalletConnect, etc.
|
||||
3. **Native Token for Gas** - ETH, LUX, etc. for transaction fees
|
||||
|
||||
### Accessing the Staking Page
|
||||
|
||||
1. Go to your DAO's dashboard
|
||||
2. Click **Staking** in the navigation
|
||||
3. Connect your wallet if not already connected
|
||||
|
||||
## Staking Your Tokens
|
||||
|
||||
### Step 1: Choose Lock Duration
|
||||
|
||||
Select how long to lock your tokens:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Select Lock Duration │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ 30 Days │ │ 90 Days │ │ 180 Days │ │ 1 Year │ │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
│ │ 1.0x APY │ │ 1.5x APY │ │ 2.0x APY │ │ 3.0x APY │ │
|
||||
│ │ ~8% │ │ ~12% │ │ ~16% │ │ ~24% │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
│ │
|
||||
│ Current Selection: 180 Days │
|
||||
│ Unlock Date: July 30, 2026 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Longer locks provide:**
|
||||
- Higher APY multiplier
|
||||
- More voting power
|
||||
- Greater governance influence
|
||||
|
||||
### Step 2: Enter Stake Amount
|
||||
|
||||
Choose how many tokens to stake:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Stake Amount │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Amount: [1,000 ] LUX │
|
||||
│ │
|
||||
│ Wallet Balance: 5,000 LUX │
|
||||
│ Minimum Stake: 100 LUX │
|
||||
│ │
|
||||
│ [25%] [50%] [75%] [MAX] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Review and Confirm
|
||||
|
||||
Review your stake details before confirming:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Confirm Stake │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Stake Amount: 1,000 LUX │
|
||||
│ Lock Duration: 180 days │
|
||||
│ Unlock Date: July 30, 2026 │
|
||||
│ │
|
||||
│ You Will Receive: │
|
||||
│ • 2,000 veLUX (voting power) │
|
||||
│ • ~16% APY (~160 LUX/year) │
|
||||
│ • Governance voting rights │
|
||||
│ │
|
||||
│ Early Exit Penalty: 20% │
|
||||
│ │
|
||||
│ [Cancel] [Confirm Stake] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 4: Approve and Stake
|
||||
|
||||
1. Click **Confirm Stake**
|
||||
2. If first time: Approve token spending
|
||||
3. Confirm the stake transaction
|
||||
4. Wait for confirmation
|
||||
|
||||
```
|
||||
Transaction Progress:
|
||||
✓ Token approval confirmed
|
||||
✓ Stake transaction submitted
|
||||
⟳ Waiting for confirmation...
|
||||
✓ Stake successful!
|
||||
|
||||
Your Position:
|
||||
• 1,000 LUX staked
|
||||
• 2,000 veLUX received
|
||||
• Rewards accruing
|
||||
```
|
||||
|
||||
## Managing Your Stake
|
||||
|
||||
### View Your Position
|
||||
|
||||
Access your staking dashboard:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ My Staking Position │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Total Staked: 1,000 LUX │
|
||||
│ Voting Power: 2,000 veLUX │
|
||||
│ Lock Expires: July 30, 2026 (180 days) │
|
||||
│ │
|
||||
│ ──────────────────────────────────────────── │
|
||||
│ │
|
||||
│ Pending Rewards: │
|
||||
│ • Staking: 12.50 LUX │
|
||||
│ • Revenue Share: 5.25 USDC │
|
||||
│ │
|
||||
│ Total Earned: 125.00 LUX + 52.00 USDC │
|
||||
│ │
|
||||
│ [Claim Rewards] [Compound] [Extend Lock] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Claiming Rewards
|
||||
|
||||
Claim accumulated rewards:
|
||||
|
||||
1. Go to your staking position
|
||||
2. Click **Claim Rewards**
|
||||
3. Choose what to claim:
|
||||
- All rewards
|
||||
- Specific token
|
||||
- Partial amount
|
||||
4. Confirm transaction
|
||||
|
||||
**Claim Options:**
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| Claim All | Withdraw all pending rewards to wallet |
|
||||
| Compound | Re-stake LUX rewards automatically |
|
||||
| Claim Selected | Choose specific reward tokens |
|
||||
|
||||
### Compounding Rewards
|
||||
|
||||
Automatically re-stake your rewards:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Compound Rewards │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Available to Compound: 125.00 LUX │
|
||||
│ │
|
||||
│ Compound into: │
|
||||
│ ● Existing position (180 days remaining) │
|
||||
│ ○ New position (select lock duration) │
|
||||
│ │
|
||||
│ After Compounding: │
|
||||
│ • Staked: 1,000 → 1,125 LUX │
|
||||
│ • veLUX: 2,000 → 2,250 veLUX │
|
||||
│ │
|
||||
│ [Compound Now] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Extending Lock
|
||||
|
||||
Increase your lock duration for higher rewards:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Extend Lock │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Current Lock: 180 days (expires July 30) │
|
||||
│ │
|
||||
│ Extend To: │
|
||||
│ ○ 270 days (+90 days) → 2.5x APY │
|
||||
│ ● 365 days (+185 days) → 3.0x APY │
|
||||
│ ○ 730 days (+550 days) → 4.0x APY │
|
||||
│ │
|
||||
│ New Unlock Date: January 30, 2027 │
|
||||
│ New veLUX: 1,000 → 3,000 veLUX │
|
||||
│ │
|
||||
│ [Extend Lock] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Adding to Stake
|
||||
|
||||
Increase your staked amount:
|
||||
|
||||
1. Click **Add Stake** on your position
|
||||
2. Enter additional amount
|
||||
3. Review updated position
|
||||
4. Confirm transaction
|
||||
|
||||
<Callout type="info">
|
||||
Adding to an existing stake typically resets the lock timer to your original lock duration.
|
||||
</Callout>
|
||||
|
||||
## Withdrawing Stake
|
||||
|
||||
### After Lock Expires
|
||||
|
||||
Once your lock period ends:
|
||||
|
||||
1. Go to your staking position
|
||||
2. Click **Withdraw**
|
||||
3. Choose amount (partial or full)
|
||||
4. Confirm transaction
|
||||
5. Tokens return to your wallet
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Withdraw Stake │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ✓ Lock period complete │
|
||||
│ │
|
||||
│ Available to Withdraw: 1,125 LUX │
|
||||
│ (includes compounded rewards) │
|
||||
│ │
|
||||
│ Withdraw Amount: [1,125 ] LUX │
|
||||
│ │
|
||||
│ [25%] [50%] [75%] [MAX] │
|
||||
│ │
|
||||
│ Note: Withdrawing ends your staking rewards │
|
||||
│ │
|
||||
│ [Cancel] [Withdraw] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Early Exit (Before Lock Expires)
|
||||
|
||||
If you need to withdraw early:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Early Withdrawal │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ⚠ Warning: Your tokens are still locked │
|
||||
│ │
|
||||
│ Lock Expires: July 30, 2026 (150 days remaining) │
|
||||
│ Early Exit Penalty: 20% │
|
||||
│ │
|
||||
│ Staked Amount: 1,000 LUX │
|
||||
│ Penalty: 200 LUX │
|
||||
│ You Will Receive: 800 LUX │
|
||||
│ │
|
||||
│ Pending rewards will be forfeited: 12.50 LUX │
|
||||
│ │
|
||||
│ [Cancel] [Accept Penalty & Withdraw] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
<Callout type="warning">
|
||||
Early withdrawal incurs a penalty. Consider carefully before exiting early.
|
||||
</Callout>
|
||||
|
||||
## Voting with Staked Tokens
|
||||
|
||||
### Voting Power
|
||||
|
||||
Your veLUX balance determines voting power:
|
||||
|
||||
```yaml
|
||||
Base Formula: 1 LUX staked × lock_multiplier = veLUX
|
||||
|
||||
Example:
|
||||
1,000 LUX × 2.0x (180 day lock) = 2,000 veLUX voting power
|
||||
```
|
||||
|
||||
### Vote on Proposals
|
||||
|
||||
1. Go to **Governance** > **Proposals**
|
||||
2. Select an active proposal
|
||||
3. Cast your vote (For/Against/Abstain)
|
||||
4. Confirm transaction
|
||||
|
||||
Your vote is weighted by your veLUX balance at the snapshot block.
|
||||
|
||||
### Delegate Voting Power
|
||||
|
||||
Delegate your votes to another address:
|
||||
|
||||
1. Go to **Staking** > **Delegation**
|
||||
2. Enter delegate address
|
||||
3. Confirm delegation
|
||||
|
||||
```yaml
|
||||
delegation:
|
||||
from: your_address
|
||||
to: delegate_address
|
||||
power: 2,000 veLUX
|
||||
revocable: true
|
||||
```
|
||||
|
||||
## Reward Calculations
|
||||
|
||||
### APY Calculation
|
||||
|
||||
```
|
||||
Base APY = (Annual Rewards / Total Staked) × 100
|
||||
|
||||
Your APY = Base APY × Lock Multiplier
|
||||
|
||||
Example:
|
||||
Base APY: 8%
|
||||
Lock Multiplier: 2.0x (180 days)
|
||||
Your APY: 16%
|
||||
```
|
||||
|
||||
### Reward Accrual
|
||||
|
||||
Rewards accrue continuously:
|
||||
|
||||
```
|
||||
Daily Reward = (Your Stake × Your APY) / 365
|
||||
|
||||
Example:
|
||||
Stake: 1,000 LUX
|
||||
APY: 16%
|
||||
Daily: (1,000 × 0.16) / 365 = 0.438 LUX/day
|
||||
```
|
||||
|
||||
### Checking Pending Rewards
|
||||
|
||||
View your accrued rewards anytime:
|
||||
|
||||
```
|
||||
Pending Rewards:
|
||||
• Staking Rewards: 12.50 LUX (claimable)
|
||||
• Revenue Share: 5.25 USDC (claimable)
|
||||
• Locked Rewards: 25.00 LUX (vesting)
|
||||
|
||||
Total Earned (All Time):
|
||||
• LUX Rewards: 125.00 LUX
|
||||
• USDC Revenue: 52.00 USDC
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Do
|
||||
|
||||
- Choose lock duration based on your timeline
|
||||
- Compound regularly to maximize returns
|
||||
- Monitor APY changes
|
||||
- Participate in governance votes
|
||||
- Diversify across lock periods if needed
|
||||
|
||||
### Don't
|
||||
|
||||
- Lock more than you can afford
|
||||
- Ignore early exit penalties
|
||||
- Miss voting opportunities
|
||||
- Let rewards sit unclaimed too long
|
||||
- Panic withdraw during market dips
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
| Issue | Possible Cause | Solution |
|
||||
|-------|---------------|----------|
|
||||
| Can't stake | Insufficient balance | Check wallet balance |
|
||||
| Can't withdraw | Lock not expired | Wait for unlock date |
|
||||
| No rewards showing | Just staked | Wait for next distribution |
|
||||
| Transaction failed | Low gas | Increase gas limit |
|
||||
| Wrong veLUX amount | Lock duration | Verify multiplier |
|
||||
|
||||
### Getting Help
|
||||
|
||||
If you encounter issues:
|
||||
|
||||
1. Check the [FAQ](/docs/faq)
|
||||
2. Visit the community Discord
|
||||
3. Contact support
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Lock Multipliers
|
||||
|
||||
| Duration | APY Multiplier | Voting Multiplier |
|
||||
|----------|---------------|-------------------|
|
||||
| 30 days | 1.0x | 1.0x |
|
||||
| 90 days | 1.5x | 1.25x |
|
||||
| 180 days | 2.0x | 1.5x |
|
||||
| 365 days | 3.0x | 2.0x |
|
||||
| 730 days | 4.0x | 2.5x |
|
||||
|
||||
### Key Actions
|
||||
|
||||
| Action | Gas Cost | Time |
|
||||
|--------|----------|------|
|
||||
| Stake | ~150k gas | Instant |
|
||||
| Claim | ~100k gas | Instant |
|
||||
| Compound | ~200k gas | Instant |
|
||||
| Withdraw | ~120k gas | Instant |
|
||||
| Extend lock | ~100k gas | Instant |
|
||||
@@ -0,0 +1,420 @@
|
||||
---
|
||||
title: Token Setup
|
||||
description: Configure tokens for your multisig or governance project
|
||||
---
|
||||
|
||||
# Token Setup
|
||||
|
||||
This guide covers how to set up and configure tokens for your multisig project or DAO. Proper token configuration is essential for governance functionality.
|
||||
|
||||
## Overview
|
||||
|
||||
A typical DAO token system includes:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Token Architecture │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Governance Token (TOKEN) │ │
|
||||
│ │ Base ERC-20/SPL token │ │
|
||||
│ └───────────────────────────┬─────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────────────┼───────────────┐ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌──────────────────┐ ┌──────────────┐ ┌──────────────────┐ │
|
||||
│ │ Vote Escrow │ │ Staking │ │ Treasury │ │
|
||||
│ │ (veTOKEN) │ │ (sTOKEN) │ │ Holdings │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ Lock for voting │ │ Stake for │ │ Protocol-owned │ │
|
||||
│ │ power │ │ rewards │ │ liquidity │ │
|
||||
│ └──────────────────┘ └──────────────┘ └──────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Token Types
|
||||
|
||||
### Governance Token
|
||||
|
||||
The primary token used for voting and governance.
|
||||
|
||||
| Property | Description |
|
||||
|----------|-------------|
|
||||
| Symbol | TOKEN (customize for your project) |
|
||||
| Standard | ERC-20 (EVM) / SPL (Solana) |
|
||||
| Decimals | 18 (EVM) / 9 (Solana) |
|
||||
| Supply | Fixed or inflationary |
|
||||
| Transferable | Yes |
|
||||
|
||||
### Vote-Escrowed Token (veToken)
|
||||
|
||||
Non-transferable token representing locked voting power.
|
||||
|
||||
| Property | Description |
|
||||
|----------|-------------|
|
||||
| Symbol | veTOKEN |
|
||||
| Standard | Non-standard (contract-specific) |
|
||||
| Transferable | No |
|
||||
| Decay | Linear decay toward unlock |
|
||||
|
||||
### Staked Token (sToken)
|
||||
|
||||
Receipt token for staked governance tokens.
|
||||
|
||||
| Property | Description |
|
||||
|----------|-------------|
|
||||
| Symbol | sTOKEN |
|
||||
| Standard | ERC-20 |
|
||||
| Transferable | Configurable |
|
||||
| Represents | Staked position + rewards |
|
||||
|
||||
## Setup for Multisig Projects
|
||||
|
||||
### Step 1: Configure Governance Token
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Governance Token Configuration │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Token Address: [0x_________________________________] │
|
||||
│ │
|
||||
│ OR │
|
||||
│ │
|
||||
│ ☐ Deploy new token │
|
||||
│ │
|
||||
│ Token Details (auto-detected): │
|
||||
│ - Name: Example Token │
|
||||
│ - Symbol: TOKEN │
|
||||
│ - Decimals: 18 │
|
||||
│ - Total Supply: 100,000,000 TOKEN │
|
||||
│ │
|
||||
│ Treasury Holdings: 25,000,000 TOKEN (25%) │
|
||||
│ │
|
||||
│ [Verify] [Continue] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Configure Vote Escrow
|
||||
|
||||
Enable token locking for voting power:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Vote Escrow Configuration │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ☑ Enable vote escrow (locking for voting power) │
|
||||
│ │
|
||||
│ Lock Parameters: │
|
||||
│ │
|
||||
│ Minimum Lock: [1___] weeks │
|
||||
│ Maximum Lock: [208_] weeks (4 years) │
|
||||
│ │
|
||||
│ Voting Power Multiplier: │
|
||||
│ │ Lock Duration │ Multiplier │ Example (1000 TOKEN) │ │
|
||||
│ │───────────────│────────────│──────────────────────│ │
|
||||
│ │ 1 week │ 0.005x │ 5 veTOKEN │ │
|
||||
│ │ 1 month │ 0.02x │ 20 veTOKEN │ │
|
||||
│ │ 6 months │ 0.125x │ 125 veTOKEN │ │
|
||||
│ │ 1 year │ 0.25x │ 250 veTOKEN │ │
|
||||
│ │ 2 years │ 0.5x │ 500 veTOKEN │ │
|
||||
│ │ 4 years │ 1.0x │ 1,000 veTOKEN │ │
|
||||
│ │
|
||||
│ Power Decay: │
|
||||
│ ● Linear decay (voting power decreases toward unlock) │
|
||||
│ ○ No decay (constant power until unlock) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Configure Treasury Token Holdings
|
||||
|
||||
Set up which tokens the treasury can hold:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Treasury Token Configuration │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Approved Treasury Tokens: │
|
||||
│ │
|
||||
│ │ Token │ Address │ Limit │ Remove │ │
|
||||
│ │────────│────────────────────────────│──────────────│────────│ │
|
||||
│ │ TOKEN │ 0x1234...abcd │ No limit │ - │ │
|
||||
│ │ USDC │ 0x5678...efgh │ $10,000,000 │ ✕ │ │
|
||||
│ │ USDT │ 0x9abc...ijkl │ $5,000,000 │ ✕ │ │
|
||||
│ │ WETH │ 0xdef0...mnop │ 1,000 ETH │ ✕ │ │
|
||||
│ │
|
||||
│ [+ Add Token] │
|
||||
│ │
|
||||
│ Note: Adding tokens requires governance approval │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 4: Configure Staking (Optional)
|
||||
|
||||
Enable staking for additional functionality:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Staking Configuration │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ☑ Enable staking │
|
||||
│ │
|
||||
│ Staking Model: │
|
||||
│ ○ Simple staking (stake TOKEN, receive rewards) │
|
||||
│ ● Liquid staking (stake TOKEN, receive sTOKEN) │
|
||||
│ ○ Locked staking (stake with lock period) │
|
||||
│ │
|
||||
│ Reward Token: [TOKEN ▼] │
|
||||
│ │
|
||||
│ Reward Source: │
|
||||
│ ☑ Protocol revenue │
|
||||
│ ☐ Inflation (new token issuance) │
|
||||
│ ☐ Treasury allocation │
|
||||
│ │
|
||||
│ Unstaking: │
|
||||
│ Cooldown Period: [7___] days │
|
||||
│ Instant Unstake Fee: [5___]% │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Token Distribution
|
||||
|
||||
### Initial Distribution
|
||||
|
||||
Configure how tokens are initially distributed:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Token Distribution │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Total Supply: 100,000,000 TOKEN │
|
||||
│ │
|
||||
│ │ Allocation │ Amount │ % │ Vesting │ │
|
||||
│ │─────────────────│─────────────│──────│────────────────│ │
|
||||
│ │ Treasury │ 25,000,000 │ 25% │ None │ │
|
||||
│ │ Team │ 15,000,000 │ 15% │ 4yr cliff+vest │ │
|
||||
│ │ Investors │ 10,000,000 │ 10% │ 1yr cliff+vest │ │
|
||||
│ │ Community │ 30,000,000 │ 30% │ Airdrop │ │
|
||||
│ │ Ecosystem │ 20,000,000 │ 20% │ Grants │ │
|
||||
│ │
|
||||
│ Circulating Supply: 30,000,000 TOKEN (30%) │
|
||||
│ Locked Supply: 70,000,000 TOKEN (70%) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Vesting Schedules
|
||||
|
||||
Configure vesting for allocated tokens:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Vesting Configuration │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Team Vesting: │
|
||||
│ - Cliff: 12 months │
|
||||
│ - Vesting: 36 months (linear) │
|
||||
│ - Total: 48 months │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Vested % │ │
|
||||
│ │ 100% │ ████████████ │ │
|
||||
│ │ 75% │ ██████████ │ │
|
||||
│ │ 50% │ ██████████ │ │
|
||||
│ │ 25% │ ██████████ │ │
|
||||
│ │ 0% │▓▓▓▓▓▓▓▓▓▓ │ │
|
||||
│ │ └──────────────────────────────────────────────────── │ │
|
||||
│ │ 0 12 24 36 48 months │ │
|
||||
│ │ ↑ cliff │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Multisig Token Management
|
||||
|
||||
### Token Approvals
|
||||
|
||||
Configure which tokens the multisig can manage:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Multisig Token Approvals │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Spending Limits per Transaction: │
|
||||
│ │
|
||||
│ │ Token │ Limit per Tx │ Daily Limit │ Approval │ │
|
||||
│ │────────│────────────────│────────────────│───────────│ │
|
||||
│ │ TOKEN │ 100,000 │ 500,000 │ 2-of-3 │ │
|
||||
│ │ USDC │ $50,000 │ $200,000 │ 2-of-3 │ │
|
||||
│ │ WETH │ 50 ETH │ 200 ETH │ 3-of-5 │ │
|
||||
│ │
|
||||
│ Large Transaction Threshold: $100,000 │
|
||||
│ Large Transaction Approval: 3-of-5 + Governance │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Token Recovery
|
||||
|
||||
Configure emergency token recovery:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Token Recovery Settings │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ☑ Enable token recovery for mistakenly sent tokens │
|
||||
│ │
|
||||
│ Recovery Permissions: │
|
||||
│ ● Requires governance proposal │
|
||||
│ ○ Multisig can recover directly │
|
||||
│ ○ Guardian can recover │
|
||||
│ │
|
||||
│ Excluded from Recovery: │
|
||||
│ ☑ Governance token (TOKEN) │
|
||||
│ ☑ Staked tokens (sTOKEN) │
|
||||
│ ☑ Vote escrow tokens (veTOKEN) │
|
||||
│ │
|
||||
│ Recovery Timelock: [7___] days │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Integration with External Tokens
|
||||
|
||||
### Adding External Tokens
|
||||
|
||||
To add support for external tokens in your DAO:
|
||||
|
||||
1. **Verify Token Contract**: Ensure it's a standard ERC-20/SPL
|
||||
2. **Add to Approved List**: Governance proposal to approve token
|
||||
3. **Set Limits**: Configure spending and holding limits
|
||||
4. **Enable Trading**: Allow swaps/transfers as needed
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Add External Token │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Token Address: [0x_________________________________] │
|
||||
│ │
|
||||
│ Detected Token: │
|
||||
│ - Name: USD Coin │
|
||||
│ - Symbol: USDC │
|
||||
│ - Decimals: 6 │
|
||||
│ - Verified: ✓ Etherscan verified │
|
||||
│ │
|
||||
│ Configuration: │
|
||||
│ Holding Limit: [$10,000,000_] │
|
||||
│ Per-Transaction Limit: [$100,000__] │
|
||||
│ │
|
||||
│ Enabled Features: │
|
||||
│ ☑ Treasury can hold │
|
||||
│ ☑ Can be used for payments │
|
||||
│ ☐ Can be used for staking rewards │
|
||||
│ ☐ Can be used for streaming │
|
||||
│ │
|
||||
│ This requires a governance proposal. │
|
||||
│ │
|
||||
│ [Cancel] [Create Proposal] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Token Contract Security
|
||||
|
||||
Ensure governance token contract includes:
|
||||
|
||||
- [ ] Pausable functionality
|
||||
- [ ] Access control for minting (if applicable)
|
||||
- [ ] No hidden mint functions
|
||||
- [ ] Standard transfer behavior
|
||||
- [ ] Audited code
|
||||
|
||||
### Treasury Security
|
||||
|
||||
Protect token holdings with:
|
||||
|
||||
- [ ] Multi-signature requirements
|
||||
- [ ] Spending limits
|
||||
- [ ] Timelock delays
|
||||
- [ ] Emergency pause capability
|
||||
- [ ] Regular audits
|
||||
|
||||
### Vote Escrow Security
|
||||
|
||||
Secure voting power with:
|
||||
|
||||
- [ ] Non-transferable locks
|
||||
- [ ] No flash loan vulnerabilities
|
||||
- [ ] Snapshot-based voting
|
||||
- [ ] Decay calculations verified
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Token Not Detected"
|
||||
|
||||
**Causes:**
|
||||
- Incorrect address
|
||||
- Non-standard token contract
|
||||
- Wrong network
|
||||
|
||||
**Solutions:**
|
||||
- Verify address on block explorer
|
||||
- Check token standard compliance
|
||||
- Ensure correct network is selected
|
||||
|
||||
### "Insufficient Balance"
|
||||
|
||||
**Causes:**
|
||||
- Tokens not transferred to treasury
|
||||
- Tokens locked in vesting
|
||||
- Different token address
|
||||
|
||||
**Solutions:**
|
||||
- Verify treasury balance
|
||||
- Check vesting unlock status
|
||||
- Confirm token address matches
|
||||
|
||||
### "Transfer Failed"
|
||||
|
||||
**Causes:**
|
||||
- Exceeds spending limit
|
||||
- Insufficient approvals
|
||||
- Token paused
|
||||
- Recipient blacklisted
|
||||
|
||||
**Solutions:**
|
||||
- Check spending limits
|
||||
- Gather required signatures
|
||||
- Verify token status
|
||||
- Confirm recipient address
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Multisig Operations" href="/docs/guide/multisig" icon="key">
|
||||
Learn to sign multisig proposals
|
||||
</Card>
|
||||
<Card title="Treasury Management" href="/docs/guide/treasury" icon="vault">
|
||||
Manage treasury funds
|
||||
</Card>
|
||||
<Card title="Staking Setup" href="/docs/guide/staking/setup" icon="lock">
|
||||
Configure staking for your token
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,448 @@
|
||||
---
|
||||
title: Delegation
|
||||
description: How to delegate and manage voting power
|
||||
---
|
||||
|
||||
# Delegation
|
||||
|
||||
Delegation allows token holders to assign their voting power to trusted representatives without transferring ownership of their tokens. This enables participation even when you lack time or expertise to vote on every proposal.
|
||||
|
||||
## What is Delegation?
|
||||
|
||||
Delegation transfers your **voting power** (not your tokens) to another address called a **delegate**. The delegate can then vote on your behalf.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Delegation Flow │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ You (Delegator) Delegate │
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ 10,000 veT │────────> │ Receives │ │
|
||||
│ │ Keep tokens │ Power │ +10,000 VP │ │
|
||||
│ │ Lose VP │ │ Can vote │ │
|
||||
│ └─────────────┘ └─────────────┘ │
|
||||
│ │
|
||||
│ Your tokens stay in your wallet. │
|
||||
│ Only voting power moves. │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Key Properties
|
||||
|
||||
| Property | Delegator | Delegate |
|
||||
|----------|-----------|----------|
|
||||
| Token ownership | Keeps tokens | No tokens received |
|
||||
| Voting power | Loses VP | Gains VP |
|
||||
| Can re-delegate | Yes, anytime | Only their own tokens |
|
||||
| Staking rewards | Still receives | No additional rewards |
|
||||
| Can revoke | Yes, anytime | Cannot prevent revoke |
|
||||
|
||||
<Callout type="info">
|
||||
Delegation is non-custodial. Your tokens never leave your wallet. Only voting power is assigned.
|
||||
</Callout>
|
||||
|
||||
## How to Delegate
|
||||
|
||||
### Step 1: Navigate to Delegation
|
||||
|
||||
Go to **Governance > Delegation** or **Profile > Voting Power**.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Your Voting Power │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Locked Tokens: 10,000 veTokens │
|
||||
│ Lock Expires: Jan 15, 2027 │
|
||||
│ Base Power: 10,000 VP │
|
||||
│ │
|
||||
│ Current Delegation: Self (you vote directly) │
|
||||
│ │
|
||||
│ [Delegate to Someone] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Find a Delegate
|
||||
|
||||
Browse delegates or enter an address directly:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Find a Delegate │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Search: [________________________] or [Enter Address] │
|
||||
│ │
|
||||
│ Sort by: [Voting Power ▼] [Participation ▼] │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ ◉ alice.eth │ │
|
||||
│ │ Voting Power: 2.4M VP Participation: 98% │ │
|
||||
│ │ Delegators: 156 Proposals Voted: 42/43 │ │
|
||||
│ │ Statement: "I vote for sustainable growth..." │ │
|
||||
│ │ [View Profile] │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ ◯ bob.eth │ │
|
||||
│ │ Voting Power: 890K VP Participation: 95% │ │
|
||||
│ │ Delegators: 89 Proposals Voted: 40/43 │ │
|
||||
│ │ Statement: "Treasury security is my priority..." │ │
|
||||
│ │ [View Profile] │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Review Delegate Profile
|
||||
|
||||
Before delegating, review the delegate's track record:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Delegate Profile: alice.eth │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Voting Power: 2,400,000 VP │
|
||||
│ Self-Owned: 500,000 VP │
|
||||
│ Delegated: 1,900,000 VP │
|
||||
│ Delegators: 156 addresses │
|
||||
│ │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ Delegate Statement: │
|
||||
│ "I believe in sustainable protocol growth. I vote for │
|
||||
│ treasury diversification, careful spending, and │
|
||||
│ long-term value creation over short-term gains." │
|
||||
│ │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ Voting History (last 10 proposals): │
|
||||
│ │
|
||||
│ #42 Fund Grants Q1 FOR ✓ Passed │
|
||||
│ #41 Staking Update AGAINST ✗ Passed │
|
||||
│ #40 New Committee FOR ✓ Passed │
|
||||
│ #39 Parameter Change FOR ✓ Passed │
|
||||
│ #38 Emergency Pause FOR ✓ Passed │
|
||||
│ ... │
|
||||
│ │
|
||||
│ Participation Rate: 98% (42/43 proposals) │
|
||||
│ │
|
||||
│ [Delegate to alice.eth] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 4: Confirm Delegation
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Confirm Delegation │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Delegate To: alice.eth │
|
||||
│ Your Power: 10,000 VP │
|
||||
│ │
|
||||
│ ⚠ This will transfer your voting power to alice.eth. │
|
||||
│ They will vote on proposals on your behalf. │
|
||||
│ You can revoke this at any time. │
|
||||
│ │
|
||||
│ [Cancel] [Confirm Delegation] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 5: Sign Transaction
|
||||
|
||||
1. Click **Confirm Delegation**
|
||||
2. Approve the transaction in your wallet
|
||||
3. Wait for confirmation
|
||||
4. Delegation is now active
|
||||
|
||||
## Finding Good Delegates
|
||||
|
||||
### Evaluation Criteria
|
||||
|
||||
| Criterion | What to Look For |
|
||||
|-----------|------------------|
|
||||
| **Participation Rate** | >90% proposals voted |
|
||||
| **Voting Alignment** | Votes match your values |
|
||||
| **Communication** | Clear delegate statement |
|
||||
| **Track Record** | Consistent over time |
|
||||
| **Availability** | Active in governance forums |
|
||||
|
||||
### Red Flags
|
||||
|
||||
- ❌ Low participation (<70%)
|
||||
- ❌ No delegate statement
|
||||
- ❌ Erratic voting patterns
|
||||
- ❌ No forum presence
|
||||
- ❌ Votes against stated principles
|
||||
|
||||
### Delegate Discovery
|
||||
|
||||
**Official Delegate Registry:**
|
||||
- Go to **Governance > Delegates**
|
||||
- Filter by participation, power, or focus area
|
||||
|
||||
**Community Resources:**
|
||||
- Governance forum delegate threads
|
||||
- Discord #delegates channel
|
||||
- Weekly delegate AMAs
|
||||
|
||||
## Delegate Responsibilities
|
||||
|
||||
If you accept delegated power, you have responsibilities:
|
||||
|
||||
### Required
|
||||
|
||||
- ✅ Vote on all proposals (or abstain with reason)
|
||||
- ✅ Maintain public delegate statement
|
||||
- ✅ Be accessible to delegators
|
||||
|
||||
### Recommended
|
||||
|
||||
- ✅ Explain voting rationale publicly
|
||||
- ✅ Participate in forum discussions
|
||||
- ✅ Attend governance calls
|
||||
- ✅ Respond to delegator questions
|
||||
- ✅ Update statement if views change
|
||||
|
||||
### Setting Up as a Delegate
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Become a Delegate │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Display Name: [____________________] │
|
||||
│ │
|
||||
│ Delegate Statement: │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ Describe your governance philosophy, priorities, │ │
|
||||
│ │ and how you plan to vote... │ │
|
||||
│ │ │ │
|
||||
│ │ Markdown supported. │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Focus Areas (select up to 3): │
|
||||
│ [x] Treasury [ ] Technical [x] Grants │
|
||||
│ [ ] Security [x] Community [ ] Protocol │
|
||||
│ │
|
||||
│ Contact: │
|
||||
│ Twitter: [@__________] │
|
||||
│ Discord: [__________#____] │
|
||||
│ Forum: [__________________] │
|
||||
│ │
|
||||
│ [Save Delegate Profile] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Revoking Delegation
|
||||
|
||||
You can revoke delegation at any time to reclaim your voting power.
|
||||
|
||||
### How to Revoke
|
||||
|
||||
1. Go to **Governance > Delegation**
|
||||
2. View your current delegation
|
||||
3. Click **Revoke Delegation**
|
||||
4. Confirm and sign
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Your Current Delegation │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Delegated To: alice.eth │
|
||||
│ Since: Jan 1, 2026 │
|
||||
│ Your Power: 10,000 VP │
|
||||
│ │
|
||||
│ Delegate Stats: │
|
||||
│ - Voted 42/43 proposals since delegation │
|
||||
│ - Your power used: 42 times │
|
||||
│ │
|
||||
│ [Change Delegate] [Revoke] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### When to Revoke
|
||||
|
||||
Consider revoking if:
|
||||
- Delegate votes against your interests repeatedly
|
||||
- Delegate becomes inactive
|
||||
- You want to vote on important proposals yourself
|
||||
- Delegate's views have changed
|
||||
|
||||
<Callout type="warning">
|
||||
Revocation takes effect immediately. If there's an active vote, you may want to wait until after to avoid missing that proposal.
|
||||
</Callout>
|
||||
|
||||
### Re-Delegation
|
||||
|
||||
After revoking, you can:
|
||||
1. **Self-delegate** - Vote directly yourself
|
||||
2. **Delegate to someone else** - Choose a new delegate
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Delegation Revoked │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Your voting power is now: │
|
||||
│ ○ Self-delegated (vote yourself) │
|
||||
│ │
|
||||
│ Would you like to delegate to someone new? │
|
||||
│ │
|
||||
│ [Keep Self-Delegation] [Find New Delegate] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Advanced Delegation
|
||||
|
||||
### Partial Delegation
|
||||
|
||||
Some DAOs support splitting voting power among multiple delegates:
|
||||
|
||||
```yaml
|
||||
Total Power: 100,000 VP
|
||||
|
||||
Delegation Split:
|
||||
- alice.eth: 50,000 VP (50%)
|
||||
- bob.eth: 30,000 VP (30%)
|
||||
- self: 20,000 VP (20%)
|
||||
```
|
||||
|
||||
<Callout type="info">
|
||||
Partial delegation is not available in all DAOs. Check your DAO's governance settings.
|
||||
</Callout>
|
||||
|
||||
### Delegation Chains
|
||||
|
||||
Delegation is **not transitive**. If Alice delegates to Bob, and Bob delegates to Carol:
|
||||
|
||||
```
|
||||
You → Alice → Bob → Carol
|
||||
|
||||
Result:
|
||||
- Your power goes to Alice only
|
||||
- Alice's power goes to Bob only
|
||||
- Bob's power goes to Carol only
|
||||
- Carol cannot vote with your power
|
||||
```
|
||||
|
||||
### Time-Locked Delegation
|
||||
|
||||
Some DAOs allow time-locked delegation that cannot be revoked for a period:
|
||||
|
||||
```yaml
|
||||
Delegation:
|
||||
to: alice.eth
|
||||
power: 10,000 VP
|
||||
lock_until: "2026-06-01"
|
||||
revokable: false (until lock expires)
|
||||
```
|
||||
|
||||
## Delegation Tracking
|
||||
|
||||
### Your Delegations
|
||||
|
||||
View who you've delegated to:
|
||||
|
||||
| Delegate | Power | Since | Actions |
|
||||
|----------|-------|-------|---------|
|
||||
| alice.eth | 10,000 VP | Jan 1, 2026 | [Revoke] |
|
||||
|
||||
### Your Delegators
|
||||
|
||||
View who has delegated to you:
|
||||
|
||||
| Delegator | Power | Since |
|
||||
|-----------|-------|-------|
|
||||
| 0x1234...abcd | 5,000 VP | Dec 15, 2025 |
|
||||
| 0x5678...efgh | 2,500 VP | Jan 5, 2026 |
|
||||
| **Total** | **7,500 VP** | - |
|
||||
|
||||
### Delegation History
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Delegation History │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Jan 15, 2026 Revoked from bob.eth │
|
||||
│ Jan 10, 2026 Delegated 10,000 VP to bob.eth │
|
||||
│ Dec 1, 2025 Revoked from alice.eth │
|
||||
│ Oct 15, 2025 Delegated 8,000 VP to alice.eth │
|
||||
│ Sep 1, 2025 Initial self-delegation │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Delegation Best Practices
|
||||
|
||||
### For Delegators
|
||||
|
||||
1. **Research thoroughly** before delegating
|
||||
2. **Monitor delegate activity** regularly
|
||||
3. **Engage with delegates** when you disagree
|
||||
4. **Revoke promptly** if delegate doesn't represent you
|
||||
5. **Re-evaluate periodically** (quarterly recommended)
|
||||
|
||||
### For Delegates
|
||||
|
||||
1. **Vote consistently** with stated principles
|
||||
2. **Communicate rationale** for each vote
|
||||
3. **Stay accessible** to delegators
|
||||
4. **Update statement** when views change
|
||||
5. **Notify delegators** of significant decisions
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Cannot Delegate - No Voting Power"
|
||||
|
||||
**Causes:**
|
||||
- No tokens locked
|
||||
- Lock has expired
|
||||
|
||||
**Solution:**
|
||||
- Lock tokens first, then delegate
|
||||
|
||||
### "Delegation Not Updating"
|
||||
|
||||
**Causes:**
|
||||
- Transaction pending
|
||||
- Network congestion
|
||||
|
||||
**Solution:**
|
||||
- Check transaction status
|
||||
- Wait for confirmation
|
||||
|
||||
### "Cannot Vote After Delegating"
|
||||
|
||||
**Expected behavior** - your power is with your delegate.
|
||||
|
||||
**To vote yourself:**
|
||||
1. Revoke delegation
|
||||
2. Wait for transaction to confirm
|
||||
3. You can now vote directly
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Voting" href="/docs/guide/voting" icon="check-square">
|
||||
Learn how to cast votes
|
||||
</Card>
|
||||
<Card title="Execution" href="/docs/guide/voting/execution" icon="play-circle">
|
||||
Execute passed proposals
|
||||
</Card>
|
||||
<Card title="Creating Proposals" href="/docs/guide/resolutions" icon="file-plus">
|
||||
Submit your own proposals
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,561 @@
|
||||
---
|
||||
title: Executing Proposals
|
||||
description: How to execute passed governance proposals
|
||||
---
|
||||
|
||||
# Executing Proposals
|
||||
|
||||
After a proposal passes voting, it doesn't take effect immediately. This guide covers the execution process, timelock mechanics, and how to execute proposals.
|
||||
|
||||
## Execution Overview
|
||||
|
||||
The execution flow ensures security while maintaining decentralization:
|
||||
|
||||
```
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ Voting │───>│ Passed │───>│ Timelock │───>│ Execute │
|
||||
│ Closed │ │ (Queue) │ │ (Wait) │ │ (Apply) │
|
||||
└──────────┘ └──────────┘ └──────────┘ └──────────┘
|
||||
│ │
|
||||
v v
|
||||
Queue to Timer runs
|
||||
Timelock (1-14 days)
|
||||
```
|
||||
|
||||
### Why Timelock?
|
||||
|
||||
The timelock delay serves critical functions:
|
||||
|
||||
| Purpose | Description |
|
||||
|---------|-------------|
|
||||
| **Security** | Time to detect malicious proposals |
|
||||
| **Exit Window** | Users can exit if they disagree |
|
||||
| **Review** | Final check before execution |
|
||||
| **Coordination** | Time for affected parties to prepare |
|
||||
|
||||
## Proposal States
|
||||
|
||||
A proposal moves through these states:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Proposal State Machine │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌────────┐ vote ┌────────┐ queue ┌────────┐ │
|
||||
│ │ Active │ ──────> │ Passed │ ──────> │ Queued │ │
|
||||
│ └────────┘ └────────┘ └────────┘ │
|
||||
│ │ │ │ │
|
||||
│ │ fails │ expires │ timelock │
|
||||
│ v v v expires │
|
||||
│ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │Defeated│ │Expired │ │ Ready │ │
|
||||
│ └────────┘ └────────┘ └────────┘ │
|
||||
│ │ │
|
||||
│ execute │ expires │
|
||||
│ │ v │ │
|
||||
│ ┌────────┐ ┌────────┐ │ │
|
||||
│ │Executed│ │ Stale │<┘ │
|
||||
│ └────────┘ └────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### State Definitions
|
||||
|
||||
| State | Description | Next Actions |
|
||||
|-------|-------------|--------------|
|
||||
| **Active** | Voting in progress | Wait for voting end |
|
||||
| **Passed** | Voting succeeded, not yet queued | Queue to timelock |
|
||||
| **Defeated** | Voting failed (quorum or threshold) | None (terminal) |
|
||||
| **Queued** | In timelock, waiting | Wait for timelock end |
|
||||
| **Ready** | Timelock complete, can execute | Execute proposal |
|
||||
| **Executed** | Actions applied on-chain | None (terminal) |
|
||||
| **Expired** | Passed but never queued in time | None (terminal) |
|
||||
| **Stale** | Ready but not executed in time | None (terminal) |
|
||||
|
||||
## Timelock Mechanics
|
||||
|
||||
### Timelock Durations
|
||||
|
||||
Different proposal types have different timelock periods:
|
||||
|
||||
| Proposal Type | Timelock | Rationale |
|
||||
|---------------|----------|-----------|
|
||||
| **Standard** | 3 days | Normal governance actions |
|
||||
| **Treasury (<$10K)** | 1 day | Low-risk payments |
|
||||
| **Treasury (>$10K)** | 7 days | High-value transactions |
|
||||
| **Constitutional** | 14 days | Protocol-changing decisions |
|
||||
| **Emergency** | 0 days | Critical security fixes |
|
||||
|
||||
<Callout type="warning">
|
||||
Emergency proposals bypass timelock but require higher approval thresholds (typically 75%+).
|
||||
</Callout>
|
||||
|
||||
### Timelock Timeline
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Proposal #42: Fund Developer Grants │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Timeline: │
|
||||
│ │
|
||||
│ Jan 1 Jan 8 Jan 11 Jan 14 Jan 21│
|
||||
│ │ │ │ │ │ │
|
||||
│ ▼ ▼ ▼ ▼ ▼ │
|
||||
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
|
||||
│ │Create│ │Voting│ │ Pass │ │Queue │ │Ready │ │
|
||||
│ │ │ │ Ends │ │ │ │ │ │ │ │
|
||||
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │
|
||||
│ │
|
||||
│ [ Draft ][ Review ][ Voting ][ Timelock ][ Execute ] │
|
||||
│ 7 days 3 days 7 days 7 days grace │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Grace Period
|
||||
|
||||
After timelock expires, there's a grace period to execute:
|
||||
|
||||
```
|
||||
Timelock End ────────> Grace Period ────────> Expiration
|
||||
(7 days)
|
||||
|
||||
Execute anytime here
|
||||
```
|
||||
|
||||
If not executed within the grace period, the proposal becomes **Stale** and cannot be executed. A new proposal must be submitted.
|
||||
|
||||
## When Proposals Can Be Executed
|
||||
|
||||
A proposal can be executed when ALL conditions are met:
|
||||
|
||||
```yaml
|
||||
Execution Requirements:
|
||||
- status: "Queued"
|
||||
- timelock_end: < current_time
|
||||
- grace_period_end: > current_time
|
||||
- not_already_executed: true
|
||||
```
|
||||
|
||||
### Checking Execution Status
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Proposal #42: Fund Developer Grants │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Status: READY TO EXECUTE │
|
||||
│ │
|
||||
│ ✓ Voting passed (72% For) │
|
||||
│ ✓ Queued to timelock (Jan 14, 2026) │
|
||||
│ ✓ Timelock complete (Jan 21, 2026) │
|
||||
│ ○ Execution window: 7 days remaining │
|
||||
│ │
|
||||
│ Grace Period Ends: Jan 28, 2026 14:00 UTC │
|
||||
│ │
|
||||
│ [Execute Proposal] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Who Can Execute
|
||||
|
||||
**Anyone** can execute a proposal once it's ready. This is by design:
|
||||
|
||||
| Aspect | Description |
|
||||
|--------|-------------|
|
||||
| **Permissionless** | No special role required |
|
||||
| **Incentive** | Anyone can ensure DAO decisions happen |
|
||||
| **Decentralization** | No single point of failure |
|
||||
| **Gas Cost** | Executor pays gas (can be reimbursed) |
|
||||
|
||||
### Typical Executors
|
||||
|
||||
1. **Proposal Author** - Most motivated to see it through
|
||||
2. **DAO Operators** - May run automated execution
|
||||
3. **Committee Members** - Relevant to their domain
|
||||
4. **Community Members** - Anyone who wants to help
|
||||
5. **Bots** - Automated execution services
|
||||
|
||||
## Execution Process
|
||||
|
||||
### Step 1: Find Executable Proposals
|
||||
|
||||
Navigate to **Governance > Proposals** and filter by "Ready":
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Proposals │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Filter: [Ready to Execute ▼] │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ #42 Fund Developer Grants Q1 [READY] │ │
|
||||
│ │ Grace period: 6 days 12 hours remaining │ │
|
||||
│ │ Actions: Transfer 50,000 USDC │ │
|
||||
│ │ [Execute] │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ #39 Update Staking Parameters [READY] │ │
|
||||
│ │ Grace period: 2 days 3 hours remaining │ │
|
||||
│ │ Actions: Call setMinStake(1000) │ │
|
||||
│ │ [Execute] │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Review Proposal Actions
|
||||
|
||||
Before executing, review what will happen:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Proposal #42: Execution Preview │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Actions to be executed: │
|
||||
│ │
|
||||
│ 1. Transfer │
|
||||
│ ├─ From: Treasury (0xDAO1...2345) │
|
||||
│ ├─ To: Grants Multisig (0x5678...abcd) │
|
||||
│ ├─ Amount: 50,000 USDC │
|
||||
│ └─ Token: 0xA0b8...3E7c (USDC) │
|
||||
│ │
|
||||
│ Simulation Result: ✓ Success │
|
||||
│ │
|
||||
│ Gas Estimate: ~250,000 gas (~$5.00) │
|
||||
│ │
|
||||
│ [Cancel] [Execute Proposal] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Execute
|
||||
|
||||
1. Click **Execute Proposal**
|
||||
2. Review transaction in wallet
|
||||
3. Confirm and sign
|
||||
4. Wait for confirmation
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Confirm Execution │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ You are executing Proposal #42 │
|
||||
│ │
|
||||
│ ⚠ This action is irreversible. │
|
||||
│ The following will happen: │
|
||||
│ - 50,000 USDC transferred from Treasury │
|
||||
│ - Grants Multisig receives funds │
|
||||
│ │
|
||||
│ Gas: ~250,000 (~$5.00) │
|
||||
│ │
|
||||
│ [Cancel] [Confirm & Execute] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 4: Verify Execution
|
||||
|
||||
After execution, verify the results:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Proposal #42: Fund Developer Grants Q1 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Status: EXECUTED ✓ │
|
||||
│ │
|
||||
│ Execution Details: │
|
||||
│ ├─ Executed by: 0xExecutor...1234 │
|
||||
│ ├─ Timestamp: Jan 22, 2026 14:32:15 UTC │
|
||||
│ ├─ Transaction: 0xabc123...def456 │
|
||||
│ └─ Block: 18,234,567 │
|
||||
│ │
|
||||
│ Results: │
|
||||
│ ✓ Action 1: Transfer 50,000 USDC - SUCCESS │
|
||||
│ │
|
||||
│ [View Transaction] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Failed Executions
|
||||
|
||||
Executions can fail for several reasons:
|
||||
|
||||
### Common Failure Causes
|
||||
|
||||
| Cause | Description | Solution |
|
||||
|-------|-------------|----------|
|
||||
| **Insufficient Funds** | Treasury lacks required tokens | Wait for funds or modify |
|
||||
| **Contract Reverted** | Target contract rejected call | Check parameters |
|
||||
| **Gas Limit** | Transaction ran out of gas | Retry with higher gas |
|
||||
| **State Changed** | On-chain state no longer valid | May need new proposal |
|
||||
| **Already Executed** | Duplicate execution attempt | No action needed |
|
||||
|
||||
### Handling Failed Execution
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Execution Failed │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Proposal #42 execution failed. │
|
||||
│ │
|
||||
│ Error: Insufficient balance │
|
||||
│ Details: Treasury has 45,000 USDC, proposal requires │
|
||||
│ 50,000 USDC. │
|
||||
│ │
|
||||
│ Transaction: 0xfailed...123 (reverted) │
|
||||
│ │
|
||||
│ Options: │
|
||||
│ - Wait for treasury to receive more funds │
|
||||
│ - Submit new proposal with adjusted amount │
|
||||
│ │
|
||||
│ Grace period remaining: 5 days │
|
||||
│ │
|
||||
│ [Retry Execution] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Retry vs. New Proposal
|
||||
|
||||
**Retry Execution** (same proposal):
|
||||
- Failure was due to temporary issue (gas, timing)
|
||||
- State can be corrected before grace period ends
|
||||
- No need for new vote
|
||||
|
||||
**New Proposal** (start over):
|
||||
- Original proposal has fundamental issue
|
||||
- Parameters need to change
|
||||
- Grace period will expire
|
||||
|
||||
## Execution Batching
|
||||
|
||||
### Single Proposal, Multiple Actions
|
||||
|
||||
A proposal can contain multiple actions executed atomically:
|
||||
|
||||
```yaml
|
||||
Proposal #45:
|
||||
actions:
|
||||
- type: transfer
|
||||
to: 0xRecipient1
|
||||
amount: 10000
|
||||
token: USDC
|
||||
- type: transfer
|
||||
to: 0xRecipient2
|
||||
amount: 5000
|
||||
token: USDC
|
||||
- type: contract_call
|
||||
target: 0xStaking
|
||||
function: setRewardRate
|
||||
args: [100]
|
||||
|
||||
Execution: All-or-nothing
|
||||
- If any action fails, all revert
|
||||
- Either all succeed or none succeed
|
||||
```
|
||||
|
||||
### Multiple Proposals
|
||||
|
||||
Multiple ready proposals can be executed in sequence:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Batch Execute │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Select proposals to execute: │
|
||||
│ │
|
||||
│ [x] #42 Fund Developer Grants 50,000 USDC transfer │
|
||||
│ [x] #39 Update Staking Parameters Parameter change │
|
||||
│ [ ] #38 Add Committee Member Role assignment │
|
||||
│ │
|
||||
│ Total Gas Estimate: ~500,000 (~$10.00) │
|
||||
│ │
|
||||
│ [Execute Selected (2)] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Automated Execution
|
||||
|
||||
### Execution Bots
|
||||
|
||||
DAOs often run automated execution:
|
||||
|
||||
```yaml
|
||||
Execution Bot Config:
|
||||
check_interval: 1 hour
|
||||
gas_price_limit: 50 gwei
|
||||
proposals:
|
||||
- monitor: all
|
||||
- execute_when: ready
|
||||
- retry_on_failure: true
|
||||
- max_retries: 3
|
||||
```
|
||||
|
||||
### Keeper Networks
|
||||
|
||||
Third-party keeper networks can execute proposals:
|
||||
|
||||
| Network | Description |
|
||||
|---------|-------------|
|
||||
| **Gelato** | Automated smart contract execution |
|
||||
| **Chainlink Keepers** | Decentralized automation |
|
||||
| **OpenZeppelin Defender** | Secure operations platform |
|
||||
|
||||
## Cancellation
|
||||
|
||||
### When Proposals Can Be Cancelled
|
||||
|
||||
| State | Can Cancel? | Who Can Cancel? |
|
||||
|-------|-------------|-----------------|
|
||||
| Active | Yes | Proposer only |
|
||||
| Passed | Yes | Guardian/Admin |
|
||||
| Queued | Yes | Guardian/Admin |
|
||||
| Ready | Yes | Guardian/Admin |
|
||||
| Executed | No | - |
|
||||
| Defeated | No | - |
|
||||
|
||||
### Guardian Role
|
||||
|
||||
Guardians can cancel queued proposals in emergencies:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Emergency Cancellation (Guardian Only) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ⚠ This is an emergency action. │
|
||||
│ │
|
||||
│ Cancelling Proposal #42 will: │
|
||||
│ - Remove from timelock queue │
|
||||
│ - Prevent execution permanently │
|
||||
│ - Require new proposal to achieve same goal │
|
||||
│ │
|
||||
│ Reason (required): │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ Security vulnerability discovered in recipient │ │
|
||||
│ │ contract. Funds would be at risk. │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ [Cancel Proposal] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Execution Monitoring
|
||||
|
||||
### Dashboard View
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Execution Dashboard │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Pending Execution (3): │
|
||||
│ │
|
||||
│ ┌──────────┬─────────────────┬──────────────┬───────────┐ │
|
||||
│ │ Proposal │ Actions │ Grace Left │ Status │ │
|
||||
│ ├──────────┼─────────────────┼──────────────┼───────────┤ │
|
||||
│ │ #42 │ 1 transfer │ 6d 12h │ Ready │ │
|
||||
│ │ #39 │ 1 param change │ 2d 3h │ Ready │ │
|
||||
│ │ #38 │ 1 role change │ 12h │ Urgent ⚠ │ │
|
||||
│ └──────────┴─────────────────┴──────────────┴───────────┘ │
|
||||
│ │
|
||||
│ Recent Executions: │
|
||||
│ │
|
||||
│ #37 Executed Jan 20, 2026 0x...1234 ✓ Success │
|
||||
│ #36 Executed Jan 18, 2026 0x...5678 ✓ Success │
|
||||
│ #35 Failed Jan 15, 2026 0x...abcd ✗ Reverted │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Notifications
|
||||
|
||||
Set up alerts for execution events:
|
||||
|
||||
```yaml
|
||||
Notification Settings:
|
||||
- event: proposal_ready
|
||||
channels: [email, discord]
|
||||
- event: grace_period_warning
|
||||
threshold: 24 hours
|
||||
channels: [email, discord, telegram]
|
||||
- event: execution_success
|
||||
channels: [discord]
|
||||
- event: execution_failure
|
||||
channels: [email, discord, telegram]
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Proposal Not Ready"
|
||||
|
||||
**Causes:**
|
||||
- Timelock not yet complete
|
||||
- Proposal not queued
|
||||
- Already executed
|
||||
|
||||
**Solution:**
|
||||
- Check proposal status and timeline
|
||||
- Wait for timelock to complete
|
||||
- Queue if in "Passed" state
|
||||
|
||||
### "Execution Reverted"
|
||||
|
||||
**Causes:**
|
||||
- Target contract reverted
|
||||
- Insufficient funds
|
||||
- Invalid parameters
|
||||
|
||||
**Solution:**
|
||||
- Check error message
|
||||
- Verify treasury balance
|
||||
- Review proposal actions
|
||||
- Contact technical support if needed
|
||||
|
||||
### "Grace Period Expired"
|
||||
|
||||
**Causes:**
|
||||
- Proposal wasn't executed in time
|
||||
|
||||
**Solution:**
|
||||
- Submit new proposal
|
||||
- Consider automated execution for future
|
||||
|
||||
### "Unauthorized"
|
||||
|
||||
**Causes:**
|
||||
- Trying to cancel without guardian role
|
||||
- Trying to execute cancelled proposal
|
||||
|
||||
**Solution:**
|
||||
- Verify proposal state
|
||||
- Check your permissions
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Voting" href="/docs/guide/voting" icon="check-square">
|
||||
Cast votes on proposals
|
||||
</Card>
|
||||
<Card title="Delegation" href="/docs/guide/voting/delegation" icon="users">
|
||||
Delegate your voting power
|
||||
</Card>
|
||||
<Card title="Creating Proposals" href="/docs/guide/resolutions" icon="file-plus">
|
||||
Submit your own proposals
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,385 @@
|
||||
---
|
||||
title: Voting on Proposals
|
||||
description: How to cast votes on governance proposals
|
||||
---
|
||||
|
||||
# Voting on Proposals
|
||||
|
||||
Voting is the core mechanism for collective decision-making in the DAO. This guide covers everything you need to participate in governance votes.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you can vote:
|
||||
|
||||
- **Connected wallet** with governance tokens
|
||||
- **Voting power** from locked tokens (veTokens) or delegation
|
||||
- **Active proposal** in voting period
|
||||
|
||||
<Callout type="info">
|
||||
Voting power is calculated at the snapshot block when a proposal is created. Tokens acquired after the snapshot cannot be used on that proposal.
|
||||
</Callout>
|
||||
|
||||
## Voting Options
|
||||
|
||||
Every proposal offers three voting choices:
|
||||
|
||||
| Option | Meaning | Effect |
|
||||
|--------|---------|--------|
|
||||
| **For** | Support the proposal | Counts toward approval threshold |
|
||||
| **Against** | Oppose the proposal | Counts against approval |
|
||||
| **Abstain** | Neither support nor oppose | Counts toward quorum only |
|
||||
|
||||
### When to Abstain
|
||||
|
||||
Abstain is useful when you:
|
||||
- Want to help reach quorum but lack expertise to judge
|
||||
- Have a conflict of interest
|
||||
- Believe the community should decide without your influence
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Vote Distribution │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ For ████████████████████░░░░░░░░░░░░░░ 52% │
|
||||
│ Against ██████████████░░░░░░░░░░░░░░░░░░░░ 35% │
|
||||
│ Abstain █████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 13% │
|
||||
│ │
|
||||
│ Total Participation: 2.3M tokens (46% of quorum) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Vote Weight Calculation
|
||||
|
||||
Your voting power depends on your token lock configuration:
|
||||
|
||||
### Base Formula
|
||||
|
||||
```
|
||||
Voting Power = Locked Amount × Time Multiplier
|
||||
```
|
||||
|
||||
### Time Multipliers
|
||||
|
||||
| Lock Duration | Multiplier | Example (1000 tokens) |
|
||||
|---------------|------------|----------------------|
|
||||
| 1 week | 0.02x | 20 votes |
|
||||
| 1 month | 0.08x | 80 votes |
|
||||
| 6 months | 0.5x | 500 votes |
|
||||
| 1 year | 1.0x | 1,000 votes |
|
||||
| 4 years | 4.0x | 4,000 votes |
|
||||
|
||||
<Callout type="warning">
|
||||
Voting power decays linearly as your lock approaches expiration. Re-lock or extend to maintain maximum power.
|
||||
</Callout>
|
||||
|
||||
### Power Decay Over Time
|
||||
|
||||
```
|
||||
Voting Power
|
||||
^
|
||||
4x │████
|
||||
│████████
|
||||
│████████████
|
||||
│████████████████
|
||||
1x │████████████████████
|
||||
│░░░░░░░░░░░░░░░░░░░░████
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░████
|
||||
└──────────────────────────────> Time
|
||||
Lock Expiry
|
||||
```
|
||||
|
||||
### Delegated Power
|
||||
|
||||
If others have delegated to you, their power adds to yours:
|
||||
|
||||
```
|
||||
Total Voting Power = Your Locked Power + Delegated Power
|
||||
```
|
||||
|
||||
## Voting Period Mechanics
|
||||
|
||||
### Proposal Lifecycle
|
||||
|
||||
```
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ Draft │───>│ Review │───>│ Voting │───>│ Timelock │
|
||||
│ 7 days │ │ 3 days │ │ 7 days │ │ 1-14 days│
|
||||
└──────────┘ └──────────┘ └──────────┘ └──────────┘
|
||||
│
|
||||
v
|
||||
┌──────────────┐
|
||||
│ Execution │
|
||||
│ or Defeat │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
### Voting Period Timeline
|
||||
|
||||
| Stage | Duration | What Happens |
|
||||
|-------|----------|--------------|
|
||||
| **Start** | Block N | Proposal becomes active, voting opens |
|
||||
| **Active** | 7 days | Members cast and change votes |
|
||||
| **Grace** | 6 hours | Final window before close |
|
||||
| **End** | Block N+50400 | Voting closes, result finalized |
|
||||
|
||||
### Quorum Requirements
|
||||
|
||||
For a vote to be valid, it must reach quorum:
|
||||
|
||||
| Proposal Type | Quorum | Approval Threshold |
|
||||
|---------------|--------|-------------------|
|
||||
| Standard | 1M tokens | >50% For |
|
||||
| Constitutional | 5M tokens | >66.7% For |
|
||||
| Emergency | 500K tokens | >75% For |
|
||||
|
||||
<Callout type="info">
|
||||
Abstain votes count toward quorum but not toward the approval calculation.
|
||||
</Callout>
|
||||
|
||||
### Result Calculation
|
||||
|
||||
```
|
||||
Approval % = For Votes / (For Votes + Against Votes) × 100
|
||||
|
||||
Quorum % = (For + Against + Abstain) / Total Supply × 100
|
||||
```
|
||||
|
||||
**Example:**
|
||||
- For: 600,000 tokens
|
||||
- Against: 300,000 tokens
|
||||
- Abstain: 100,000 tokens
|
||||
- Total Supply: 10,000,000 tokens
|
||||
|
||||
```
|
||||
Approval = 600,000 / (600,000 + 300,000) = 66.7% ✓
|
||||
Quorum = 1,000,000 / 10,000,000 = 10% (need 1M for standard)
|
||||
Result: PASSED (if 1M quorum met)
|
||||
```
|
||||
|
||||
## How to Vote
|
||||
|
||||
### Step 1: Find Active Proposals
|
||||
|
||||
Navigate to **Governance > Proposals** and filter by status:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Proposals [+ New] │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Filter: [All ▼] [Active ▼] [Treasury ▼] Search: [____] │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ #42 Fund Developer Grants Q1 [ACTIVE] │ │
|
||||
│ │ Ends in 3 days 14 hours Quorum: 67% │ │
|
||||
│ │ Requested: 50,000 USDC │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ #41 Update Staking Parameters [ACTIVE] │ │
|
||||
│ │ Ends in 1 day 6 hours Quorum: 89% │ │
|
||||
│ │ Changes: min stake, cooldown │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Review Proposal Details
|
||||
|
||||
Click a proposal to see full details:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ #42: Fund Developer Grants Q1 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Status: ACTIVE Ends: Jan 15, 2026 at 14:00 UTC │
|
||||
│ Author: 0x1234...abcd Type: Treasury Transfer │
|
||||
│ │
|
||||
│ ───────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
│ ## Summary │
|
||||
│ Allocate 50,000 USDC from treasury to fund developer │
|
||||
│ grants for Q1 2026. │
|
||||
│ │
|
||||
│ ## Actions │
|
||||
│ 1. Transfer 50,000 USDC to Grants Multisig (0x5678...) │
|
||||
│ │
|
||||
│ ## Discussion │
|
||||
│ - Forum: [View Thread] │
|
||||
│ - Discord: #proposal-42 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 3: Cast Your Vote
|
||||
|
||||
Select your voting choice:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Cast Your Vote │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Your Voting Power: 12,500 veTokens │
|
||||
│ (10,000 locked + 2,500 delegated) │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ FOR │ │ AGAINST │ │ ABSTAIN │ │
|
||||
│ │ ○ │ │ ○ │ │ ○ │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
│ │
|
||||
│ Reason (optional): │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ Supporting this because the grants program has │ │
|
||||
│ │ consistently produced valuable contributions... │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ [Cancel] [Submit Vote] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 4: Confirm Transaction
|
||||
|
||||
1. Click **Submit Vote**
|
||||
2. Review the transaction in your wallet
|
||||
3. Confirm and sign
|
||||
4. Wait for confirmation
|
||||
|
||||
<Callout type="info">
|
||||
On-chain votes require gas. For gasless voting options, see [Gasless Voting](/docs/guide/gasless).
|
||||
</Callout>
|
||||
|
||||
## Changing Your Vote
|
||||
|
||||
You can change your vote any time before the voting period ends:
|
||||
|
||||
1. Navigate to the proposal
|
||||
2. Your current vote is displayed
|
||||
3. Click **Change Vote**
|
||||
4. Select new option
|
||||
5. Submit and sign
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Your Vote: FOR (cast 2 days ago) [Change] │
|
||||
│ │
|
||||
│ 12,500 veTokens committed │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
<Callout type="warning">
|
||||
Once the voting period ends, votes are final and cannot be changed.
|
||||
</Callout>
|
||||
|
||||
## Voting Strategies
|
||||
|
||||
### Active Participation
|
||||
|
||||
- Review all proposals before voting
|
||||
- Participate in forum discussions
|
||||
- Consider long-term implications
|
||||
- Vote on every proposal to maximize influence
|
||||
|
||||
### Informed Delegation
|
||||
|
||||
If you lack time or expertise:
|
||||
- [Delegate to trusted representatives](/docs/guide/voting/delegation)
|
||||
- Monitor delegate voting records
|
||||
- Revoke if delegates vote against your interests
|
||||
|
||||
### Committee Focus
|
||||
|
||||
- Join committees aligned with your expertise
|
||||
- Focus voting on committee-relevant proposals
|
||||
- Abstain on topics outside your knowledge
|
||||
|
||||
## Vote Tracking
|
||||
|
||||
### Your Voting History
|
||||
|
||||
View past votes in **Profile > Voting History**:
|
||||
|
||||
| Proposal | Your Vote | Result | Power Used |
|
||||
|----------|-----------|--------|------------|
|
||||
| #42 Fund Grants | For | Pending | 12,500 |
|
||||
| #41 Staking Update | Against | Passed | 12,500 |
|
||||
| #40 New Committee | For | Passed | 12,000 |
|
||||
|
||||
### Proposal Analytics
|
||||
|
||||
Each proposal shows voting analytics:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Voting Progress │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Quorum Progress │
|
||||
│ ████████████████████████████████░░░░░░░░░░ 89% of 1M │
|
||||
│ │
|
||||
│ Current Result │
|
||||
│ For: ████████████████████████████░░░░░░ 72% │
|
||||
│ Against: ████████████░░░░░░░░░░░░░░░░░░░░░░ 28% │
|
||||
│ │
|
||||
│ Participation │
|
||||
│ Unique Voters: 234 │
|
||||
│ Avg Vote Size: 3,803 tokens │
|
||||
│ Largest Vote: 150,000 tokens │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Insufficient Voting Power"
|
||||
|
||||
**Causes:**
|
||||
- No tokens locked
|
||||
- Lock has expired
|
||||
- Snapshot taken before your lock
|
||||
|
||||
**Solutions:**
|
||||
- Lock tokens for future proposals
|
||||
- Extend existing lock
|
||||
- Request delegation from others
|
||||
|
||||
### "Voting Not Available"
|
||||
|
||||
**Causes:**
|
||||
- Proposal not in voting period
|
||||
- Already voted (check history)
|
||||
- Wallet not connected
|
||||
|
||||
**Solutions:**
|
||||
- Check proposal status
|
||||
- Connect correct wallet
|
||||
- Wait for voting period to start
|
||||
|
||||
### "Transaction Failed"
|
||||
|
||||
**Causes:**
|
||||
- Insufficient gas
|
||||
- Network congestion
|
||||
- Contract paused
|
||||
|
||||
**Solutions:**
|
||||
- Increase gas limit
|
||||
- Retry during low-traffic periods
|
||||
- Check DAO status announcements
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Delegation" href="/docs/guide/voting/delegation" icon="users">
|
||||
Delegate your voting power to others
|
||||
</Card>
|
||||
<Card title="Execution" href="/docs/guide/voting/execution" icon="play-circle">
|
||||
Execute passed proposals
|
||||
</Card>
|
||||
<Card title="Creating Proposals" href="/docs/guide/resolutions" icon="file-plus">
|
||||
Submit your own proposals
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,99 @@
|
||||
---
|
||||
title: Welcome
|
||||
description: Complete documentation for DAO governance
|
||||
---
|
||||
|
||||
# Welcome to DAO Governance
|
||||
|
||||
<Callout type="info">
|
||||
This documentation covers everything you need to participate in decentralized governance, from creating proposals to managing treasuries.
|
||||
</Callout>
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Cards>
|
||||
<Card title="Getting Started" href="/docs/guide/getting-started" icon="rocket">
|
||||
Learn the basics and connect your wallet
|
||||
</Card>
|
||||
<Card title="Create a Proposal" href="/docs/guide/resolutions" icon="file-plus">
|
||||
Submit your first governance proposal
|
||||
</Card>
|
||||
<Card title="Vote" href="/docs/guide/voting" icon="vote">
|
||||
Cast votes on active proposals
|
||||
</Card>
|
||||
<Card title="Treasury" href="/docs/guide/treasury" icon="vault">
|
||||
Manage community funds
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## Documentation Sections
|
||||
|
||||
### User Guide
|
||||
|
||||
Everything you need to participate in governance:
|
||||
|
||||
- [Getting Started](/docs/guide/getting-started) - The basics, governance types, setup
|
||||
- [Creating Proposals](/docs/guide/resolutions) - Submit and manage proposals
|
||||
- [Voting](/docs/guide/voting) - Cast votes and delegate
|
||||
- [Roles](/docs/guide/roles) - Create and manage roles
|
||||
- [Treasury](/docs/guide/treasury) - Fund management
|
||||
- [Hierarchy](/docs/guide/hierarchy) - Sub-DAOs and working groups
|
||||
- [Payments](/docs/guide/payments) - Airdrops, streams, transfers
|
||||
- [Staking](/docs/guide/staking) - Stake tokens for voting power
|
||||
- [Gasless Voting](/docs/guide/gasless) - Vote without gas fees
|
||||
- [Distributions](/docs/guide/distributions) - Revenue sharing
|
||||
- [Token Sales](/docs/guide/token-sales) - Conduct token sales
|
||||
|
||||
### Technical Documentation
|
||||
|
||||
Deep dives into the protocol:
|
||||
|
||||
- [Governance](/docs/governance) - Voting mechanics and parameters
|
||||
- [Bonding](/docs/bonding) - Bond mechanics and collateral
|
||||
- [Committees](/docs/committees) - Committee structure and operations
|
||||
|
||||
### Learn More
|
||||
|
||||
- [Try the App](/docs/learn-more/app)
|
||||
- [Contract Audit](/docs/learn-more/audit)
|
||||
- [FAQ](/docs/learn-more/faq)
|
||||
|
||||
## Key Concepts
|
||||
|
||||
| Term | Description |
|
||||
|------|-------------|
|
||||
| **Proposal** | A governance action submitted for voting |
|
||||
| **Vote** | Cast support or opposition to a proposal |
|
||||
| **Quorum** | Minimum participation required for a valid vote |
|
||||
| **Timelock** | Delay period before execution |
|
||||
| **Multisig** | Multi-signature wallet requiring multiple approvals |
|
||||
| **Sub-DAO** | Child organization with delegated authority |
|
||||
| **Treasury** | Community-controlled funds |
|
||||
|
||||
## Governance Flow
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ Draft │───▶│ Review │───▶│ Voting │───▶│ Timelock │
|
||||
│ Proposal │ │ Period │ │ Period │ │ Queue │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘ └──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ Execution │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
## Need Help?
|
||||
|
||||
<Cards>
|
||||
<Card title="Discord" href="https://discord.gg/dao" icon="discord">
|
||||
Join the community chat
|
||||
</Card>
|
||||
<Card title="Forum" href="https://forum.dao.vote" icon="messages">
|
||||
Discuss governance proposals
|
||||
</Card>
|
||||
<Card title="Support" href="mailto:support@dao.vote" icon="mail">
|
||||
Contact the team
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,230 @@
|
||||
---
|
||||
title: Try the App
|
||||
description: Get started with the governance application
|
||||
---
|
||||
|
||||
# Try the App
|
||||
|
||||
Launch the governance application and start participating in decentralized decision-making.
|
||||
|
||||
<Callout type="info">
|
||||
The application is available on mainnet. Make sure you have a compatible wallet and governance tokens to participate.
|
||||
</Callout>
|
||||
|
||||
## Launch Application
|
||||
|
||||
<Cards>
|
||||
<Card title="Open App" href="#" icon="external-link">
|
||||
Launch the governance dashboard
|
||||
</Card>
|
||||
<Card title="Testnet" href="#" icon="flask">
|
||||
Try on testnet first (no real tokens required)
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Step 1: Connect Wallet
|
||||
|
||||
The app supports multiple wallet providers:
|
||||
|
||||
| Wallet | Type | Recommended |
|
||||
|--------|------|-------------|
|
||||
| MetaMask | Browser Extension | Yes |
|
||||
| WalletConnect | Mobile/Desktop | Yes |
|
||||
| Coinbase Wallet | Browser/Mobile | Yes |
|
||||
| Ledger | Hardware | High Security |
|
||||
| Trezor | Hardware | High Security |
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Connect Wallet │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Select your wallet to connect: │
|
||||
│ │
|
||||
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ MetaMask │ │ WalletConnect │ │ Coinbase │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ └────────────────┘ └────────────────┘ └────────────────┘ │
|
||||
│ │
|
||||
│ ┌────────────────┐ ┌────────────────┐ │
|
||||
│ │ │ │ │ │
|
||||
│ │ Ledger │ │ Trezor │ │
|
||||
│ │ │ │ │ │
|
||||
│ └────────────────┘ └────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 2: Acquire Tokens
|
||||
|
||||
To participate in governance, you need governance tokens:
|
||||
|
||||
**Options to acquire tokens:**
|
||||
|
||||
1. **Purchase**: Buy tokens on supported exchanges or DEXs
|
||||
2. **Earn**: Participate in community programs
|
||||
3. **Receive**: Get tokens via grants or airdrops
|
||||
4. **Bond**: Bond assets for tokens (if bonding is enabled)
|
||||
|
||||
### Step 3: Lock for Voting Power
|
||||
|
||||
Lock your tokens to receive vote-escrowed tokens:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Lock Tokens │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Amount to Lock: [___________] TOKEN │
|
||||
│ Balance: 10,000 TOKEN [MAX] │
|
||||
│ │
|
||||
│ Lock Duration: │
|
||||
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
|
||||
│ │1 wk │ │1 mo │ │6 mo │ │1 yr │ │2 yr │ │4 yr │ │
|
||||
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
|
||||
│ │
|
||||
│ Preview: │
|
||||
│ - Lock Amount: 10,000 TOKEN │
|
||||
│ - Lock Duration: 1 year │
|
||||
│ - Voting Power: 10,000 veTOKEN │
|
||||
│ - Unlock Date: January 30, 2027 │
|
||||
│ │
|
||||
│ [Cancel] [Lock Tokens] │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Step 4: Start Participating
|
||||
|
||||
Once you have voting power, you can:
|
||||
|
||||
- **Vote**: Cast votes on active proposals
|
||||
- **Delegate**: Delegate voting power to others
|
||||
- **Propose**: Submit governance proposals (if threshold met)
|
||||
- **Join Committees**: Participate in working groups
|
||||
|
||||
## Application Features
|
||||
|
||||
### Dashboard
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Dashboard [Connect Wallet] │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Your Position │
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ ┌────────────────┐ │
|
||||
│ │ Tokens Locked │ │ Voting Power │ │ Delegated │ │
|
||||
│ │ 10,000 TOKEN │ │ 10,000 veTOKEN │ │ 2,500 veTOKEN │ │
|
||||
│ │ Unlocks: 365 days│ │ Rank: #1,234 │ │ From: 3 users │ │
|
||||
│ └──────────────────┘ └──────────────────┘ └────────────────┘ │
|
||||
│ │
|
||||
│ Active Proposals │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ #42 Treasury Allocation Q1 [VOTING] Ends: 3 days │ │
|
||||
│ │ #41 Parameter Update [QUEUED] Exec: 1 day │ │
|
||||
│ │ #40 New Committee Formation [PASSED] Complete │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Recent Activity │
|
||||
│ - Voted FOR on #42 Treasury Allocation │
|
||||
│ - Received delegation from 0x1234... │
|
||||
│ - Extended lock by 180 days │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Governance
|
||||
|
||||
- View all proposals (active, passed, defeated)
|
||||
- Filter by type, status, or category
|
||||
- Cast votes with optional reasoning
|
||||
- Track voting history and statistics
|
||||
|
||||
### Treasury
|
||||
|
||||
- View treasury balances across assets
|
||||
- Monitor spending and allocations
|
||||
- Track payment streams
|
||||
- Review historical transactions
|
||||
|
||||
### Staking
|
||||
|
||||
- Lock tokens for voting power
|
||||
- Extend or increase locks
|
||||
- View lock schedule and unlock dates
|
||||
- Manage multiple lock positions
|
||||
|
||||
## Network Support
|
||||
|
||||
The application supports multiple networks:
|
||||
|
||||
| Network | Status | Features |
|
||||
|---------|--------|----------|
|
||||
| Mainnet | Live | Full governance |
|
||||
| Testnet | Live | Testing and development |
|
||||
|
||||
<Callout type="warning">
|
||||
Always verify you are on the correct network before signing transactions. Check the network indicator in your wallet.
|
||||
</Callout>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Wallet Connection Issues
|
||||
|
||||
**Problem**: Wallet not connecting
|
||||
|
||||
**Solutions**:
|
||||
1. Refresh the page
|
||||
2. Clear browser cache
|
||||
3. Ensure wallet extension is updated
|
||||
4. Try a different browser
|
||||
5. Disable conflicting extensions
|
||||
|
||||
### Transaction Failures
|
||||
|
||||
**Problem**: Transactions failing or pending
|
||||
|
||||
**Solutions**:
|
||||
1. Check you have enough native tokens for gas
|
||||
2. Increase gas limit if needed
|
||||
3. Wait for network congestion to clear
|
||||
4. Cancel and retry with higher gas
|
||||
|
||||
### Display Issues
|
||||
|
||||
**Problem**: Data not loading or displaying incorrectly
|
||||
|
||||
**Solutions**:
|
||||
1. Clear browser cache
|
||||
2. Hard refresh (Ctrl/Cmd + Shift + R)
|
||||
3. Check network connectivity
|
||||
4. Try a different RPC endpoint
|
||||
|
||||
## Mobile Support
|
||||
|
||||
The application is fully responsive and works on mobile devices:
|
||||
|
||||
- **Mobile Browsers**: Chrome, Safari, Firefox
|
||||
- **Mobile Wallets**: MetaMask Mobile, Coinbase Wallet, Rainbow
|
||||
|
||||
<Callout type="info">
|
||||
For the best mobile experience, use a wallet with built-in browser support.
|
||||
</Callout>
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="User Guide" href="/docs/guide" icon="book">
|
||||
Complete documentation for all features
|
||||
</Card>
|
||||
<Card title="Create Proposal" href="/docs/guide/resolutions" icon="file-plus">
|
||||
Learn how to submit proposals
|
||||
</Card>
|
||||
<Card title="Voting Guide" href="/docs/guide/voting" icon="check-square">
|
||||
Understand voting mechanics
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,284 @@
|
||||
---
|
||||
title: Contract Audit
|
||||
description: Security audits and smart contract verification
|
||||
---
|
||||
|
||||
# Contract Audit
|
||||
|
||||
Security is paramount for any governance protocol. This page provides information about our security audits, verified contracts, and ongoing security measures.
|
||||
|
||||
## Audit Status
|
||||
|
||||
<Callout type="info">
|
||||
All core smart contracts have been audited by independent security firms before mainnet deployment.
|
||||
</Callout>
|
||||
|
||||
### Audit Summary
|
||||
|
||||
| Audit | Firm | Date | Status | Report |
|
||||
|-------|------|------|--------|--------|
|
||||
| Core Contracts v1.0 | Security Firm | Q1 2026 | Completed | [View Report](#) |
|
||||
| Governance Module | Security Firm | Q1 2026 | Completed | [View Report](#) |
|
||||
| Staking Contracts | Security Firm | Q1 2026 | Completed | [View Report](#) |
|
||||
| Treasury Module | Security Firm | Q2 2026 | In Progress | Pending |
|
||||
|
||||
### Audit Scope
|
||||
|
||||
The following contracts were included in the security audit:
|
||||
|
||||
```
|
||||
Audited Contracts
|
||||
├── Governance
|
||||
│ ├── Governor.sol
|
||||
│ ├── Timelock.sol
|
||||
│ ├── ProposalRegistry.sol
|
||||
│ └── VotingModule.sol
|
||||
├── Token
|
||||
│ ├── GovernanceToken.sol
|
||||
│ ├── VoteEscrow.sol
|
||||
│ └── StakingRewards.sol
|
||||
├── Treasury
|
||||
│ ├── Treasury.sol
|
||||
│ ├── PaymentRouter.sol
|
||||
│ └── StreamingPayments.sol
|
||||
└── Access
|
||||
├── AccessControl.sol
|
||||
├── RoleManager.sol
|
||||
└── Multisig.sol
|
||||
```
|
||||
|
||||
## Findings Summary
|
||||
|
||||
### Critical Findings
|
||||
|
||||
| Finding | Severity | Status |
|
||||
|---------|----------|--------|
|
||||
| None identified | Critical | N/A |
|
||||
|
||||
### High Findings
|
||||
|
||||
| Finding | Severity | Status |
|
||||
|---------|----------|--------|
|
||||
| None identified | High | N/A |
|
||||
|
||||
### Medium Findings
|
||||
|
||||
| Finding | Description | Status |
|
||||
|---------|-------------|--------|
|
||||
| M-01 | Potential reentrancy in payment flow | Resolved |
|
||||
| M-02 | Integer overflow in vote calculation | Resolved |
|
||||
|
||||
### Low Findings
|
||||
|
||||
| Finding | Description | Status |
|
||||
|---------|-------------|--------|
|
||||
| L-01 | Missing event emissions | Resolved |
|
||||
| L-02 | Inconsistent error messages | Resolved |
|
||||
| L-03 | Gas optimization suggestions | Implemented |
|
||||
|
||||
### Informational
|
||||
|
||||
| Finding | Description | Status |
|
||||
|---------|-------------|--------|
|
||||
| I-01 | Documentation improvements | Addressed |
|
||||
| I-02 | Test coverage recommendations | Implemented |
|
||||
|
||||
## Verified Contracts
|
||||
|
||||
All deployed contracts are verified on block explorers. You can review the source code directly:
|
||||
|
||||
### Mainnet Contracts
|
||||
|
||||
| Contract | Address | Verified |
|
||||
|----------|---------|----------|
|
||||
| Governor | `0x...` | [View](#) |
|
||||
| Timelock | `0x...` | [View](#) |
|
||||
| Token | `0x...` | [View](#) |
|
||||
| VoteEscrow | `0x...` | [View](#) |
|
||||
| Treasury | `0x...` | [View](#) |
|
||||
| Staking | `0x...` | [View](#) |
|
||||
|
||||
### Testnet Contracts
|
||||
|
||||
| Contract | Address | Verified |
|
||||
|----------|---------|----------|
|
||||
| Governor | `0x...` | [View](#) |
|
||||
| Timelock | `0x...` | [View](#) |
|
||||
| Token | `0x...` | [View](#) |
|
||||
| VoteEscrow | `0x...` | [View](#) |
|
||||
| Treasury | `0x...` | [View](#) |
|
||||
| Staking | `0x...` | [View](#) |
|
||||
|
||||
## Security Measures
|
||||
|
||||
### Smart Contract Security
|
||||
|
||||
1. **Access Controls**
|
||||
- Role-based permission system
|
||||
- Multi-signature requirements for critical operations
|
||||
- Timelock delays on governance actions
|
||||
|
||||
2. **Reentrancy Protection**
|
||||
- ReentrancyGuard on all external calls
|
||||
- Check-effects-interactions pattern
|
||||
- Pull-over-push payment patterns
|
||||
|
||||
3. **Integer Safety**
|
||||
- SafeMath operations (Solidity 0.8+)
|
||||
- Overflow/underflow checks
|
||||
- Decimal precision handling
|
||||
|
||||
4. **Upgrade Safety**
|
||||
- Transparent proxy pattern
|
||||
- Storage layout compatibility checks
|
||||
- Upgrade timelocks
|
||||
|
||||
### Operational Security
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Security Architecture │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ User Action │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Frontend │───▶│ RPC │───▶│ Contract │───▶│ Timelock │ │
|
||||
│ │ Auth │ │ Guard │ │ Access │ │ Delay │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
│ │
|
||||
│ Multi-layer Protection: │
|
||||
│ 1. Frontend validation and rate limiting │
|
||||
│ 2. RPC endpoint security and monitoring │
|
||||
│ 3. Smart contract access controls │
|
||||
│ 4. Timelock delays for execution │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Monitoring
|
||||
|
||||
- **Real-time Alerts**: Automated monitoring for unusual activity
|
||||
- **Transaction Monitoring**: All governance transactions tracked
|
||||
- **Health Checks**: Regular contract state verification
|
||||
- **Incident Response**: Documented procedures for security incidents
|
||||
|
||||
## Bug Bounty Program
|
||||
|
||||
We maintain an active bug bounty program to encourage responsible disclosure of security vulnerabilities.
|
||||
|
||||
### Scope
|
||||
|
||||
| Category | In Scope |
|
||||
|----------|----------|
|
||||
| Smart Contracts | All deployed contracts |
|
||||
| Infrastructure | RPC endpoints, APIs |
|
||||
| Frontend | Web application |
|
||||
|
||||
### Rewards
|
||||
|
||||
| Severity | Reward Range |
|
||||
|----------|--------------|
|
||||
| Critical | $10,000 - $50,000 |
|
||||
| High | $5,000 - $10,000 |
|
||||
| Medium | $1,000 - $5,000 |
|
||||
| Low | $100 - $1,000 |
|
||||
|
||||
### Submission Process
|
||||
|
||||
1. **Discovery**: Find a potential vulnerability
|
||||
2. **Document**: Create detailed report with reproduction steps
|
||||
3. **Submit**: Send to security team via secure channel
|
||||
4. **Review**: Team reviews and validates finding
|
||||
5. **Reward**: Bounty paid upon confirmation
|
||||
|
||||
<Callout type="warning">
|
||||
**Responsible Disclosure**: Please do not publicly disclose vulnerabilities before they are patched. Contact the security team directly.
|
||||
</Callout>
|
||||
|
||||
### Contact
|
||||
|
||||
For security issues, contact:
|
||||
- **Email**: security@dao.vote
|
||||
- **PGP Key**: Available on request
|
||||
|
||||
## Audit Reports
|
||||
|
||||
### Full Audit Report
|
||||
|
||||
Download the complete audit report:
|
||||
|
||||
<Cards>
|
||||
<Card title="Core Audit Report" href="#" icon="file-text">
|
||||
Full audit report (PDF)
|
||||
</Card>
|
||||
<Card title="Governance Audit" href="#" icon="file-text">
|
||||
Governance module audit (PDF)
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
### Report Contents
|
||||
|
||||
The audit reports include:
|
||||
|
||||
1. **Executive Summary**: High-level findings and recommendations
|
||||
2. **Methodology**: Audit approach and tools used
|
||||
3. **Findings**: Detailed vulnerability descriptions
|
||||
4. **Recommendations**: Suggested fixes and improvements
|
||||
5. **Resolution**: Team responses and fixes applied
|
||||
|
||||
## Third-Party Integrations
|
||||
|
||||
Security considerations for integrated services:
|
||||
|
||||
| Integration | Purpose | Security Review |
|
||||
|-------------|---------|-----------------|
|
||||
| RPC Providers | Blockchain access | Provider SLA reviewed |
|
||||
| Oracles | Price feeds | Contract audited |
|
||||
| Bridges | Cross-chain | Bridge audit reviewed |
|
||||
| Frontend Hosting | Web application | Security hardened |
|
||||
|
||||
## Ongoing Security
|
||||
|
||||
Security is an ongoing process, not a one-time audit:
|
||||
|
||||
- **Continuous Monitoring**: 24/7 transaction monitoring
|
||||
- **Regular Reviews**: Quarterly security assessments
|
||||
- **Upgrade Process**: All upgrades go through security review
|
||||
- **Community Reporting**: Incentivized vulnerability disclosure
|
||||
|
||||
## FAQ
|
||||
|
||||
### Are the contracts upgradeable?
|
||||
|
||||
Yes, contracts use the transparent proxy pattern. Upgrades require governance approval and timelock delay.
|
||||
|
||||
### How are admin keys secured?
|
||||
|
||||
Admin functions are controlled by multi-signature wallets requiring multiple approvals. No single party can make changes.
|
||||
|
||||
### What happens if a vulnerability is found?
|
||||
|
||||
1. Pause affected functionality (if possible)
|
||||
2. Deploy fix through governance
|
||||
3. Post-mortem analysis
|
||||
4. Bug bounty payment (if applicable)
|
||||
|
||||
### How often are audits conducted?
|
||||
|
||||
Major updates undergo full audit. Minor changes are reviewed internally with periodic external assessments.
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Try the App" href="/docs/learn-more/app" icon="external-link">
|
||||
Start using the governance platform
|
||||
</Card>
|
||||
<Card title="FAQ" href="/docs/learn-more/faq" icon="help-circle">
|
||||
Common questions and answers
|
||||
</Card>
|
||||
<Card title="User Guide" href="/docs/guide" icon="book">
|
||||
Complete documentation
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,292 @@
|
||||
---
|
||||
title: FAQ
|
||||
description: Frequently asked questions about governance and the protocol
|
||||
---
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
Find answers to common questions about governance, tokens, voting, and the platform.
|
||||
|
||||
## General
|
||||
|
||||
### What is this protocol?
|
||||
|
||||
A decentralized governance platform that enables token holders to collectively manage protocol parameters, treasury funds, and community initiatives through on-chain voting.
|
||||
|
||||
### How does governance work?
|
||||
|
||||
Token holders lock their tokens to receive voting power. They can then vote on proposals, delegate their power to others, or submit their own proposals. Approved proposals are executed after a timelock delay.
|
||||
|
||||
### Is this protocol decentralized?
|
||||
|
||||
Yes. All governance decisions are made by token holders through on-chain voting. No single party has control over the protocol.
|
||||
|
||||
### What blockchain does this run on?
|
||||
|
||||
The protocol is deployed on [Network]. See the [Contract Audit](/docs/learn-more/audit) page for deployed contract addresses.
|
||||
|
||||
## Tokens
|
||||
|
||||
### What is the governance token?
|
||||
|
||||
The governance token (TOKEN) is the native token used for voting and governance participation. Holders can lock tokens to receive voting power.
|
||||
|
||||
### How do I get tokens?
|
||||
|
||||
You can acquire tokens through:
|
||||
- **Exchanges**: Purchase on supported DEXs or CEXs
|
||||
- **Bonding**: Bond assets for tokens (if enabled)
|
||||
- **Earning**: Participate in community programs
|
||||
- **Grants**: Apply for community grants
|
||||
|
||||
### What is the vote-escrowed token (veTOKEN)?
|
||||
|
||||
When you lock TOKEN, you receive veTOKEN representing your voting power. The longer you lock, the more voting power you receive. veTOKEN is non-transferable and decays over time as your lock approaches expiration.
|
||||
|
||||
### What is the staked token (sTOKEN)?
|
||||
|
||||
sTOKEN represents tokens staked in the protocol to earn rewards. Unlike veTOKEN, staked tokens can be unstaked (subject to cooldown periods).
|
||||
|
||||
### Can I transfer my locked tokens?
|
||||
|
||||
No. Locked tokens cannot be transferred until the lock expires. This ensures committed governance participation.
|
||||
|
||||
## Voting
|
||||
|
||||
### How do I vote?
|
||||
|
||||
1. Lock tokens to receive voting power
|
||||
2. Find an active proposal in the app
|
||||
3. Review the proposal details
|
||||
4. Cast your vote (For, Against, or Abstain)
|
||||
5. Sign the transaction
|
||||
|
||||
See the [Voting Guide](/docs/guide/voting) for detailed instructions.
|
||||
|
||||
### How much voting power do I have?
|
||||
|
||||
Your voting power depends on:
|
||||
- **Amount locked**: More tokens = more power
|
||||
- **Lock duration**: Longer locks = higher multiplier
|
||||
- **Time remaining**: Power decays as lock approaches expiration
|
||||
|
||||
Formula: `Voting Power = Locked Amount x Time Multiplier`
|
||||
|
||||
### Can I change my vote?
|
||||
|
||||
Yes, you can change your vote any time before the voting period ends. After the period closes, votes are final.
|
||||
|
||||
### What if I miss a vote?
|
||||
|
||||
Missing a vote means your voice isn't counted on that proposal. Consider:
|
||||
- **Delegation**: Delegate to someone who votes actively
|
||||
- **Notifications**: Enable alerts for new proposals
|
||||
- **Calendar**: Track voting deadlines
|
||||
|
||||
### What is quorum?
|
||||
|
||||
Quorum is the minimum participation required for a valid vote. If quorum isn't reached, the proposal fails regardless of the vote split.
|
||||
|
||||
### What happens after a vote passes?
|
||||
|
||||
Passed proposals enter a timelock queue. After the timelock period (typically 1-14 days), the proposal can be executed by anyone.
|
||||
|
||||
## Delegation
|
||||
|
||||
### What is delegation?
|
||||
|
||||
Delegation allows you to assign your voting power to another address. The delegate votes on your behalf, but you retain your locked tokens.
|
||||
|
||||
### Can I delegate to multiple people?
|
||||
|
||||
It depends on the configuration. Some DAOs support split delegation where you can assign different percentages to multiple delegates.
|
||||
|
||||
### Can I override my delegate's vote?
|
||||
|
||||
Yes. If you vote on a proposal, your vote overrides any delegation for that specific proposal.
|
||||
|
||||
### How do I become a delegate?
|
||||
|
||||
Anyone can become a delegate. To attract delegations:
|
||||
1. Build reputation through active participation
|
||||
2. Share your voting philosophy
|
||||
3. Communicate your positions on proposals
|
||||
4. Maintain a consistent voting record
|
||||
|
||||
### Is delegation revocable?
|
||||
|
||||
Yes. You can revoke or change your delegation at any time.
|
||||
|
||||
## Proposals
|
||||
|
||||
### Who can create proposals?
|
||||
|
||||
Anyone with sufficient voting power can create proposals. The threshold varies by DAO but typically requires a minimum amount of veTOKEN.
|
||||
|
||||
### What can proposals do?
|
||||
|
||||
Proposals can:
|
||||
- Transfer treasury funds
|
||||
- Change protocol parameters
|
||||
- Add or remove roles
|
||||
- Create sub-DAOs or committees
|
||||
- Upgrade contracts
|
||||
- Execute arbitrary calls
|
||||
|
||||
### How long does the proposal process take?
|
||||
|
||||
Typical timeline:
|
||||
|
||||
| Stage | Duration |
|
||||
|-------|----------|
|
||||
| Discussion | 3-7 days |
|
||||
| Voting | 7 days |
|
||||
| Timelock | 1-14 days |
|
||||
| **Total** | **11-28 days** |
|
||||
|
||||
### What happens if my proposal fails?
|
||||
|
||||
Failed proposals can be:
|
||||
- Modified based on feedback and resubmitted
|
||||
- Split into smaller, more focused proposals
|
||||
- Discussed further in the forum
|
||||
|
||||
### Is there a cost to create proposals?
|
||||
|
||||
Creating a proposal requires locking a proposal deposit (if configured). This deposit is returned if the proposal passes or reaches quorum.
|
||||
|
||||
## Treasury
|
||||
|
||||
### How is the treasury managed?
|
||||
|
||||
The treasury is managed through governance proposals. Token holders vote on how funds are allocated.
|
||||
|
||||
### What assets are in the treasury?
|
||||
|
||||
The treasury can hold any ERC-20 tokens. Common assets include:
|
||||
- Governance tokens
|
||||
- Stablecoins (USDC, DAI)
|
||||
- Protocol revenue
|
||||
- Partner tokens
|
||||
|
||||
### How are treasury funds protected?
|
||||
|
||||
- **Multi-sig**: Critical operations require multiple signatures
|
||||
- **Timelock**: All transfers have delay periods
|
||||
- **Limits**: Spending limits for different roles
|
||||
- **Transparency**: All transactions are on-chain
|
||||
|
||||
### Can the treasury be drained?
|
||||
|
||||
The multi-layer security (governance vote + timelock + multi-sig) makes unauthorized treasury access extremely difficult.
|
||||
|
||||
## Technical
|
||||
|
||||
### Are the contracts audited?
|
||||
|
||||
Yes. All core contracts have been audited by independent security firms. See [Contract Audit](/docs/learn-more/audit) for details.
|
||||
|
||||
### Are the contracts upgradeable?
|
||||
|
||||
Yes, contracts use a transparent proxy pattern. Upgrades require:
|
||||
1. Governance proposal approval
|
||||
2. Timelock delay
|
||||
3. Multi-sig execution (for critical contracts)
|
||||
|
||||
### What wallets are supported?
|
||||
|
||||
- MetaMask
|
||||
- WalletConnect
|
||||
- Coinbase Wallet
|
||||
- Ledger
|
||||
- Trezor
|
||||
|
||||
### Is there a mobile app?
|
||||
|
||||
The web application is fully responsive and works on mobile browsers. Mobile wallets with built-in browsers (MetaMask Mobile, Coinbase Wallet) provide the best experience.
|
||||
|
||||
### What are the gas costs?
|
||||
|
||||
Gas costs depend on network conditions. Typical costs:
|
||||
|
||||
| Action | Gas Used | Approximate Cost |
|
||||
|--------|----------|------------------|
|
||||
| Lock tokens | ~150,000 | Varies |
|
||||
| Vote | ~100,000 | Varies |
|
||||
| Delegate | ~80,000 | Varies |
|
||||
| Create proposal | ~300,000 | Varies |
|
||||
|
||||
### Is gasless voting available?
|
||||
|
||||
Yes, gasless voting is supported through meta-transactions. See [Gasless Voting](/docs/guide/gasless) for setup instructions.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### My transaction is stuck
|
||||
|
||||
1. Check network congestion
|
||||
2. Speed up with higher gas
|
||||
3. Cancel and retry
|
||||
4. Wait for network to clear
|
||||
|
||||
### I can't see my voting power
|
||||
|
||||
1. Ensure tokens are locked (not just held)
|
||||
2. Check if lock has expired
|
||||
3. Verify you're on the correct network
|
||||
4. Refresh the page
|
||||
|
||||
### My vote didn't count
|
||||
|
||||
1. Confirm transaction completed successfully
|
||||
2. Check you voted during the voting period
|
||||
3. Verify voting power at snapshot block
|
||||
4. Contact support if issue persists
|
||||
|
||||
### I can't connect my wallet
|
||||
|
||||
1. Ensure wallet is unlocked
|
||||
2. Clear browser cache
|
||||
3. Disable conflicting extensions
|
||||
4. Try a different browser
|
||||
5. Update wallet to latest version
|
||||
|
||||
## Community
|
||||
|
||||
### How can I get involved?
|
||||
|
||||
- **Discord**: Join discussions
|
||||
- **Forum**: Participate in governance
|
||||
- **GitHub**: Contribute to development
|
||||
- **Twitter**: Follow for updates
|
||||
- **Committees**: Join working groups
|
||||
|
||||
### Where can I get help?
|
||||
|
||||
- **Discord**: Community support channel
|
||||
- **Forum**: Governance discussions
|
||||
- **Documentation**: This site
|
||||
- **Email**: Support team
|
||||
|
||||
### How can I contribute?
|
||||
|
||||
- Vote on proposals
|
||||
- Delegate responsibly
|
||||
- Submit improvement proposals
|
||||
- Contribute to documentation
|
||||
- Build integrations
|
||||
- Report bugs
|
||||
|
||||
## Still Have Questions?
|
||||
|
||||
<Cards>
|
||||
<Card title="Discord" href="#" icon="message-circle">
|
||||
Ask the community
|
||||
</Card>
|
||||
<Card title="Forum" href="#" icon="messages">
|
||||
Detailed discussions
|
||||
</Card>
|
||||
<Card title="Support" href="#" icon="mail">
|
||||
Contact the team
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,121 @@
|
||||
---
|
||||
title: Learn More
|
||||
description: Additional resources, audits, and frequently asked questions
|
||||
---
|
||||
|
||||
# Learn More
|
||||
|
||||
Explore additional resources to deepen your understanding of the protocol and governance system.
|
||||
|
||||
## Resources
|
||||
|
||||
<Cards>
|
||||
<Card title="Try the App" href="/docs/learn-more/app" icon="external-link">
|
||||
Launch the governance application and start participating
|
||||
</Card>
|
||||
<Card title="Contract Audit" href="/docs/learn-more/audit" icon="shield-check">
|
||||
Review security audits and smart contract verification
|
||||
</Card>
|
||||
<Card title="FAQ" href="/docs/learn-more/faq" icon="help-circle">
|
||||
Answers to frequently asked questions
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
## Quick Links
|
||||
|
||||
### Documentation
|
||||
|
||||
| Resource | Description |
|
||||
|----------|-------------|
|
||||
| [User Guide](/docs/guide) | Complete guide to using the platform |
|
||||
| [Governance](/docs/governance) | Technical governance documentation |
|
||||
| [Proposals](/docs/guide/resolutions) | How to create and manage proposals |
|
||||
|
||||
### External Resources
|
||||
|
||||
| Resource | Link |
|
||||
|----------|------|
|
||||
| GitHub | View source code and contribute |
|
||||
| Discord | Join the community |
|
||||
| Forum | Discuss governance proposals |
|
||||
| Twitter | Follow for updates |
|
||||
|
||||
## Protocol Overview
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Governance Layer │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Proposals │ │ Voting │ │ Timelock │ │
|
||||
│ │ Registry │ │ Contract │ │ Executor │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Token Layer │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Governance │ │ Staking │ │ Vote Escrow │ │
|
||||
│ │ Token │ │ Contract │ │ (veToken) │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Treasury Layer │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Treasury │ │ Payments │ │ Streaming │ │
|
||||
│ │ Vault │ │ Router │ │ Module │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Key Features
|
||||
|
||||
- **Decentralized Governance**: Token holders control protocol parameters
|
||||
- **Vote Escrow Model**: Lock tokens for voting power that decays over time
|
||||
- **Flexible Proposals**: Support for treasury transfers, parameter changes, and upgrades
|
||||
- **Hierarchical DAOs**: Create sub-DAOs and working groups with delegated authority
|
||||
- **Gasless Voting**: Vote without paying gas fees via meta-transactions
|
||||
- **Streaming Payments**: Continuous payment streams for contributors
|
||||
|
||||
## Security
|
||||
|
||||
The protocol prioritizes security through:
|
||||
|
||||
1. **Audited Contracts**: All smart contracts undergo professional security audits
|
||||
2. **Timelocks**: Governance actions have mandatory delay periods
|
||||
3. **Multi-sig Controls**: Critical operations require multiple signatures
|
||||
4. **Bug Bounty**: Active program rewarding vulnerability disclosure
|
||||
|
||||
<Callout type="info">
|
||||
For detailed security information, see the [Contract Audit](/docs/learn-more/audit) page.
|
||||
</Callout>
|
||||
|
||||
## Community
|
||||
|
||||
Join the community to participate in governance discussions:
|
||||
|
||||
- **Discord**: Real-time chat and support
|
||||
- **Forum**: Long-form governance discussions
|
||||
- **Twitter**: Announcements and updates
|
||||
- **GitHub**: Technical contributions and issues
|
||||
|
||||
## Need Help?
|
||||
|
||||
<Cards>
|
||||
<Card title="FAQ" href="/docs/learn-more/faq" icon="help-circle">
|
||||
Check common questions and answers
|
||||
</Card>
|
||||
<Card title="Discord" href="#" icon="message-circle">
|
||||
Get help from the community
|
||||
</Card>
|
||||
<Card title="Support" href="#" icon="mail">
|
||||
Contact the team directly
|
||||
</Card>
|
||||
</Cards>
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"title": "Documentation",
|
||||
"description": "Complete documentation for DAO governance",
|
||||
"root": true,
|
||||
"pages": [
|
||||
"index",
|
||||
"---Getting Started---",
|
||||
"guide/index",
|
||||
"guide/getting-started",
|
||||
"guide/getting-started/governance-types",
|
||||
"guide/getting-started/creating-committee",
|
||||
"---Proposals & Voting---",
|
||||
"guide/resolutions/index",
|
||||
"guide/resolutions/from-scratch",
|
||||
"guide/resolutions/templates",
|
||||
"guide/resolutions/action-based",
|
||||
"guide/voting/index",
|
||||
"guide/voting/delegation",
|
||||
"guide/voting/execution",
|
||||
"---Organization---",
|
||||
"guide/roles",
|
||||
"guide/treasury",
|
||||
"guide/hierarchy/index",
|
||||
"guide/hierarchy/node-creation",
|
||||
"guide/hierarchy/freezing",
|
||||
"guide/hierarchy/clawback",
|
||||
"---Payments & Finance---",
|
||||
"guide/payments/index",
|
||||
"guide/payments/transfer",
|
||||
"guide/payments/stream",
|
||||
"guide/payments/stream-to-role",
|
||||
"guide/payments/airdrop",
|
||||
"guide/staking/index",
|
||||
"guide/staking/setup",
|
||||
"guide/staking/using-staking",
|
||||
"guide/staking/distributions",
|
||||
"guide/distributions",
|
||||
"guide/token-sales",
|
||||
"---Advanced---",
|
||||
"guide/multisig",
|
||||
"guide/token-setup",
|
||||
"guide/settings/index",
|
||||
"guide/settings/general",
|
||||
"guide/settings/governance",
|
||||
"guide/gasless/index",
|
||||
"guide/gasless/setup",
|
||||
"guide/gasless/using",
|
||||
"guide/gasless/paymaster",
|
||||
"guide/gasless/disabling",
|
||||
"---Technical---",
|
||||
"governance",
|
||||
"bonding",
|
||||
"committees",
|
||||
"---Learn More---",
|
||||
"learn-more/index",
|
||||
"learn-more/app",
|
||||
"learn-more/audit",
|
||||
"learn-more/faq"
|
||||
],
|
||||
"defaultOpen": true
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* DAO Documentation Configuration
|
||||
*
|
||||
* This configuration file contains template variables that can be overridden
|
||||
* when forking this documentation for different projects (Pars, Zoo, MIGA, etc.)
|
||||
*
|
||||
* Usage:
|
||||
* 1. Fork this docs/ directory to your project
|
||||
* 2. Update the values below to match your project
|
||||
* 3. Run the build process to generate branded documentation
|
||||
*/
|
||||
|
||||
export interface DocsConfig {
|
||||
// Project identity
|
||||
name: string
|
||||
description: string
|
||||
url: string
|
||||
logo: string
|
||||
|
||||
// External links
|
||||
github: string
|
||||
discord: string
|
||||
twitter: string
|
||||
forum?: string
|
||||
support?: string
|
||||
|
||||
// Token configuration
|
||||
tokens: {
|
||||
governance: string // Main governance token symbol
|
||||
staked: string // Staked token symbol (sDAO, sTOKEN)
|
||||
veToken: string // Vote-escrowed token (veDAO, veTOKEN)
|
||||
native?: string // Native network token (ETH, LUX, SOL)
|
||||
}
|
||||
|
||||
// Network configuration
|
||||
network: {
|
||||
name: string
|
||||
chainId: number
|
||||
rpc: string
|
||||
explorer: string
|
||||
isTestnet?: boolean
|
||||
}
|
||||
|
||||
// Governance parameters (defaults, can be customized per DAO)
|
||||
governance: {
|
||||
votingPeriod: string // e.g., "7 days"
|
||||
timelockDelay: string // e.g., "3 days"
|
||||
proposalThreshold: string // e.g., "100,000 tokens"
|
||||
quorumThreshold: string // e.g., "1,000,000 tokens"
|
||||
}
|
||||
|
||||
// Feature flags
|
||||
features: {
|
||||
multisig: boolean
|
||||
gaslessVoting: boolean
|
||||
delegation: boolean
|
||||
staking: boolean
|
||||
streaming: boolean
|
||||
hierarchy: boolean
|
||||
}
|
||||
|
||||
// Audit information
|
||||
audit: {
|
||||
firm: string
|
||||
date: string
|
||||
reportUrl: string
|
||||
status: "completed" | "in-progress" | "scheduled"
|
||||
}
|
||||
|
||||
// App URLs
|
||||
app: {
|
||||
main: string
|
||||
governance: string
|
||||
staking?: string
|
||||
bridge?: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default configuration - override these values for your project
|
||||
*/
|
||||
export const docsConfig: DocsConfig = {
|
||||
// Project identity
|
||||
name: "DAO Docs",
|
||||
description: "Complete documentation for decentralized governance",
|
||||
url: "https://docs.dao.vote",
|
||||
logo: "/logo.svg",
|
||||
|
||||
// External links
|
||||
github: "https://github.com/org/dao",
|
||||
discord: "https://discord.gg/dao",
|
||||
twitter: "@dao",
|
||||
forum: "https://forum.dao.vote",
|
||||
support: "support@dao.vote",
|
||||
|
||||
// Token configuration
|
||||
tokens: {
|
||||
governance: "TOKEN",
|
||||
staked: "sTOKEN",
|
||||
veToken: "veTOKEN",
|
||||
native: "ETH",
|
||||
},
|
||||
|
||||
// Network configuration
|
||||
network: {
|
||||
name: "Network",
|
||||
chainId: 1,
|
||||
rpc: "https://rpc.network.com",
|
||||
explorer: "https://explorer.network.com",
|
||||
isTestnet: false,
|
||||
},
|
||||
|
||||
// Governance parameters
|
||||
governance: {
|
||||
votingPeriod: "7 days",
|
||||
timelockDelay: "3 days",
|
||||
proposalThreshold: "100,000 tokens",
|
||||
quorumThreshold: "1,000,000 tokens",
|
||||
},
|
||||
|
||||
// Feature flags
|
||||
features: {
|
||||
multisig: true,
|
||||
gaslessVoting: true,
|
||||
delegation: true,
|
||||
staking: true,
|
||||
streaming: true,
|
||||
hierarchy: true,
|
||||
},
|
||||
|
||||
// Audit information
|
||||
audit: {
|
||||
firm: "Auditor Name",
|
||||
date: "2026-01-01",
|
||||
reportUrl: "/audit-report.pdf",
|
||||
status: "completed",
|
||||
},
|
||||
|
||||
// App URLs
|
||||
app: {
|
||||
main: "https://app.dao.vote",
|
||||
governance: "https://app.dao.vote/governance",
|
||||
staking: "https://app.dao.vote/staking",
|
||||
bridge: "https://bridge.dao.vote",
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Example project configurations for reference
|
||||
*/
|
||||
export const projectExamples = {
|
||||
pars: {
|
||||
name: "Pars DAO",
|
||||
tokens: { governance: "PARS", staked: "sPARS", veToken: "vePARS" },
|
||||
network: { name: "Pars Network", chainId: 6133 },
|
||||
},
|
||||
miga: {
|
||||
name: "MIGA DAO",
|
||||
tokens: { governance: "MIGA", staked: "sMIGA", veToken: "veMIGA" },
|
||||
network: { name: "Solana", chainId: 101 },
|
||||
},
|
||||
zoo: {
|
||||
name: "Zoo DAO",
|
||||
tokens: { governance: "ZOO", staked: "sZOO", veToken: "veZOO" },
|
||||
network: { name: "Lux Network", chainId: 96369 },
|
||||
},
|
||||
}
|
||||
|
||||
export default docsConfig
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "@luxdao/brand-config",
|
||||
"version": "1.0.0",
|
||||
"description": "White-label brand configuration for Lux DAO governance stack",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/luxfi/dao.git",
|
||||
"directory": "packages/brand-config"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import type { BrandConfig } from "../index";
|
||||
|
||||
export const hanzoBrand: BrandConfig = {
|
||||
id: "hanzo",
|
||||
name: "Hanzo",
|
||||
description: "AI infrastructure and frontier model governance",
|
||||
website: "https://hanzo.ai",
|
||||
docsUrl: "https://docs.hanzo.ai",
|
||||
communityUrl: "https://discord.gg/hanzo",
|
||||
githubOrg: "hanzoai",
|
||||
|
||||
tokens: {
|
||||
native: "HANZO",
|
||||
governance: "HANZO",
|
||||
staked: "sHANZO",
|
||||
gWrapped: "gHANZO",
|
||||
wsWrapped: "wsHANZO",
|
||||
veToken: "veHANZO",
|
||||
decimals: 18,
|
||||
},
|
||||
|
||||
chains: {
|
||||
mainnet: {
|
||||
name: "Hanzo Network",
|
||||
chainId: 36963,
|
||||
rpcUrl: "https://api.hanzo.ai/ext/bc/C/rpc",
|
||||
explorerUrl: "https://explorer.hanzo.ai",
|
||||
},
|
||||
testnet: {
|
||||
name: "Hanzo Testnet",
|
||||
chainId: 36962,
|
||||
rpcUrl: "https://api.hanzo-test.ai/ext/bc/C/rpc",
|
||||
explorerUrl: "https://explorer.hanzo-test.ai",
|
||||
},
|
||||
},
|
||||
|
||||
contracts: {
|
||||
36963: {
|
||||
governanceToken: "",
|
||||
treasury: "",
|
||||
staking: "",
|
||||
},
|
||||
36962: {},
|
||||
},
|
||||
|
||||
theme: {
|
||||
light: {
|
||||
primaryColor: "#0ea5e9",
|
||||
secondaryColor: "#38bdf8",
|
||||
accentColor: "#f43f5e",
|
||||
backgroundColor: "#ffffff",
|
||||
paperColor: "#f0f9ff",
|
||||
fontFamily: "'Inter', sans-serif",
|
||||
},
|
||||
dark: {
|
||||
primaryColor: "#38bdf8",
|
||||
secondaryColor: "#0ea5e9",
|
||||
accentColor: "#fb7185",
|
||||
backgroundColor: "#0c0a1d",
|
||||
paperColor: "#1a1333",
|
||||
fontFamily: "'Inter', sans-serif",
|
||||
},
|
||||
},
|
||||
|
||||
api: {
|
||||
treasurySubgraph: "https://treasury-subgraph.hanzo.ai",
|
||||
coingeckoId: "hanzo",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
import type { BrandConfig } from "../index";
|
||||
|
||||
export const luxBrand: BrandConfig = {
|
||||
id: "lux",
|
||||
name: "Lux",
|
||||
description: "Multi-consensus blockchain with post-quantum security",
|
||||
website: "https://lux.network",
|
||||
docsUrl: "https://docs.lux.network",
|
||||
communityUrl: "https://discord.gg/lux",
|
||||
githubOrg: "luxfi",
|
||||
|
||||
tokens: {
|
||||
native: "LUX",
|
||||
governance: "LUX",
|
||||
staked: "sLUX",
|
||||
gWrapped: "gLUX",
|
||||
wsWrapped: "wsLUX",
|
||||
veToken: "veLUX",
|
||||
decimals: 18,
|
||||
},
|
||||
|
||||
chains: {
|
||||
mainnet: {
|
||||
name: "Lux C-Chain",
|
||||
chainId: 96369,
|
||||
rpcUrl: "https://api.lux.network/ext/bc/C/rpc",
|
||||
explorerUrl: "https://explorer.lux.network",
|
||||
subgraphUrl: "https://subgraph.lux.network",
|
||||
},
|
||||
testnet: {
|
||||
name: "Lux Testnet",
|
||||
chainId: 96368,
|
||||
rpcUrl: "https://api.lux-test.network/ext/bc/C/rpc",
|
||||
explorerUrl: "https://explorer.lux-test.network",
|
||||
},
|
||||
},
|
||||
|
||||
contracts: {
|
||||
96369: {
|
||||
governanceToken: "",
|
||||
treasury: "",
|
||||
staking: "",
|
||||
},
|
||||
96368: {},
|
||||
},
|
||||
|
||||
theme: {
|
||||
light: {
|
||||
primaryColor: "#6366f1",
|
||||
secondaryColor: "#818cf8",
|
||||
accentColor: "#f59e0b",
|
||||
backgroundColor: "#ffffff",
|
||||
paperColor: "#f5f3ff",
|
||||
fontFamily: "'Inter', sans-serif",
|
||||
},
|
||||
dark: {
|
||||
primaryColor: "#818cf8",
|
||||
secondaryColor: "#6366f1",
|
||||
accentColor: "#fbbf24",
|
||||
backgroundColor: "#0f0f23",
|
||||
paperColor: "#1e1b4b",
|
||||
fontFamily: "'Inter', sans-serif",
|
||||
},
|
||||
},
|
||||
|
||||
api: {
|
||||
treasurySubgraph: "https://treasury-subgraph.lux.network",
|
||||
coingeckoId: "lux",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
import type { BrandConfig } from "../index";
|
||||
|
||||
export const parsBrand: BrandConfig = {
|
||||
id: "pars",
|
||||
name: "Pars",
|
||||
description: "Sovereign L1 with post-quantum secure messaging",
|
||||
website: "https://pars.network",
|
||||
docsUrl: "https://docs.pars.network",
|
||||
communityUrl: "https://discord.gg/pars",
|
||||
githubOrg: "pars-network",
|
||||
|
||||
tokens: {
|
||||
native: "PARS",
|
||||
governance: "PARS",
|
||||
staked: "sPARS",
|
||||
gWrapped: "gPARS",
|
||||
wsWrapped: "wsPARS",
|
||||
veToken: "vePARS",
|
||||
migration: "MIGA",
|
||||
decimals: 9,
|
||||
},
|
||||
|
||||
chains: {
|
||||
mainnet: {
|
||||
name: "Pars Mainnet",
|
||||
chainId: 7070,
|
||||
rpcUrl: "https://rpc.pars.network/ext/bc/C/rpc",
|
||||
explorerUrl: "https://explorer.pars.network",
|
||||
},
|
||||
testnet: {
|
||||
name: "Pars Testnet",
|
||||
chainId: 7071,
|
||||
rpcUrl: "https://rpc-testnet.pars.network/ext/bc/C/rpc",
|
||||
explorerUrl: "https://explorer-testnet.pars.network",
|
||||
},
|
||||
},
|
||||
|
||||
contracts: {
|
||||
// Mainnet (7070) - addresses TBD after CREATE2 deployment
|
||||
7070: {
|
||||
governanceToken: "",
|
||||
stakedToken: "",
|
||||
gWrappedToken: "",
|
||||
treasury: "",
|
||||
staking: "",
|
||||
feeRouter: "",
|
||||
charter: "",
|
||||
kernel: "",
|
||||
veToken: "",
|
||||
migrationToken: "",
|
||||
},
|
||||
// Testnet (7071)
|
||||
7071: {},
|
||||
},
|
||||
|
||||
theme: {
|
||||
light: {
|
||||
primaryColor: "#1a73e8",
|
||||
secondaryColor: "#4285f4",
|
||||
accentColor: "#ea4335",
|
||||
backgroundColor: "#ffffff",
|
||||
paperColor: "#f8f9fa",
|
||||
fontFamily: "'Inter', sans-serif",
|
||||
},
|
||||
dark: {
|
||||
primaryColor: "#8ab4f8",
|
||||
secondaryColor: "#4285f4",
|
||||
accentColor: "#f28b82",
|
||||
backgroundColor: "#1a1a2e",
|
||||
paperColor: "#16213e",
|
||||
fontFamily: "'Inter', sans-serif",
|
||||
},
|
||||
},
|
||||
|
||||
api: {
|
||||
treasurySubgraph: "https://treasury-subgraph.pars.network",
|
||||
coingeckoId: "pars",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
import type { BrandConfig } from "../index";
|
||||
|
||||
export const zooBrand: BrandConfig = {
|
||||
id: "zoo",
|
||||
name: "Zoo",
|
||||
description: "Open AI research network for decentralized science",
|
||||
website: "https://zoo.ngo",
|
||||
docsUrl: "https://docs.zoo.ngo",
|
||||
communityUrl: "https://discord.gg/zoo",
|
||||
githubOrg: "zoo-labs",
|
||||
|
||||
tokens: {
|
||||
native: "ZOO",
|
||||
governance: "ZOO",
|
||||
staked: "sZOO",
|
||||
gWrapped: "gZOO",
|
||||
wsWrapped: "wsZOO",
|
||||
veToken: "veZOO",
|
||||
decimals: 18,
|
||||
},
|
||||
|
||||
chains: {
|
||||
mainnet: {
|
||||
name: "Zoo Network",
|
||||
chainId: 200200,
|
||||
rpcUrl: "https://api.zoo.ngo/ext/bc/C/rpc",
|
||||
explorerUrl: "https://explorer.zoo.ngo",
|
||||
},
|
||||
testnet: {
|
||||
name: "Zoo Testnet",
|
||||
chainId: 200201,
|
||||
rpcUrl: "https://api.zoo-test.ngo/ext/bc/C/rpc",
|
||||
explorerUrl: "https://explorer.zoo-test.ngo",
|
||||
},
|
||||
},
|
||||
|
||||
contracts: {
|
||||
200200: {
|
||||
governanceToken: "",
|
||||
treasury: "",
|
||||
staking: "",
|
||||
},
|
||||
200201: {},
|
||||
},
|
||||
|
||||
theme: {
|
||||
light: {
|
||||
primaryColor: "#10b981",
|
||||
secondaryColor: "#34d399",
|
||||
accentColor: "#f97316",
|
||||
backgroundColor: "#ffffff",
|
||||
paperColor: "#ecfdf5",
|
||||
fontFamily: "'Inter', sans-serif",
|
||||
},
|
||||
dark: {
|
||||
primaryColor: "#34d399",
|
||||
secondaryColor: "#10b981",
|
||||
accentColor: "#fb923c",
|
||||
backgroundColor: "#0a1628",
|
||||
paperColor: "#064e3b",
|
||||
fontFamily: "'Inter', sans-serif",
|
||||
},
|
||||
},
|
||||
|
||||
api: {
|
||||
treasurySubgraph: "https://treasury-subgraph.zoo.ngo",
|
||||
coingeckoId: "zoo",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* @luxdao/brand-config
|
||||
*
|
||||
* White-label brand configuration for the Lux DAO governance stack.
|
||||
* Import a brand preset or create a custom BrandConfig to white-label
|
||||
* the full governance UI for any DAO.
|
||||
*
|
||||
* Usage:
|
||||
* import { parsBrand } from "@luxdao/brand-config/pars"
|
||||
* import { luxBrand } from "@luxdao/brand-config/lux"
|
||||
* import { zooBrand } from "@luxdao/brand-config/zoo"
|
||||
* import type { BrandConfig } from "@luxdao/brand-config"
|
||||
*/
|
||||
|
||||
export interface TokenConfig {
|
||||
/** Native/network token symbol */
|
||||
native: string;
|
||||
/** Governance token symbol */
|
||||
governance: string;
|
||||
/** Staked governance token symbol */
|
||||
staked: string;
|
||||
/** Governance-wrapped token symbol */
|
||||
gWrapped: string;
|
||||
/** Wrapped staked token symbol */
|
||||
wsWrapped: string;
|
||||
/** Vote-escrowed token symbol */
|
||||
veToken: string;
|
||||
/** Migration token symbol (if applicable) */
|
||||
migration?: string;
|
||||
/** Token decimals (default: 9 for governance, 18 for ERC20) */
|
||||
decimals?: number;
|
||||
}
|
||||
|
||||
export interface ChainConfig {
|
||||
/** Chain name */
|
||||
name: string;
|
||||
/** Chain ID */
|
||||
chainId: number;
|
||||
/** RPC endpoint */
|
||||
rpcUrl: string;
|
||||
/** Block explorer URL */
|
||||
explorerUrl: string;
|
||||
/** Treasury subgraph endpoint */
|
||||
subgraphUrl?: string;
|
||||
}
|
||||
|
||||
export interface ContractAddresses {
|
||||
/** Governance token */
|
||||
governanceToken: string;
|
||||
/** Staked token */
|
||||
stakedToken: string;
|
||||
/** gWrapped token */
|
||||
gWrappedToken: string;
|
||||
/** Treasury */
|
||||
treasury: string;
|
||||
/** Staking contract */
|
||||
staking: string;
|
||||
/** Bond depository */
|
||||
bondDepository?: string;
|
||||
/** Fee router */
|
||||
feeRouter?: string;
|
||||
/** Charter (governance parameters) */
|
||||
charter?: string;
|
||||
/** Kernel (module system) */
|
||||
kernel?: string;
|
||||
/** Vote-escrowed token */
|
||||
veToken?: string;
|
||||
/** Migration token */
|
||||
migrationToken?: string;
|
||||
}
|
||||
|
||||
export interface ThemeConfig {
|
||||
/** Primary brand color (hex) */
|
||||
primaryColor: string;
|
||||
/** Secondary brand color (hex) */
|
||||
secondaryColor: string;
|
||||
/** Accent color for special elements */
|
||||
accentColor: string;
|
||||
/** Background color */
|
||||
backgroundColor: string;
|
||||
/** Paper/card color */
|
||||
paperColor: string;
|
||||
/** Font family */
|
||||
fontFamily?: string;
|
||||
}
|
||||
|
||||
export interface BrandConfig {
|
||||
/** Brand identifier (lowercase, no spaces) */
|
||||
id: string;
|
||||
/** Display name */
|
||||
name: string;
|
||||
/** Short description */
|
||||
description: string;
|
||||
/** Website URL */
|
||||
website: string;
|
||||
/** Documentation URL */
|
||||
docsUrl: string;
|
||||
/** Discord/community URL */
|
||||
communityUrl?: string;
|
||||
/** GitHub organization */
|
||||
githubOrg: string;
|
||||
|
||||
/** Token configuration */
|
||||
tokens: TokenConfig;
|
||||
|
||||
/** Chain configuration */
|
||||
chains: {
|
||||
mainnet: ChainConfig;
|
||||
testnet?: ChainConfig;
|
||||
};
|
||||
|
||||
/** Contract addresses by chain ID */
|
||||
contracts: Record<number, Partial<ContractAddresses>>;
|
||||
|
||||
/** Theme configuration */
|
||||
theme: {
|
||||
light: ThemeConfig;
|
||||
dark: ThemeConfig;
|
||||
};
|
||||
|
||||
/** API endpoints */
|
||||
api: {
|
||||
/** Treasury subgraph WunderGraph endpoint */
|
||||
treasurySubgraph?: string;
|
||||
/** Cooler loans API */
|
||||
coolerLoansApi?: string;
|
||||
/** Token price API (CoinGecko ID) */
|
||||
coingeckoId?: string;
|
||||
};
|
||||
}
|
||||
|
||||
// Brand implementations are NOT exported here.
|
||||
// Each project owns its own brand config locally.
|
||||
// This package exports only the type interfaces.
|
||||
@@ -0,0 +1,14 @@
|
||||
import { AccordionProps } from "@mui/material";
|
||||
import { FC, ReactChild, ReactElement, ReactFragment, ReactPortal } from "react";
|
||||
export interface PARSAccordionProps extends AccordionProps {
|
||||
summary: ReactElement;
|
||||
children: boolean | ReactChild | ReactFragment | ReactPortal;
|
||||
/** Disables clicking on entire row to expand/collapse and only expands/collapses when arrow is clicked */
|
||||
arrowOnlyCollapse?: boolean;
|
||||
}
|
||||
/**
|
||||
* Accordion Component for UI.
|
||||
*/
|
||||
declare const Accordion: FC<PARSAccordionProps>;
|
||||
export default Accordion;
|
||||
//# sourceMappingURL=Accordion.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../src/components/Accordion/Accordion.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+C,cAAc,EAAoB,MAAM,eAAe,CAAC;AAE9G,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAuB,MAAM,OAAO,CAAC;AAiCtG,MAAM,WAAW,iBAAkB,SAAQ,cAAc;IACvD,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,OAAO,GAAG,UAAU,GAAG,aAAa,GAAG,WAAW,CAAC;IAC7D,0GAA0G;IAC1G,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,QAAA,MAAM,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAmCpC,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default } from "./Accordion";
|
||||
export { default as Accordion } from "./Accordion";
|
||||
export type { PARSAccordionProps } from "./Accordion";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Accordion/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { AlertProps } from "@mui/material";
|
||||
import { FC } from "react";
|
||||
export interface PARSAlertProps {
|
||||
open: boolean;
|
||||
severity: AlertProps["severity"];
|
||||
title: string;
|
||||
text: string;
|
||||
onClose: () => void;
|
||||
progress: number;
|
||||
}
|
||||
declare const Alert: FC<PARSAlertProps>;
|
||||
export default Alert;
|
||||
//# sourceMappingURL=Alert.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"Alert.d.ts","sourceRoot":"","sources":["../../../src/components/Alert/Alert.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4B,MAAM,eAAe,CAAC;AAGrE,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAoB3B,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,QAAA,MAAM,KAAK,EAAE,EAAE,CAAC,aAAa,CAU5B,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default } from "./Alert";
|
||||
export { default as Alert } from "./Alert";
|
||||
export type { PARSAlertProps } from "./Alert";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Alert/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAC;AAC3C,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC"}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { FC, ReactElement } from "react";
|
||||
export interface PARSArticleCardProps {
|
||||
imageSrc: string;
|
||||
title: string;
|
||||
publishDate?: string;
|
||||
content: string | ReactElement | Element;
|
||||
href?: string;
|
||||
}
|
||||
/**
|
||||
* Component for Displaying ArticleCard
|
||||
*/
|
||||
declare const ArticleCard: FC<PARSArticleCardProps>;
|
||||
export default ArticleCard;
|
||||
//# sourceMappingURL=ArticleCard.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"ArticleCard.d.ts","sourceRoot":"","sources":["../../../src/components/ArticleCard/ArticleCard.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AA2DzC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,OAAO,CAAC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,QAAA,MAAM,WAAW,EAAE,EAAE,CAAC,mBAAmB,CAuBxC,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default } from "./ArticleCard";
|
||||
export { default as ArticleCard } from "./ArticleCard";
|
||||
export type { PARSArticleCardProps } from "./ArticleCard";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ArticleCard/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { FC } from "react";
|
||||
import { PARSTokenStackProps } from "../TokenStack";
|
||||
export interface PARSAssetCardProps {
|
||||
token?: PARSTokenStackProps["tokens"];
|
||||
timeRemaining?: string;
|
||||
assetValue?: string | number;
|
||||
assetBalance?: string | number;
|
||||
pnl?: string | number;
|
||||
label?: string;
|
||||
pnlColor?: "green" | "red";
|
||||
ctaText?: string;
|
||||
lineThreeLabel?: string;
|
||||
lineThreeValue?: string | number;
|
||||
ctaOnClick?: () => void;
|
||||
}
|
||||
/**
|
||||
* Asset Card Component for Wallet.
|
||||
*/
|
||||
declare const AssetCard: FC<PARSAssetCardProps>;
|
||||
export default AssetCard;
|
||||
//# sourceMappingURL=AssetCard.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"AssetCard.d.ts","sourceRoot":"","sources":["../../../src/components/AssetCard/AssetCard.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,EAAE,EAAY,MAAM,OAAO,CAAC;AAGrC,OAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAqE/D,MAAM,WAAW,iBAAiB;IAEhC,KAAK,CAAC,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAErC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE7B,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE/B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED;;GAEG;AACH,QAAA,MAAM,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAyFpC,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default } from "./AssetCard";
|
||||
export { default as AssetCard } from "./AssetCard";
|
||||
export type { PARSAssetCardProps } from "./AssetCard";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/AssetCard/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { ButtonProps } from "@mui/material";
|
||||
import { FC } from "react";
|
||||
import { IconName } from "../Icon";
|
||||
export interface PARSButtonProps extends ButtonProps {
|
||||
template?: "primary" | "secondary" | "tertiary" | "text" | "success" | "feedback";
|
||||
icon?: IconName;
|
||||
onClick?: any;
|
||||
startIconName?: IconName;
|
||||
endIconName?: IconName;
|
||||
loading?: boolean;
|
||||
}
|
||||
/**
|
||||
* Primary Button Component for UI.
|
||||
*/
|
||||
declare const Button: FC<PARSButtonProps>;
|
||||
export default Button;
|
||||
//# sourceMappingURL=Button.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/Button/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,WAAW,EAAoB,MAAM,eAAe,CAAC;AAEnF,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAE3B,OAAa,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AA8DzC,MAAM,WAAW,cAAe,SAAQ,WAAW;IACjD,QAAQ,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;IAClF,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,aAAa,CAAC,EAAE,QAAQ,CAAC;IACzB,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,QAAA,MAAM,MAAM,EAAE,EAAE,CAAC,cAAc,CA6D9B,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
||||
@@ -0,0 +1,7 @@
|
||||
export declare const PrimaryButton: (props: any) => JSX.Element;
|
||||
export declare const SecondaryButton: (props: any) => JSX.Element;
|
||||
export declare const TertiaryButton: (props: any) => JSX.Element;
|
||||
export declare const TextButton: (props: any) => JSX.Element;
|
||||
export declare const SuccessButton: (props: any) => JSX.Element;
|
||||
export type { PARSButtonProps } from "./Button";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Button/index.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,UAAW,GAAG,gBAEvC,CAAC;AAEF,eAAO,MAAM,eAAe,UAAW,GAAG,gBAEzC,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,GAAG,gBAExC,CAAC;AAEF,eAAO,MAAM,UAAU,UAAW,GAAG,gBAEpC,CAAC;AACF,eAAO,MAAM,aAAa,UAAW,GAAG,gBAEvC,CAAC;AAEF,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC"}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { ChipProps } from "@mui/material";
|
||||
import { ThemeOptions } from "@mui/material/styles";
|
||||
import { FC } from "react";
|
||||
export interface PARSChipProps extends ChipProps {
|
||||
template?: keyof ThemeOptions["colors"]["feedback"] | "purple" | "gray" | "darkGray";
|
||||
strong?: boolean;
|
||||
}
|
||||
/**
|
||||
* Component for Displaying Chip
|
||||
*/
|
||||
declare const Chip: FC<PARSChipProps>;
|
||||
export default Chip;
|
||||
//# sourceMappingURL=Chip.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"Chip.d.ts","sourceRoot":"","sources":["../../../src/components/Chip/Chip.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,SAAS,EAAE,MAAM,eAAe,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA2C3B,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,QAAQ,CAAC,EAAE,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACrF,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,QAAA,MAAM,IAAI,EAAE,EAAE,CAAC,YAAY,CAE1B,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default } from "./Chip";
|
||||
export { default as Chip } from "./Chip";
|
||||
export type { PARSChipProps } from "./Chip";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Chip/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,YAAY,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC"}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { FC, ReactElement, ReactNode } from "react";
|
||||
export interface PARSDataRowProps {
|
||||
title: string | ReactElement | Element;
|
||||
indented?: boolean;
|
||||
id?: string;
|
||||
balance?: string | ReactElement | Element;
|
||||
isLoading?: boolean;
|
||||
children?: ReactNode;
|
||||
tooltip?: string;
|
||||
}
|
||||
declare const DataRow: FC<PARSDataRowProps>;
|
||||
export default DataRow;
|
||||
//# sourceMappingURL=DataRow.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"DataRow.d.ts","sourceRoot":"","sources":["../../../src/components/DataRow/DataRow.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAoDpD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,OAAO,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,OAAO,CAAC;IAC1C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,QAAA,MAAM,OAAO,EAAE,EAAE,CAAC,eAAe,CA8ChC,CAAC;AAEF,eAAe,OAAO,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default } from "./DataRow";
|
||||
export { default as DataRow } from "./DataRow";
|
||||
export type { PARSDataRowProps } from "./DataRow";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DataRow/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { FC, ReactElement } from "react";
|
||||
export interface PARSDottedDataRowProps {
|
||||
title: string | ReactElement | Element;
|
||||
value?: string | number | ReactElement | Element;
|
||||
bold?: boolean;
|
||||
}
|
||||
/**
|
||||
* Component for Displaying DottedDataRow
|
||||
*/
|
||||
declare const DottedDataRow: FC<PARSDottedDataRowProps>;
|
||||
export default DottedDataRow;
|
||||
//# sourceMappingURL=DottedDataRow.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"DottedDataRow.d.ts","sourceRoot":"","sources":["../../../src/components/DottedDataRow/DottedDataRow.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAwBzC,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,OAAO,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,OAAO,CAAC;IACjD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,QAAA,MAAM,aAAa,EAAE,EAAE,CAAC,qBAAqB,CA2B5C,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default } from "./DottedDataRow";
|
||||
export { default as DottedDataRow } from "./DottedDataRow";
|
||||
export type { PARSDottedDataRowProps } from "./DottedDataRow";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DottedDataRow/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { FC, ReactElement } from "react";
|
||||
export interface PARSGetOnButtonProps {
|
||||
href: string;
|
||||
logo: ReactElement;
|
||||
exchangeName: string;
|
||||
}
|
||||
/**
|
||||
* Component for Displaying GetOnButton
|
||||
*/
|
||||
declare const GetOnButton: FC<PARSGetOnButtonProps>;
|
||||
export default GetOnButton;
|
||||
//# sourceMappingURL=GetOnButton.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"GetOnButton.d.ts","sourceRoot":"","sources":["../../../src/components/GetOnButton/GetOnButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAiCzC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,QAAA,MAAM,WAAW,EAAE,EAAE,CAAC,mBAAmB,CAqBxC,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default } from "./GetOnButton";
|
||||
export { default as GetOnButton } from "./GetOnButton";
|
||||
export type { PARSGetOnButtonProps } from "./GetOnButton";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/GetOnButton/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { SvgIconProps } from "@mui/material";
|
||||
import { FC } from "react";
|
||||
import iconPath from "./iconsLib";
|
||||
export interface PARSIconProps extends SvgIconProps {
|
||||
name: keyof typeof iconPath;
|
||||
}
|
||||
declare const Icon: FC<PARSIconProps>;
|
||||
export default Icon;
|
||||
export declare type IconName = keyof typeof iconPath;
|
||||
//# sourceMappingURL=Icon.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"Icon.d.ts","sourceRoot":"","sources":["../../../src/components/Icon/Icon.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,YAAY,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAE3B,OAAO,QAAQ,MAAM,YAAY,CAAC;AAiBlC,MAAM,WAAW,YAAa,SAAQ,YAAY;IAChD,IAAI,EAAE,MAAM,OAAO,QAAQ,CAAC;CAC7B;AAED,QAAA,MAAM,IAAI,EAAE,EAAE,CAAC,YAAY,CAE1B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,oBAAY,QAAQ,GAAG,MAAM,OAAO,QAAQ,CAAC"}
|
||||
@@ -0,0 +1,79 @@
|
||||
declare const icons: {
|
||||
"33-together": JSX.Element;
|
||||
"alert-circle": JSX.Element;
|
||||
"arrow-right": JSX.Element;
|
||||
"arrow-up": JSX.Element;
|
||||
"arrow-down": JSX.Element;
|
||||
bond: JSX.Element;
|
||||
bridge: JSX.Element;
|
||||
"bug-report": JSX.Element;
|
||||
"caret-down": JSX.Element;
|
||||
"check-circle": JSX.Element;
|
||||
clock: JSX.Element;
|
||||
dashboard: JSX.Element;
|
||||
deposited: JSX.Element;
|
||||
discord: JSX.Element;
|
||||
docs: JSX.Element;
|
||||
donated: JSX.Element;
|
||||
donors: JSX.Element;
|
||||
feedback: JSX.Element;
|
||||
forum: JSX.Element;
|
||||
"flag-ru": JSX.Element;
|
||||
"flag-pl": JSX.Element;
|
||||
"flag-tr": JSX.Element;
|
||||
"flag-cn": JSX.Element;
|
||||
"flag-ae": JSX.Element;
|
||||
"flag-es": JSX.Element;
|
||||
"flag-vn": JSX.Element;
|
||||
"flag-fr": JSX.Element;
|
||||
"flag-gb": JSX.Element;
|
||||
"flag-kr": JSX.Element;
|
||||
"flag-de": JSX.Element;
|
||||
fullscreen: JSX.Element;
|
||||
goal: JSX.Element;
|
||||
governance: JSX.Element;
|
||||
github: JSX.Element;
|
||||
give: JSX.Element;
|
||||
grants: JSX.Element;
|
||||
"info-fill": JSX.Element;
|
||||
hamburger: JSX.Element;
|
||||
info: JSX.Element;
|
||||
lock: JSX.Element;
|
||||
medium: JSX.Element;
|
||||
moon: JSX.Element;
|
||||
more: JSX.Element;
|
||||
olympus: JSX.Element;
|
||||
lux: JSX.Element;
|
||||
settings: JSX.Element;
|
||||
"sasha-total": JSX.Element;
|
||||
"sasha-yield": JSX.Element;
|
||||
"sasha-yield-goal": JSX.Element;
|
||||
"sasha-yield-sent": JSX.Element;
|
||||
stake: JSX.Element;
|
||||
"step-1": JSX.Element;
|
||||
"step-2": JSX.Element;
|
||||
"step-complete": JSX.Element;
|
||||
sun: JSX.Element;
|
||||
"time-remaining": JSX.Element;
|
||||
twitter: JSX.Element;
|
||||
"vault-lock": JSX.Element;
|
||||
"vault-recipient": JSX.Element;
|
||||
"vault-wallet": JSX.Element;
|
||||
wallet: JSX.Element;
|
||||
website: JSX.Element;
|
||||
wrap: JSX.Element;
|
||||
x: JSX.Element;
|
||||
zap: JSX.Element;
|
||||
yield: JSX.Element;
|
||||
repeat: JSX.Element;
|
||||
calendar: JSX.Element;
|
||||
"radio-filled": JSX.Element;
|
||||
"radio-empty": JSX.Element;
|
||||
"arrow-up-right": JSX.Element;
|
||||
timeLeft: JSX.Element;
|
||||
range: JSX.Element;
|
||||
voting: JSX.Element;
|
||||
transparency: JSX.Element;
|
||||
};
|
||||
export default icons;
|
||||
//# sourceMappingURL=iconsLib.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"iconsLib.d.ts","sourceRoot":"","sources":["../../../src/components/Icon/iconsLib.tsx"],"names":[],"mappings":"AAAA,QAAA,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAs4EV,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default } from "./Icon";
|
||||
export type { PARSIconProps, IconName } from "./Icon";
|
||||
export { default as Icon } from "./Icon";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Icon/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC"}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { FC, ReactElement } from "react";
|
||||
export interface PARSInfoCardProps {
|
||||
status?: "active" | "closed" | "passed" | "failed";
|
||||
statusLabel?: string;
|
||||
title?: string;
|
||||
content?: string | ReactElement | Element;
|
||||
timeRemaining?: string;
|
||||
href?: string;
|
||||
}
|
||||
/**
|
||||
* Component for Displaying InfoCard
|
||||
*/
|
||||
declare const InfoCard: FC<PARSInfoCardProps>;
|
||||
export default InfoCard;
|
||||
//# sourceMappingURL=InfoCard.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"InfoCard.d.ts","sourceRoot":"","sources":["../../../src/components/InfoCard/InfoCard.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAiEzC,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,OAAO,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,QAAA,MAAM,QAAQ,EAAE,EAAE,CAAC,gBAAgB,CAgClC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default } from "./InfoCard";
|
||||
export { default as InfoCard } from "./InfoCard";
|
||||
export type { PARSInfoCardProps } from "./InfoCard";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/InfoCard/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { FC } from "react";
|
||||
export interface PARSInfoTooltipProps {
|
||||
message: string;
|
||||
}
|
||||
declare const InfoTooltip: FC<PARSInfoTooltipProps>;
|
||||
export default InfoTooltip;
|
||||
//# sourceMappingURL=InfoTooltip.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"InfoTooltip.d.ts","sourceRoot":"","sources":["../../../src/components/InfoTooltip/InfoTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAK3B,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,QAAA,MAAM,WAAW,EAAE,EAAE,CAAC,mBAAmB,CAMxC,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
||||
@@ -0,0 +1,12 @@
|
||||
/// <reference types="react" />
|
||||
interface Props {
|
||||
messagesArray: Array<string>;
|
||||
}
|
||||
/**
|
||||
* InfoTooltipMulti allows passing an ARRAY of message strings w each Array Element on a new line
|
||||
* @param {*} messagesArray = Array of Message Strings
|
||||
* @returns MUI Popover on document.body
|
||||
*/
|
||||
declare const InfoTooltipMulti: React.FC<Props>;
|
||||
export default InfoTooltipMulti;
|
||||
//# sourceMappingURL=InfoTooltipMulti.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"InfoTooltipMulti.d.ts","sourceRoot":"","sources":["../../../src/components/InfoTooltip/InfoTooltipMulti.tsx"],"names":[],"mappings":";AAGA,UAAU,KAAK;IACb,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED;;;;GAIG;AACH,QAAA,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAWrC,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default as InfoTooltip } from "./InfoTooltip";
|
||||
export { default as InfoTooltipMulti } from "./InfoTooltipMulti";
|
||||
export type { PARSInfoTooltipProps } from "./InfoTooltip";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/InfoTooltip/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user