Public Goods Liquidity Engine
transforms idle capital to investment
Created on 9th November 2025
•
Public Goods Liquidity Engine
transforms idle capital to investment
The problem Public Goods Liquidity Engine solves
The Public Goods Liquidity Engine solves three critical problems in the public goods funding ecosystem:
1. Unsustainable Funding Models
Traditional public goods funding relies on one-time donations or grants that eventually deplete. Our solution creates perpetual funding - as long as deposits remain in the vault, public goods receive continuous yield. Users keep 100% of their principal and can withdraw anytime, while 100% of generated yield flows to public goods projects.
2. Centralized Allocation Decisions
Grant committees and DAOs often make allocation decisions that favor large stakeholders or insiders. Our quadratic funding mechanism democratizes this process - small contributors' votes are amplified through the quadratic formula (sqrt(votes) × unique voters), ensuring that community consensus matters more than capital size.
3. Capital Inefficiency in Public Goods Support
People want to support public goods but don't want to permanently lose their capital. Our solution makes it risk-free to support public goods - deposit your DAI, it generates yield through battle-tested protocols (Aave v3 + Spark), and you can withdraw your principal anytime. The yield you would have earned goes to public goods instead.
What People Can Use It For:
For Individual Users:
- Passive Impact: Turn idle stablecoins into public goods funding without losing principal
- Democratic Voice: Vote on which projects receive funding using your pgDAI balance
- No Lock-ups: Withdraw your deposit anytime with no penalties
- Portfolio Diversification: Benefit from dual-protocol risk management (Aave + Spark)
For Public Goods Projects:
- Sustainable Revenue: Receive ongoing funding stream from harvested yield
- No Grant Applications: Get discovered and funded through community votes
- Instant Liquidity: Redeem pgDAI shares immediately when distributed
- Transparent Allocation: See exactly how funds are calculated via quadratic funding
For DAOs & Communities:
- Treasury Yield Donation: Deploy idle treasury assets to support ecosystem
- Democratic Funding: Let community decide allocation through quadratic voting
- Measurable Impact: Track all deposits, yields, and distributions on-chain
- Composable Integration: ERC-4626 standard enables DeFi integrations
How It Makes Things Easier/Safer:
✅ Easier than Traditional Donations: No permanent capital loss - deposit and withdraw freely
✅ Safer than Single Protocol: Dual-strategy diversification across Aave v3 and Spark
✅ Easier Allocation: No grant committees - community votes determine distribution
✅ Safer than New Protocols: Built on battle-tested, audited protocols (Aave, Spark, OpenZeppelin)
✅ Easier Discovery: Projects registered on-chain are visible to all voters
✅ Safer Governance: Quadratic funding prevents whale manipulation of allocation
Real-World Use Cases:
- DeFi Protocol Treasury: Deploy 10M DAI → Earn ~$400K/year yield → Fund 20+ public goods projects
- Individual Crypto Holder: Deposit $50K stables → Generate $2K/year for public goods → Withdraw principal anytime
- Public Goods Project: Register once → Receive recurring funding from community votes → Redeem shares instantly
- DAO Community: Vote with governance tokens (pgDAI) → Allocate harvested yield → Transparent on-chain results
Challenges I ran into
1. Yield Strategy Integration Complexity
Challenge: Integrating with both Aave v3 and Spark Protocol simultaneously required understanding different interfaces - Aave uses direct lending pools while Spark uses the sDAI wrapper. The strategies needed to handle deposits, withdrawals, and yield harvesting differently for each protocol.
Solution:
- Created abstracted
IYieldStrategy
interface with standardizeddeposit()
,withdraw()
, andharvest()
methods - Implemented protocol-specific logic in separate
AaveStrategy
andSparkStrategy
contracts - Built
YieldAggregator
to manage allocation and coordinate between strategies - Used extensive testing (33 tests) to verify each strategy independently and together
Code Example:
interface IYieldStrategy { function deposit(uint256 amount) external; function withdraw(uint256 amount) external; function harvest() external returns (uint256 yield); function totalAssets() external view returns (uint256); }
2. Quadratic Funding Score Calculation
Challenge: Implementing the quadratic funding formula on-chain was tricky - needed to calculate square roots efficiently without floating-point math, handle edge cases (0 votes, 0 voters), and prevent overflow/underflow issues.
Solution:
- Implemented Babylonian square root algorithm in Solidity for gas efficiency
- Added comprehensive edge case handling (checks for 0 values)
- Used two-pass distribution: first calculate all scores, then proportionally distribute
- Stored intermediate values to avoid recalculation
- Tested with multiple voting scenarios to verify fairness
Code Implementation:
// Babylonian method for square root function sqrt(uint256 x) internal pure returns (uint256) { if (x == 0) return 0; uint256 z = (x + 1) / 2; uint256 y = x; while (z < y) { y = z; z = (x / z + z) / 2; } return y; } // Quadratic funding score quadraticScores[i] = sqrt(projects[i].totalVotes) * projects[i].uniqueVoters;
3. ERC-4626 Vault Share Calculation
Challenge: When yield is donated to the splitter, it shouldn't dilute existing depositors' shares. The vault needed to track yield separately and convert it to shares for the splitter without affecting the share price for regular depositors.
Solution:
- Separated yield harvesting from user deposits/withdrawals
- When harvesting, mint new pgDAI shares directly to splitter based on yield amount
- Used
convertToShares()
to calculate correct share amounts - Maintained 1:1 principal-to-share ratio for depositors through careful accounting
- Added extensive tests for share price stability
Key Insight: Yield is deposited as new DAI, converted to shares, and those shares go to splitter - regular users' shares remain unaffected.
4. Tenderly Fork Deployment & Configuration
Challenge: Initial deployment on Tenderly fork failed due to constructor parameter mismatches, address ordering issues, and configuration verification problems. Contracts deployed but weren't properly connected.
Solution:
- Created comprehensive deployment script (
DeployTenderly.s.sol
) with step-by-step execution - Added validation checks after each deployment step
- Implemented
verify-deployment.sh
script to confirm all connections - Used
cast
commands to verify state on-chain - Documented deployment addresses and configuration in
TENDERLY_DEPLOYMENT.md
Lessons Learned:
- Always verify deployment order (dependencies first)
- Check contract connections immediately after deployment
- Use verification scripts to catch configuration issues early
- Document everything for reproducibility
Key Takeaways:
✅ Modular architecture made complex integrations manageable
✅ Comprehensive testing caught edge cases early
✅ Clear documentation explains both implementation and usage
✅ Gas-efficient patterns from established libraries (OpenZeppelin)
✅ Iterative deployment with verification at each step prevented major issues
Tracks Applied (5)
Best use of a Yield Donating Strategy
Most creative use of Octant v2 for public goods
Best public goods projects
Best use of Aave v3 (Aave Vaults)
Best use of Spark
Technologies used
Cheer Project
Cheering for a project means supporting a project you like with as little as 0.0025 ETH. Right now, you can Cheer using ETH on Arbitrum, Optimism and Base.