Source Code

;; title: crowdfunding-goal-engine
;; summary: Funds are locked until a goal is met or the deadline passes.

;; Constants
(define-constant CONTRACT-OWNER tx-sender)
(define-constant TARGET-GOAL u5000000000) ;; 5,000 STX Goal
(define-constant DEADLINE-BLOCKS u144)    ;; ~24 hours from deployment
(define-constant DEPLOY-HEIGHT burn-block-height)

;; Error Codes
(define-constant ERR-NOT-AUTHORIZED (err u401))
(define-constant ERR-GOAL-NOT-MET (err u402))
(define-constant ERR-DEADLINE-PASSED (err u403))
(define-constant ERR-DEADLINE-NOT-REACHED (err u404))
(define-constant ERR-NO-CONTRIBUTION (err u405))

;; Data Storage
(define-map Contributions principal uint)
(define-data-var total-raised uint u0)

;; Public Functions

;; 1. Contribute: Send STX to the project
(define-public (contribute (amount uint))
    (let (
        (current-contribution (default-to u0 (map-get? Contributions tx-sender)))
    )
    (begin
        ;; Cannot contribute after the deadline
        (asserts! (< burn-block-height (+ DEPLOY-HEIGHT DEADLINE-BLOCKS)) ERR-DEADLINE-PASSED)
        
        ;; Move STX to contract
        (try! (stx-transfer? amount tx-sender (as-contract tx-sender)))
        
        ;; Update records
        (map-set Contributions tx-sender (+ current-contribution amount))
        (var-set total-raised (+ (var-get total-raised) amount))
        (ok true)
    )
    )
)

;; 2. Payout: Creator claims funds if goal is met
(define-public (claim-payout)
    (begin
        (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
        (asserts! (>= (var-get total-raised) TARGET-GOAL) ERR-GOAL-NOT-MET)
        
        ;; Send all funds to creator
        (as-contract (stx-transfer? (stx-get-balance (as-contract tx-sender)) (as-contract tx-sender) CONTRACT-OWNER))
    )
)

;; 3. Refund: Donors claim back STX if deadline passes and goal is NOT met
(define-public (claim-refund)
    (let (
        (amount (unwrap! (map-get? Contributions tx-sender) ERR-NO-CONTRIBUTION))
    )
    (begin
        ;; Must be after deadline
        (asserts! (>= burn-block-height (+ DEPLOY-HEIGHT DEADLINE-BLOCKS)) ERR-DEADLINE-NOT-REACHED)
        ;; Goal must have failed
        (asserts! (< (var-get total-raised) TARGET-GOAL) (err u406))
        
        ;; Reset contribution to zero BEFORE sending to prevent multi-claims
        (map-delete Contributions tx-sender)
        (as-contract (stx-transfer? amount (as-contract tx-sender) tx-sender))
    )
    )
)

;; Read-Only Functions
(define-read-only (get-project-status)
    {
        raised: (var-get total-raised),
        goal: TARGET-GOAL,
        deadline: (+ DEPLOY-HEIGHT DEADLINE-BLOCKS),
        current-height: burn-block-height,
        is-active: (< burn-block-height (+ DEPLOY-HEIGHT DEADLINE-BLOCKS))
    }
)

Functions (4)

FunctionAccessArgs
contributepublicamount: uint
claim-payoutpublic
claim-refundpublic
get-project-statusread-only