Source Code

;; @contract Commission stSTXbtc
;; @version 1
;;
;; Part of the stacking rewards are captured as commission.
;; The commission can be 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 DENOMINATOR_BPS u10000)

;;-------------------------------------
;; 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 (
    (cycle-end-block (reward-cycle-to-burn-height (+ (get-pox-cycle) u2)))
    (pox-prepare-length (get-prepare-cycle-length))
  )
    (+ 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>) (sbtc-amount uint))
  (let (
    (amount-for-staking (/ (* sbtc-amount (get-staking-basispoints)) DENOMINATOR_BPS))
    (amount-to-keep (- sbtc-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! (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token transfer amount-to-keep contract-caller (as-contract tx-sender) none))
      false
    )

    (ok sbtc-amount)
  )
)

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

(define-public (withdraw-commission (amount uint) (receiver principal))
  (begin
    (try! (contract-call? .dao check-is-protocol contract-caller))

    (try! (as-contract (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token transfer amount tx-sender receiver none)))

    (ok amount)
  )
)

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

(define-public (set-staking-basispoints (new-basispoints uint))
  (begin
    (try! (contract-call? .dao check-is-protocol tx-sender))

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

;;-------------------------------------
;; PoX Helpers
;;-------------------------------------

(define-read-only (get-pox-cycle)
  (contract-call? 'SP000000000000000000002Q6VF78.pox-4 current-pox-reward-cycle)
)

(define-read-only (reward-cycle-to-burn-height (cycle-id uint)) 
  (contract-call? 'SP000000000000000000002Q6VF78.pox-4 reward-cycle-to-burn-height cycle-id)
)

(define-read-only (get-prepare-cycle-length)
  (get prepare-cycle-length (unwrap-panic (contract-call? 'SP000000000000000000002Q6VF78.pox-4 get-pox-info)))
)

Functions (8)

FunctionAccessArgs
get-staking-basispointsread-only
get-cycle-rewards-end-blockread-only
add-commissionpublicstaking-contract: <staking-trait>, sbtc-amount: uint
withdraw-commissionpublicamount: uint, receiver: principal
set-staking-basispointspublicnew-basispoints: uint
get-pox-cycleread-only
reward-cycle-to-burn-heightread-onlycycle-id: uint
get-prepare-cycle-lengthread-only