This project is a complete university-style DAO governance system for Blockchain Technologies 2
Assignment 4. It uses Solidity, Hardhat, OpenZeppelin Governor, TimelockController, an
ERC20Votes token, a treasury contract, a controlled Box contract, tests, deployment scripts,
and a minimal HTML/CSS/JavaScript frontend.
- Governance token with
ERC20VotesandERC20Permit - Linear vesting contract for team tokens
- Governor + Timelock governance flow
- Treasury owned by the timelock
- Controlled
Boxcontract for demo proposals - Minimal frontend for wallet connection, delegation, proposal lookup, and voting
- Documentation for deployment, monitoring, security, and theory
contracts/
docs/
frontend/
scripts/
test/
hardhat.config.js
package.json
README.md
- ERC-20 governance token
- Supports vote delegation through
ERC20Votes - Supports gasless approvals through
ERC20Permit - Total supply is minted once during deployment
- Holds the 40% team allocation
- Releases tokens linearly over 12 months
- Calculates releasable tokens based on time passed
- OpenZeppelin Governor implementation
- Voting delay: 7200 blocks
- Voting period: 50400 blocks
- Proposal threshold: 1% of total supply
- Quorum: 4% of total supply
- Holds ERC-20 tokens and ETH
- Only the timelock owner can move funds or change treasury settings
- Emits clear events for transfers and parameter changes
- Simple controlled contract
- Owned by the timelock
- Used to demonstrate a governance call like
store(42)
- 40% team allocation ->
TokenVesting - 30% treasury allocation ->
Treasury - 20% community allocation -> community wallet
- 10% liquidity allocation -> liquidity wallet
See token-distribution-diagram.md for the diagram.
npm installCopy .env.example to .env and fill in the real values if you want to deploy to Sepolia.
Required for testnet deployment:
RPC_URLPRIVATE_KEYETHERSCAN_API_KEYTEAM_BENEFICIARYCOMMUNITY_AIRDROP_RECEIVERLIQUIDITY_RECEIVER
npx hardhat compileOr with npm:
npm run compilenpx hardhat testOr with npm:
npm testStart a local Hardhat node:
npx hardhat nodeIn another terminal, deploy:
npm run deploy:localCheck timelock roles and ownership:
npm run roles:localAfter filling .env:
npm run deploy:testnetServe the frontend:
npm run frontendThen open:
http://127.0.0.1:8080
Important:
- The frontend reads
frontend/contracts.json - That file is updated automatically by
scripts/deploy.js - MetaMask must be connected to the same chain where you deployed the contracts
npm run compilenpm testnpm run deploy:localnpm run deploy:testnetnpm run roles:localnpm run frontend
- token deployment
- total supply
- token distribution
- delegation
- vote snapshots
- permit signatures
- vesting before release
- partial vesting after time passes
- full vesting after 12 months
- propose -> vote -> queue -> execute
- treasury transfer proposal
- parameter change proposal
- delegatee voting on behalf of delegator
- quorum failure
- defeated proposal
- full Box.store(42) end-to-end flow
- security-audit-report.md
- deployment-checklist.md
- monitoring-plan.md
- governance-research.md
- demo-script.md
- proposal-lifecycle-log.md
- Successful compile
- Passing tests
- Deployed contract addresses
- Token delegation transaction
- Proposal creation
- Voting transaction
- Queue transaction
- Execute transaction
Box.retrieve()returns42- Treasury transfer proposal
- Frontend wallet connected
- Frontend voting power
- Frontend delegation
- Frontend vote transaction proof
- Slither output
- Compile the contracts
- Run the tests
- Start a local node
- Deploy the contracts locally
- Open the frontend
- Delegate votes
- Create and execute proposals
- Capture screenshots as you go
- Update
.envbefore Sepolia deployment - Replace placeholder wallet addresses in
.env - Install Slither separately if you want the static analysis output
- Etherscan verification requires a real
ETHERSCAN_API_KEY - The frontend contract addresses must match the network currently selected in MetaMask