Source Code

;; @contract Stacker Contract
;; @version 1

;; Stacker can initiate stacking, increase or extend
;; Stacks the STX tokens in pox-3

;; Mainnet pox contract: SP000000000000000000002Q6VF78.pox-3
;; Random addr to use for hashbytes testing: 0x00 & 0xf632e6f9d29bfb07bc8948ca6e0dd09358f003ac

(use-trait reserve-trait .reserve-trait-v1.reserve-trait)

;;-------------------------------------
;; Constants 
;;-------------------------------------

(define-constant ERR_NOT_AUTHORIZED u14401)

;;-------------------------------------
;; Variables 
;;-------------------------------------

(define-data-var stacking-unlock-burn-height uint u0) ;; When is this cycle over
(define-data-var stacking-stx-stacked uint u0) ;; How many stx did we stack in this cycle

;;-------------------------------------
;; Getters 
;;-------------------------------------

(define-read-only (get-stacking-unlock-burn-height)
  (var-get stacking-unlock-burn-height)
)

;; Gets the variable info directly
;; However, when stacking stopped this var is not reset to 0
;; Use method `get-stx-stacked` to know how many STX stacked
(define-read-only (get-stacking-stx-stacked)
  (var-get stacking-stx-stacked)
)

(define-read-only (get-stx-balance)
  (stx-get-balance (as-contract tx-sender))
)

(define-read-only (get-stx-stacked)
  (if (> burn-block-height (get-stacking-unlock-burn-height))
    u0
    (var-get stacking-stx-stacked)
  )
)

(define-read-only (get-stacker-info)
  (contract-call? 'SP000000000000000000002Q6VF78.pox-3 get-stacker-info (as-contract tx-sender))
)

(define-read-only (get-stx-account)
  (stx-account (as-contract tx-sender))
)

(define-read-only (get-pox-info)
  (unwrap-panic (contract-call? 'SP000000000000000000002Q6VF78.pox-3 get-pox-info))
)

;;-------------------------------------
;; Stacking helpers (error int to uint)
;;-------------------------------------

(define-private (pox-stack-stx
    (pox-address (tuple (version (buff 1)) (hashbytes (buff 32))))
    (tokens-to-stack uint)
    (start-burn-height uint)
    (lock-period uint)
  )
  (match (as-contract (contract-call? 'SP000000000000000000002Q6VF78.pox-3 stack-stx tokens-to-stack pox-address start-burn-height lock-period))
    result (ok result)
    error (err (to-uint error))
  )
)

(define-private (pox-stack-increase (additional-tokens-to-stack uint))
  (match (as-contract (contract-call? 'SP000000000000000000002Q6VF78.pox-3 stack-increase additional-tokens-to-stack))
    result (ok result)
    error (err (to-uint error))
  )
)

(define-private (pox-stack-extend (extend-count uint) (pox-address { version: (buff 1), hashbytes: (buff 32) }))
  (match (as-contract (contract-call? 'SP000000000000000000002Q6VF78.pox-3 stack-extend extend-count pox-address))
    result (ok result)
    error (err (to-uint error))
  )
)

;;-------------------------------------
;; Stacking 
;;-------------------------------------

;; Initiate stacking
;; Only to be called when contract is not stacking yet
(define-public (initiate-stacking
    (reserve-contract <reserve-trait>)
    (pox-address (tuple (version (buff 1)) (hashbytes (buff 32))))
    (tokens-to-stack uint)
    (start-burn-height uint)
    (lock-period uint)
  )
  (begin
    (try! (contract-call? .dao check-is-protocol tx-sender))
    (try! (contract-call? .dao check-is-enabled))
    (try! (contract-call? .dao check-is-protocol (contract-of reserve-contract)))

    ;; Get STX tokens from reserve
    (try! (as-contract (contract-call? reserve-contract request-stx-to-stack tokens-to-stack)))

    ;; Stack
    (let (
      (result (try! (pox-stack-stx pox-address tokens-to-stack start-burn-height lock-period)))
    )
      (var-set stacking-unlock-burn-height (get unlock-burn-height result))
      (var-set stacking-stx-stacked (get lock-amount result))
    )

    (ok tokens-to-stack)
  )
)

;; Call when extra STX tokens need to be stacked. Call `stack-extend` afterwards.
(define-public (stack-increase (reserve-contract <reserve-trait>) (additional-tokens-to-stack uint))
  (let (
    (stx-balance (get-stx-balance))
  )
    (try! (contract-call? .dao check-is-protocol tx-sender))
    (try! (contract-call? .dao check-is-enabled))
    (try! (contract-call? .dao check-is-protocol (contract-of reserve-contract)))

    ;; Get extra STX tokens
    (try! (contract-call? reserve-contract request-stx-to-stack additional-tokens-to-stack))

    ;; Increase stacking
    (let (
      (result (try! (pox-stack-increase additional-tokens-to-stack)))
    )
      (var-set stacking-stx-stacked (get total-locked result))
    )

    (ok additional-tokens-to-stack)
  )
)

;; Extend stacking cycle. Should be called after `stack-increase`.
(define-public (stack-extend (extend-count uint) (pox-address { version: (buff 1), hashbytes: (buff 32) }))
  (begin
    (try! (contract-call? .dao check-is-protocol tx-sender))
    (try! (contract-call? .dao check-is-enabled))

    ;; Extend stacking
    (let (
      (result (try! (pox-stack-extend extend-count pox-address)))
    )
      (var-set stacking-unlock-burn-height (get unlock-burn-height result))
    )

    (ok extend-count)
  )
)

;;-------------------------------------
;; Admin 
;;-------------------------------------

;; Return STX to the STX reserve
(define-public (return-stx (reserve-contract <reserve-trait>))
  (let (
    (stx-amount (stx-get-balance (as-contract tx-sender)))
  )
    (try! (contract-call? .dao check-is-enabled))
    (try! (contract-call? .dao check-is-protocol (contract-of reserve-contract)))

    (if (> stx-amount u0)
      (try! (as-contract (contract-call? reserve-contract return-stx-from-stacking stx-amount)))
      u0
    )
    (ok stx-amount)
  )
)

Functions (12)

FunctionAccessArgs
get-stacking-unlock-burn-heightread-only
get-stacking-stx-stackedread-only
get-stx-balanceread-only
get-stx-stackedread-only
get-stacker-inforead-only
get-stx-accountread-only
get-pox-inforead-only
pox-stack-stxprivatepox-address: (tuple (version (buff 1
pox-stack-increaseprivateadditional-tokens-to-stack: uint
initiate-stackingpublicreserve-contract: <reserve-trait>, pox-address: (tuple (version (buff 1
stack-increasepublicreserve-contract: <reserve-trait>, additional-tokens-to-stack: uint
return-stxpublicreserve-contract: <reserve-trait>