Source Code

;; @contract Commission
;; @version 1
;;
;; Part of the stacking rewards are captured as commission.
;; The commission is split between the protocol and stakers.

(impl-trait .commission-trait-v1.commission-trait)
(use-trait staking-trait .staking-trait-v1.staking-trait)

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

(define-constant ERR_MIN_STAKING_BASISPOINTS u29001)

(define-constant MIN_STAKING_BASISPOINTS u7000) ;; 70% in basis points

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

(define-data-var staking-basispoints uint u0) ;; 0% in basis points, set later

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

(define-read-only (get-staking-basispoints)
  (var-get staking-basispoints)
)

;;-------------------------------------
;; Helpers 
;;-------------------------------------

;; Adding rewards for cycle X happens at the end of cycle X+1
;; These rewards are distributed per block during cycle X+2,
;; and the distribution ends at the end of cycle X+2 plus pox-prepare-length
(define-read-only (get-cycle-rewards-end-block) 
  (let (
    (current-cycle (contract-call? 'SP000000000000000000002Q6VF78.pox-3 current-pox-reward-cycle))
    (cycle-end-block (contract-call? 'SP000000000000000000002Q6VF78.pox-3 reward-cycle-to-burn-height (+ current-cycle u2)))
    (pox-prepare-length (get prepare-cycle-length (unwrap-panic (contract-call? 'SP000000000000000000002Q6VF78.pox-3 get-pox-info))))
  )
    (+ cycle-end-block pox-prepare-length)
  )
)

;;-------------------------------------
;; Trait 
;;-------------------------------------

;; Used by core contract
;; Commission is split between stakers and protocol
(define-public (add-commission (staking-contract <staking-trait>) (stx-amount uint))
  (let (
    (amount-for-staking (/ (* stx-amount (get-staking-basispoints)) u10000))
    (amount-to-keep (- stx-amount amount-for-staking))
  )
    (try! (contract-call? .dao check-is-protocol (contract-of staking-contract)))

    ;; Send to stakers
    (if (> amount-for-staking u0)
      (try! (contract-call? staking-contract add-rewards amount-for-staking (get-cycle-rewards-end-block)))
      u0    
    )

    ;; Keep in contract
    (if (> amount-to-keep u0)
      (try! (stx-transfer? amount-to-keep tx-sender (as-contract tx-sender)))
      false
    )

    (ok stx-amount)
  )
)

;;-------------------------------------
;; Get commission 
;;-------------------------------------

(define-public (withdraw-commission)
  (let (
    (receiver tx-sender)
    (amount (stx-get-balance (as-contract tx-sender)))
  )
    (try! (contract-call? .dao check-is-protocol tx-sender))

    (try! (as-contract (stx-transfer? amount tx-sender receiver)))

    (ok amount)
  )
)

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

(define-public (set-staking-basispoints (new-basispoints uint))
  (begin
    (try! (contract-call? .dao check-is-protocol tx-sender))
    (asserts! (>= new-basispoints MIN_STAKING_BASISPOINTS) (err ERR_MIN_STAKING_BASISPOINTS))

    (var-set staking-basispoints new-basispoints)
    (ok true)
  )
)

Functions (5)

FunctionAccessArgs
get-staking-basispointsread-only
get-cycle-rewards-end-blockread-only
add-commissionpublicstaking-contract: <staking-trait>, stx-amount: uint
withdraw-commissionpublic
set-staking-basispointspublicnew-basispoints: uint