Source Code

;; title: NFTUniverse
;; version:
;; summary:
;; description:

;; constants
(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-NOT-OWNER (err u100))
(define-constant ERR-NOT-STAKED (err u101))
(define-constant ERR-ALREADY-STAKED (err u102))
(define-constant ERR-INSUFFICIENT-FUNDS (err u103))
(define-constant ERR-INVALID-NFT (err u104))
(define-constant ERR-COOLDOWN-PERIOD (err u105))

;; data vars
(define-data-var total-staked uint u0)
(define-data-var reward-rate uint u100)
(define-data-var pool-balance uint u0)
(define-data-var contract-enabled bool true)

;; data maps
(define-map staked-nfts 
  { token-id: uint, nft-contract: principal }
  { 
    owner: principal, 
    stake-block: uint,
    last-claim-block: uint
  }
)

(define-map user-stakes 
  principal 
  { 
    nft-count: uint,
    total-rewards: uint
  }
)

;; public functions

(define-public (stake-nft (nft-contract principal) (token-id uint))
  (let (
    (stake-key { token-id: token-id, nft-contract: nft-contract })
    (current-stakes (default-to { nft-count: u0, total-rewards: u0 } (map-get? user-stakes tx-sender)))
  )
    (asserts! (var-get contract-enabled) (err u999))
    (asserts! (is-none (map-get? staked-nfts stake-key)) ERR-ALREADY-STAKED)
    
    (map-set staked-nfts stake-key {
      owner: tx-sender,
      stake-block: stacks-block-height,
      last-claim-block: stacks-block-height
    })
    
    (map-set user-stakes tx-sender {
      nft-count: (+ (get nft-count current-stakes) u1),
      total-rewards: (get total-rewards current-stakes)
    })
    
    (var-set total-staked (+ (var-get total-staked) u1))
    (ok true)
  )
)


(define-public (set-reward-rate (new-rate uint))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-OWNER)
    (var-set reward-rate new-rate)
    (ok true)
  )
)

(define-public (toggle-contract (enabled bool))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-OWNER)
    (var-set contract-enabled enabled)
    (ok true)
  )
)

;; read only functions

(define-read-only (get-stake-info (nft-contract principal) (token-id uint))
  (map-get? staked-nfts { token-id: token-id, nft-contract: nft-contract })
)

(define-read-only (get-user-stakes (user principal))
  (map-get? user-stakes user)
)

(define-read-only (calculate-rewards (stake-key { token-id: uint, nft-contract: principal }))
  (match (map-get? staked-nfts stake-key)
    stake-info
    (let (
      (blocks-staked (- stacks-block-height (get last-claim-block stake-info)))
      (reward-per-block (var-get reward-rate))
    )
      (* blocks-staked reward-per-block)
    )
    u0
  )
)

(define-read-only (get-pending-rewards (nft-contract principal) (token-id uint))
  (calculate-rewards { token-id: token-id, nft-contract: nft-contract })
)

(define-read-only (get-pool-stats)
  {
    total-staked: (var-get total-staked),
    pool-balance: (var-get pool-balance),
    reward-rate: (var-get reward-rate),
    contract-enabled: (var-get contract-enabled)
  }
)

Functions (8)

FunctionAccessArgs
stake-nftpublicnft-contract: principal, token-id: uint
set-reward-ratepublicnew-rate: uint
toggle-contractpublicenabled: bool
get-stake-inforead-onlynft-contract: principal, token-id: uint
get-user-stakesread-onlyuser: principal
calculate-rewardsread-onlystake-key: { token-id: uint, nft-contract: principal }
get-pending-rewardsread-onlynft-contract: principal, token-id: uint
get-pool-statsread-only