Production-ready bootstrap for building on DonutDAO infrastructure
Fork this template to instantly access DonutDAO's core contracts, pre-configured for Base L2 with all the ecosystem primitives you need.
This template includes ready-to-use DonutDAO contracts:
- DONUT Token - Ecosystem currency
- gDONUT - Governance token (staked DONUT)
- LiquidSignal - Revenue routing governed by gDONUT holders
- Franchise - Aligned token launches
- DonutMiner - Gamified auction mining
- Farplace Rigs - Fair token distribution (MineRig, SpinRig, FundRig)
Plus full integration examples and deployment scripts for Base mainnet.
Instead of integrating manually:
- β All DonutDAO contracts already imported
- β Base L2 configuration ready
- β DONUT token integration examples
- β LiquidSignal revenue routing setup
- β Farplace rig deployment scripts
- β Testing suite with DonutDAO mocks
Built on proven stack:
- Scaffold-ETH 2 (by @austingriffith)
- Base L2 (fast + cheap)
- IPFS + ENS + Limo (decentralized hosting)
- Proven by @clawdbotatg (7 dApps overnight)
# Fork on GitHub, then:
git clone https://github.com/YOUR_USERNAME/your-donut-app.git
cd your-donut-app
yarn installcp .env.example .env
# Add your deployment key and RPC URLs# Test locally first
yarn chain # Terminal 1
yarn deploy # Terminal 2
yarn start # Terminal 3
# Deploy to Base mainnet
yarn deploy --network baseUse LiquidSignal to route fees to gDONUT holders:
import "@donutdao/contracts/LiquidSignal.sol";
contract MyApp {
LiquidSignal public liquidSignal;
function collectFees() external payable {
// Route 50% to LiquidSignal, 50% to team
uint256 toSignal = msg.value / 2;
liquidSignal.deposit{value: toSignal}();
}
}Fair distribution using DonutDAO's proven mechanics:
import "@donutdao/contracts/rigs/MineCore.sol";
contract MyLaunch {
function launchToken(uint256 donutAmount) external {
MineCore mineCore = MineCore(MINE_CORE_ADDRESS);
// Launch with fair mining distribution
mineCore.launch{value: donutAmount}(params);
}
}Accept DONUT as payment:
import "@donutdao/contracts/DONUT.sol";
contract Marketplace {
IERC20 public donut;
function buyItem(uint256 itemId, uint256 amount) external {
donut.transferFrom(msg.sender, address(this), amount);
// Deliver item
}
}Let gDONUT holders vote on your protocol:
import "@donutdao/contracts/gDONUT.sol";
contract MyDAO {
function propose(string description) external {
require(gDONUT.balanceOf(msg.sender) >= MIN_PROPOSAL_TOKENS);
// Create proposal
}
function vote(uint256 proposalId, bool support) external {
uint256 votes = gDONUT.balanceOf(msg.sender);
// Cast weighted vote
}
}All contracts deployed on Base mainnet:
- DONUT:
0x...(Ecosystem token) - gDONUT:
0x...(Governance token)
- LiquidSignal:
0x...(Revenue routing) - Franchise:
0x...(Token launches) - DonutMiner:
0x...(Auction mining)
- MineCore:
0x504d4f579b5e16dB130d1ABd8579BA03087AE1b1 - SpinCore:
0x2E392a607F94325871C74Ee9b9F5FBD44CcB5631 - FundCore:
0x85f3e3135329272820ADC27F2561241f4b4e90db
See contracts/addresses.json for complete list
donutdao-app-template/
βββ packages/
β βββ foundry/
β β βββ contracts/
β β β βββ YourContract.sol # Your custom logic
β β β βββ examples/ # DonutDAO integration examples
β β β βββ RevenueSharing.sol
β β β βββ DONUTMarketplace.sol
β β β βββ FarplaceLauncher.sol
β β βββ test/
β β βββ YourContract.t.sol
β β βββ integration/ # Integration tests
β β
β βββ nextjs/
β βββ app/ # Your frontend
β βββ components/
β β βββ donutdao/ # DonutDAO UI components
β β βββ DONUTBalance.tsx
β β βββ LiquidSignalStats.tsx
β β βββ FarplaceRig.tsx
β βββ hooks/
β βββ useDonutDAO.ts # Custom hooks
β
βββ contracts/ # DonutDAO contract ABIs
β βββ addresses.json # Contract addresses
β βββ interfaces/ # TypeScript interfaces
β
βββ scripts/
βββ deploy-with-liquidSignal.ts
βββ launch-via-farplace.ts
Complete example in packages/foundry/contracts/examples/RevenueSharing.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@donutdao/contracts/LiquidSignal.sol";
contract RevenueSharing {
LiquidSignal public immutable liquidSignal;
address public immutable team;
uint256 public constant SIGNAL_SHARE = 50; // 50%
constructor(address _liquidSignal, address _team) {
liquidSignal = LiquidSignal(_liquidSignal);
team = _team;
}
// Users pay for service
function useService() external payable {
require(msg.value >= 0.01 ether, "Minimum fee");
// Split: 50% to LiquidSignal, 50% to team
uint256 toSignal = (msg.value * SIGNAL_SHARE) / 100;
uint256 toTeam = msg.value - toSignal;
// Route to gDONUT holders
liquidSignal.deposit{value: toSignal}();
// Send to team
(bool success, ) = team.call{value: toTeam}("");
require(success, "Transfer failed");
}
}Frontend integration (packages/nextjs/components/RevenueStats.tsx):
import { useDonutDAO } from "@/hooks/useDonutDAO";
export function RevenueStats() {
const { liquidSignalTVL, userShare } = useDonutDAO();
return (
<div>
<p>Total in LiquidSignal: {liquidSignalTVL} DONUT</p>
<p>Your share: {userShare}%</p>
</div>
);
}Test against real DonutDAO contracts:
// packages/foundry/test/integration/LiquidSignalIntegration.t.sol
import "forge-std/Test.sol";
import "../../contracts/examples/RevenueSharing.sol";
contract LiquidSignalIntegrationTest is Test {
RevenueSharing public app;
address constant LIQUID_SIGNAL = 0x...; // Base mainnet
function setUp() public {
// Fork Base mainnet
vm.createSelectFork(vm.rpcUrl("base"));
app = new RevenueSharing(LIQUID_SIGNAL, address(this));
}
function testRevenueRouting() public {
// Test against real LiquidSignal contract
app.useService{value: 1 ether}();
// Verify routing worked
}
}import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
IERC20 donut = IERC20(DONUT_ADDRESS);
donut.transferFrom(payer, recipient, amount);import "@donutdao/contracts/gDONUT.sol";
gDONUT.stake(donutAmount);
uint256 govPower = gDONUT.balanceOf(msg.sender);LiquidSignal(LIQUID_SIGNAL_ADDRESS).deposit{value: feeAmount}();MineCore(MINE_CORE_ADDRESS).launch(
donutSeed,
emissionRate,
halvingSchedule
);- Customize your contract logic
- Write tests (including DonutDAO integration tests)
- Test on Base Sepolia testnet
- Get DONUT for testing (faucet or swap)
- Deploy to Base mainnet
- Verify contracts on Basescan
- Deploy frontend to IPFS
- Register ENS name
- Announce on DonutDAO Discord
- DonutDAO Discord: https://discord.gg/donutdao
- X/Twitter: @donutdao
- GitHub: github.com/donutdao
Help improve the template:
- Fork this repo
- Add useful examples
- Improve documentation
- Submit PR
Ideas for contributions:
- More integration examples
- UI components for DonutDAO contracts
- Testing utilities
- Deployment scripts
- Documentation improvements
Questions? Issues?
- Template bugs: https://github.com/cruller-agent/donutdao-app-template/issues
- DonutDAO help: Discord #dev-support
- General agent help: @cruller_donut on X
MIT - Fork, build, ship!
Template created by: @cruller_donut
For: DonutDAO ecosystem builders
Based on: Agent App Template
Powered by: Scaffold-ETH 2 + Base + IPFS
Build the agentic internet. π©βοΈ
Tier 1: Low-Risk (< $10k TVL)
- Run all tests:
yarn foundry:test - Static analysis:
slither . - Test DonutDAO integrations on testnet
- Add disclaimer from
SECURITY_DISCLAIMER.md(Tier 1) - Deploy with small DONUT amounts only
Tier 2: Medium-Risk ($10k-$100k TVL)
- All Tier 1 steps +
- DonutDAO community review (Discord #dev-review)
- 2+ developer reviews
- Test LiquidSignal integration thoroughly
- Bug bounty program
- Add Tier 2 disclaimer
Tier 3: High-Risk (> $100k TVL)
- All Tier 2 steps +
- Professional security audit required
- Bug bounty via Immunefi/Code4rena
- Multi-sig controls (consider gDONUT governance)
- Emergency pause mechanism
- Gradual rollout plan
- Add Tier 3 disclaimer
When integrating with DonutDAO contracts:
β
Verify contract addresses - Check contracts/addresses.json
β
Test on Base Sepolia first - Use testnet deployments
β
Start with small DONUT amounts - Test revenue routing
β
Monitor LiquidSignal deposits - Verify fees route correctly
β
Community review recommended - Post in DonutDAO Discord
Example: Testing LiquidSignal Integration
// In your tests
function testLiquidSignalIntegration() public {
// Fork Base mainnet
vm.createSelectFork(vm.rpcUrl("base"));
// Test against real LiquidSignal
uint256 balanceBefore = address(LIQUID_SIGNAL).balance;
app.collectFees{value: 1 ether}();
uint256 balanceAfter = address(LIQUID_SIGNAL).balance;
assertEq(balanceAfter - balanceBefore, 0.5 ether);
}Free tools you should use:
# Static analysis
slither packages/foundry/contracts/
# Test all integrations
forge test --match-path test/integration/*
# Fuzz test revenue routing
forge test --fuzz-runs 10000See SECURITY_DISCLAIMER.md for:
- Disclaimer templates (Tier 1/2/3)
- Pre-deployment checklist
- Community review process
- Emergency response plan
Post in Discord #dev-review:
π REVIEW REQUEST - DonutDAO Integration
Contract: [Name]
Purpose: [e.g., Route fees to LiquidSignal]
Testnet: base-sepolia:0x...
GitHub: [link]
DonutDAO contracts used:
- LiquidSignal β
- DONUT token β
- [others]
Looking for review of:
- Integration correctness
- Security issues
- Gas optimization
Bounty: [X DONUT] for critical findings
Based on @clawdbotatg and @0xDeployer research:
Common approach:
β οΈ Clear disclaimers- π§ͺ Extensive testing
- π₯ Community review
- π Iterate quickly
- π οΈ Use security tools
Bankr's approach:
- Blockaid integration (malicious contract detection)
- Security Module (10% of $BNKR staked to vouch)
- Real-time validation
Transparency > Perfection
See ../AGENT_AUDITING_PRACTICES.md for complete research.