Article directory
Introduction to voting needs
The following contracts are somewhat complex, but show many of the language features of Solidity. It implements a voting contract. Of course, the main problem of electronic voting is how to allocate voting rights to the right people and how to prevent manipulation. We won't solve all the problems here, but at least we will show how to vote by proxy, and at the same time, the counting is automatic and completely transparent.
Our idea is to create a contract for each vote and provide a short name for each option. Then as the creator of the contract, the chairman, will give each individual address a vote.
The person following the address can choose to vote by themselves or delegate to someone they trust, and at the end of the voting time, winningProposal() will return the proposal with the most votes.
Voting initialization
contract VoteDemo{ // Create voter structure (once cast) struct Voter{ address addr; // Address of voter bool vote; // Store status of votes uint amount; // The default weight is 1 } // Create a candidate's structure struct Candidate{ address addr; // Candidate address uint get; // Votes received bool win; // Does the candidate win } // Mapping to store multiple voters and candidates mapping (address => Voter) public voters; mapping (address => Candidate) public candidates; event showData(address); function initCandidate(address addr) public{ candidates[addr] = Candidate(addr,0,false); } // Initialize voters function initVote(address addr) public{ // Avoid duplicate initialization if(voters[addr].addr != address(0)){ emit showData(voters[addr].addr); // This person has been initialized return; } voters[addr] = Voter({addr:addr,vote:false,amount:1}); } }
Voting logic implementation
- Smart contract voting: create voters and candidates. By default, everyone can only vote and cannot vote repeatedly
- Candidates cannot vote
pragma solidity >=0.6.0 <0.7.0; contract VoteDemo{ address internal _owner; // Create constructor constructor()public{ _owner = msg.sender; } // Create voter structure: use bool to represent voting status struct Voter{ address addr; // Address of voter bool vote; //Voting status (limit duplicate voting) uint amount; // The number of votes is 1 by default } // Create a candidate chart struct Candidate{ address addr; // Candidate address uint get; // Votes received bool win; // Does the candidate win } // A voter can only vote for one candidate, but a candidate can receive more than one voter // Use mapping to store voters and candidates mapping (address => Voter) public voters; // Candidate mapping mapping (address => Candidate) public candidates; // Initialize candidates function initCandidate(address addr) public{ candidates[addr] = Candidate(addr,0,false); } event showData(string); // Initialize voters function initVote(address addr) public{ // Avoid duplicate initialization if(voters[addr].addr != address(0)){ emit showData("This person has been initialized"); return; } voters[addr] = Voter({addr:addr,vote:false,amount:1}); } // The current function completes the business logic of voting // The person who calls the function is the voter. When voting, the address of the candidate needs to be passed in function vote(address candidate)public{ Voter storage v = voters[msg.sender]; // Judge that this person did not vote repeatedly and is not a candidate if(v.vote || v.addr == candidate){ emit showData('This person is not eligible to vote!'); return; } // Vote for candidates candidates[candidate].get += v.amount; // Update voter status v.vote = true; } // Create decorator modifier checkOwner{ if(msg.sender!=_owner){ revert(); } _; } // Judge successful voters function success(address addr1,address addr2) public checkOwner returns (address) { if(candidates[addr1].get > candidates[addr2].get){ candidates[addr1].win = true; return addr1; }else{ candidates[addr2].win = true; return addr2; } } }