Citizen Feedback DAO

What it does:
Allows citizens to submit feedback, suggestions, and proposals for public projects or community initiatives, with on-chain voting and prioritization.

Why it matters:
Enhances participatory governance, ensures policies and projects reflect community needs, and provides transparent tracking of citizen input.

How it works:

  • Citizens register on-chain with verified identity or reputation

  • Feedback or proposals are submitted with description, category, and metadata

  • DAO members vote or rank submissions to prioritize actions

  • Approved proposals can trigger fund allocation, project execution, or policy changes

  • Voting and feedback history is auditable and immutable

  • Public dashboards display submitted ideas, votes, and execution status

  • Integrates with local governance DAOs, budget allocation, and transparency modules

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

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

/**
 * @title CitizenFeedbackDAO
 * @author Nam
 * @notice DAO for citizens to submit proposals and provide feedback with on-chain voting
 */
contract CitizenFeedbackDAO is Ownable {

    struct Citizen {
        bool registered;
        string metadataURI;
    }

    struct Feedback {
        address proposer;
        string description;
        string category;
        uint256 votesFor;
        uint256 votesAgainst;
        bool executed;
    }

    mapping(address => Citizen) public citizens;
    mapping(uint256 => Feedback) public feedbacks;
    mapping(address => mapping(uint256 => bool)) public hasVoted;

    uint256 public feedbackCount;

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

    event CitizenRegistered(address indexed citizen, string metadataURI);
    event FeedbackSubmitted(uint256 indexed feedbackId, address proposer);
    event Voted(uint256 indexed feedbackId, address voter, bool support);
    event FeedbackExecuted(uint256 indexed feedbackId);

    // -------------------- CITIZEN REGISTRATION --------------------

    function registerCitizen(string calldata _metadataURI) external {
        require(!citizens[msg.sender].registered, "Already registered");
        citizens[msg.sender] = Citizen({
            registered: true,
            metadataURI: _metadataURI
        });

        emit CitizenRegistered(msg.sender, _metadataURI);
    }

    function isCitizen(address _user) public view returns (bool) {
        return citizens[_user].registered;
    }

    // -------------------- FEEDBACK SUBMISSION --------------------

    function submitFeedback(string calldata _description, string calldata _category) external {
        require(isCitizen(msg.sender), "Not a registered citizen");

        feedbackCount += 1;
        feedbacks[feedbackCount] = Feedback({
            proposer: msg.sender,
            description: _description,
            category: _category,
            votesFor: 0,
            votesAgainst: 0,
            executed: false
        });

        emit FeedbackSubmitted(feedbackCount, msg.sender);
    }

    // -------------------- VOTING --------------------

    function vote(uint256 _feedbackId, bool _support) external {
        require(isCitizen(msg.sender), "Not a citizen");
        require(!hasVoted[msg.sender][_feedbackId], "Already voted");

        Feedback storage f = feedbacks[_feedbackId];
        require(!f.executed, "Already executed");

        if (_support) {
            f.votesFor += 1;
        } else {
            f.votesAgainst += 1;
        }

        hasVoted[msg.sender][_feedbackId] = true;
        emit Voted(_feedbackId, msg.sender, _support);
    }

    // -------------------- EXECUTION --------------------

    function executeFeedback(uint256 _feedbackId) external {
        Feedback storage f = feedbacks[_feedbackId];
        require(!f.executed, "Already executed");
        require(f.votesFor > f.votesAgainst, "Not approved");

        f.executed = true;
        emit FeedbackExecuted(_feedbackId);
        // Optional: trigger on-chain fund allocation or project initiation
    }
}