Source Code

;; Quadratic Funding - Clarity 4
;; Quadratic funding for public goods

(define-constant contract-owner tx-sender)
(define-constant err-round-not-active (err u10000))
(define-constant err-not-found (err u10001))
(define-constant err-round-ended (err u10002))

(define-data-var round-nonce uint u0)
(define-data-var current-round uint u0)

(define-map funding-rounds
    uint
    {
        matching-pool: uint,
        start-height: uint,
        end-height: uint,
        total-contributions: uint,
        active: bool
    }
)

(define-map projects
    {round-id: uint, project-id: uint}
    {
        creator: principal,
        title: (string-utf8 100),
        description: (string-utf8 500),
        total-raised: uint,
        contributor-count: uint,
        matching-amount: uint
    }
)

(define-map contributions
    {round-id: uint, project-id: uint, contributor: principal}
    uint
)

(define-read-only (get-round (round-id uint))
    (map-get? funding-rounds round-id)
)

(define-read-only (get-project (round-id uint) (project-id uint))
    (map-get? projects {round-id: round-id, project-id: project-id})
)

(define-public (create-round (matching-pool uint) (duration-blocks uint))
    (let (
        (round-id (var-get round-nonce))
    )
        (asserts! (is-eq tx-sender contract-owner) err-not-found)
        (try! (stx-transfer? matching-pool tx-sender (as-contract tx-sender)))
        
        (map-set funding-rounds round-id {
            matching-pool: matching-pool,
            start-height: stacks-block-height,
            end-height: (+ stacks-block-height duration-blocks),
            total-contributions: u0,
            active: true
        })
        
        (var-set round-nonce (+ round-id u1))
        (var-set current-round round-id)
        (ok round-id)
    )
)

(define-public (submit-project
    (round-id uint)
    (project-id uint)
    (title (string-utf8 100))
    (description (string-utf8 500))
)
    (let (
        (round (unwrap! (get-round round-id) err-not-found))
    )
        (asserts! (get active round) err-round-not-active)
        (asserts! (< stacks-block-height (get end-height round)) err-round-ended)
        
        (ok (map-set projects {round-id: round-id, project-id: project-id}
            {
                creator: tx-sender,
                title: title,
                description: description,
                total-raised: u0,
                contributor-count: u0,
                matching-amount: u0
            }
        ))
    )
)

(define-public (contribute (round-id uint) (project-id uint) (amount uint))
    (let (
        (round (unwrap! (get-round round-id) err-not-found))
        (project (unwrap! (get-project round-id project-id) err-not-found))
        (existing-contribution (default-to u0 
            (map-get? contributions {round-id: round-id, project-id: project-id, contributor: tx-sender})))
    )
        (asserts! (get active round) err-round-not-active)
        (asserts! (< stacks-block-height (get end-height round)) err-round-ended)
        
        (try! (stx-transfer? amount tx-sender (as-contract tx-sender)))
        
        (map-set contributions {round-id: round-id, project-id: project-id, contributor: tx-sender}
            (+ existing-contribution amount)
        )
        
        (map-set projects {round-id: round-id, project-id: project-id}
            (merge project {
                total-raised: (+ (get total-raised project) amount),
                contributor-count: (if (is-eq existing-contribution u0)
                    (+ (get contributor-count project) u1)
                    (get contributor-count project)
                )
            })
        )
        
        (ok true)
    )
)

(define-public (finalize-round (round-id uint))
    (let (
        (round (unwrap! (get-round round-id) err-not-found))
    )
        (asserts! (is-eq tx-sender contract-owner) err-not-found)
        (asserts! (>= stacks-block-height (get end-height round)) err-round-ended)
        
        ;; In production, calculate quadratic matching using sqrt formula
        (ok (map-set funding-rounds round-id (merge round {active: false})))
    )
)

Functions (6)

FunctionAccessArgs
get-roundread-onlyround-id: uint
get-projectread-onlyround-id: uint, project-id: uint
create-roundpublicmatching-pool: uint, duration-blocks: uint
submit-projectpublicround-id: uint, project-id: uint, title: (string-utf8 100
contributepublicround-id: uint, project-id: uint, amount: uint
finalize-roundpublicround-id: uint