Source Code

;; title: stability-vpv-5

;; Stability Trait 
(impl-trait .stability-trait-vpv-5.stability-trait)

;; bsd protocol
(use-trait bsd-trait .bsd-trait-vpv-5.bsd-trait)

;; sip-010-trait
(use-trait sbtc-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait)

;; registry
(use-trait registry-trait .registry-trait-vpv-5.registry-trait)

;; sorted vaults
(use-trait sorted-vaults-trait .sorted-vaults-trait-vpv-5.sorted-vaults-trait)

(define-constant ERR_STABILITY_PROVIDER_NOT_FOUND (err u400))
(define-constant ERR_INSUFFICIENT_LIQUIDITY (err u401))
(define-constant ERR_INSUFFICIENT_REWARDS (err u402))
(define-constant ERR_PROTOCOL_STATE (err u403))
(define-constant ERR_NO_PROTOCOL_DATA (err u404))
(define-constant ERR_MIN_BALANCE (err u405))
(define-constant ERR_NOT_AUTH (err u406))
(define-constant ERR_NO_KEEPER (err u407))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; stability-trait BEGIN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; add-liquidity
(define-public (add-liquidity-wrapper (amount uint) (bsd <bsd-trait>) (sbtc <sbtc-trait>) (registry <registry-trait>) (sorted-vaults <sorted-vaults-trait>))
    (let 
        (
            (valid-registry (try! (contract-call? .controller-vpv-5 check-approved-contract "registry" (contract-of registry))))
            (valid-bsd (try! (contract-call? .controller-vpv-5 check-approved-contract "bsd" (contract-of bsd))))
            (current-provider (try! (contract-call? registry get-stability-pool-provider tx-sender)))
            (is-new-provider (is-eq current-provider none))
            (provider-balance (if is-new-provider u0 (unwrap! (get liquidity-staked current-provider) ERR_STABILITY_PROVIDER_NOT_FOUND)))
            (calculated-rewards (if is-new-provider u0 (try! (contract-call? registry calculate-provider-rewards tx-sender))))
            (protocol-attributes (unwrap-panic (contract-call? registry get-protocol-attributes sorted-vaults)))
            (min-stability-provider-balance (get min-stability-provider-balance protocol-attributes))
            (is-paused (unwrap-panic (contract-call? registry get-is-paused)))        
            (is-maintenance (unwrap-panic (contract-call? registry get-is-maintenance)))        
        )

        ;; check paused
        (asserts! (not is-paused) ERR_PROTOCOL_STATE)

        ;; check maintenance
        (asserts! (not is-maintenance) ERR_PROTOCOL_STATE)

        ;; assert deposit amount is greater than zero
        (asserts! (> amount u0) ERR_MIN_BALANCE)

        (asserts! (>= (+ provider-balance amount) min-stability-provider-balance) ERR_MIN_BALANCE)

        ;; transfer bsd to the stability pool
        (try! (contract-call? bsd protocol-transfer amount tx-sender (as-contract tx-sender)))

        (if (> calculated-rewards u0)
            ;; transfer rewards to the user
            (try! (contract-call? sbtc transfer calculated-rewards  (as-contract tx-sender) tx-sender none))
            true
        )

        ;; call registry to complete
        (try! (contract-call? registry add-liquidity amount tx-sender))
        
        (ok 
            (unwrap-panic (contract-call? registry get-stability-pool-provider tx-sender))
        )
    )
)

;; remove-liquidity
(define-public (remove-liquidity-wrapper (amount uint) (bsd <bsd-trait>) (sbtc <sbtc-trait>) (registry <registry-trait>) (sorted-vaults <sorted-vaults-trait>))
    (let
        (
            (valid-registry (try! (contract-call? .controller-vpv-5 check-approved-contract "registry" (contract-of registry))))
            (valid-bsd (try! (contract-call? .controller-vpv-5 check-approved-contract "bsd" (contract-of bsd))))
            (valid-sbtc (try! (contract-call? .controller-vpv-5 check-approved-contract "sbtc" (contract-of sbtc))))
            (stability-pool (try! (contract-call? registry get-stability-pool-data)))
            (stability-pool-aggregate-balance (get aggregate-bsd stability-pool))
            (current-provider tx-sender)
            (current-entry (unwrap! (contract-call? registry get-stability-pool-provider tx-sender) ERR_STABILITY_PROVIDER_NOT_FOUND))
            (protocol-attributes (unwrap-panic (contract-call? registry get-protocol-attributes sorted-vaults)))
            (min-stability-provider-balance (get min-stability-provider-balance protocol-attributes))
            (current-liquidity-staked (unwrap! (get liquidity-staked current-entry) ERR_STABILITY_PROVIDER_NOT_FOUND))
            (calculated-rewards (try! (contract-call? registry calculate-provider-rewards tx-sender)))
            (is-paused (get is-paused protocol-attributes))
    )

        ;; check paused
        (asserts! (not is-paused) ERR_PROTOCOL_STATE)

        ;; assert deposit amount is greater than zero
        (asserts! (> amount u0) ERR_MIN_BALANCE)

        ;; check that amount being withdrawn is not greater than the aggregate staked
        (asserts! (<= amount stability-pool-aggregate-balance) ERR_INSUFFICIENT_LIQUIDITY)

        ;; check that amount to remove is less than or equal to the amount of liquidity the user has
        (asserts! (<= amount current-liquidity-staked) ERR_INSUFFICIENT_LIQUIDITY)

        (if (or (is-eq amount current-liquidity-staked) (>= (- current-liquidity-staked amount) min-stability-provider-balance))

            (begin
                ;; withdraw liquidity from the stability pool
                (try! (as-contract (contract-call? bsd protocol-transfer amount tx-sender current-provider)))

                (if (> calculated-rewards u0)
                    ;; transfer rewards to the user
                    (try! (contract-call? sbtc transfer calculated-rewards  (as-contract tx-sender) tx-sender none))
                    true
                )
                
                (try! (contract-call? registry remove-liquidity amount tx-sender))
                (ok 
                    (unwrap-panic (contract-call? registry get-stability-pool-provider tx-sender))
                )
            )

            ERR_MIN_BALANCE
        )
    )
)

;; claim-rewards
(define-public (claim-rewards (sbtc <sbtc-trait>) (registry <registry-trait>)) 
(let
        (
            (valid-registry (try! (contract-call? .controller-vpv-5 check-approved-contract "registry" (contract-of registry))))
            (valid-sbtc (try! (contract-call? .controller-vpv-5 check-approved-contract "sbtc" (contract-of sbtc))))
            (current-provider tx-sender)
            (current-entry (try! (contract-call? registry get-stability-pool-provider tx-sender)))
            (provider-balance-bsd (unwrap-panic (get liquidity-staked current-entry)))
            (is-paused (unwrap-panic (contract-call? registry get-is-paused)))
            (calculated-rewards (try! (contract-call? registry calculate-provider-rewards tx-sender)))
    )

        ;; check paused
        (asserts! (not is-paused) ERR_PROTOCOL_STATE)

        ;; check that user has rewards to claim
        (asserts! (> calculated-rewards u0) ERR_INSUFFICIENT_REWARDS)

        (print {
            claim-rewards-event: {
                claim-amount: calculated-rewards,
            }
        })

        ;; transfer rewards to the user
        (try! (contract-call? sbtc transfer calculated-rewards  (as-contract tx-sender) tx-sender none))

        (ok (try! (contract-call? registry claim-rewards tx-sender)))
    )
)

(define-public (unwind-provider (provider principal) (sbtc <sbtc-trait>) (registry <registry-trait>))
    (let
        (
            (valid-registry (try! (contract-call? .controller-vpv-5 check-approved-contract "registry" (contract-of registry))))
            (valid-sbtc (try! (contract-call? .controller-vpv-5 check-approved-contract "sbtc" (contract-of sbtc))))
            (is-keeper (unwrap! (contract-call? .controller-vpv-5 is-keeper tx-sender) ERR_NO_KEEPER))            
            (balance (try! (contract-call? registry get-provider-calculated-balance provider)))
            (rewards (try! (contract-call? registry calculate-provider-rewards provider)))
        )

        ;; check that caller is the keeper
        (asserts! (is-eq true is-keeper) ERR_NOT_AUTH)

        ;; check that vault has no debt
        (asserts! (is-eq balance u0) ERR_MIN_BALANCE)

        ;; send rewards to borrower
        (try! (contract-call? sbtc transfer rewards (as-contract tx-sender) provider none))

        (ok (try! (contract-call? registry unwind-provider provider)))
    )

)

;; vault-manager-burn
(define-public (vault-manager-burn (amount uint) (bsd <bsd-trait>) (registry <registry-trait>))
    (let 
        (
            (valid-registry (try! (contract-call? .controller-vpv-5 check-approved-contract "registry" (contract-of registry))))
            (valid-bsd (try! (contract-call? .controller-vpv-5 check-approved-contract "bsd" (contract-of bsd))))
            (is-paused (unwrap-panic (contract-call? registry get-is-paused)))
        )

        ;; check paused
        (asserts! (not is-paused) ERR_PROTOCOL_STATE)

        ;; check that caller is protocol-caller
        (try! (contract-call? .controller-vpv-5 is-protocol-caller contract-caller))
        
        ;; burn liquidity
        (ok (try! (contract-call? bsd protocol-burn (as-contract tx-sender) amount)))
    )
)

;; protocol-transfer
(define-public (protocol-transfer (to principal) (amount uint) (bsd <bsd-trait>) (registry <registry-trait>))
     (let 
        (
            (valid-registry (try! (contract-call? .controller-vpv-5 check-approved-contract "registry" (contract-of registry))))
            (valid-bsd (try! (contract-call? .controller-vpv-5 check-approved-contract "bsd" (contract-of bsd))))
            (is-paused (unwrap-panic (contract-call? registry get-is-paused)))
        )

        ;; check paused
        (asserts! (not is-paused) ERR_PROTOCOL_STATE)

        ;; check that caller is a protocol contract
        (try! (contract-call? .controller-vpv-5 is-protocol-caller contract-caller))

        ;; finalize transfer of sbtc
        (as-contract (contract-call? bsd protocol-transfer amount tx-sender to))
    )
)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; stability-trait END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Functions (6)

FunctionAccessArgs
add-liquidity-wrapperpublicamount: uint, bsd: <bsd-trait>, sbtc: <sbtc-trait>, registry: <registry-trait>, sorted-vaults: <sorted-vaults-trait>
remove-liquidity-wrapperpublicamount: uint, bsd: <bsd-trait>, sbtc: <sbtc-trait>, registry: <registry-trait>, sorted-vaults: <sorted-vaults-trait>
claim-rewardspublicsbtc: <sbtc-trait>, registry: <registry-trait>
unwind-providerpublicprovider: principal, sbtc: <sbtc-trait>, registry: <registry-trait>
vault-manager-burnpublicamount: uint, bsd: <bsd-trait>, registry: <registry-trait>
protocol-transferpublicto: principal, amount: uint, bsd: <bsd-trait>, registry: <registry-trait>