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];
    }
}
Rise In Logo

Rise together in web3