Source Code

(define-constant contract-owner tx-sender)
(define-constant err-owner-only (err u100))
(define-constant err-not-found (err u101))
(define-constant err-unauthorized (err u102))
(define-constant err-invalid-amount (err u104))

(define-data-var valuation-nonce uint u0)

(define-map valuations
  uint
  {
    analyst: principal,
    entity: principal,
    discount-rate: uint,
    growth-rate: uint,
    terminal-growth: uint,
    projection-years: uint,
    enterprise-value: uint,
    equity-value: uint,
    debt-value: uint,
    cash-value: uint,
    created-block: uint
  }
)

(define-map cash-flows
  {valuation-id: uint, year: uint}
  {
    projected-fcf: uint,
    discount-factor: uint,
    present-value: uint
  }
)

(define-map analyst-valuations principal (list 50 uint))

(define-public (create-valuation (entity principal) (discount uint) (growth uint) (terminal uint) 
                                  (years uint) (debt uint) (cash uint))
  (let
    (
      (valuation-id (+ (var-get valuation-nonce) u1))
    )
    (asserts! (> years u0) err-invalid-amount)
    (map-set valuations valuation-id {
      analyst: tx-sender,
      entity: entity,
      discount-rate: discount,
      growth-rate: growth,
      terminal-growth: terminal,
      projection-years: years,
      enterprise-value: u0,
      equity-value: u0,
      debt-value: debt,
      cash-value: cash,
      created-block: stacks-block-height
    })
    (map-set analyst-valuations tx-sender
      (unwrap-panic (as-max-len? (append (default-to (list) (map-get? analyst-valuations tx-sender)) valuation-id) u50)))
    (var-set valuation-nonce valuation-id)
    (ok valuation-id)
  )
)

(define-public (add-cash-flow (valuation-id uint) (year uint) (fcf uint))
  (let
    (
      (valuation (unwrap! (map-get? valuations valuation-id) err-not-found))
      (discount-factor (calculate-discount-factor valuation-id year))
      (pv (/ (* fcf u100) discount-factor))
    )
    (asserts! (is-eq tx-sender (get analyst valuation)) err-unauthorized)
    (asserts! (<= year (get projection-years valuation)) err-invalid-amount)
    (map-set cash-flows {valuation-id: valuation-id, year: year} {
      projected-fcf: fcf,
      discount-factor: discount-factor,
      present-value: pv
    })
    (ok pv)
  )
)

(define-public (calculate-enterprise-value (valuation-id uint))
  (let
    (
      (valuation (unwrap! (map-get? valuations valuation-id) err-not-found))
      (terminal (calculate-terminal-value valuation-id))
      (pv-fcf (sum-present-values valuation-id))
      (ev (+ pv-fcf terminal))
    )
    (asserts! (is-eq tx-sender (get analyst valuation)) err-unauthorized)
    (map-set valuations valuation-id (merge valuation {enterprise-value: ev}))
    (ok ev)
  )
)

(define-public (calculate-equity-value (valuation-id uint))
  (let
    (
      (valuation (unwrap! (map-get? valuations valuation-id) err-not-found))
      (ev (get enterprise-value valuation))
      (debt (get debt-value valuation))
      (cash (get cash-value valuation))
      (equity (+ (- ev debt) cash))
    )
    (asserts! (is-eq tx-sender (get analyst valuation)) err-unauthorized)
    (map-set valuations valuation-id (merge valuation {equity-value: equity}))
    (ok equity)
  )
)

(define-read-only (get-valuation (valuation-id uint))
  (ok (map-get? valuations valuation-id))
)

(define-read-only (get-cash-flow (valuation-id uint) (year uint))
  (ok (map-get? cash-flows {valuation-id: valuation-id, year: year}))
)

(define-read-only (get-analyst-valuations (analyst principal))
  (ok (map-get? analyst-valuations analyst))
)

(define-read-only (calculate-discount-factor (valuation-id uint) (year uint))
  (let
    (
      (valuation (unwrap-panic (map-get? valuations valuation-id)))
      (rate (get discount-rate valuation))
      (factor (+ u100 (/ rate u100)))
    )
    (pow factor year)
  )
)

(define-read-only (calculate-terminal-value (valuation-id uint))
  (let
    (
      (valuation (unwrap-panic (map-get? valuations valuation-id)))
      (years (get projection-years valuation))
      (last-fcf-data (unwrap-panic (map-get? cash-flows {valuation-id: valuation-id, year: years})))
      (last-fcf (get projected-fcf last-fcf-data))
      (terminal-growth (get terminal-growth valuation))
      (discount (get discount-rate valuation))
      (terminal-fcf (/ (* last-fcf (+ u100 terminal-growth)) u100))
    )
    (/ terminal-fcf (- discount terminal-growth))
  )
)

(define-read-only (sum-present-values (valuation-id uint))
  (let
    (
      (valuation (unwrap-panic (map-get? valuations valuation-id)))
      (years (get projection-years valuation))
    )
    (fold + (map get-pv-for-year (list u1 u2 u3 u4 u5)) u0)
  )
)

(define-private (get-pv-for-year (year uint))
  u0
)

(define-read-only (get-valuation-metrics (valuation-id uint))
  (let
    (
      (valuation (unwrap-panic (map-get? valuations valuation-id)))
    )
    (ok {
      enterprise-value: (get enterprise-value valuation),
      equity-value: (get equity-value valuation),
      discount-rate: (get discount-rate valuation),
      growth-rate: (get growth-rate valuation)
    })
  )
)

Functions (12)

FunctionAccessArgs
create-valuationpublicentity: principal, discount: uint, growth: uint, terminal: uint, years: uint, debt: uint, cash: uint
add-cash-flowpublicvaluation-id: uint, year: uint, fcf: uint
calculate-enterprise-valuepublicvaluation-id: uint
calculate-equity-valuepublicvaluation-id: uint
get-valuationread-onlyvaluation-id: uint
get-cash-flowread-onlyvaluation-id: uint, year: uint
get-analyst-valuationsread-onlyanalyst: principal
calculate-discount-factorread-onlyvaluation-id: uint, year: uint
calculate-terminal-valueread-onlyvaluation-id: uint
sum-present-valuesread-onlyvaluation-id: uint
get-pv-for-yearprivateyear: uint
get-valuation-metricsread-onlyvaluation-id: uint