Source Code

;; ECONOMY CONTRACT - Prize Pools + Reward Distribution (merged)
;; Manages all funds, escrow, and token rewards

;; ============================================================================
;; CONSTANTS
;; ============================================================================

(define-constant CONTRACT_OWNER tx-sender)
(define-constant ERR_NOT_AUTHORIZED (err u700))
(define-constant ERR_INSUFFICIENT_BALANCE (err u701))
(define-constant ERR_TRANSFER_FAILED (err u702))

(define-constant PLATFORM_FEE_PERCENT u5) ;; 5%
(define-constant BASE_REWARD_TOKENS u10)

;; ============================================================================
;; DATA VARS
;; ============================================================================

(define-data-var platform-treasury uint u0)
(define-data-var total-rewards-distributed uint u0)
(define-data-var reward-pool-balance uint u100000000) ;; 100M initial tokens

;; ============================================================================
;; DATA MAPS
;; ============================================================================

;; Prize pools (for tournaments, wagers, etc.)
(define-map prize-pools
  { pool-id: uint }
  {
    pool-type: (string-ascii 20),
    total-amount: uint,
    distributed: bool,
    created-at: uint
  }
)

;; Escrow balances
(define-map escrow-balances
  { pool-id: uint, player: principal }
  { locked-amount: uint }
)

;; Pending rewards (tokens)
(define-map pending-rewards
  { player: principal }
  {
    platform-tokens: uint,
    stx-amount: uint,
    last-updated: uint
  }
)

;; Claimed rewards history
(define-map claimed-rewards
  { player: principal }
  {
    total-tokens-claimed: uint,
    total-stx-claimed: uint,
    last-claim-at: uint
  }
)

;; ============================================================================
;; REWARD CALCULATION
;; ============================================================================

;; Calculate and add rewards for game completion
(define-public (calculate-rewards (game-id uint))
  (let
    (
      ;; Get game information
      (game (unwrap! (contract-call? .game-core-01 get-game-info game-id) ERR_NOT_AUTHORIZED))
      (player (get player game))
      (won (is-eq (get status game) "won"))
      (difficulty (get difficulty game))
      (time (default-to u0 (get final-time game)))
      (score (default-to u0 (get final-score game)))
      
      ;; Base reward
      (base BASE_REWARD_TOKENS)
      
      ;; Win bonus
      (win-bonus (if won u50 u0))
      
      ;; Difficulty multiplier
      (diff-mult (if (is-eq difficulty u1) u1 (if (is-eq difficulty u2) u2 u4)))
      
      ;; Speed bonus (max 100 tokens)
      (speed-bonus (if (< time u100) (- u100 time) u0))
      
      ;; Get win streak multiplier from player profile
      (streak-mult (contract-call? .player-profile-01 get-streak-multiplier player))
      
      ;; Calculate total
      (subtotal (+ (+ base win-bonus) speed-bonus))
      (with-difficulty (* subtotal diff-mult))
      (final-tokens (* with-difficulty streak-mult))
    )
    ;; Add to pending rewards
    (begin
      (add-pending-rewards player final-tokens u0)
      (ok final-tokens)
    )
  )
)

;; Add tokens to pending rewards
(define-private (add-pending-rewards (player principal) (tokens uint) (stx uint))
  (let
    (
      (current (default-to {platform-tokens: u0, stx-amount: u0, last-updated: u0} 
                           (map-get? pending-rewards {player: player})))
    )
    (map-set pending-rewards
      {player: player}
      {
        platform-tokens: (+ (get platform-tokens current) tokens),
        stx-amount: (+ (get stx-amount current) stx),
        last-updated: stacks-block-height
      }
    )
    true
  )
)

;; ============================================================================
;; ACHIEVEMENT BONUSES
;; ============================================================================

;; Public function to add pending rewards (for external contracts like daily-challenge)
(define-public (add-rewards (player principal) (tokens uint) (stx uint))
  (begin
    (add-pending-rewards player tokens stx)
    (ok true)
  )
)

(define-public (award-achievement-bonus (player principal) (achievement-id uint))
  (let
    (
      ;; Different bonuses per achievement
      (bonus (get-achievement-bonus achievement-id))
    )
    (begin
      (add-pending-rewards player bonus u0)
      (ok bonus)
    )
  )
)

(define-private (get-achievement-bonus (achievement-id uint))
  ;; Legendary achievements = 1000 tokens
  ;; Epic = 500
  ;; Rare = 100
  ;; Common = 50
  (if (or (is-eq achievement-id u12) (is-eq achievement-id u13))
    u1000 ;; World Record, Tournament Victor
    (if (is-eq achievement-id u11)
      u500 ;; Century Club
      (if (or (is-eq achievement-id u2) (is-eq achievement-id u3) (is-eq achievement-id u4))
        u100 ;; Master achievements
        u50 ;; Others
      )
    )
  )
)

;; ============================================================================
;; CLAIM REWARDS
;; ============================================================================

;; Claim pending rewards
(define-public (claim-rewards)
  (let
    (
      (player tx-sender)
      (pending (unwrap! (map-get? pending-rewards {player: player}) ERR_INSUFFICIENT_BALANCE))
      (tokens (get platform-tokens pending))
      (stx (get stx-amount pending))
      (claimed (default-to {total-tokens-claimed: u0, total-stx-claimed: u0, last-claim-at: u0}
                          (map-get? claimed-rewards {player: player})))
    )
    ;; Validate has rewards
    (asserts! (or (> tokens u0) (> stx u0)) ERR_INSUFFICIENT_BALANCE)
    
    ;; Transfer tokens (in production, use FT transfer)
    ;; For now, just update balances
    
    ;; Update claimed history
    (map-set claimed-rewards
      {player: player}
      {
        total-tokens-claimed: (+ (get total-tokens-claimed claimed) tokens),
        total-stx-claimed: (+ (get total-stx-claimed claimed) stx),
        last-claim-at: stacks-block-height
      }
    )
    
    ;; Clear pending
    (map-set pending-rewards
      {player: player}
      {
        platform-tokens: u0,
        stx-amount: u0,
        last-updated: stacks-block-height
      }
    )
    
    ;; Update totals
    (var-set total-rewards-distributed (+ (var-get total-rewards-distributed) tokens))
    
    (ok {tokens: tokens, stx: stx})
  )
)

;; ============================================================================
;; PRIZE POOL MANAGEMENT
;; ============================================================================

;; Lock funds in escrow
(define-public (lock-funds (pool-id uint) (amount uint))
  (let
    (
      (player tx-sender)
    )
    ;; In production, transfer STX to contract
    ;; For now, just track
    (map-set escrow-balances
      {pool-id: pool-id, player: player}
      {locked-amount: amount}
    )
    (ok true)
  )
)

;; Release funds to winner
(define-public (release-funds (pool-id uint) (winner principal) (amount uint))
  (let
    (
      (pool (unwrap! (map-get? prize-pools {pool-id: pool-id}) ERR_NOT_AUTHORIZED))
    )
    ;; Validate not already distributed
    (asserts! (not (get distributed pool)) ERR_NOT_AUTHORIZED)
    
    ;; Calculate platform fee
    (let
      (
        (fee (/ (* amount PLATFORM_FEE_PERCENT) u100))
        (net-amount (- amount fee))
      )
      ;; Add STX to winner's pending rewards
      (begin
        (add-pending-rewards winner u0 net-amount)
        true
      )
      
      ;; Add fee to treasury
      (var-set platform-treasury (+ (var-get platform-treasury) fee))
      
      ;; Mark as distributed
      (map-set prize-pools
        {pool-id: pool-id}
        (merge pool {distributed: true})
      )
      
      (ok net-amount)
    )
  )
)

;; Refund escrowed funds
(define-public (refund-funds (pool-id uint))
  (let
    (
      (player tx-sender)
      (escrow (unwrap! (map-get? escrow-balances {pool-id: pool-id, player: player}) ERR_NOT_AUTHORIZED))
      (amount (get locked-amount escrow))
    )
    ;; In production, transfer STX back
    ;; Clear escrow
    (map-delete escrow-balances {pool-id: pool-id, player: player})
    
    (ok amount)
  )
)

;; ============================================================================
;; READ-ONLY FUNCTIONS
;; ============================================================================

;; Get pending rewards
(define-read-only (get-pending-rewards (player principal))
  (ok (map-get? pending-rewards {player: player}))
)

;; Get claimed rewards
(define-read-only (get-claimed-rewards (player principal))
  (ok (map-get? claimed-rewards {player: player}))
)

;; Get treasury balance
(define-read-only (get-treasury-balance)
  (ok (var-get platform-treasury))
)

;; Get total distributed
(define-read-only (get-total-distributed)
  (ok (var-get total-rewards-distributed))
)

Functions (13)

FunctionAccessArgs
calculate-rewardspublicgame-id: uint
add-pending-rewardsprivateplayer: principal, tokens: uint, stx: uint
add-rewardspublicplayer: principal, tokens: uint, stx: uint
award-achievement-bonuspublicplayer: principal, achievement-id: uint
get-achievement-bonusprivateachievement-id: uint
claim-rewardspublic
lock-fundspublicpool-id: uint, amount: uint
release-fundspublicpool-id: uint, winner: principal, amount: uint
refund-fundspublicpool-id: uint
get-pending-rewardsread-onlyplayer: principal
get-claimed-rewardsread-onlyplayer: principal
get-treasury-balanceread-only
get-total-distributedread-only