Source Code

;; prediction-market - Clarity 4
;; Prediction markets for healthcare outcomes and genomic research

(define-constant ERR-NOT-FOUND (err u100))
(define-constant ERR-NOT-AUTHORIZED (err u101))
(define-constant ERR-MARKET-CLOSED (err u102))
(define-constant ERR-ALREADY-RESOLVED (err u103))
(define-constant ERR-INSUFFICIENT-STAKE (err u104))

(define-map prediction-markets uint
  {
    market-question: (string-utf8 500),
    category: (string-ascii 50),
    creator: principal,
    created-at: uint,
    resolution-deadline: uint,
    total-stake: uint,
    is-resolved: bool,
    outcome: (optional (string-ascii 50)),
    resolved-at: (optional uint)
  }
)

(define-map market-outcomes { market-id: uint, outcome: (string-ascii 50) }
  {
    total-stake: uint,
    outcome-probability: uint,
    last-updated: uint
  }
)

(define-map participant-positions { market-id: uint, participant: principal, outcome: (string-ascii 50) }
  {
    stake-amount: uint,
    staked-at: uint,
    is-claimed: bool
  }
)

(define-map market-validators principal
  {
    validator-name: (string-utf8 100),
    total-validations: uint,
    successful-validations: uint,
    reputation-score: uint,
    is-active: bool
  }
)

(define-data-var market-counter uint u0)
(define-data-var min-stake-amount uint u1000)

(define-public (create-market
    (market-question (string-utf8 500))
    (category (string-ascii 50))
    (duration uint))
  (let ((market-id (+ (var-get market-counter) u1)))
    (map-set prediction-markets market-id
      {
        market-question: market-question,
        category: category,
        creator: tx-sender,
        created-at: stacks-block-time,
        resolution-deadline: (+ stacks-block-time duration),
        total-stake: u0,
        is-resolved: false,
        outcome: none,
        resolved-at: none
      })
    (var-set market-counter market-id)
    (ok market-id)))

(define-public (place-stake
    (market-id uint)
    (outcome (string-ascii 50))
    (stake-amount uint))
  (let ((market (unwrap! (map-get? prediction-markets market-id) ERR-NOT-FOUND))
        (current-outcome (default-to
                          { total-stake: u0, outcome-probability: u0, last-updated: u0 }
                          (map-get? market-outcomes { market-id: market-id, outcome: outcome }))))
    (asserts! (> stake-amount (var-get min-stake-amount)) ERR-INSUFFICIENT-STAKE)
    (asserts! (not (get is-resolved market)) ERR-ALREADY-RESOLVED)
    (asserts! (< stacks-block-time (get resolution-deadline market)) ERR-MARKET-CLOSED)
    (map-set participant-positions { market-id: market-id, participant: tx-sender, outcome: outcome }
      {
        stake-amount: stake-amount,
        staked-at: stacks-block-time,
        is-claimed: false
      })
    (map-set market-outcomes { market-id: market-id, outcome: outcome }
      {
        total-stake: (+ (get total-stake current-outcome) stake-amount),
        outcome-probability: u0,
        last-updated: stacks-block-time
      })
    (map-set prediction-markets market-id
      (merge market { total-stake: (+ (get total-stake market) stake-amount) }))
    (ok true)))

(define-public (resolve-market
    (market-id uint)
    (winning-outcome (string-ascii 50)))
  (let ((market (unwrap! (map-get? prediction-markets market-id) ERR-NOT-FOUND)))
    (asserts! (is-eq tx-sender (get creator market)) ERR-NOT-AUTHORIZED)
    (asserts! (not (get is-resolved market)) ERR-ALREADY-RESOLVED)
    (asserts! (>= stacks-block-time (get resolution-deadline market)) ERR-MARKET-CLOSED)
    (ok (map-set prediction-markets market-id
      (merge market {
        is-resolved: true,
        outcome: (some winning-outcome),
        resolved-at: (some stacks-block-time)
      })))))

(define-public (claim-winnings
    (market-id uint)
    (outcome (string-ascii 50)))
  (let ((market (unwrap! (map-get? prediction-markets market-id) ERR-NOT-FOUND))
        (position (unwrap! (map-get? participant-positions { market-id: market-id, participant: tx-sender, outcome: outcome }) ERR-NOT-FOUND)))
    (asserts! (get is-resolved market) ERR-NOT-FOUND)
    (asserts! (is-eq (unwrap! (get outcome market) ERR-NOT-FOUND) outcome) ERR-NOT-AUTHORIZED)
    (asserts! (not (get is-claimed position)) ERR-NOT-AUTHORIZED)
    (ok (map-set participant-positions { market-id: market-id, participant: tx-sender, outcome: outcome }
      (merge position { is-claimed: true })))))

(define-public (register-validator
    (validator-name (string-utf8 100)))
  (ok (map-set market-validators tx-sender
    {
      validator-name: validator-name,
      total-validations: u0,
      successful-validations: u0,
      reputation-score: u50,
      is-active: true
    })))

(define-read-only (get-market (market-id uint))
  (ok (map-get? prediction-markets market-id)))

(define-read-only (get-outcome-stats (market-id uint) (outcome (string-ascii 50)))
  (ok (map-get? market-outcomes { market-id: market-id, outcome: outcome })))

(define-read-only (get-participant-position (market-id uint) (participant principal) (outcome (string-ascii 50)))
  (ok (map-get? participant-positions { market-id: market-id, participant: participant, outcome: outcome })))

(define-read-only (get-validator (validator principal))
  (ok (map-get? market-validators validator)))

(define-read-only (validate-principal (p principal))
  (principal-destruct? p))

(define-read-only (format-market-id (market-id uint))
  (ok (int-to-ascii market-id)))

(define-read-only (parse-market-id (id-str (string-ascii 20)))
  (string-to-uint? id-str))

(define-read-only (get-bitcoin-block)
  (ok burn-block-height))

Functions (13)

FunctionAccessArgs
create-marketpublicmarket-question: (string-utf8 500
place-stakepublicmarket-id: uint, outcome: (string-ascii 50
resolve-marketpublicmarket-id: uint, winning-outcome: (string-ascii 50
claim-winningspublicmarket-id: uint, outcome: (string-ascii 50
register-validatorpublicvalidator-name: (string-utf8 100
get-marketread-onlymarket-id: uint
get-outcome-statsread-onlymarket-id: uint, outcome: (string-ascii 50
get-participant-positionread-onlymarket-id: uint, participant: principal, outcome: (string-ascii 50
get-validatorread-onlyvalidator: principal
validate-principalread-onlyp: principal
format-market-idread-onlymarket-id: uint
parse-market-idread-onlyid-str: (string-ascii 20
get-bitcoin-blockread-only