Source Code

;; errors
(define-constant err-not-enough-funds u100)
(define-constant err-already-funded u101)
(define-constant err-max-funders u102)
(define-constant err-unwrap u103)
(define-constant err-contract-funded u104)
(define-constant err-already-claimed u105)
(define-constant err-has-not-submitted-milestone u106)
(define-constant err-not-owner u107)
(define-constant err-already-voted u108)
(define-constant err-contract-frozen u109)

;; global variables
(define-data-var funding-goal uint u0)
(define-data-var end-block uint u0)
(define-data-var milestones uint u0)
(define-map donator-tokens principal uint)
(define-data-var num-donators uint u0)
(define-data-var funded bool false)
(define-data-var total-tokens uint u0)
(define-data-var stats-per-token uint u0)
(define-data-var claimed-first bool false)
(define-data-var owner principal tx-sender)
(define-map milestone-details uint {details: (string-ascii 50)})
(define-data-var current-milestone uint u1)
(define-map has-submitted-milestone uint bool)
(define-map milestone-votes uint uint)
(define-map has-voted-milestone { user:principal, milestone:uint} bool)
(define-map vote-frozen principal bool)
(define-data-var num-frozen-votes uint u0)
(define-data-var frozen bool false)
(define-map refunded principal bool)

(define-data-var temp-tx-sender principal tx-sender)


;; Procedural Private functions
(define-private (funding-ended)
    (ok (asserts! (is-eq (var-get funded) false) (err err-already-funded)))
)

(define-private (check-end-deadline) 
    (begin
        (asserts! (is-eq true true) (err u1))
        (if (>= block-height (var-get funding-goal))
        (begin 
            (var-set frozen true)
            (ok (var-set stats-per-token (/ (stx-get-balance (as-contract tx-sender)) (var-get total-tokens))))
        )
        (ok true))
    )
)


;; Create Campaign

(define-public (start (goal uint) (block-duration uint) (num-milestones uint)) 
    (begin
        (var-set funding-goal goal)
        (var-set end-block (+ block-height block-duration))
        (var-set milestones num-milestones)
        (ok true)
    )
)

;; Funding Related Functions

(define-public (donate (amount uint))
    (begin 
        (try! (funding-ended))        (try! (check-end-deadline))
        (asserts! (> (stx-get-balance tx-sender) amount) (err err-not-enough-funds))
        (map-insert donator-tokens tx-sender amount)
        (var-set num-donators (+ u1 (var-get num-donators)))
        (var-set total-tokens (+ (var-get total-tokens) amount))
        (if (>= (var-get funding-goal) (stx-get-balance (as-contract tx-sender))) (var-set funded true) (var-set funded false))
        (stx-transfer? amount tx-sender (as-contract tx-sender))
    )
)

(define-public (claim-refund) 
    (begin
        (asserts! (< (var-get funding-goal) (stx-get-balance (as-contract tx-sender))) (err err-not-enough-funds))
        (asserts! (is-eq (var-get frozen) true)  (err err-contract-frozen))
        (asserts! (default-to true (map-get? refunded tx-sender)) (err err-already-claimed))
        (asserts! 
            (>= 
                (stx-get-balance (as-contract tx-sender)) 
                (* (var-get stats-per-token) (default-to u0 (map-get? donator-tokens tx-sender)))
            ) 
            (err err-not-enough-funds)
        )
        (var-set temp-tx-sender tx-sender)
        (as-contract (stx-transfer? (* (var-get stats-per-token) (default-to u0 (map-get? donator-tokens (var-get temp-tx-sender)))) tx-sender (var-get temp-tx-sender)))) ;; Returns 20
)

(define-public (claim-first-milestone) 
    (begin 
        (asserts! (is-eq (var-get funded) true) (err err-not-enough-funds))
        (asserts! (is-eq (var-get claimed-first) false) (err err-already-claimed))
        (var-set current-milestone (+ u1 (var-get current-milestone)))
        (as-contract (stx-transfer? (/ (stx-get-balance tx-sender) (var-get milestones)) tx-sender (var-get owner)))
    )
)

;; DAO Functions
(define-public (submit-milestone (submission-details (string-ascii 50)))
    (begin 
        (asserts! (is-eq tx-sender (var-get owner)) (err err-not-owner))
        (map-insert milestone-details (var-get current-milestone) {details:submission-details})
        (map-insert has-submitted-milestone (var-get current-milestone) true)
        (ok true)
    )
)

(define-public (vote-on-milestone) 
    (begin  
        (asserts! (default-to false (map-get? has-submitted-milestone (var-get current-milestone))) (err err-has-not-submitted-milestone))
        (asserts! (default-to true (map-get? has-voted-milestone {user:tx-sender, milestone:(var-get current-milestone)})) (err err-already-voted))
        (map-insert milestone-votes (var-get current-milestone) 
            (+ 
                (default-to u0 (map-get? donator-tokens tx-sender)) 
                (default-to u0 (map-get? milestone-votes (var-get current-milestone)))
            )
        )
        (map-insert has-voted-milestone {user:tx-sender, milestone:(var-get current-milestone)} false)
        (if (> (default-to u0 (map-get? milestone-votes (var-get current-milestone))) (/ (var-get total-tokens) u2)) 
                (begin 
                    (var-set current-milestone (+ u1 (var-get current-milestone)))
                    (as-contract (stx-transfer? (/ (stx-get-balance tx-sender) (var-get milestones)) tx-sender (var-get owner)))
                )
                (ok (var-set current-milestone (var-get current-milestone)))
        )
    )
)

(define-public (vote-to-freeze)
    (begin
        (asserts! (default-to true (map-get? vote-frozen tx-sender)) (err err-already-voted))
        (map-insert vote-frozen tx-sender false)
        (var-set num-frozen-votes (+ (default-to u0 (map-get? donator-tokens tx-sender)) (var-get num-frozen-votes)))
        (if ( > (var-get num-frozen-votes) (/ (var-get total-tokens) u2))
            (begin 
                (var-set frozen true)
                (ok (var-set stats-per-token (/ (stx-get-balance (as-contract tx-sender)) (var-get total-tokens))))
            )
            (ok true)
        ) 
    ) 
)

;; Read Functions

;; (define-data-var funding-goal uint u0)
(define-read-only (read-funding-goal) 
    (var-get funding-goal)
)
;; (define-data-var end-block uint u0)
(define-read-only (read-end-block) 
    (var-get end-block)
)
;; (define-data-var milestones uint u0)
(define-read-only (read-milestones) 
    (var-get milestones)
)
;; (define-map donator-tokens principal uint)
(define-read-only (get-num-donator-tokens (address principal)) 
    (default-to u0 (map-get? donator-tokens address))
)
;; (define-data-var num-donators uint u0)
(define-read-only (read-num-donators)
    (var-get num-donators)
)

;; (define-data-var funded bool false)
(define-read-only (read-funded)
    (var-get funded)
)

;; (define-data-var total-tokens uint u0)
(define-read-only (read-total-tokens)
    (var-get total-tokens)
)

;; (define-data-var stats-per-token uint u0)
(define-read-only (read-stats-per-token)
    (var-get stats-per-token)
)

;; (define-data-var claimed-first bool false)
(define-read-only (read-claimed-first)
    (var-get claimed-first)
)

;; (define-data-var owner principal tx-sender)
(define-read-only (read-owner)
    (var-get owner)
)

;; (define-map milestone-details uint {details: (string-ascii 50)})
(define-read-only (get-milestone-details (milestone uint)) 
    (map-get? milestone-details milestone)
)

;; (define-data-var current-milestone uint u1)
(define-read-only (read-current-milestone)
    (var-get current-milestone)
)

;; (define-map has-submitted-milestone uint bool)
(define-read-only (has-milestone-been-submitted (milestone uint))
    (default-to false (map-get? has-submitted-milestone milestone))
)

;; (define-map milestone-votes uint uint)
(define-read-only (get-milestone-votes (milestone uint))
    (default-to u0 (map-get? milestone-votes milestone))
)

;; (define-map has-voted-milestone { user:principal, milestone:uint} bool)
(define-read-only (has-user-voted (user principal) (milestone uint))
    (default-to false (map-get? has-voted-milestone {user: user, milestone: milestone}))
)

;; (define-map vote-frozen principal bool)
(define-read-only (is-vote-frozen (address principal))
    (default-to false (map-get? vote-frozen address))
)

;; (define-data-var num-frozen-votes uint u0)
(define-read-only (read-num-frozen-votes)
    (var-get num-frozen-votes))

;; (define-data-var frozen bool false)
(define-read-only (read-frozen)
    (var-get frozen)
)

;; (define-map refunded principal bool)
(define-read-only (has-been-refunded (address principal))
    (default-to false (map-get? refunded address))
)

(define-read-only (get-balance)
    (stx-get-balance (as-contract tx-sender))
)







Functions (29)

FunctionAccessArgs
funding-endedprivate
check-end-deadlineprivate
startpublicgoal: uint, block-duration: uint, num-milestones: uint
donatepublicamount: uint
claim-refundpublic
claim-first-milestonepublic
submit-milestonepublicsubmission-details: (string-ascii 50
vote-on-milestonepublic
vote-to-freezepublic
read-funding-goalread-only
read-end-blockread-only
read-milestonesread-only
get-num-donator-tokensread-onlyaddress: principal
read-num-donatorsread-only
read-fundedread-only
read-total-tokensread-only
read-stats-per-tokenread-only
read-claimed-firstread-only
read-ownerread-only
get-milestone-detailsread-onlymilestone: uint
read-current-milestoneread-only
has-milestone-been-submittedread-onlymilestone: uint
get-milestone-votesread-onlymilestone: uint
has-user-votedread-onlyuser: principal, milestone: uint
is-vote-frozenread-onlyaddress: principal
read-num-frozen-votesread-only
read-frozenread-only
has-been-refundedread-onlyaddress: principal
get-balanceread-only