Sitemap

From Democracy to Decentralization: How I Built a Voting DAO with Smart Contracts & React

3 min readAug 2, 2025

--

What if elections were trustless, tamper-proof, and open to everyone with a wallet?
This was the spark that led me to build VoteVerse, a decentralized governance system where every token holder counts.

In this post, I’ll walk you through

  • What a DAO Voting System actually is (in simple terms)
  • How I designed and implemented it (without getting overwhelmed)
  • How smart contracts, quadratic voting, and IPFS work together
  • Real code + deployment tips
  • How you can build your own

Why Build a DAO Voting System?

In traditional systems, voting power often favors the few. Even in web3, most DAOs rely on simple 1-token-1-vote models. But what if we could:

  • Introduce quadratic voting (a fairer system)
  • Prevent sybil attacks
  • Make everything transparent, secure, and decentralized

That’s what VoteVerse was about.

Architecture Overview

Here’s how the system works

Press enter or click to view image in full size

Key Components

1. Governance Token (ERC-20)

A token that represents membership and voting rights.
If you hold it, you can propose and vote.

// Pseudo code
contract GovernanceToken is ERC20 {
constructor() {
_mint(msg.sender, 1000000 * 10 ** 18);
}
}

2. DAO Governance Contract

Handles

  • Proposals: Who can create them
  • Voting: Quadratic style
  • Delegation: If you can’t vote, delegate
function vote(uint proposalId, uint votes) public {
uint cost = sqrt(votes); // quadratic cost
require(balance[msg.sender] >= cost, "Not enough tokens");
...
}

✅ Prevents rich whales from dominating votes.

3. DAO Treasury

A separate smart contract holding tokens or ETH.

Only successful proposals can move funds (with proper governance).

function executeProposal(uint id) external {
require(proposalPassed(id), "Proposal not passed");
treasury.transfer(to, amount);
}

4. IPFS for Proposal Storage

You don’t store text-heavy proposals on-chain (too expensive).

Get Subaskar Sivakumar’s stories in your inbox

Join Medium for free to get updates from this writer.

Instead

  • Upload proposal data (Markdown, JSON) to IPFS
  • Store just the IPFS hash (CID) in the smart contract
// JS Code
const { cid } = await ipfs.add(JSON.stringify({ title: 'New Treasury Rules', description: '...' }));
await contract.createProposal(cid);

👁️ Anyone reading the CID can view the proposal from IPFS.

Frontend: MetaMask + React + Ethers.js

I used

  • React for UI
  • Ethers.js to connect smart contracts
  • MetaMask for wallet authentication
const provider = new ethers.providers.Web3Provider(window.ethereum);
const contract = new ethers.Contract(address, abi, provider.getSigner());

await contract.vote(proposalId, votes);

Users can vote directly from their browser.

Deployment Stack

  • Hardhat: Write/test/deploy smart contracts
  • Chai/Mocha: Unit testing contracts
  • Firebase Hosting: Simple frontend hosting
  • IPFS via Web3.Storage: Decentralized storage

Lessons Learned

What worked

  • Smart contract modularity
  • Clean separation of logic
  • IPFS + CID makes frontend scalable and cheap

What I’d improve

  • Add ZK-proofs for anonymous voting
  • On-chain proposal metadata hashes for better validation
  • DAO roles (admins, executors) for more real-world control

Want to Build Your Own?

Clone the architecture

  • GovernanceToken.sol – Membership
  • DAOContract.sol – Voting logic
  • Treasury.sol – Fund control
  • React + MetaMask for UI
  • IPFS for proposal storage

Final Words

This project wasn’t just about code. It was about rethinking digital governance — letting communities self-govern in a fair, transparent, and tamper-proof way.

“Code is law, but fair code is governance.”

Let’s make democracy programmable.

--

--