Simple DAO Voting DApp
✅ What is a DAO Voting DApp?
A DAO Voting DApp lets users:
Propose ideas or actions (e.g., “Change logo”, “Fund Project A”)
Vote on proposals
Automatically execute or store results based on the vote outcome
🧱 Tech Stack
Smart Contracts: Solidity
Blockchain Development Framework: Hardhat
Frontend: React.js
Web3 Interaction: Ethers.js
Wallet: MetaMask
🧠 Features of the DApp
Create Proposals (e.g., "Add feature X")
View Proposals
Vote: “Yes” or “No”
See voting results
Only members (e.g., token holders) can vote
🔨 Smart Contract (Solidity Example)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract SimpleDAO {
struct Proposal {
string description;
uint voteYes;
uint voteNo;
bool executed;
}
address public owner;
mapping(address => bool) public members;
Proposal[] public proposals;
modifier onlyOwner() {
require(msg.sender == owner, "Not the owner");
_;
}
modifier onlyMembers() {
require(members[msg.sender], "Not a DAO member");
_;
}
constructor() {
owner = msg.sender;
members[msg.sender] = true;
}
function addMember(address _member) public onlyOwner {
members[_member] = true;
}
function createProposal(string calldata _desc) public onlyMembers {
proposals.push(Proposal(_desc, 0, 0, false));
}
function vote(uint _proposalId, bool _support) public onlyMembers {
Proposal storage proposal = proposals[_proposalId];
require(!proposal.executed, "Already executed");
if (_support) {
proposal.voteYes += 1;
} else {
proposal.voteNo += 1;
}
}
function executeProposal(uint _proposalId) public onlyOwner {
Proposal storage proposal = proposals[_proposalId];
require(!proposal.executed, "Already executed");
proposal.executed = true;
// You could add logic here like fund transfer, etc.
}
function getProposalsCount() public view returns (uint) {
return proposals.length;
}
function getProposal(uint _id) public view returns (string memory, uint, uint, bool) {
Proposal memory p = proposals[_id];
return (p.description, p.voteYes, p.voteNo, p.executed);
}
}
🖥️ Frontend (React + Ethers.js Overview)
Connect to MetaMask
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
Read Proposals
const daoContract = new ethers.Contract(contractAddress, abi, signer);
const proposal = await daoContract.getProposal(0);
Vote on a Proposal
await daoContract.vote(0, true); // true = yes
🧪 Testing (Hardhat)
describe("SimpleDAO", function () {
it("Should allow members to create and vote on proposals", async function () {
const [owner, member1] = await ethers.getSigners();
const DAO = await ethers.getContractFactory("SimpleDAO");
const dao = await DAO.deploy();
await dao.addMember(member1.address);
await dao.connect(member1).createProposal("Test proposal");
await dao.connect(member1).vote(0, true);
const proposal = await dao.getProposal(0);
expect(proposal.voteYes).to.equal(1);
});
});
📦 Optional Improvements
Use ERC-20 tokens for membership
Time-based voting window
Voting power based on token holdings
Add event logging for UI updates
Use IPFS for proposal descriptions (off-chain storage)
📁 Folder Structure
simple-dao/
│
├── contracts/
│ └── SimpleDAO.sol
│
├── frontend/
│ ├── src/
│ ├── App.js
│ └── dao.js (ethers.js setup)
│
├── scripts/
│ └── deploy.js
│
├── test/
│ └── dao-test.js
│
├── hardhat.config.js
└── package.json
✅ Deployment Tips
Deploy smart contract using Hardhat + Alchemy/Infura
Host frontend using Vercel, Netlify, or GitHub Pages
Ensure MetaMask is connected to the correct network
🧠 Final Tip
Keep it simple, clean, and well-documented. Include:
Screenshots of UI
A demo video or live link
GitHub README with setup instructions
Learn Blockchain Course in Hyderabad
Read More
Crypto Portfolio Tracker Using Web3
Decentralized Chat App on IPFS
Comments
Post a Comment