Capital Distributor is an Aragon OSx plugin that enables onchain organizations to create and manage capital distribution campaigns. Organizations can distribute tokens to their members through various allocation strategies and payout methods, making it ideal for airdrops, gauge distributions, incentive programs, grants, and rewards.
The system follows a modular architecture where the main plugin orchestrates campaigns using dynamically deployed strategies and encoders through factory contracts:
graph TB
subgraph "Setup"
PS[PluginSetup] -->|deploys| P[Plugin]
PS -->|connects| F1[AllocatorStrategyFactory]
PS -->|connects| F2[ActionEncoderFactory]
end
subgraph "Campaign Creation"
P -->|creates campaign| C[Campaign]
F1 -->|deploys| AS[Allocation Strategy Instance]
F2 -->|deploys| AE[Action Encoder Instance]
AS -->|linked to| C
AE -->|linked to| C
end
subgraph "Campaign Execution"
U[User] -->|claims from| C
C -->|validates via| AS
C -->|encodes payout via| AE
AE -->|executes| T[Token Transfer]
T -->|to| U
end
The main plugin contract that manages the lifecycle of distribution campaigns. It handles:
- Campaign creation with customizable parameters
- Claim processing and validation
- Campaign state management (active, paused, ended)
- Integration with allocation strategies and payout encoders
Manages the deployment and registration of allocation strategies. Each strategy determines how tokens are allocated to recipients.
Available Strategies:
- MerkleDistributorStrategy: Uses Merkle trees for efficient large-scale distributions (airdrops)
Manages payout action encoders that transform distribution amounts into executable DAO actions.
Available Encoders:
- Direct Transfer: Simple ERC20 token transfers
- VaultDepositPayoutActionEncoder: Deposits tokens into ERC-4626 vaults
struct Campaign {
bytes metadataURI; // Campaign metadata (IPFS)
IAllocatorStrategy strategy; // Allocation logic
IERC20 token; // Token to distribute
IPayoutActionEncoder encoder; // Payout method
CampaignState state; // ACTIVE, PAUSED, ENDED
uint256 startTime; // Campaign start timestamp
uint256 endTime; // Campaign end timestamp
}- Flexible Allocation Strategies: Choose from multiple methods to determine recipient allocations
- Multiple Payout Methods: Direct transfers, vault deposits, or streaming payments
- Campaign Management: Full lifecycle control with pause, resume, and end capabilities
- Batch Operations: Process multiple claims in a single transaction for gas efficiency
- Modular Architecture: Easily extend with new strategies and encoders
- Permission System: Integrated with Aragon's permission management
- Event Tracking: Comprehensive events for monitoring and indexing
Clone the repository and install dependencies:
git clone https://github.com/aragon/osx-capital-distributor
cd osx-capital-distributor
bun install # or npm installforge buildRun the test suite with verbose output:
forge test -vvvGenerate test coverage report:
forge coverageGenerate gas reports for optimization:
# Gas report for tests
forge test --gas-report
# Create gas snapshot
forge snapshotThe deployment process follows these steps:
-
Deploy Factory Contracts
AllocatorStrategyFactory allocatorFactory = new AllocatorStrategyFactory(); ActionEncoderFactory actionFactory = new ActionEncoderFactory();
-
Register Strategies and Encoders
// Register allocation strategies allocatorFactory.registerStrategyType("merkle-distributor", merkleStrategy, ...); allocatorFactory.registerStrategyType("gauge-voter", gaugeStrategy, ...); // Register action encoders actionFactory.registerActionEncoder("vault-deposit", vaultEncoder, ...);
-
Deploy Plugin Setup
CapitalDistributorPluginSetup setup = new CapitalDistributorPluginSetup();
-
Publish to Aragon Registry
PluginRepo repo = repoFactory.createPluginRepoWithFirstVersion( "capital-distributor", address(setup), maintainer, buildMetadata, releaseMetadata );
-
Install Plugin in DAO
DAO.createDao(daoSettings, pluginSettings);
Deploy using the provided script:
forge script script/Deploy.s.sol --rpc-url <RPC_URL> --broadcastRequired environment variables:
PLUGIN_REPO_FACTORY: Aragon Plugin Repository Factory addressDAO_FACTORY: Aragon DAO Factory addressADMIN_REPO: Admin plugin repository addressADMIN_OWNER: Address of the admin owner
| Network | Plugin Setup | AllocatorStrategyFactory | ActionEncoderFactory |
|---|---|---|---|
| Ethereum Mainnet | TBD | TBD | TBD |
| Polygon | TBD | TBD | TBD |
| Arbitrum One | TBD | TBD | TBD |
| Optimism | TBD | TBD | TBD |
| Base | TBD | TBD | TBD |
| Sepolia Testnet | TBD | TBD | TBD |
// Example: Create an airdrop campaign with Merkle distribution
plugin.createCampaign(
"ipfs://QmCampaignMetadata", // Metadata URI
"merkle-distributor", // Strategy ID
address(token), // Token to distribute
"direct-transfer", // Encoder ID (simple transfer)
false, // Single claim per user
block.timestamp, // Start immediately
block.timestamp + 30 days // End in 30 days
);// User claims their allocation with proof
bytes memory proof = abi.encode(merkleProof, amount);
plugin.claimCampaignPayout(campaignId, recipient, proof);
// Batch claim for multiple recipients
plugin.batchClaimCampaignPayout(campaignId, recipients, proofs);- Built on battle-tested Aragon OSx framework
- Follows checks-effects-interactions pattern
- Comprehensive access control via Aragon permissions
- Input validation and bounds checking
- Events for all state changes
We welcome contributions! Please see our Contributing Guidelines for details.
- Run formatter:
forge fmt - Run linter:
bun run lint - Follow Solidity style guide and NatSpec documentation
This project is licensed under the GNU Affero General Public License v3.0 or later - see the LICENSE file for details.