Overview
A voting system allows users to cast votes on various proposals. In this guide, we will create a simple voting system using Ethers.js, which will include writing a smart contract for voting, deploying it to the Ethereum blockchain, and building a front-end application to interact with the contract.
1. Setting Up Your Development Environment
First, you need to set up your development environment. You can use tools like Node.js and npm to create a new React application:
npx create-react-app voting-dapp
cd voting-dapp
npm install ethers
2. Writing the Smart Contract
Next, we will write a simple smart contract in Solidity that allows users to create proposals and vote on them:
// contracts/Voting.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Voting {
struct Proposal {
string name;
uint voteCount;
}
mapping(uint => Proposal) public proposals;
mapping(address => bool) public voters;
uint public proposalsCount;
constructor(string[] memory proposalNames) {
for (uint i = 0; i < proposalNames.length; i++) {
proposals[i] = Proposal({
name: proposalNames[i],
voteCount: 0
});
}
proposalsCount = proposalNames.length;
}
function vote(uint proposalIndex) public {
require(!voters[msg.sender], "You have already voted.");
require(proposalIndex < proposalsCount, "Invalid proposal index.");
voters[msg.sender] = true;
proposals[proposalIndex].voteCount++;
}
function getProposal(uint proposalIndex) public view returns (string memory name, uint voteCount) {
require(proposalIndex < proposalsCount, "Invalid proposal index.");
Proposal memory proposal = proposals[proposalIndex];
return (proposal.name, proposal.voteCount);
}
}
3. Deploying the Smart Contract
To deploy the smart contract, you can use a tool like Hardhat. Below is an example of how to deploy the contract:
// scripts/deploy.js
const { ethers } = require("hardhat");
async function main() {
const proposalNames = ["Proposal 1", "Proposal 2", "Proposal 3"];
const Voting = await ethers.getContractFactory("Voting");
const voting = await Voting.deploy(proposalNames);
await voting.deployed();
console.log("Voting contract deployed to:", voting.address);
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
Run the deployment script:
npx hardhat run scripts/deploy.js --network rinkeby
4. Building the Front-End Application
Now that we have our smart contract deployed, we can build a front-end application using React and Ethers.js to interact with the contract. Below is a simple example:
// src/App.js
import React, { useEffect, useState } from 'react';
import { ethers } from 'ethers';
import Voting from './artifacts /Voting.json'; // ABI file
function App() {
const [account, setAccount] = useState(null);
const [provider, setProvider] = useState(null);
const [contract, setContract] = useState(null);
const [proposals, setProposals] = useState([]);
const [selectedProposal, setSelectedProposal] = useState(0);
const [message, setMessage] = useState("");
useEffect(() => {
const connectWallet = async () => {
if (window.ethereum) {
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
setAccount(accounts[0]);
const provider = new ethers.providers.Web3Provider(window.ethereum);
setProvider(provider);
const contractAddress = "DEPLOYED_CONTRACT_ADDRESS"; // Replace with your deployed contract address
const votingContract = new ethers.Contract(contractAddress, Voting.abi, provider);
setContract(votingContract);
await loadProposals(votingContract);
} else {
alert("Please install MetaMask!");
}
};
connectWallet();
}, []);
const loadProposals = async (votingContract) => {
const proposalsCount = await votingContract.proposalsCount();
const proposalsArray = [];
for (let i = 0; i < proposalsCount; i++) {
const proposal = await votingContract.getProposal(i);
proposalsArray.push(proposal);
}
setProposals(proposalsArray);
};
const vote = async () => {
if (contract && account) {
const signer = provider.getSigner();
const contractWithSigner = contract.connect(signer);
const tx = await contractWithSigner.vote(selectedProposal);
await tx.wait();
console.log("Voted for proposal:", selectedProposal);
}
};
return (
Voting DApp
{account ? Connected account: {account}
: }
Proposals
{proposals.map((proposal, index) => (
{proposal.name} - Votes: {proposal.voteCount.toString()}
))}
);
}
export default App;
5. Conclusion
In this guide, we walked through the steps to implement a simple voting system using Ethers.js. We set up our development environment, wrote and deployed a smart contract for voting, and built a front-end application to interact with it. This foundational knowledge will help you create more complex decentralized applications on the Ethereum blockchain.