A decentralized decision-making system built on the Stacks blockchain using Clarity smart contracts. DecisionHub enables transparent, tamper-proof voting on proposals with built-in validation and time-based restrictions.
- Decentralized Governance: Create and vote on motions without intermediaries
- Time-Limited Polling: Automatic expiration based on block height
- One Vote Per Address: Prevents duplicate voting from the same participant
- Input Validation: Ensures motion subjects and details meet length requirements
- Admin Controls: Contract owner can manually end polling when deadline is reached
- Motions Map: Stores all created motions with their metadata and vote counts
- Ballots Map: Records individual votes to prevent duplicate voting
- Motion Counter: Tracks the next available motion ID
create-motion
(create-motion (subject (string-ascii 50)) (details (string-ascii 280)) (timespan uint))Creates a new motion for voting.
subject: Motion title (1-50 characters)details: Motion description (1-280 characters)timespan: Duration in blocks (1-10,000 blocks)- Returns: Motion ID or error code
cast-ballot
(cast-ballot (motion-id uint) (choice-bool bool))Casts a vote on an existing motion.
motion-id: ID of the motion to vote onchoice-bool:truefor support,falsefor opposition- Returns: Success confirmation or error code
end-polling (Admin Only)
(end-polling (motion-id uint))Manually closes polling for a motion that has reached its deadline.
- Requires: Contract admin privileges
motion-id: ID of the motion to close
get-motion
(get-motion (motion-id uint))Retrieves motion details including vote counts and status.
get-ballot
(get-ballot (participant principal) (motion-id uint))Checks if a specific address has voted on a motion.
is-polling-active
(is-polling-active (motion-id uint))Returns whether voting is still open for a motion.
| Code | Constant | Description |
|---|---|---|
| u100 | ERROR_UNAUTHORIZED | Caller lacks required permissions |
| u101 | ERROR_DUPLICATE_BALLOT | Address has already voted on this motion |
| u102 | ERROR_MOTION_NOT_EXISTS | Motion ID does not exist |
| u103 | ERROR_POLLING_ENDED | Voting period has expired |
| u104 | ERROR_INVALID_SUBJECT | Subject length validation failed |
| u105 | ERROR_INVALID_DETAILS | Details length validation failed |
| u106 | ERROR_INVALID_TIMESPAN | Duration outside acceptable range |
;; Create a motion
(contract-call? .decision-hub create-motion
"Upgrade Protocol"
"Proposal to upgrade the protocol to version 2.0 with improved security features"
u1000) ;; ~1 week assuming 10-minute blocks
;; Vote on motion #1
(contract-call? .decision-hub cast-ballot u1 true) ;; Support
(contract-call? .decision-hub cast-ballot u1 false) ;; Oppose
;; Check motion status
(contract-call? .decision-hub get-motion u1)
(contract-call? .decision-hub is-polling-active u1)- Immutable Records: All votes are permanently stored on-chain
- Time-Based Expiration: Prevents indefinite voting periods
- Access Controls: Admin functions restricted to contract owner
- Input Sanitization: Length validation prevents spam and oversized data
- Duplicate Prevention: Each address can only vote once per motion