;; Basic DAO Contract
;; Generated by StacksAgent MCP
;; Constants
(define-constant contract-owner tx-sender)
(define-constant err-owner-only (err u100))
(define-constant err-already-voted (err u101))
(define-constant err-proposal-not-found (err u102))
(define-constant err-voting-closed (err u103))
(define-constant err-not-member (err u104))
;; Data variables
(define-data-var proposal-count uint u0)
(define-data-var member-count uint u0)
;; Data maps
(define-map proposals
uint
{
proposer: principal,
title: (string-utf8 256),
description: (string-utf8 1024),
yes-votes: uint,
no-votes: uint,
end-block: uint,
executed: bool
})
(define-map votes {proposal-id: uint, voter: principal} bool)
(define-map members principal bool)
;; Membership functions
(define-public (add-member (member principal))
(begin
(asserts! (is-eq tx-sender contract-owner) err-owner-only)
(map-set members member true)
(var-set member-count (+ (var-get member-count) u1))
(ok true)))
(define-read-only (is-member (account principal))
(default-to false (map-get? members account)))
;; Proposal functions
(define-public (create-proposal (title (string-utf8 256)) (description (string-utf8 1024)) (duration uint))
(let
(
(proposal-id (+ (var-get proposal-count) u1))
)
(asserts! (is-member tx-sender) err-not-member)
(map-set proposals proposal-id {
proposer: tx-sender,
title: title,
description: description,
yes-votes: u0,
no-votes: u0,
end-block: (+ block-height duration),
executed: false
})
(var-set proposal-count proposal-id)
(ok proposal-id)))
(define-public (vote (proposal-id uint) (vote-yes bool))
(let
(
(proposal (unwrap! (map-get? proposals proposal-id) err-proposal-not-found))
(voter-key {proposal-id: proposal-id, voter: tx-sender})
)
(asserts! (is-member tx-sender) err-not-member)
(asserts! (is-none (map-get? votes voter-key)) err-already-voted)
(asserts! (< block-height (get end-block proposal)) err-voting-closed)
(if vote-yes
(map-set proposals proposal-id (merge proposal {yes-votes: (+ (get yes-votes proposal) u1)}))
(map-set proposals proposal-id (merge proposal {no-votes: (+ (get no-votes proposal) u1)})))
(map-set votes voter-key true)
(ok true)))
;; Read-only functions
(define-read-only (get-proposal (proposal-id uint))
(map-get? proposals proposal-id))
(define-read-only (get-proposal-count)
(ok (var-get proposal-count)))
(define-read-only (has-voted (proposal-id uint) (voter principal))
(is-some (map-get? votes {proposal-id: proposal-id, voter: voter})))