Source Code

;; Prediction Market Smart Contract
;; Author: Christopher Perceptions
;; Powered by NoCodeClarity v2

;; Constants
(define-constant contract-owner tx-sender)
(define-constant err-owner-only (err u100))
(define-constant err-not-found (err u101))
(define-constant err-already-resolved (err u102))
(define-constant err-market-not-resolved (err u103))
(define-constant err-no-reward (err u104))
(define-constant err-already-participated (err u105))
(define-constant err-transfer-failed (err u106))
(define-constant err-invalid-question (err u107))
(define-constant err-invalid-amount (err u108))

;; Platform fee constant (0.01 STX = 10000 uSTX)
(define-constant platform-fee u10000)

;; Data vars
(define-data-var market-nonce uint u1)
(define-data-var platform-balance uint u0)

;; Maps
(define-map markets uint {question: (string-utf8 256), creator: principal, yes-amount: uint, no-amount: uint, resolved: bool, outcome: (optional bool)})
(define-map market-balances {market-id: uint, user: principal} {yes: uint, no: uint, claimed: bool})

;; Public functions

(define-public (create-market (question (string-utf8 256)))
  (let
    ((market-id (var-get market-nonce))
     (question-length (len question)))
    
    ;; Validate question length
    (asserts! (and (> question-length u0) (<= question-length u256)) (err err-invalid-question))
    
    ;; Create market
    (map-set markets market-id 
      {question: question, 
       creator: tx-sender, 
       yes-amount: u0, 
       no-amount: u0, 
       resolved: false, 
       outcome: none})
    
    ;; Increment market nonce
    (var-set market-nonce (+ market-id u1))
    
    (ok market-id)))

(define-public (buy-prediction (market-id uint) (amount uint) (prediction bool))
  (let
    ((market (unwrap! (map-get? markets market-id) (err err-not-found)))
     (balance (default-to {yes: u0, no: u0, claimed: false} (map-get? market-balances {market-id: market-id, user: tx-sender}))))
    
    ;; Validate input
    (asserts! (> amount u0) (err err-invalid-amount))
    (asserts! (not (get resolved market)) (err err-already-resolved))
    (asserts! (if prediction
                (is-eq (get no balance) u0)
                (is-eq (get yes balance) u0))
              (err err-already-participated))
    
    (match (stx-transfer? (+ amount platform-fee) tx-sender (as-contract tx-sender))
      success (begin
        ;; Update platform balance
        (var-set platform-balance (+ (var-get platform-balance) platform-fee))
        
        ;; Update market
        (map-set markets market-id 
          (merge market 
            {yes-amount: (if prediction (+ (get yes-amount market) amount) (get yes-amount market)),
             no-amount: (if prediction (get no-amount market) (+ (get no-amount market) amount))}))

        ;; Update user balance
        (map-set market-balances {market-id: market-id, user: tx-sender} 
          (merge balance 
            {yes: (if prediction (+ (get yes balance) amount) (get yes balance)),
             no: (if prediction (get no balance) (+ (get no balance) amount))}))
        
        (ok true))
      error (err err-transfer-failed))))

(define-public (resolve-market (market-id uint) (outcome bool))
  (let
    ((market (unwrap! (map-get? markets market-id) (err err-not-found))))
    
    (asserts! (is-eq tx-sender (get creator market)) (err err-owner-only))
    (asserts! (not (get resolved market)) (err err-already-resolved))
    
    (map-set markets market-id (merge market {resolved: true, outcome: (some outcome)}))
    
    (print (merge {event: "market-resolved"} market))
    
    (ok true)))

(define-public (claim-reward (market-id uint))
  (let 
    ((market (unwrap! (map-get? markets market-id) (err err-not-found)))
     (balance (unwrap! (map-get? market-balances {market-id: market-id, user: tx-sender}) (err err-not-found))))
    
    (asserts! (get resolved market) (err err-market-not-resolved))
    (asserts! (not (get claimed balance)) (err err-no-reward))
    
    (match (get outcome market)
      outcome (let 
        ((total-pot (+ (get yes-amount market) (get no-amount market)))
         (winning-amount (if outcome (get yes-amount market) (get no-amount market)))
         (user-stake (if outcome (get yes balance) (get no balance)))
         (reward (/ (* user-stake total-pot) winning-amount)))
        
        (asserts! (> reward u0) (err err-no-reward))
        (match (as-contract (stx-transfer? reward tx-sender tx-sender))
          success (begin
            (map-set market-balances {market-id: market-id, user: tx-sender} (merge balance {claimed: true}))
            (ok reward))
          error (err err-transfer-failed)))
      (err err-market-not-resolved))))

(define-public (withdraw-platform-fees)
  (let ((balance (var-get platform-balance)))
    (asserts! (is-eq tx-sender contract-owner) (err err-owner-only))
    (asserts! (> balance u0) (err err-no-reward))
    (match (as-contract (stx-transfer? balance contract-owner tx-sender))
      success (begin
        (var-set platform-balance u0)
        (ok balance))
      error (err err-transfer-failed))))

;; Read-only functions

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

(define-read-only (get-balance (market-id uint) (user principal))
  (map-get? market-balances {market-id: market-id, user: user}))

(define-read-only (get-platform-balance)
  (var-get platform-balance))

Functions (8)

FunctionAccessArgs
create-marketpublicquestion: (string-utf8 256
buy-predictionpublicmarket-id: uint, amount: uint, prediction: bool
resolve-marketpublicmarket-id: uint, outcome: bool
claim-rewardpublicmarket-id: uint
withdraw-platform-feespublic
get-marketread-onlymarket-id: uint
get-balanceread-onlymarket-id: uint, user: principal
get-platform-balanceread-only