
Octapad
Launpad automatically fund public goods forever
About
The problem it solves **The Problem It Solves** Fundraising is broken for early-stage projects. OctaPad fixes this. Right now, if you want to launch a token, you have two bad options: Traditional launchpads take massive fees (5-10%), lock your liquidity for months, and give you zero yield on deposited funds. Your community's money just sits there, doing nothing. Fair launches sound great in theory, but they're a race to the bottom. No vesting, no protection, just pure chaos where bots win and real supporters get dumped on. **My Solution** OctaPad is a token launchpad integrated with Octant's YieldDonating Strategy to create a regenerative funding model where platform fees automatically generate yield for public goods. Every campaign launched on OctaPad contributes capital to a yield-generating strategy, creating a sustainable revenue stream that benefits both the ecosystem and campaign participants. **OctaPad is different** It's regenerative fundraising. Here's what makes it special: **For Project Creators** - Launch token and raise funds with USDC (bonding curve pricing). (All platform launch fee goes to the yield donation strategy) - Sponsor a campaign to get featured, attract more buyers, and get visibility. (All sponsorship fees are sent to the yield donation strategy to generate yield) - Instant liquidity is deployed to Uniswap v4 pools and ready for instant trading when desired funding is met. (50% of all trading fees are contributed to the yield donation strategy using Uniswap v4 afterSwap () hook) - Part of the creator's raised funds share is vested and deposited into my yield donation strategy to generate yield; 3-month linear vesting protects you from rug pulls **For Contributors** - Contribute USDC, get project tokens at a fair price - Earn OG Tokens just for participating (non-transferable loyalty points/tokens) - 50% of all reported yield goes to OG Points/token holders - forever - The remaining 50% is donated to public goods. - The more campaigns you support, the more you rack up og tokens, the more yield share you get - No lockups - your tokens are liquid immediately via DEX - You keep earning even after the campaign ends **The Regenerative Loop** This is where it gets beautiful. Every campaign creates a flywheel: - Project raises funds in USDC - All platform fees (launch fees, sponsorship fees, vested creator funds, and trading fees) in USDC go to the strategy vault → earns Yield - Yield is split: 50% to the public goods address, 50% to OG Points holders via payment splitter contract. Principal stays intact. Every campaign launched on Octopad contributes capital to the yield-donating strategy, creating a sustainable revenue stream that benefits both the ecosystem and campaign participants. The more the ecosystem grows, the more early supporters earn This is regenerative finance in action. Your early support compounds over time. The protocol doesn't extract value - it distributes it back to the community that built it. **Why This Matters** Current launchpads are extractive. They take fees and provide no ongoing value. OctaPad is regenerative - it creates a sustainable ecosystem where: Projects get fair fundraising + yield on deposits Early supporters earn ongoing rewards Liquidity stays healthy via Uniswap v4 Everyone benefits from ecosystem growth
How it's made
Challenges we ran into **The circular dependency nightmare. ** About halfway through building this, I hit a wall that made me question my architecture entirely. Here's what happened: I needed to deploy two contracts that both needed each other's addresses: - PaymentSplitter requires the OGPointsRewards address (and the payee list is immutable). - OGPointsRewards needed PaymentSplitter address Same problem with VestingManager and OctaPad. They form a circular dependency loop. My first instinct was "just use CREATE2 to predict addresses" - but that felt hacky and error-prone. What if I miscalculate? What if the constructor changes? One wrong byte and everything breaks. The breakthrough came from understanding mutability. I realized: not all dependencies are equal. Some are set in stone (immutable), others can be updated (mutable). For PaymentSplitter ↔ OGPointsRewards: - PaymentSplitter.payees is immutable (security feature - can't change who gets paid) - OGPointsRewards.paymentSplitter is mutable (has updatePaymentSplitter()) Solution: Deploy with a placeholder, then update. 1. Deploy OGPointsRewards with placeholder address (0x0...001) 2. Deploy PaymentSplitter with real OGPointsRewards address 3. Call ogPointsRewards.updatePaymentSplitter(realAddress) **The proxy pattern surprise. ** I spent 2 hours debugging InvalidInitialization() errors when deploying PaymentSplitter. The contract would deploy, but calling initialize() would fail every time. Turns out, PaymentSplitter uses the ERC1967 proxy pattern: - The implementation has _disableInitializers() in the constructor - I'm supposed to deploy a proxy that points to the implementation - The proxy gets initialized, not the implementation I was trying to deploy it directly like a normal contract. Classic mistake. Fix: Deploy in two steps: - Deploy implementation: PaymentSplitter implementation = new PaymentSplitter() - Deploy proxy with initialization: ERC1967Proxy(implementation, initData) This actually made the contract more gas-efficient and upgradeable, so the struggle was worth it. PROOF THAT IT WORKS **Before _harvestAndReport()** Screenshot 2025-11-09 at 3.56.19 PM **After _harvestAndReport()** Screenshot 2025-11-09 at 3.57.38 PM