Appendix D. impleVoting contract

Listing D.1. SimpleVoting.sol: full voting contract
pragma solidity ^0.4.22;

contract SimpleVoting {
    
    struct Voter {
        bool isRegistered;
        bool hasVoted;  
        uint votedProposalId;   
    }

    struct Proposal {
        string description;   
        uint voteCount; 
    }

    enum WorkflowStatus {
        RegisteringVoters, 
        ProposalsRegistrationStarted,
        ProposalsRegistrationEnded,
        VotingSessionStarted,
        VotingSessionEnded,
        VotesTallied
    }

    WorkflowStatus public workflowStatus;
    address public administrator;
    mapping(address => Voter) public voters;
    Proposal[] public proposals;
    uint private winningProposalId;

    modifier onlyAdministrator() {
       require(msg.sender == administrator, 

       "the caller of this function must be the administrator");
       _;
    }
    
    modifier onlyRegisteredVoter() {
        require(voters[msg.sender].isRegistered, 
           "the caller of this function must be a registered voter");
       _;
    }
    
    modifier onlyDuringVotersRegistration() {
        require(workflowStatus == WorkflowStatus.RegisteringVoters, 
           "this function can be called only before proposals registration
 has started");
       _;
    }
    
    modifier onlyDuringProposalsRegistration() {
        require(workflowStatus == 
            WorkflowStatus.ProposalsRegistrationStarted, 
           "this function can be called only during proposals
 registration");
       _;
    }
    
    modifier onlyAfterProposalsRegistration() {
        require(workflowStatus == WorkflowStatus.ProposalsRegistrationEnded, 
           "this function can be called only after proposals registration
 has ended");
       _;
    }
    
    modifier onlyDuringVotingSession() {
        require(workflowStatus == WorkflowStatus.VotingSessionStarted, 
           "this function can be called only during the voting session");
       _;
    }
    
    modifier onlyAfterVotingSession() {
        require(workflowStatus == WorkflowStatus.VotingSessionEnded,  
           "this function can be called only after the voting session
 has ended");
       _;
    }
    
    modifier onlyAfterVotesTallied() {
        require(workflowStatus == WorkflowStatus.VotesTallied,  
           "this function can be called only after votes have been
 tallied");
       _;
    }
    
     event VoterRegisteredEvent (
            address voterAddress
     ); 

     event ProposalsRegistrationStartedEvent ();
     
     event ProposalsRegistrationEndedEvent ();
     
     event ProposalRegisteredEvent( 
         uint proposalId
     );
     
     event VotingSessionStartedEvent ();
     
     event VotingSessionEndedEvent ();
     
     event VotedEvent (
         address voter,
         uint proposalId
     );
     
     event VotesTalliedEvent ();
     
     event WorkflowStatusChangeEvent (
        WorkflowStatus previousStatus,
        WorkflowStatus newStatus
    );
    
    constructor() public {
        administrator = msg.sender;
        workflowStatus = WorkflowStatus.RegisteringVoters;
    }
    
    function registerVoter(address _voterAddress) 
        public onlyAdministrator onlyDuringVotersRegistration {
        
        require(!voters[_voterAddress].isRegistered, 
           "the voter is already registered");
        
        voters[_voterAddress].isRegistered = true;
        voters[_voterAddress].hasVoted = false;
        voters[_voterAddress].votedProposalId = 0;
        
        emit VoterRegisteredEvent(_voterAddress);
    }
    
    function startProposalsRegistration() 
        public onlyAdministrator onlyDuringVotersRegistration {
        workflowStatus = WorkflowStatus.ProposalsRegistrationStarted;
        
        emit ProposalsRegistrationStartedEvent();
        emit WorkflowStatusChangeEvent(
            WorkflowStatus.RegisteringVoters, workflowStatus);
    }
    
    function endProposalsRegistration() 
        public onlyAdministrator onlyDuringProposalsRegistration {
        workflowStatus = WorkflowStatus.ProposalsRegistrationEnded;
        

        emit ProposalsRegistrationEndedEvent();
        emit WorkflowStatusChangeEvent(
            WorkflowStatus.ProposalsRegistrationStarted, workflowStatus);
    }
    
    function registerProposal(string proposalDescription) 
        public onlyRegisteredVoter onlyDuringProposalsRegistration {
        proposals.push(Proposal({
            description: proposalDescription,
            voteCount: 0
        }));
        
        emit ProposalRegisteredEvent(proposals.length - 1);
    }
    
     function getProposalsNumber() public view
         returns (uint) {
         return proposals.length;
     }
     
     function getProposalDescription(uint index) public view 
         returns (string) {
         return proposals[index].description;
     }    

    function startVotingSession() 
        public onlyAdministrator onlyAfterProposalsRegistration {
        workflowStatus = WorkflowStatus.VotingSessionStarted;
        
        emit VotingSessionStartedEvent();
        emit WorkflowStatusChangeEvent(
            WorkflowStatus.ProposalsRegistrationEnded, workflowStatus);
    }
    
    function endVotingSession() 
        public onlyAdministrator onlyDuringVotingSession {
        workflowStatus = WorkflowStatus.VotingSessionEnded;
        
        emit VotingSessionEndedEvent();
        emit WorkflowStatusChangeEvent(
            WorkflowStatus.VotingSessionStarted, workflowStatus);        
    }
    function vote(uint proposalId) 
        onlyRegisteredVoter 
        onlyDuringVotingSession public {
        require(!voters[msg.sender].hasVoted, 
            "the caller has already voted");

        voters[msg.sender].hasVoted = true;
        voters[msg.sender].votedProposalId = proposalId;

        proposals[proposalId].voteCount += 1;

        emit VotedEvent(msg.sender, proposalId);
    }

    function tallyVotes() onlyAdministrator onlyAfterVotingSession public {
        uint winningVoteCount = 0;
        uint winningProposalIndex = 0;
        
        for (uint i = 0; i < proposals.length; i++) {
            if (proposals[i].voteCount > winningVoteCount) {
                winningVoteCount = proposals[i].voteCount;
                winningProposalIndex = i;
            }
        }
        
        winningProposalId = winningProposalIndex;
        workflowStatus = WorkflowStatus.VotesTallied;
        
        emit VotesTalliedEvent();
        emit WorkflowStatusChangeEvent(
            WorkflowStatus.VotingSessionEnded, workflowStatus);     
    }
    
    function getWinningProposalId() onlyAfterVotesTallied public view
       returns (uint) {
        return winningProposalId;
    }
    
    function getWinningProposalDescription() 
       onlyAfterVotesTallied public view
       returns (string) {
        return proposals[winningProposalId].description;
    }  
    
    function getWinningProposaVoteCounts() onlyAfterVotesTallied public view
       returns (uint) {
        return proposals[winningProposalId].voteCount;
    }   
    
    function isRegisteredVoter(address _voterAddress) public view
        returns (bool) {
        return voters[_voterAddress].isRegistered;
     }
     
     function isAdministrator(address _address) public view 
         returns (bool) {
         return _address == administrator;
     }     
     
     function getWorkflowStatus() public view
         returns (WorkflowStatus) {
         return workflowStatus;       
     }
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset