sqrtDAO

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.

Creator & userssingle transactionFactoryV1entry pointTokenV1FactoryTokenV1ERC20 with allocationsDistributionV1FactoryDistributorV1users participate & claimcreates pool · LP burnedUniswap V3 pool0.3% fee tiershares (bps)TransferToHookBuyAndBurnHookV3
v1 architecture: FactoryV1 orchestrates the sub-factories, distributor and hooks
FactoryV1Single entry point. Orchestrates token creation, pool creation and distribution setup; injects the protocol fee and optional buy-back-and-burn shares.
TokenV1Minimal ERC20 (OpenZeppelin) that mints fixed initial allocations at construction.
TokenV1FactoryDeploys TokenV1 instances and records who requested each one.
DistributorV1The epoch engine: participation, pro-rata rewards, claiming, drain hooks, allowlists.
DistributionV1FactoryDeploys 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.

TokenV1.sol
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:

TokenV1Factory.sol — createToken() (trimmed)
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:

DistributorV1.sol — DistributorConfig
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:

DistributionV1Factory.sol — createDistributor()
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:

  1. Deploys the new token with its allocations.
  2. Creates the Uniswap V3 pool at the chosen price and adds liquidity — LP tokens are sent to the dead address, locking liquidity forever.
  3. Injects the buy-back-and-burn share if requested.
  4. Deploys the distributor and funds it with the full distribution amount of the new token.
FactoryV1.sol — createLiquidityAndDistribution() (trimmed)
createPoolAndAddLiquidity(
    _config.participationToken, _config.distributionToken, _sqrtPriceX96,
    _participationTokenAmountDesired, _distributionTokenAmountDesired,
    _amount0Min, _amount1Min, true, _participationPermit2, _distributionPermit2
);

_injectBuyAndBurnShare(_config, _buyBackAndBurnShareBps);

distributorAddress = createDistributor(_config, true);
Supporting pieces: 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.