HOA Voting Smart Contract
What it does:
Enables homeowners in a Homeowners Association (HOA) to propose, vote, and decide on community matters such as budgets, rules, and maintenance projects through an on-chain voting system.
Why it matters:
Replaces opaque, low-participation HOA meetings with transparent, verifiable voting that increases trust, accountability, and resident engagement.
How it works:
-
Homeowners are registered with voting power based on unit ownership
-
Any eligible member can submit a proposal
-
Voting period is opened for a fixed duration
-
Votes are weighted according to ownership shares
-
Results are finalized automatically after voting ends
-
Approved proposals are recorded immutably on-chain
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title HOAVoting
* @author Nam
* @notice On-chain voting system for Homeowners Associations
*/
contract HOAVoting {
// -------------------- HOA ADMIN --------------------
address public admin;
// -------------------- HOMEOWNERS --------------------
mapping(address => uint256) public votingPower; // based on unit ownership
uint256 public totalVotingPower;
// -------------------- PROPOSALS --------------------
struct Proposal {
string description;
uint256 votesFor;
uint256 votesAgainst;
uint256 endTime;
bool executed;
}
Proposal[] public proposals;
mapping(uint256 => mapping(address => bool)) public hasVoted;
// -------------------- EVENTS --------------------
event HomeownerRegistered(address indexed owner, uint256 votingPower);
event ProposalCreated(uint256 indexed proposalId, string description);
event VoteCast(
address indexed voter,
uint256 indexed proposalId,
bool support,
uint256 weight
);
event ProposalExecuted(uint256 indexed proposalId);
// -------------------- MODIFIERS --------------------
modifier onlyAdmin() {
require(msg.sender == admin, "Not admin");
_;
}
modifier onlyHomeowner() {
require(votingPower[msg.sender] > 0, "Not homeowner");
_;
}
// -------------------- CONSTRUCTOR --------------------
constructor() {
admin = msg.sender;
}
// -------------------- HOMEOWNER MANAGEMENT --------------------
/**
* @notice Register a homeowner with voting power
*/
function registerHomeowner(address _owner, uint256 _votingPower)
external
onlyAdmin
{
require(_owner != address(0), "Invalid owner");
require(_votingPower > 0, "Invalid voting power");
require(votingPower[_owner] == 0, "Already registered");
votingPower[_owner] = _votingPower;
totalVotingPower += _votingPower;
emit HomeownerRegistered(_owner, _votingPower);
}
// -------------------- PROPOSAL LOGIC --------------------
/**
* @notice Create a new HOA proposal
*/
function createProposal(
string calldata _description,
uint256 _votingDuration
)
external
onlyHomeowner
{
proposals.push(
Proposal({
description: _description,
votesFor: 0,
votesAgainst: 0,
endTime: block.timestamp + _votingDuration,
executed: false
})
);
emit ProposalCreated(proposals.length - 1, _description);
}
/**
* @notice Vote on a proposal
*/
function vote(uint256 _proposalId, bool _support)
external
onlyHomeowner
{
Proposal storage proposal = proposals[_proposalId];
require(block.timestamp = proposal.endTime, "Voting ongoing");
require(!proposal.executed, "Already executed");
require(proposal.votesFor > proposal.votesAgainst, "Proposal rejected");
proposal.executed = true;
emit ProposalExecuted(_proposalId);
}
}