Source Code

;; Equity Token Contract
;; Manages equity tokenization, vesting schedules, and transfers

(define-constant ERR-UNAUTHORIZED (err u3001))
(define-constant ERR-INSUFFICIENT-BALANCE (err u3002))
(define-constant ERR-VESTING-ACTIVE (err u3003))
(define-constant ERR-INVALID-AMOUNT (err u3004))
(define-constant ERR-STARTUP-NOT-FOUND (err u3005))

(define-constant CONTRACT-OWNER tx-sender)

;; Token balances
(define-map balances
    { owner: principal }
    uint
)

;; Vesting schedules
(define-map vesting-schedules
    { recipient: principal, startup-id: uint }
    {
        total-amount: uint,
        vested-amount: uint,
        start-time: uint,
        cliff-duration: uint,
        vesting-duration: uint,
        release-interval: uint,
        last-release: uint
    }
)

;; Startup equity allocations
(define-map startup-equity
    { startup-id: uint }
    {
        total-supply: uint,
        reserved-amount: uint,
        distributed-amount: uint
    }
)

;; Initialize equity for a startup
(define-public (initialize-equity
    (startup-id uint)
    (total-supply uint)
    (reserved-amount uint)
)
    (let
        (
            (timestamp (unwrap! (get-block-info? time u0) ERR-UNAUTHORIZED))
        )
        (asserts! (is-none (map-get? startup-equity { startup-id: startup-id })) ERR-STARTUP-NOT-FOUND)
        (asserts! (>= total-supply reserved-amount) ERR-INVALID-AMOUNT)
        (ok (map-set startup-equity
            { startup-id: startup-id }
            {
                total-supply: total-supply,
                reserved-amount: reserved-amount,
                distributed-amount: u0
            }
        ))
    )
)

;; Mint equity tokens to a recipient
(define-public (mint-equity
    (recipient principal)
    (startup-id uint)
    (amount uint)
)
    (let
        (
            (equity (unwrap! (map-get? startup-equity { startup-id: startup-id }) ERR-STARTUP-NOT-FOUND))
            (current-balance (default-to u0 (map-get? balances { owner: recipient })))
            (new-distributed (+ (get distributed-amount equity) amount))
        )
        (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-UNAUTHORIZED)
        (asserts! (<= new-distributed (get total-supply equity)) ERR-INVALID-AMOUNT)
        (begin
            (map-set balances { owner: recipient } (+ current-balance amount))
            (map-set startup-equity
                { startup-id: startup-id }
                {
                    total-supply: (get total-supply equity),
                    reserved-amount: (get reserved-amount equity),
                    distributed-amount: new-distributed
                }
            )
            (ok true)
        )
    )
)

;; Create vesting schedule
(define-public (create-vesting-schedule
    (recipient principal)
    (startup-id uint)
    (total-amount uint)
    (cliff-duration uint)
    (vesting-duration uint)
    (release-interval uint)
)
    (let
        (
            (timestamp (unwrap! (get-block-info? time u0) ERR-UNAUTHORIZED))
        )
        (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-UNAUTHORIZED)
        (asserts! (is-none (map-get? vesting-schedules { recipient: recipient, startup-id: startup-id })) ERR-VESTING-ACTIVE)
        (ok (map-set vesting-schedules
            { recipient: recipient, startup-id: startup-id }
            {
                total-amount: total-amount,
                vested-amount: u0,
                start-time: timestamp,
                cliff-duration: cliff-duration,
                vesting-duration: vesting-duration,
                release-interval: release-interval,
                last-release: timestamp
            }
        ))
    )
)

;; Release vested tokens
(define-public (release-vested-tokens
    (recipient principal)
    (startup-id uint)
)
    (let
        (
            (schedule (unwrap! (map-get? vesting-schedules { recipient: recipient, startup-id: startup-id }) ERR-VESTING-ACTIVE))
            (current-time (unwrap! (get-block-info? time u0) ERR-UNAUTHORIZED))
            (start-time (get start-time schedule))
            (cliff-end (+ start-time (get cliff-duration schedule)))
            (vesting-end (+ start-time (get vesting-duration schedule)))
        )
        (asserts! (>= current-time cliff-end) ERR-VESTING-ACTIVE)
        (let
            (
                (time-elapsed (- current-time start-time))
                (total-vested (if
                    (>= current-time vesting-end)
                    (get total-amount schedule)
                    (/ (* (get total-amount schedule) time-elapsed) (get vesting-duration schedule))
                ))
                (newly-vested (- total-vested (get vested-amount schedule)))
                (current-balance (default-to u0 (map-get? balances { owner: recipient })))
            )
            (asserts! (> newly-vested u0) ERR-INVALID-AMOUNT)
            (begin
                (map-set balances { owner: recipient } (+ current-balance newly-vested))
                (map-set vesting-schedules
                    { recipient: recipient, startup-id: startup-id }
                    {
                        total-amount: (get total-amount schedule),
                        vested-amount: total-vested,
                        start-time: start-time,
                        cliff-duration: (get cliff-duration schedule),
                        vesting-duration: (get vesting-duration schedule),
                        release-interval: (get release-interval schedule),
                        last-release: current-time
                    }
                )
                (ok newly-vested)
            )
        )
    )
)

;; Transfer equity tokens
(define-public (transfer-equity
    (recipient principal)
    (amount uint)
)
    (let
        (
            (sender tx-sender)
            (sender-balance (unwrap! (map-get? balances { owner: sender }) ERR-INSUFFICIENT-BALANCE))
            (recipient-balance (default-to u0 (map-get? balances { owner: recipient })))
        )
        (asserts! (>= sender-balance amount) ERR-INSUFFICIENT-BALANCE)
        (begin
            (map-set balances { owner: sender } (- sender-balance amount))
            (map-set balances { owner: recipient } (+ recipient-balance amount))
            (ok true)
        )
    )
)

;; Get balance
(define-read-only (get-balance (owner principal))
    (default-to u0 (map-get? balances { owner: owner }))
)

;; Get vesting schedule
(define-read-only (get-vesting-schedule (recipient principal) (startup-id uint))
    (map-get? vesting-schedules { recipient: recipient, startup-id: startup-id })
)

;; Get startup equity info
(define-read-only (get-startup-equity (startup-id uint))
    (map-get? startup-equity { startup-id: startup-id })
)

Functions (3)

FunctionAccessArgs
get-balanceread-onlyowner: principal
get-vesting-scheduleread-onlyrecipient: principal, startup-id: uint
get-startup-equityread-onlystartup-id: uint