Skip to content

Commit

Permalink
modified the election contract and its associate test (#54)
Browse files Browse the repository at this point in the history
* modified the election contract and its associate test

* Enabling gasReporter

---------

Co-authored-by: mickeymond <[email protected]>
  • Loading branch information
Ratawine7 and mickeymond authored Sep 20, 2024
1 parent e72db92 commit e9a072f
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 82 deletions.
61 changes: 37 additions & 24 deletions blockchain/contracts/Election.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;
// Custom errors
error ElectionNotStarted();
error ElectionEnded();
error CandidateAlreadyExists();
error AlreadyVoted();
error VoterAlreadyRegistered();
error InvalidCandidateID();

contract Election {
string public title;
Expand All @@ -8,27 +15,23 @@ contract Election {
uint public startDate;
uint public endDate;

// variable for keeping the number of candidates in election, increases when a new candidate is added
uint public candidatesCount;

//defines structure for a candidate
struct Candidate {
uint id;
string name;
uint voteCount;
string team;
string image;
}
// defines structure for a voter
struct Voter {
bool hasVoted;
bool voted;
uint candidateId;
}

//creates mapping to map a unique candidate Id to a Candidate struct
mapping(uint => Candidate) candidates;
// also to tie/map a unique blockchain adresss to a voter
mapping(address => Voter) voters;

// event to be emitted when a voter casts a vote
event VoteCast(address indexed voter, uint indexed candidateId);

constructor(
Expand All @@ -38,30 +41,43 @@ contract Election {
uint _startDate,
uint _endDate
) {
require(_startDate < _endDate, "Start date must be before end date");
if (_startDate >= _endDate) revert ElectionEnded();
title = _title;
description = _description;
isPublic = _isPublic;
startDate = _startDate;
endDate = _endDate;
}

// Modifier to ensure the election is active
modifier onlyWhileOpen() {
require(block.timestamp >= startDate, "Election has not started yet");
require(block.timestamp <= endDate, "Election has ended");
if (block.timestamp < startDate) revert ElectionNotStarted();
if (block.timestamp > endDate) revert ElectionEnded();
_;
}

// function to create a new candidate
function addCandidate(string memory _name) public onlyWhileOpen {
// increamented to assign a new id to a candidate
function addCandidate(
string memory _name,
string memory _team,
string memory _image
) public onlyWhileOpen {
for (uint i = 1; i <= candidatesCount; i++) {
if (
keccak256(abi.encodePacked(candidates[i].name)) ==
keccak256(abi.encodePacked(_name))
) {
revert CandidateAlreadyExists();
}
}
candidatesCount++;
// a new candidate struct is created and stored in the candiates mapping
candidates[candidatesCount] = Candidate(candidatesCount, _name, 0);
candidates[candidatesCount] = Candidate(
candidatesCount,
_name,
0,
_team,
_image
);
}

//function to get all candidates
function getCandidates() public view returns (Candidate[] memory) {
Candidate[] memory allCandidates = new Candidate[](candidatesCount);
for (uint i = 1; i <= candidatesCount; i++) {
Expand All @@ -70,27 +86,24 @@ contract Election {
return allCandidates;
}

// Function to add a voter to the election
function addVoter(address _voterAddress) public onlyWhileOpen {
require(!voters[_voterAddress].hasVoted, "Voter is already registered");
require(!voters[_voterAddress].voted, "Voter is already registered");
voters[_voterAddress] = Voter(false, 0);
}

//function to get a voter by their Address
function getVoter(address _voterAddress) public view returns (bool, uint) {
Voter memory voter = voters[_voterAddress];
return (voter.hasVoted, voter.candidateId);
return (voter.voted, voter.candidateId);
}

//function to cast a vote
function castVote(uint _candidateId) public onlyWhileOpen {
require(!voters[msg.sender].hasVoted, "You have already voted.");
require(!voters[msg.sender].voted, "You have already voted.");
require(
_candidateId > 0 && _candidateId <= candidatesCount,
"Invalid candidate. Please enter a valid candidate ID"
);

voters[msg.sender].hasVoted = true;
voters[msg.sender].voted = true;
voters[msg.sender].candidateId = _candidateId;

candidates[_candidateId].voteCount++;
Expand Down
3 changes: 3 additions & 0 deletions blockchain/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import "dotenv/config";

const config: HardhatUserConfig = {
solidity: "0.8.24",
gasReporter: {
enabled: true
},
networks: {
sepolia_testnet: {
url: `https://ethereum-sepolia-rpc.publicnode.com`,
Expand Down
Loading

0 comments on commit e9a072f

Please sign in to comment.