Contracts v1
v1 consists of five contracts plus a few small libraries and hooks. FactoryV1 is the only contract end users interact with directly; everything else is deployed through it.
| FactoryV1 | Single entry point. Orchestrates token creation, pool creation and distribution setup; injects the protocol fee and optional buy-back-and-burn shares. |
| TokenV1 | Minimal ERC20 (OpenZeppelin) that mints fixed initial allocations at construction. |
| TokenV1Factory | Deploys TokenV1 instances and records who requested each one. |
| DistributorV1 | The epoch engine: participation, pro-rata rewards, claiming, drain hooks, allowlists. |
| DistributionV1Factory | Deploys DistributorV1 instances and keeps a list of all distributions for the website. |
TokenV1 & TokenV1Factory
TokenV1 is an OpenZeppelin ERC20 with on-chain vesting and on-chain key/value metadata. Its constructor mints any already-vested allocations to their recipients and stores the initial metadata; the owner can add metadata later (e.g. an avatar) until it is locked.
constructor(TokenConfig memory _config, address _initialOwner)
ERC20(_config.name, _config.symbol)
MetadataStore(_initialOwner, _config.initialMetadata, _config.metadataEditable)
{
for (uint256 i = 0; i < _config.allocations.length; i++) {
share[_config.allocations[i].recipient] = _config.allocations[i];
}
}TokenV1Factory deploys tokens on request and stores the requester per token in creatorOf, so anyone can verify a token was created through the protocol:
tokenAddress = new TokenV1(_config, _creator);
creatorOf[tokenAddress] = _creator;
tokenList.push(tokenAddress);
emit NewToken(tokenAddress);DistributorV1
The heart of the protocol — one immutable instance per distribution. All behaviour is fixed at construction via its config:
struct DistributorConfig {
address distributionToken; // token given out to participants
address participationToken; // token received when users participate
uint256 epochDuration; // length of each epoch (seconds)
uint256 startTimestamp; // when epoch 0 begins
uint256 minParticipation; // minimum per-epoch amount
uint256 claimDelaySeconds; // wait after an epoch ends before claiming
bool allowFutureEpochParticipation;
ReleasePolicy releasePolicy; // who may release ended epoch funds
Share[] shares; // where released epoch funds go
EmissionFunction emissionFunction; // computes each epoch's reward
address allowlistSigner; // address(0) = allowlist disabled
uint256 allowlistDeadline;
uint256 numberOfEpochs;
uint256 totalDistributionAmount;
MetadataEntry[] initialMetadata; // on-chain key/value metadata
bool metadataEditable;
}Beyond participate and claim (detailed in epoch-based distribution), it exposes batch helpers (participateMany, claimMany) for power users and bots, third-party claim fees (setClaimFeeBps), and read helpers the app uses to render distributions: getContractInfo, getEpochInfo and discoverRewards.
DistributionV1Factory
Deploys distributors and keeps an append-only list so the website can page through every distribution ever created without scanning events:
distributorAddress = new DistributorV1(_creator, factory, _config);
creatorOf[distributorAddress] = _creator;
distributionList.push(distributorAddress);
emit NewDistributor(distributorAddress);FactoryV1
The orchestrator. It owns the protocol fee (set by governance), holds references to both sub-factories and hooks, and composes them into one-click flows. The flagship function runs the whole launch:
- Deploys the new token with its allocations.
- Creates the Uniswap V3 pool at the chosen price and adds liquidity — LP tokens are sent to the dead address, locking liquidity forever.
- Injects the buy-back-and-burn share if requested.
- Deploys the distributor and funds it with the full distribution amount of the new token.
createPoolAndAddLiquidity(
_config.participationToken, _config.distributionToken, _sqrtPriceX96,
_participationTokenAmountDesired, _distributionTokenAmountDesired,
_amount0Min, _amount1Min, true, _participationPermit2, _distributionPermit2
);
_injectBuyAndBurnShare(_config, _buyBackAndBurnShareBps);
distributorAddress = createDistributor(_config, true);SharesLib (basis-point splits validated to sum to 100%), HookLib (approve-and-call plumbing), the three emission curves, and the TransferToHook/BuyAndBurnHookV3 hooks. Full source is on GitHub at sqrtDAO/contracts under src/v1.