Source Code

;; dao-core.clar
;; Core DAO framework - initialization, membership, roles, parameters
;; Clarity 4 / Epoch 3.3

;; -----------------------------------------------
;; Constants
;; -----------------------------------------------
(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-NOT-AUTHORIZED (err u100))
(define-constant ERR-ALREADY-INITIALIZED (err u101))
(define-constant ERR-NOT-INITIALIZED (err u102))
(define-constant ERR-ALREADY-MEMBER (err u103))
(define-constant ERR-NOT-MEMBER (err u104))
(define-constant ERR-INVALID-ROLE (err u105))
(define-constant ERR-DAO-PAUSED (err u106))
(define-constant ERR-INVALID-PARAM (err u107))

(define-constant ROLE-ADMIN u1)
(define-constant ROLE-MEMBER u2)
(define-constant ROLE-OBSERVER u3)

;; -----------------------------------------------
;; Data Variables
;; -----------------------------------------------
(define-data-var dao-name (string-ascii 64) "")
(define-data-var dao-initialized bool false)
(define-data-var dao-paused bool false)
(define-data-var dao-version uint u1)
(define-data-var member-count uint u0)
(define-data-var voting-period uint u144)
(define-data-var quorum-threshold uint u20)
(define-data-var pass-threshold uint u51)
(define-data-var upgrade-address (optional principal) none)

;; -----------------------------------------------
;; Data Maps
;; -----------------------------------------------
(define-map members
  principal
  {
    role: uint,
    joined-at: uint,
    active: bool
  }
)

(define-map dao-parameters
  (string-ascii 32)
  uint
)

;; -----------------------------------------------
;; Private Functions
;; -----------------------------------------------
(define-private (is-admin (caller principal))
  (match (map-get? members caller)
    member (and (is-eq (get role member) ROLE-ADMIN) (get active member))
    false
  )
)

(define-private (is-active-member (caller principal))
  (match (map-get? members caller)
    member (get active member)
    false
  )
)

;; -----------------------------------------------
;; Public Functions
;; -----------------------------------------------

;; Initialize the DAO with a name and config
(define-public (initialize (name (string-ascii 64)) (voting-len uint) (quorum uint) (pass uint))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (asserts! (not (var-get dao-initialized)) ERR-ALREADY-INITIALIZED)
    (asserts! (> voting-len u0) ERR-INVALID-PARAM)
    (asserts! (<= quorum u100) ERR-INVALID-PARAM)
    (asserts! (<= pass u100) ERR-INVALID-PARAM)
    (var-set dao-name name)
    (var-set voting-period voting-len)
    (var-set quorum-threshold quorum)
    (var-set pass-threshold pass)
    (var-set dao-initialized true)
    (map-set members CONTRACT-OWNER
      { role: ROLE-ADMIN, joined-at: tenure-height, active: true })
    (var-set member-count u1)
    (ok true)
  )
)

;; Register a new member with a role
(define-public (register-member (new-member principal) (role uint))
  (begin
    (asserts! (var-get dao-initialized) ERR-NOT-INITIALIZED)
    (asserts! (not (var-get dao-paused)) ERR-DAO-PAUSED)
    (asserts! (is-admin tx-sender) ERR-NOT-AUTHORIZED)
    (asserts! (is-none (map-get? members new-member)) ERR-ALREADY-MEMBER)
    (asserts! (or (is-eq role ROLE-ADMIN)
                  (is-eq role ROLE-MEMBER)
                  (is-eq role ROLE-OBSERVER)) ERR-INVALID-ROLE)
    (map-set members new-member
      { role: role, joined-at: tenure-height, active: true })
    (var-set member-count (+ (var-get member-count) u1))
    (ok true)
  )
)

;; Update a member role
(define-public (update-role (member principal) (new-role uint))
  (begin
    (asserts! (var-get dao-initialized) ERR-NOT-INITIALIZED)
    (asserts! (not (var-get dao-paused)) ERR-DAO-PAUSED)
    (asserts! (is-admin tx-sender) ERR-NOT-AUTHORIZED)
    (asserts! (or (is-eq new-role ROLE-ADMIN)
                  (is-eq new-role ROLE-MEMBER)
                  (is-eq new-role ROLE-OBSERVER)) ERR-INVALID-ROLE)
    (match (map-get? members member)
      existing (begin
        (map-set members member (merge existing { role: new-role }))
        (ok true)
      )
      ERR-NOT-MEMBER
    )
  )
)

;; Remove a member (deactivate)
(define-public (remove-member (member principal))
  (begin
    (asserts! (var-get dao-initialized) ERR-NOT-INITIALIZED)
    (asserts! (is-admin tx-sender) ERR-NOT-AUTHORIZED)
    (match (map-get? members member)
      existing (begin
        (map-set members member (merge existing { active: false }))
        (var-set member-count (- (var-get member-count) u1))
        (ok true)
      )
      ERR-NOT-MEMBER
    )
  )
)

;; Pause the DAO
(define-public (pause-dao)
  (begin
    (asserts! (is-admin tx-sender) ERR-NOT-AUTHORIZED)
    (var-set dao-paused true)
    (ok true)
  )
)

;; Unpause the DAO
(define-public (unpause-dao)
  (begin
    (asserts! (is-admin tx-sender) ERR-NOT-AUTHORIZED)
    (var-set dao-paused false)
    (ok true)
  )
)

;; Set upgrade address for future migration
(define-public (set-upgrade-address (new-address principal))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (var-set upgrade-address (some new-address))
    (var-set dao-version (+ (var-get dao-version) u1))
    (ok true)
  )
)

;; Update a named DAO parameter
(define-public (set-parameter (param-name (string-ascii 32)) (value uint))
  (begin
    (asserts! (is-admin tx-sender) ERR-NOT-AUTHORIZED)
    (asserts! (not (var-get dao-paused)) ERR-DAO-PAUSED)
    (map-set dao-parameters param-name value)
    (ok true)
  )
)

;; Update voting period directly
(define-public (set-voting-period (new-period uint))
  (begin
    (asserts! (is-admin tx-sender) ERR-NOT-AUTHORIZED)
    (asserts! (> new-period u0) ERR-INVALID-PARAM)
    (var-set voting-period new-period)
    (ok true)
  )
)

;; Update quorum threshold directly
(define-public (set-quorum (new-quorum uint))
  (begin
    (asserts! (is-admin tx-sender) ERR-NOT-AUTHORIZED)
    (asserts! (<= new-quorum u100) ERR-INVALID-PARAM)
    (var-set quorum-threshold new-quorum)
    (ok true)
  )
)

;; -----------------------------------------------
;; Read-Only Functions
;; -----------------------------------------------
(define-read-only (get-dao-info)
  {
    name: (var-get dao-name),
    initialized: (var-get dao-initialized),
    paused: (var-get dao-paused),
    version: (var-get dao-version),
    member-count: (var-get member-count),
    voting-period: (var-get voting-period),
    quorum: (var-get quorum-threshold),
    pass-threshold: (var-get pass-threshold)
  }
)

(define-read-only (get-member-info (member principal))
  (map-get? members member)
)

(define-read-only (is-dao-member (who principal))
  (is-active-member who)
)

(define-read-only (get-parameter (param-name (string-ascii 32)))
  (map-get? dao-parameters param-name)
)

(define-read-only (get-upgrade-address)
  (var-get upgrade-address)
)

Functions (17)

FunctionAccessArgs
is-adminprivatecaller: principal
is-active-memberprivatecaller: principal
initializepublicname: (string-ascii 64
register-memberpublicnew-member: principal, role: uint
update-rolepublicmember: principal, new-role: uint
remove-memberpublicmember: principal
pause-daopublic
unpause-daopublic
set-upgrade-addresspublicnew-address: principal
set-parameterpublicparam-name: (string-ascii 32
set-voting-periodpublicnew-period: uint
set-quorumpublicnew-quorum: uint
get-dao-inforead-only
get-member-inforead-onlymember: principal
is-dao-memberread-onlywho: principal
get-parameterread-onlyparam-name: (string-ascii 32
get-upgrade-addressread-only