Concepts
How pools work
Each pool is its own smart contract. No shared treasury, no proxy upgrades — just an immutable contract per fundraise.
Three roles
- Deployer — the address that called the constructor. Immutable. Receives remaining funds after expiry.
- Owners — the deployer plus any co-owners passed into the constructor. Any owner may withdraw before expiry.
- Funders — anyone who sends ETH or a whitelisted ERC-20. Their contributions are tracked per-address.
Per-pool state
Each pool contract stores its own name, description, USD minimum, expiry, co-owner set, ETH/ERC-20 balances, and per-funder totals. Because every pool is a separate contract, pools are fully isolated: a bug, exploit, or stuck state in one pool cannot affect another.
Immutable parameters
The following are fixed at deploy time and cannot be changed:
- Deployer address
- USD minimum contribution
- Expiry timestamp
- ETH/USD Chainlink feed
- Co-owner set
- Whitelisted tokens and their USD feeds
This is deliberate. A pool's rules should not change after funders commit. If you need different parameters, deploy a new pool.
Funds flow
- Funders send ETH or approved ERC-20s to the pool contract.
- The contract checks the Chainlink-priced USD value against the minimum. Below-minimum contributions revert.
- Owners may withdraw (partial or full) at any time before
expiresAt. - After
expiresAt, owner withdraws are disabled. Anyone can callreleaseExpiredFundsToDeployerto sweep the remaining balance back to the deployer.
Why every pool is a new contract
Sharing state across fundraises would mean a shared admin, shared upgrade risk, and shared blast radius. An immutable one-contract-per- pool model keeps trust assumptions small: funders only need to audit the bytecode they are sending money to, and the deployer cannot retroactively change the rules.
Related
- USD pricing & Chainlink feeds — how dollar amounts are enforced on-chain.
- Pool lifecycle — funding, withdraws, expiry, and release.