Source Code

(use-trait nft-trait 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait)

(define-constant ERR-NOT-AUTHORIZED u401)
(define-constant ERR-BID-NOT-HIGH-ENOUGH u100)
(define-constant ERR-ITEM-NOT-FOR-SALE u101)
(define-constant ERR-INVALID-TRADE u103)
(define-constant ERR-INVALID-STAKE u104)
(define-constant ERR-NOT-A-WHOLE-BUNCH u105)
(define-constant ERR-ITEM-PRICE-TOO-LOW u102)
(define-constant CONTRACT-OWNER tx-sender)

(define-data-var blocks-per-banana uint u72)
(define-data-var monkey-staking-fee uint u5000000)
(define-data-var monkey-unstaking-fee uint u5000000)
(define-data-var split-1 uint u4000)
(define-data-var split-2 uint u2000)
(define-data-var split-3 uint u4000)
(define-data-var address-1 principal 'SP1FGT2GA12XQVFDCBZBVZJTAHX6GSN4P7M8AEPMC)
(define-data-var address-2 principal 'SP2597NW8VYYVV4C22WQF3DK0WGQS8TAVDDPXQ5H8)
(define-data-var address-3 principal 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C)
(define-data-var bgr-address principal .bgr-v2)
(define-data-var monkeys principal 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys)
(define-data-var shutoff-valve bool false)
(define-data-var removing-item-id uint u0)

(define-map stakes { staker: principal, collection: principal, item: uint } { stake-time: uint, points: uint, bgr: uint })
(define-map pool { staker: principal } { stake-time: uint, lifetime-points: uint, points-balance: uint, total-bgr: uint })
(define-map staked-nfts { staker: principal } { ids: (list 2500 uint) })
(define-map owners { collection: principal, item: uint } { owner: principal })

(define-public (stake (item uint))
    (let (
        (points (if (is-some (map-get? stakes { staker: tx-sender, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item })) (unwrap-panic (get points (map-get? stakes { staker: tx-sender, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item }))) u0))
        (balance (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get points-balance (map-get? pool { staker: tx-sender }))) u0))
        (lifetime (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get lifetime-points (map-get? pool { staker: tx-sender }))) u0))
        (bgr (unwrap-panic (contract-call? .bgr-v2 lookup (- item u1))))
        (total-bgr (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get total-bgr (map-get? pool { staker: tx-sender }))) u0))
        (block block-height)
        (prev-time (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get stake-time (map-get? pool { staker: tx-sender }))) u0))
        (points-added (/ (/ (* u1000000 (* total-bgr (- block prev-time))) u10000) (var-get blocks-per-banana)))
        (staked-ids (get-staked-nfts tx-sender))
    )
    (asserts! (is-eq (var-get shutoff-valve) false) (err ERR-NOT-AUTHORIZED))
    (asserts! (is-eq (unwrap-panic (unwrap-panic (contract-call? 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys get-owner item))) tx-sender) (err ERR-NOT-AUTHORIZED))
    (begin 
        (if (> (contract-call? .stake-passes get-passes tx-sender) u0)
          (begin
            (try! (contract-call? 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys transfer item tx-sender (as-contract tx-sender)))  
          )
          (begin
            (try! (contract-call? 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys transfer item tx-sender (as-contract tx-sender)))
            (try! (stx-transfer? (/ (* (var-get monkey-staking-fee) (var-get split-1)) u10000) tx-sender (var-get address-1)))
            (try! (stx-transfer? (/ (* (var-get monkey-staking-fee) (var-get split-2)) u10000) tx-sender (var-get address-2)))
            (try! (stx-transfer? (/ (* (var-get monkey-staking-fee) (var-get split-3)) u10000) tx-sender (var-get address-3)))
          )
        )
        (map-set stakes { staker: tx-sender, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item } { stake-time: block, points: points, bgr: bgr })
        (map-set pool { staker: tx-sender } { stake-time: block, lifetime-points: (+ lifetime points-added), points-balance: (+ balance points-added), total-bgr: (+ total-bgr bgr) })
        (map-set owners { collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item } { owner: tx-sender })
        (map-set staked-nfts { staker: tx-sender }
          { ids: (unwrap-panic (as-max-len? (append staked-ids item) u2500)) }
        )
        (print (map-get? pool { staker: tx-sender }))
        (print (map-get? stakes { staker: tx-sender, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item }))
        (ok (unwrap-panic (contract-call? .stake-passes update-passes tx-sender)))
    )
    )
)

(define-public (unstake (item uint))
    (let (
        (owner (unwrap-panic (get owner (map-get? owners { collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item }))))
        (block block-height)
        (points (if (is-some (map-get? stakes { staker: tx-sender, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item })) (unwrap-panic (get points (map-get? stakes { staker: tx-sender, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item }))) u0))
        (balance (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get points-balance (map-get? pool { staker: tx-sender }))) u0))
        (lifetime (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get lifetime-points (map-get? pool { staker: tx-sender }))) u0))
        (bgr (unwrap-panic (contract-call? .bgr-v2 lookup (- item u1))))
        (total-bgr (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get total-bgr (map-get? pool { staker: tx-sender }))) u0))
        (prev-time (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get stake-time (map-get? pool { staker: tx-sender }))) u0))
        (points-added (/ (/ (* u1000000 (* total-bgr (- block prev-time))) u10000) (var-get blocks-per-banana)))
        (ids (get-staked-nfts tx-sender))
    )
    (asserts! (is-eq (var-get shutoff-valve) false) (err ERR-NOT-AUTHORIZED))
    (asserts! (is-eq owner tx-sender) (err ERR-NOT-AUTHORIZED))
    (var-set removing-item-id item)
    (begin 
        (print points)
        (try! (as-contract (contract-call? 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys transfer item (as-contract tx-sender) owner )))
        (try! (stx-transfer? (/ (* (var-get monkey-unstaking-fee) (var-get split-1)) u10000) tx-sender (var-get address-1)))
        (try! (stx-transfer? (/ (* (var-get monkey-unstaking-fee) (var-get split-2)) u10000) tx-sender (var-get address-2)))
        (try! (stx-transfer? (/ (* (var-get monkey-unstaking-fee) (var-get split-3)) u10000) tx-sender (var-get address-3)))
        (map-set stakes { staker: tx-sender, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item } { stake-time: block, points: points-added, bgr: bgr  })
        (map-set pool { staker: tx-sender } { stake-time: block, lifetime-points: (+ lifetime points-added), points-balance: (+ balance points-added), total-bgr: (- total-bgr bgr) })
        (map-set staked-nfts { staker: tx-sender }
          { ids: (filter remove-item-id ids) }
        )
        (print (map-get? stakes { staker: tx-sender, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item }))
        (print (map-get? pool { staker: tx-sender }))
        (ok true)
    )
    )
)

(define-private (remove-item-id (item-id uint))
  (if (is-eq item-id (var-get removing-item-id))
    false
    true
  )
)

(define-public (harvest)
    (let (
        (block block-height)
        (owner tx-sender)
        (balance (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get points-balance (map-get? pool { staker: tx-sender }))) u0))
        (lifetime (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get lifetime-points (map-get? pool { staker: tx-sender }))) u0))
        (total-bgr (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get total-bgr (map-get? pool { staker: tx-sender }))) u0))
        (prev-time (if (is-some (map-get? pool { staker: tx-sender })) (unwrap-panic (get stake-time (map-get? pool { staker: tx-sender }))) u0))
        (points-added (/ (/ (* u1000000 (* total-bgr (- block prev-time))) u10000) (var-get blocks-per-banana)))
        (to-harvest (+ balance points-added))
    )
    (asserts! (is-eq (var-get shutoff-valve) false) (err ERR-NOT-AUTHORIZED))
    (begin 
        (try! (as-contract (contract-call? .btc-monkeys-bananas harvest-bananas owner to-harvest)))
        (map-set pool { staker: tx-sender } { stake-time: block, lifetime-points: (+ lifetime points-added), points-balance: u0, total-bgr: total-bgr })
        (print (map-get? pool { staker: tx-sender }))
        (ok true)
    )
    )
)

(define-public (admin-unstake (item uint))
    (let (
        (owner (unwrap-panic (get owner (map-get? owners { collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item }))))
        (block block-height)
        (points (if (is-some (map-get? stakes { staker: owner, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item })) (unwrap-panic (get points (map-get? stakes { staker: owner, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item }))) u0))
        (balance (if (is-some (map-get? pool { staker: owner })) (unwrap-panic (get points-balance (map-get? pool { staker: owner }))) u0))
        (lifetime (if (is-some (map-get? pool { staker: owner })) (unwrap-panic (get lifetime-points (map-get? pool { staker: owner }))) u0))
        (bgr (unwrap-panic (contract-call? .bgr-v2 lookup (- item u1))))
        (total-bgr (if (is-some (map-get? pool { staker: owner })) (unwrap-panic (get total-bgr (map-get? pool { staker: owner }))) u0))
        (prev-time (if (is-some (map-get? pool { staker: owner })) (unwrap-panic (get stake-time (map-get? pool { staker: owner }))) u0))
        (points-added (/ (/ (* u1000000 (* total-bgr (- block prev-time))) u10000) (var-get blocks-per-banana)))
        (ids (get-staked-nfts owner))
    )
    (asserts! (is-eq tx-sender CONTRACT-OWNER) (err ERR-NOT-AUTHORIZED))
    (begin 
        (print points)
        (try! (as-contract (contract-call? 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys transfer item (as-contract tx-sender) owner )))
        (map-set stakes { staker: owner, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item } { stake-time: block, points: points-added, bgr: bgr  })
        (map-set pool { staker: owner } { stake-time: block, lifetime-points: (+ lifetime points-added), points-balance: (+ balance points-added), total-bgr: (- total-bgr bgr) })
        (map-set staked-nfts { staker: owner }
          { ids: (filter remove-item-id ids) }
        )
        (print (map-get? stakes { staker: owner, collection: 'SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.bitcoin-monkeys, item: item }))
        (print (map-get? pool { staker: owner }))
        (ok true)
    )
    )
)

(define-read-only (check-staker (staker principal))
    (ok (map-get? pool { staker: staker }))
)

(define-read-only (check-harvest (staker principal))
    (let (
        (block block-height)
        (owner staker)
        (balance (if (is-some (map-get? pool { staker: owner })) (unwrap-panic (get points-balance (map-get? pool { staker: owner }))) u0))
        (lifetime (if (is-some (map-get? pool { staker: owner })) (unwrap-panic (get lifetime-points (map-get? pool { staker: owner }))) u0))
        (total-bgr (if (is-some (map-get? pool { staker: owner })) (unwrap-panic (get total-bgr (map-get? pool { staker: owner }))) u0))
        (prev-time (if (is-some (map-get? pool { staker: owner })) (unwrap-panic (get stake-time (map-get? pool { staker: owner }))) u0))
        (points-added (/ (/ (* u1000000 (* total-bgr (- block prev-time))) u10000) (var-get blocks-per-banana)))
        (to-harvest (+ balance points-added))
    )
    to-harvest
    )
)

(define-read-only (get-staked-nfts (staker principal))
  (default-to
    (list )
    (get ids (map-get? staked-nfts { staker: staker }))
  )
)

(define-public (shutoff-switch (switch bool))
  (if (is-eq tx-sender CONTRACT-OWNER)
    (ok (var-set shutoff-valve switch))
    (err ERR-NOT-AUTHORIZED)
  )
)

(define-public (change-emissions (blocks uint))
  (if (is-eq tx-sender CONTRACT-OWNER)
    (ok (var-set blocks-per-banana blocks))
    (err ERR-NOT-AUTHORIZED)
  )
)

(define-public (monkey-staking-fee-change (amount uint))
  (if (is-eq tx-sender CONTRACT-OWNER)
    (ok (var-set monkey-staking-fee amount))
    (err ERR-NOT-AUTHORIZED)
  )
)

(define-public (monkey-unstaking-fee-change (amount uint))
  (if (is-eq tx-sender CONTRACT-OWNER)
    (ok (var-set monkey-unstaking-fee amount))
    (err ERR-NOT-AUTHORIZED)
  )
)

(define-public (split-one-change (amount uint))
  (if (is-eq tx-sender CONTRACT-OWNER)
    (ok (var-set split-1 amount))
    (err ERR-NOT-AUTHORIZED)
  )
)

(define-public (split-two-change (amount uint))
  (if (is-eq tx-sender CONTRACT-OWNER)
    (ok (var-set split-2 amount))
    (err ERR-NOT-AUTHORIZED)
  )
)

(define-public (split-three-change (amount uint))
  (if (is-eq tx-sender CONTRACT-OWNER)
    (ok (var-set split-3 amount))
    (err ERR-NOT-AUTHORIZED)
  )
)

(define-public (address-one-change (address principal))
  (if (is-eq tx-sender (var-get address-1))
    (ok (var-set address-1 address))
    (err ERR-NOT-AUTHORIZED)
  )
)

(define-public (address-two-change (address principal))
  (if (is-eq tx-sender (var-get address-2))
    (ok (var-set address-2 address))
    (err ERR-NOT-AUTHORIZED)
  )
)

(define-public (address-three-change (address principal))
  (if (is-eq tx-sender (var-get address-3))
    (ok (var-set address-3 address))
    (err ERR-NOT-AUTHORIZED)
  )
)

Functions (18)

FunctionAccessArgs
stakepublicitem: uint
unstakepublicitem: uint
remove-item-idprivateitem-id: uint
harvestpublic
admin-unstakepublicitem: uint
check-stakerread-onlystaker: principal
check-harvestread-onlystaker: principal
get-staked-nftsread-onlystaker: principal
shutoff-switchpublicswitch: bool
change-emissionspublicblocks: uint
monkey-staking-fee-changepublicamount: uint
monkey-unstaking-fee-changepublicamount: uint
split-one-changepublicamount: uint
split-two-changepublicamount: uint
split-three-changepublicamount: uint
address-one-changepublicaddress: principal
address-two-changepublicaddress: principal
address-three-changepublicaddress: principal