Source Code

;; Emergency Fund Contract
;; Community emergency relief fund
;; Halal - mutual aid
;; Clarity 4 compatible

(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-NOT-AUTHORIZED (err u401))
(define-constant ERR-NOT-FOUND (err u404))
(define-constant ERR-ALREADY-CLAIMED (err u405))

(define-data-var fund-balance uint u0)
(define-data-var request-count uint u0)
(define-data-var total-disbursed uint u0)

(define-map contributors principal { total: uint, contributions: uint })
(define-map relief-requests uint {
  requester: principal, reason: (string-utf8 200), amount: uint,
  urgency: uint, status: (string-ascii 20), created: uint
})
(define-map approvers principal bool)

(map-set approvers CONTRACT-OWNER true)

(define-public (add-approver (a principal))
  (begin (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED) (map-set approvers a true) (ok true)))

(define-public (contribute (amount uint))
  (let ((prev (default-to { total: u0, contributions: u0 } (map-get? contributors tx-sender))))
    (try! (stx-transfer? amount tx-sender CONTRACT-OWNER))
    (map-set contributors tx-sender { total: (+ (get total prev) amount), contributions: (+ (get contributions prev) u1) })
    (var-set fund-balance (+ (var-get fund-balance) amount))
    (ok amount)))

(define-public (request-relief (reason (string-utf8 200)) (amount uint) (urgency uint))
  (let ((id (+ (var-get request-count) u1)))
    (map-set relief-requests id { requester: tx-sender, reason: reason, amount: amount, urgency: urgency, status: "pending", created: stacks-block-height })
    (var-set request-count id) (ok id)))

(define-public (approve-relief (request-id uint))
  (let ((req (unwrap! (map-get? relief-requests request-id) ERR-NOT-FOUND)))
    (asserts! (default-to false (map-get? approvers tx-sender)) ERR-NOT-AUTHORIZED)
    (asserts! (is-eq (get status req) "pending") ERR-ALREADY-CLAIMED)
    (try! (stx-transfer? (get amount req) CONTRACT-OWNER (get requester req)))
    (map-set relief-requests request-id (merge req { status: "approved" }))
    (var-set fund-balance (- (var-get fund-balance) (get amount req)))
    (var-set total-disbursed (+ (var-get total-disbursed) (get amount req)))
    (ok (get amount req))))

(define-public (deny-relief (request-id uint))
  (let ((req (unwrap! (map-get? relief-requests request-id) ERR-NOT-FOUND)))
    (asserts! (default-to false (map-get? approvers tx-sender)) ERR-NOT-AUTHORIZED)
    (map-set relief-requests request-id (merge req { status: "denied" })) (ok true)))

(define-read-only (get-request (id uint)) (map-get? relief-requests id))
(define-read-only (get-contributor (who principal)) (map-get? contributors who))
(define-read-only (get-fund-balance) (ok (var-get fund-balance)))
(define-read-only (get-request-count) (ok (var-get request-count)))
(define-read-only (get-total-disbursed) (ok (var-get total-disbursed)))

Functions (10)

FunctionAccessArgs
add-approverpublica: principal
contributepublicamount: uint
request-reliefpublicreason: (string-utf8 200
approve-reliefpublicrequest-id: uint
deny-reliefpublicrequest-id: uint
get-requestread-onlyid: uint
get-contributorread-onlywho: principal
get-fund-balanceread-only
get-request-countread-only
get-total-disbursedread-only