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
}
}