Source Code

;; DAO Token Contract
;; SIP-010 compliant fungible token for DAO membership and voting
;; Clarity 4

;; =====================
;; TRAIT IMPLEMENTATION
;; =====================

(impl-trait .sip-010-trait.sip-010-trait)

;; =====================
;; CONSTANTS
;; =====================

(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-NOT-AUTHORIZED (err u100))
(define-constant ERR-NOT-TOKEN-OWNER (err u101))
(define-constant ERR-INSUFFICIENT-BALANCE (err u102))
(define-constant ERR-INVALID-AMOUNT (err u103))
(define-constant ERR-MINT-FAILED (err u104))
(define-constant ERR-BURN-FAILED (err u105))
(define-constant ERR-TRANSFER-FAILED (err u106))

;; Token metadata
(define-constant TOKEN-NAME "DAO Governance Token")
(define-constant TOKEN-SYMBOL "DAOG")
(define-constant TOKEN-DECIMALS u6)
(define-constant TOKEN-URI (some u"https://clarity-dao-system.io/token-metadata.json"))

;; Initial supply: 1 million tokens (with 6 decimals)
(define-constant INITIAL-SUPPLY u1000000000000)

;; =====================
;; DATA VARIABLES
;; =====================

(define-data-var token-supply uint u0)
(define-data-var minting-enabled bool true)

;; =====================
;; DATA MAPS
;; =====================

(define-map balances principal uint)
(define-map allowances { owner: principal, spender: principal } uint)

;; Authorized minters (governance contract can mint)
(define-map authorized-minters principal bool)

;; =====================
;; SIP-010 FUNCTIONS
;; =====================

;; Get the token balance of a principal
(define-read-only (get-balance (account principal))
  (ok (default-to u0 (map-get? balances account)))
)

;; Get the total supply of tokens
(define-read-only (get-total-supply)
  (ok (var-get token-supply))
)

;; Get the token name
(define-read-only (get-name)
  (ok TOKEN-NAME)
)

;; Get the token symbol
(define-read-only (get-symbol)
  (ok TOKEN-SYMBOL)
)

;; Get the number of decimals
(define-read-only (get-decimals)
  (ok TOKEN-DECIMALS)
)

;; Get the token URI for metadata
(define-read-only (get-token-uri)
  (ok TOKEN-URI)
)

;; Transfer tokens from sender to recipient
(define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34))))
  (begin
    ;; Validate sender is tx-sender
    (asserts! (is-eq tx-sender sender) ERR-NOT-AUTHORIZED)
    ;; Validate amount is positive
    (asserts! (> amount u0) ERR-INVALID-AMOUNT)
    ;; Check sufficient balance
    (let ((sender-balance (default-to u0 (map-get? balances sender))))
      (asserts! (>= sender-balance amount) ERR-INSUFFICIENT-BALANCE)
      ;; Update balances
      (map-set balances sender (- sender-balance amount))
      (map-set balances recipient (+ (default-to u0 (map-get? balances recipient)) amount))
      ;; Print memo if provided
      (match memo
        memo-value (begin (print memo-value) true)
        true
      )
      (print { event: "transfer", sender: sender, recipient: recipient, amount: amount })
      (ok true)
    )
  )
)

;; =====================
;; MINTING FUNCTIONS
;; =====================

;; Mint new tokens (only authorized minters)
(define-public (mint (amount uint) (recipient principal))
  (begin
    (asserts! (or (is-eq tx-sender CONTRACT-OWNER) (is-authorized-minter tx-sender)) ERR-NOT-AUTHORIZED)
    (asserts! (var-get minting-enabled) ERR-MINT-FAILED)
    (asserts! (> amount u0) ERR-INVALID-AMOUNT)
    ;; Update supply and balance
    (var-set token-supply (+ (var-get token-supply) amount))
    (map-set balances recipient (+ (default-to u0 (map-get? balances recipient)) amount))
    (print { event: "mint", recipient: recipient, amount: amount })
    (ok true)
  )
)

;; Burn tokens
(define-public (burn (amount uint) (owner principal))
  (begin
    (asserts! (is-eq tx-sender owner) ERR-NOT-TOKEN-OWNER)
    (asserts! (> amount u0) ERR-INVALID-AMOUNT)
    (let ((owner-balance (default-to u0 (map-get? balances owner))))
      (asserts! (>= owner-balance amount) ERR-INSUFFICIENT-BALANCE)
      ;; Update supply and balance
      (var-set token-supply (- (var-get token-supply) amount))
      (map-set balances owner (- owner-balance amount))
      (print { event: "burn", owner: owner, amount: amount })
      (ok true)
    )
  )
)

;; =====================
;; ADMIN FUNCTIONS
;; =====================

;; Add authorized minter (only contract owner)
(define-public (add-minter (minter principal))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (map-set authorized-minters minter true)
    (print { event: "minter-added", minter: minter })
    (ok true)
  )
)

;; Remove authorized minter
(define-public (remove-minter (minter principal))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (map-delete authorized-minters minter)
    (print { event: "minter-removed", minter: minter })
    (ok true)
  )
)

;; Toggle minting
(define-public (set-minting-enabled (enabled bool))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (var-set minting-enabled enabled)
    (print { event: "minting-toggled", enabled: enabled })
    (ok true)
  )
)

;; =====================
;; READ-ONLY FUNCTIONS
;; =====================

;; Check if principal is authorized minter
(define-read-only (is-authorized-minter (who principal))
  (default-to false (map-get? authorized-minters who))
)

;; Check if minting is enabled
(define-read-only (is-minting-enabled)
  (var-get minting-enabled)
)

;; Get allowance
(define-read-only (get-allowance (owner principal) (spender principal))
  (ok (default-to u0 (map-get? allowances { owner: owner, spender: spender })))
)

;; =====================
;; INITIALIZATION
;; =====================

;; Mint initial supply to contract owner on deployment
(begin
  (var-set token-supply INITIAL-SUPPLY)
  (map-set balances CONTRACT-OWNER INITIAL-SUPPLY)
  (print { event: "initialized", initial-supply: INITIAL-SUPPLY, owner: CONTRACT-OWNER })
)

Functions (15)

FunctionAccessArgs
get-balanceread-onlyaccount: principal
get-total-supplyread-only
get-nameread-only
get-symbolread-only
get-decimalsread-only
get-token-uriread-only
transferpublicamount: uint, sender: principal, recipient: principal, memo: (optional (buff 34
mintpublicamount: uint, recipient: principal
burnpublicamount: uint, owner: principal
add-minterpublicminter: principal
remove-minterpublicminter: principal
set-minting-enabledpublicenabled: bool
is-authorized-minterread-onlywho: principal
is-minting-enabledread-only
get-allowanceread-onlyowner: principal, spender: principal