Rise In Logo



Solidity Fundamentals

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;


contract ProposalContract {
    // ****************** Data ***********************


    //Owner
    address owner;


    uint256 private counter;


    struct Proposal {
        string description; // Description of the proposal
        uint256 approve; // Number of approve votes
        uint256 reject; // Number of reject votes
        uint256 pass; // Number of pass votes
        uint256 total_vote_to_end; // When the total votes in the proposal reaches this limit, proposal ends
        bool current_state; // This shows the current state of the proposal, meaning whether if passes of fails
        bool is_active; // This shows if others can vote to our contract
    }


    mapping(uint256 => Proposal) proposal_history; // Recordings of previous proposals


    address[] private voted_addresses; 


    //constructor
    constructor() {
        owner = msg.sender;
        voted_addresses.push(msg.sender);
    }


    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }


    modifier active() {
        require(proposal_history[counter].is_active == true);
        _;
    }


    modifier newVoter(address _address) {
        require(!isVoted(_address), "Address has not voted yet");
        _;
    }


    // ****************** Execute Functions ***********************




    function setOwner(address new_owner) external onlyOwner {
        owner = new_owner;
    }


    function create(string calldata _description, uint256 _total_vote_to_end) external onlyOwner {
        counter += 1;
        proposal_history[counter] = Proposal(_description, 0, 0, 0, _total_vote_to_end, false, true);
    }
    


    function vote(uint8 choice) external active newVoter(msg.sender){
        Proposal storage proposal = proposal_history[counter];
        uint256 total_vote = proposal.approve + proposal.reject + proposal.pass;


        voted_addresses.push(msg.sender);


        if (choice == 1) {
            proposal.approve += 1;
            proposal.current_state = calculateCurrentState();
        } else if (choice == 2) {
            proposal.reject += 1;
            proposal.current_state = calculateCurrentState();
        } else if (choice == 0) {
            proposal.pass += 1;
            proposal.current_state = calculateCurrentState();
        }


        if ((proposal.total_vote_to_end - total_vote == 1) && (choice == 1 || choice == 2 || choice == 0)) {
            proposal.is_active = false;
            voted_addresses = [owner];
        }
    }


    function terminateProposal() external onlyOwner active {
        proposal_history[counter].is_active = false;
    }




    function calculateCurrentState() private view returns(bool) {
        Proposal storage proposal = proposal_history[counter];


        uint256 approve = proposal.approve;
        uint256 reject = proposal.reject;
        uint256 pass = proposal.pass;
        
        if (proposal.pass %2 == 1) {
            pass += 1;
        }


        pass = pass / 2;


        if (approve > reject + pass) {
            return true;
        } else {
            return false;
        }
    }




    // ****************** Query Functions ***********************


    function isVoted(address _address) public view returns (bool) {
        for (uint i = 0; i < voted_addresses.length; i++) {
            if (voted_addresses[i] == _address) {
                return true;
            }
        }
        return false;
    }




    function getCurrentProposal() external view returns(Proposal memory) {
        return proposal_history[counter];
    }


    function getProposal(uint256 number) external view returns(Proposal memory) {
        return proposal_history[number];
    }
}

Comments

You need to enroll in the course to be able to comment!

Stay in the know

Never miss updates on new programs and opportunities.

Rise In Logo

Rise together in web3!