Smart Referendum System

What it does:
Enables communities or DAOs to conduct binding or advisory referendums on-chain with transparent, verifiable results.

Why it matters:
Increases democratic participation, prevents tampering, and ensures that collective decisions are recorded immutably for audit and accountability.

How it works:

  • Administrators create referendum proposals with options and deadlines

  • Eligible voters register and are verified via on-chain identity or reputation

  • Votes are cast and recorded on-chain

  • Results are automatically tallied after the referendum ends

  • Outcome can trigger on-chain actions, fund disbursement, or governance changes

  • Public dashboards display live participation and results

  • Can integrate with reputation-weighted or token-weighted governance systems

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

import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title SmartReferendum
 * @author Nam
 * @notice On-chain referendum system with transparent voting and outcome execution
 */
contract SmartReferendum is Ownable {

    struct Referendum {
        string description;
        string[] options;
        uint256 startTime;
        uint256 endTime;
        bool executed;
        mapping(address => bool) hasVoted;
        mapping(uint256 => uint256) votes; // option index => vote count
    }

    uint256 public referendumCount;
    mapping(uint256 => Referendum) private referendums;
    mapping(address => bool) public eligibleVoters;

    // -------------------- EVENTS --------------------

    event ReferendumCreated(uint256 indexed id, string description);
    event Voted(uint256 indexed referendumId, address voter, uint256 option);
    event ReferendumExecuted(uint256 indexed id, uint256 winningOption);

    // -------------------- VOTER MANAGEMENT --------------------

    function setVoterEligibility(address _voter, bool _eligible) external onlyOwner {
        eligibleVoters[_voter] = _eligible;
    }

    // -------------------- REFERENDUM CREATION --------------------

    function createReferendum(string calldata _description, string[] calldata _options, uint256 _duration) external onlyOwner {
        require(_options.length >= 2, "At least 2 options required");
        referendumCount += 1;

        Referendum storage r = referendums[referendumCount];
        r.description = _description;
        r.startTime = block.timestamp;
        r.endTime = block.timestamp + _duration;

        for (uint256 i = 0; i = r.startTime && block.timestamp <= r.endTime, "Voting period closed");
        require(!r.hasVoted[msg.sender], "Already voted");
        require(_option  r.endTime, "Voting still active");

        uint256 winningOption = 0;
        uint256 highestVotes = 0;

        for (uint256 i = 0; i  highestVotes) {
                highestVotes = r.votes[i];
                winningOption = i;
            }
        }

        r.executed = true;
        emit ReferendumExecuted(_referendumId, winningOption);
        // Optional: trigger on-chain action based on result
    }

    // -------------------- VIEW FUNCTIONS --------------------

    function getVotes(uint256 _referendumId, uint256 _option) external view returns (uint256) {
        return referendums[_referendumId].votes[_option];
    }

    function getOptions(uint256 _referendumId) external view returns (string[] memory) {
        return referendums[_referendumId].options;
    }
}