Source Code

;; Title: Stream Math Library
;; Version: 1.0.0
;; Summary: Precision calculation engine for salary streaming
;; Description: Handles rate calculations, vesting schedules, and earnings with overflow protection

;; ============================================
;; Constants - Error Codes
;; ============================================
(define-constant ERR_DIVISION_BY_ZERO (err u3000))
(define-constant ERR_OVERFLOW (err u3001))
(define-constant ERR_INVALID_INPUT (err u3002))
(define-constant ERR_CLIFF_NOT_REACHED (err u3003))

;; ============================================
;; Constants - Configuration
;; ============================================
(define-constant PRECISION_MULTIPLIER u1000000) ;; 6 decimal places for precision
(define-constant MAX_UINT u340282366920938463463374607431768211455) ;; u128 max

;; ============================================
;; Read-Only Functions - Rate Calculations
;; ============================================

;; Calculate rate per block: total-amount / duration-blocks
;; Returns rate with precision multiplier applied
(define-read-only (calculate-rate-per-block (total-amount uint) (duration-blocks uint))
    (begin
        (asserts! (> duration-blocks u0) ERR_DIVISION_BY_ZERO)
        (asserts! (> total-amount u0) ERR_INVALID_INPUT)
        
        ;; Simple division for rate per block
        (ok (/ total-amount duration-blocks))
    )
)

;; Calculate earned amount based on blocks elapsed
;; earned = (current-block - last-withdrawal-block) * rate-per-block
(define-read-only (calculate-earned 
    (current-block uint) 
    (last-withdrawal-block uint) 
    (rate-per-block uint))
    (let
        (
            (blocks-elapsed (- current-block last-withdrawal-block))
        )
        (asserts! (>= current-block last-withdrawal-block) ERR_INVALID_INPUT)
        
        ;; Check for overflow before multiplication
        (asserts! (<= blocks-elapsed (/ MAX_UINT rate-per-block)) ERR_OVERFLOW)
        
        (ok (* blocks-elapsed rate-per-block))
    )
)

;; ============================================
;; Read-Only Functions - Vesting Calculations
;; ============================================

;; Calculate vested amount with linear vesting
;; Returns the amount that has vested up to current-block
(define-read-only (calculate-linear-vested
    (total-amount uint)
    (start-block uint)
    (end-block uint)
    (current-block uint))
    (begin
        (asserts! (> end-block start-block) ERR_INVALID_INPUT)
        (asserts! (>= current-block start-block) ERR_INVALID_INPUT)
        
        (if (>= current-block end-block)
            ;; Fully vested
            (ok total-amount)
            ;; Partially vested: (current - start) / (end - start) * total
            (let
                (
                    (elapsed (- current-block start-block))
                    (duration (- end-block start-block))
                )
                (ok (/ (* total-amount elapsed) duration))
            )
        )
    )
)

;; Calculate vested amount with cliff period
;; Returns 0 if cliff not reached, otherwise calculates linear vesting from cliff
(define-read-only (calculate-cliff-vested
    (total-amount uint)
    (start-block uint)
    (cliff-block uint)
    (end-block uint)
    (current-block uint))
    (begin
        (asserts! (>= cliff-block start-block) ERR_INVALID_INPUT)
        (asserts! (>= end-block cliff-block) ERR_INVALID_INPUT)
        
        ;; Check if cliff has been reached
        (if (< current-block cliff-block)
            ;; Cliff not reached, nothing vested
            (ok u0)
            ;; Cliff reached, calculate linear vesting
            (if (>= current-block end-block)
                ;; Fully vested
                (ok total-amount)
                ;; Partially vested from cliff to end
                (let
                    (
                        (elapsed (- current-block cliff-block))
                        (duration (- end-block cliff-block))
                    )
                    (if (is-eq duration u0)
                        ;; Cliff at end, fully vest
                        (ok total-amount)
                        (ok (/ (* total-amount elapsed) duration))
                    )
                )
            )
        )
    )
)

;; ============================================
;; Read-Only Functions - Withdrawable Amount
;; ============================================

;; Calculate withdrawable amount (earned and vested, minus already withdrawn)
(define-read-only (calculate-withdrawable
    (total-earned uint)
    (total-vested uint)
    (total-withdrawn uint))
    (let
        (
            ;; Withdrawable is the minimum of earned and vested
            (available (if (< total-earned total-vested) total-earned total-vested))
        )
        (asserts! (>= available total-withdrawn) ERR_INVALID_INPUT)
        (ok (- available total-withdrawn))
    )
)

;; ============================================
;; Read-Only Functions - Remaining Amount
;; ============================================

;; Calculate remaining amount in stream
(define-read-only (calculate-remaining (total-amount uint) (total-withdrawn uint))
    (begin
        (asserts! (>= total-amount total-withdrawn) ERR_INVALID_INPUT)
        (ok (- total-amount total-withdrawn))
    )
)

;; ============================================
;; Read-Only Functions - Completion Check
;; ============================================

;; Check if stream is completed (all funds withdrawn)
(define-read-only (is-stream-completed (total-amount uint) (total-withdrawn uint))
    (ok (is-eq total-amount total-withdrawn))
)

;; ============================================
;; Read-Only Functions - Progress Percentage
;; ============================================

;; Calculate progress percentage (0-100)
(define-read-only (calculate-progress-percentage 
    (current-block uint)
    (start-block uint)
    (end-block uint))
    (begin
        (asserts! (> end-block start-block) ERR_DIVISION_BY_ZERO)
        
        (if (< current-block start-block)
            (ok u0)
            (if (>= current-block end-block)
                (ok u100)
                (let
                    (
                        (elapsed (- current-block start-block))
                        (duration (- end-block start-block))
                    )
                    (ok (/ (* elapsed u100) duration))
                )
            )
        )
    )
)

;; ============================================
;; Read-Only Functions - Safe Math Operations
;; ============================================

;; Safe addition with overflow check
(define-read-only (safe-add (a uint) (b uint))
    (let
        (
            (result (+ a b))
        )
        (asserts! (>= result a) ERR_OVERFLOW)
        (ok result)
    )
)

;; Safe subtraction with underflow check
(define-read-only (safe-sub (a uint) (b uint))
    (begin
        (asserts! (>= a b) ERR_INVALID_INPUT)
        (ok (- a b))
    )
)

;; Safe multiplication with overflow check
(define-read-only (safe-mul (a uint) (b uint))
    (begin
        (if (is-eq a u0)
            (ok u0)
            (begin
                (asserts! (<= b (/ MAX_UINT a)) ERR_OVERFLOW)
                (ok (* a b))
            )
        )
    )
)

;; Safe division with zero check
(define-read-only (safe-div (a uint) (b uint))
    (begin
        (asserts! (> b u0) ERR_DIVISION_BY_ZERO)
        (ok (/ a b))
    )
)

Functions (12)

FunctionAccessArgs
calculate-rate-per-blockread-onlytotal-amount: uint, duration-blocks: uint
calculate-earnedread-onlycurrent-block: uint, last-withdrawal-block: uint, rate-per-block: uint
calculate-linear-vestedread-onlytotal-amount: uint, start-block: uint, end-block: uint, current-block: uint
calculate-cliff-vestedread-onlytotal-amount: uint, start-block: uint, cliff-block: uint, end-block: uint, current-block: uint
calculate-withdrawableread-onlytotal-earned: uint, total-vested: uint, total-withdrawn: uint
calculate-remainingread-onlytotal-amount: uint, total-withdrawn: uint
is-stream-completedread-onlytotal-amount: uint, total-withdrawn: uint
calculate-progress-percentageread-onlycurrent-block: uint, start-block: uint, end-block: uint
safe-addread-onlya: uint, b: uint
safe-subread-onlya: uint, b: uint
safe-mulread-onlya: uint, b: uint
safe-divread-onlya: uint, b: uint