Source Code

;; Crowd-Driven VC Pool Smart Contract
;; Manages decentralized venture capital pools with voting and investment distribution

;; Constants
(define-constant CONTRACT_OWNER tx-sender)
(define-constant MIN_CONTRIBUTION u1000000) ;; Minimum contribution in microSTX
(define-constant VOTING_PERIOD u144) ;; ~24 hours in blocks
(define-constant PROPOSAL_THRESHOLD u100000000) ;; Minimum pool size for proposals

;; Error codes
(define-constant ERR_NOT_AUTHORIZED (err u100))
(define-constant ERR_INSUFFICIENT_FUNDS (err u101))
(define-constant ERR_POOL_NOT_FOUND (err u102))
(define-constant ERR_INVALID_AMOUNT (err u103))
(define-constant ERR_ALREADY_VOTED (err u104))
(define-constant ERR_VOTING_CLOSED (err u105))
(define-constant ERR_BELOW_THRESHOLD (err u106))

;; Data Maps
(define-map pools
    { pool-id: uint }
    {
        total-funds: uint,
        active: bool,
        creator: principal,
        created-at: uint
    }
)

(define-map contributions
    { pool-id: uint, contributor: principal }
    { amount: uint }
)

(define-map proposals
    { pool-id: uint, proposal-id: uint }
    {
        startup: principal,
        amount: uint,
        description: (string-utf8 256),
        votes-for: uint,
        votes-against: uint,
        status: (string-utf8 20),
        created-at: uint
    }
)

(define-map votes
    { pool-id: uint, proposal-id: uint, voter: principal }
    { vote: bool }
)

;; Pool counter
(define-data-var pool-counter uint u0)
(define-data-var proposal-counter uint u0)

;; Read-only functions
(define-read-only (get-pool (pool-id uint))
    (map-get? pools { pool-id: pool-id })
)

(define-read-only (get-contribution (pool-id uint) (contributor principal))
    (map-get? contributions { pool-id: pool-id, contributor: contributor })
)

(define-read-only (get-proposal (pool-id uint) (proposal-id uint))
    (map-get? proposals { pool-id: pool-id, proposal-id: proposal-id })
)

(define-read-only (get-vote (pool-id uint) (proposal-id uint) (voter principal))
    (map-get? votes { pool-id: pool-id, proposal-id: proposal-id, voter: voter })
)

;; Create new pool
(define-public (create-pool)
    (let
        ((new-pool-id (+ (var-get pool-counter) u1)))
        (map-set pools
            { pool-id: new-pool-id }
            {
                total-funds: u0,
                active: true,
                creator: tx-sender,
                created-at: block-height
            }
        )
        (var-set pool-counter new-pool-id)
        (ok new-pool-id)
    )
)

;; Contribute to pool
(define-public (contribute (pool-id uint) (amount uint))
    (let
        ((pool (unwrap! (get-pool pool-id) ERR_POOL_NOT_FOUND))
         (current-contribution (default-to { amount: u0 }
            (get-contribution pool-id tx-sender))))
        
        ;; Checks
        (asserts! (>= amount MIN_CONTRIBUTION) ERR_INVALID_AMOUNT)
        (asserts! (get active pool) ERR_POOL_NOT_FOUND)
        
        ;; Transfer STX to contract
        (try! (stx-transfer? amount tx-sender (as-contract tx-sender)))
        
        ;; Update pool and contribution records
        (map-set pools
            { pool-id: pool-id }
            (merge pool { total-funds: (+ (get total-funds pool) amount) })
        )
        (map-set contributions
            { pool-id: pool-id, contributor: tx-sender }
            { amount: (+ amount (get amount current-contribution)) }
        )
        (ok true)
    )
)

;; Submit proposal
(define-public (submit-proposal 
    (pool-id uint)
    (startup principal)
    (amount uint)
    (description (string-utf8 256)))
    
    (let
        ((pool (unwrap! (get-pool pool-id) ERR_POOL_NOT_FOUND))
         (new-proposal-id (+ (var-get proposal-counter) u1)))
        
        ;; Checks
        (asserts! (>= (get total-funds pool) PROPOSAL_THRESHOLD) ERR_BELOW_THRESHOLD)
        (asserts! (<= amount (get total-funds pool)) ERR_INSUFFICIENT_FUNDS)
        
        ;; Create proposal
        (map-set proposals
            { pool-id: pool-id, proposal-id: new-proposal-id }
            {
                startup: startup,
                amount: amount,
                description: description,
                votes-for: u0,
                votes-against: u0,
                status: u"active",
                created-at: block-height
            }
        )
        (var-set proposal-counter new-proposal-id)
        (ok new-proposal-id)
    )
)

;; Vote on proposal
(define-public (vote (pool-id uint) (proposal-id uint) (vote-for bool))
    (let
        ((proposal (unwrap! (get-proposal pool-id proposal-id) ERR_POOL_NOT_FOUND))
         (contribution (unwrap! (get-contribution pool-id tx-sender) ERR_NOT_AUTHORIZED))
         (voting-power (get amount contribution)))
        
        ;; Checks
        (asserts! (is-eq (get status proposal) u"active") ERR_VOTING_CLOSED)
        (asserts! (is-none (get-vote pool-id proposal-id tx-sender)) ERR_ALREADY_VOTED)
        
        ;; Record vote
        (map-set votes
            { pool-id: pool-id, proposal-id: proposal-id, voter: tx-sender }
            { vote: vote-for }
        )
        
        ;; Update proposal votes
        (map-set proposals
            { pool-id: pool-id, proposal-id: proposal-id }
            (merge proposal {
                votes-for: (if vote-for 
                    (+ (get votes-for proposal) voting-power)
                    (get votes-for proposal)),
                votes-against: (if vote-for
                    (get votes-against proposal)
                    (+ (get votes-against proposal) voting-power))
            })
        )
        (ok true)
    )
)

;; Execute proposal
(define-public (execute-proposal (pool-id uint) (proposal-id uint))
    (let
        ((proposal (unwrap! (get-proposal pool-id proposal-id) ERR_POOL_NOT_FOUND))
         (pool (unwrap! (get-pool pool-id) ERR_POOL_NOT_FOUND)))
        
        ;; Checks
        (asserts! (is-eq (get status proposal) u"active") ERR_VOTING_CLOSED)
        (asserts! (>= (- block-height (get created-at proposal)) VOTING_PERIOD) ERR_VOTING_CLOSED)
        
        ;; Check if proposal passed
        (if (> (get votes-for proposal) (get votes-against proposal))
            (begin
                ;; Transfer funds to startup
                (try! (as-contract (stx-transfer? 
                    (get amount proposal)
                    (as-contract tx-sender)
                    (get startup proposal))))
                
                ;; Update proposal status
                (map-set proposals
                    { pool-id: pool-id, proposal-id: proposal-id }
                    (merge proposal { status: u"executed" })
                )
                (ok true)
            )
            (begin
                ;; Update proposal status
                (map-set proposals
                    { pool-id: pool-id, proposal-id: proposal-id }
                    (merge proposal { status: u"rejected" })
                )
                (ok false)
            )
        )
    )
)

Functions (9)

FunctionAccessArgs
get-poolread-onlypool-id: uint
get-contributionread-onlypool-id: uint, contributor: principal
get-proposalread-onlypool-id: uint, proposal-id: uint
get-voteread-onlypool-id: uint, proposal-id: uint, voter: principal
create-poolpublic
contributepublicpool-id: uint, amount: uint
submit-proposalpublicpool-id: uint, startup: principal, amount: uint, description: (string-utf8 256
votepublicpool-id: uint, proposal-id: uint, vote-for: bool
execute-proposalpublicpool-id: uint, proposal-id: uint