Protocol Architecture

LP24 consists of six smart contracts that work together to manage the full token lifecycle. All contracts are written in Vyper 0.4.3 and deployed as minimal proxies (EIP-1167) where applicable.

Contract Overview

ContractPatternRole
Factory_v2SingletonEntry point. Deploys token + bonding curve pairs via CREATE2 with vanity address enforcement.
TokenTemplateMinimal ProxyERC-20 token with minter-only mint/burn, trading lock until graduation, and 9-decimal precision.
BondingCurveTemplateMinimal ProxyManages bonding curve trading, price calculation, graduation trigger, and refund system.
LiquidityGenHookSingleton (Uniswap V4 Hook)All-in-one post-graduation manager: fee collection, LP management, fee distribution, reinvestment, CTO voting.
CTOVoteTemplateMinimal ProxyCommunity Takeover voting logic. Cloned per-vote by the Hook.
TokenSocialsSingletonOn-chain registry for token metadata (socials). Packed bytes32 storage.

Interaction Flow

The contracts interact in a specific sequence during the token lifecycle:

Deployment

User → Factory.deploy_pair(name, symbol, salt, packed_socials)
         ├─→ create_minimal_proxy_to(token_master, salt)    → TokenTemplate clone
         ├─→ create_minimal_proxy_to(bonding_curve_master)  → BondingCurve clone
         ├─→ TokenTemplate.initialize(name, symbol, curve)
         ├─→ BondingCurve.initialize(token)  {value: deployment_fee}
         └─→ TokenSocials.register_token(token, deployer, packed_socials)

Buy on Bonding Curve

User → BondingCurve.buy(token_lots)  {value: total_price}
         ├─→ TokenTemplate.balanceOf(user)        // check user limit
         ├─→ _calculate_price(supply, lots, true)  // quadratic pricing
         ├─→ TokenTemplate.mint(user, lots * LOT_SIZE)
         └─→ if supply == MAX_SUPPLY_LOTS:
              └─→ _graduate()
                   ├─→ raw_call(deployer, fees * 90%)
                   ├─→ TokenTemplate.mint(HOOK, 400M tokens)
                   ├─→ TokenTemplate.enableTrading()
                   └─→ Hook.createPositionAndRegister(token, deployer)

Graduation (inside Hook)

BondingCurve → Hook.createPositionAndRegister(token, deployer)  {value: ETH}
                ├─→ IERC20(token).approve(PERMIT2, MAX)
                ├─→ IAllowanceTransfer.approve(token, POSITION_MANAGER, MAX)
                ├─→ PositionManager.multicall([initializePool, modifyLiquidities])
                ├─→ platformBalance += excess ETH
                └─→ tokenInfo[token] = {deployer, positionId}

Post-Graduation Swap (via Uniswap V4)

User → UniversalRouter.execute(swap)
         └─→ PoolManager calls Hook:
              ├─→ beforeSwap()  // Tax buys: take ETH fee from PoolManager
              └─→ afterSwap()   // Tax sells: take ETH fee from PoolManager
              // Fees accumulate in pendingFees[token]

Design Principles

No Admin Keys

The protocol is fully permissionless. There is no owner, no admin, no multisig, and no upgrade path. Once deployed, the contracts are immutable. The only privileged role is "deployer" which receives fee shares — and even that can be transferred via CTO vote.

Gas Optimization

The contracts are heavily gas-optimized. Key techniques include:

  • No per-user storage on the bonding curve (saves ~17k gas on first buy per user)
  • Token balance checked via balanceOf() instead of internal mapping
  • Transient storage (EIP-1153) for the internal swap flag on the Hook
  • Standalone pendingFees mapping instead of struct field (saves ~200 gas/swap)
  • Cached fee tiers with lazy computation

Minimal Proxy Pattern

Tokens, bonding curves, and CTO vote contracts are deployed as EIP-1167 minimal proxies. This means each new deployment is a tiny bytecode stub that delegates all calls to a shared implementation contract. Deployment cost is ~45k gas instead of ~2M gas for a full contract.