Source Code

(define-constant ERR-NOT-AUTHORIZED (err u1000))
(define-constant ERR-INVALID-LIQUIDITY (err u2003))
(define-constant ERR-NOT-ACTIVATED (err u2043))
(define-constant ERR-ACTIVATED (err u2044))
(define-constant ERR-PAUSED (err u2046))
(define-constant ERR-INVALID-PERCENT (err u5000))
(define-constant ERR-GET-BALANCE-FIXED-FAIL (err u6001))
(define-constant ERR-USER-ID-NOT-FOUND (err u10003))
(define-constant ERR-STAKING-NOT-AVAILABLE (err u10015))
(define-constant ERR-REWARD-CYCLE-NOT-COMPLETED (err u10017))
(define-constant ERR-CLAIM-AND-STAKE (err u10018))
(define-constant ERR-REQUEST-ID-NOT-FOUND (err u10019))
(define-constant ERR-REQUEST-FINALIZED-OR-REVOKED (err u10020))
(define-constant ERR-REDEMPTION-TOO-HIGH (err u10021))
(define-constant ERR-END-CYCLE-V2 (err u10022))
(define-constant ONE_8 u100000000)
(define-constant REWARD-CYCLE-INDEXES (list u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15 u16 u17 u18 u19 u20 u21 u22 u23 u24 u25 u26 u27 u28 u29 u30 u31 u32))
(define-data-var contract-owner principal tx-sender)
(define-map approved-contracts principal bool)
(define-data-var create-paused bool true)
(define-data-var redeem-paused bool true)
(define-constant redeem-delay-cycles u32)
(define-read-only (get-contract-owner)
  (var-get contract-owner))
(define-read-only (get-pending)
  (contract-call? .auto-alex-v3-1-registry get-pending))
(define-read-only (get-finalized)
  (contract-call? .auto-alex-v3-1-registry get-finalized))
(define-read-only (get-revoked)
  (contract-call? .auto-alex-v3-1-registry get-revoked))
(define-read-only (get-start-cycle)
  (contract-call? .auto-alex-v3-1-registry get-start-cycle))
(define-read-only (is-cycle-staked (reward-cycle uint))
  (contract-call? .auto-alex-v3-1-registry is-cycle-staked reward-cycle))
(define-read-only (get-staked-cycle-shares-to-tokens-or-fail (reward-cycle uint))
  (contract-call? .auto-alex-v3-1-registry get-staked-cycle-shares-to-tokens-or-fail reward-cycle))
(define-read-only (get-redeem-shares-per-cycle-or-default (reward-cycle uint))
  (contract-call? .auto-alex-v3-1-registry get-redeem-shares-per-cycle-or-default reward-cycle))
(define-read-only (get-redeem-tokens-per-cycle-or-default (reward-cycle uint))
  (contract-call? .auto-alex-v3-1-registry get-redeem-tokens-per-cycle-or-default reward-cycle))
(define-read-only (get-redeem-request-or-fail (request-id uint))
  (contract-call? .auto-alex-v3-1-registry get-redeem-request-or-fail request-id))
(define-read-only (is-create-paused)
  (var-get create-paused))
(define-read-only (is-redeem-paused)
  (var-get redeem-paused))
(define-read-only (get-next-base)
  (let (
      (current-cycle (unwrap! (get-reward-cycle block-height) ERR-STAKING-NOT-AVAILABLE))
      (auto-alex-v2-bal (unwrap! (contract-call? .auto-alex-v2 get-balance-fixed .auto-alex-v3-1) ERR-GET-BALANCE-FIXED-FAIL)))
    (asserts! (or (is-eq current-cycle (get-start-cycle)) (is-cycle-staked (- current-cycle u1))) ERR-CLAIM-AND-STAKE)
    (ok
      (+
        (get amount-staked (as-contract (get-staker-at-cycle (+ current-cycle u1))))
        (get to-return (as-contract (get-staker-at-cycle current-cycle)))
        (as-contract (get-staking-reward current-cycle))
        (unwrap! (contract-call? .age000-governance-token get-balance-fixed .auto-alex-v3-1) ERR-GET-BALANCE-FIXED-FAIL)
        (if (is-eq auto-alex-v2-bal u0) u0 (mul-down auto-alex-v2-bal (try! (contract-call? .auto-alex-v2 get-intrinsic))))))))
(define-read-only (get-intrinsic)
  (contract-call? .auto-alex-v3-1 get-shares-to-tokens ONE_8))
(define-read-only (get-shares-to-tokens (dx uint))
  (contract-call? .auto-alex-v3-1 get-shares-to-tokens dx))
(define-read-only (get-tokens-to-shares (dx uint))
  (contract-call? .auto-alex-v3-1 get-tokens-to-shares dx))
(define-public (set-contract-owner (owner principal))
  (begin
    (try! (check-is-owner))
    (ok (var-set contract-owner owner))))
(define-public (set-approved-contract (owner principal) (approved bool))
	(begin
		(try! (check-is-owner))
		(ok (map-set approved-contracts owner approved))))
(define-public (pause-create (pause bool))
  (begin
    (try! (check-is-owner))
    (ok (var-set create-paused pause))))
(define-public (pause-redeem (pause bool))
  (begin
    (try! (check-is-owner))
    (ok (var-set redeem-paused pause))))
(define-public (rebase)
  (let (
      (current-cycle (unwrap! (get-reward-cycle block-height) ERR-STAKING-NOT-AVAILABLE))
      (start-cycle (get-start-cycle))
      (check-start-cycle (asserts! (<= start-cycle current-cycle) ERR-NOT-ACTIVATED)))
    (and (> current-cycle start-cycle) (not (is-cycle-staked (- current-cycle u1))) (try! (claim-and-stake (- current-cycle u1))))
    (as-contract (try! (contract-call? .auto-alex-v3-1 set-reserve (try! (get-next-base)))))
    (ok current-cycle)))
(define-public (add-to-position (dx uint))
  (let (
      (current-cycle (try! (rebase)))
      (new-supply (get-tokens-to-shares dx))
      (sender tx-sender))
    (asserts! (> dx u0) ERR-INVALID-LIQUIDITY)
    (asserts! (not (is-create-paused)) ERR-PAUSED)
    ;; transfer dx to contract to stake for max cycles
    (try! (contract-call? .age000-governance-token transfer-fixed dx sender .auto-alex-v3-1 none))
    (try! (fold stake-tokens-iter REWARD-CYCLE-INDEXES (ok { current-cycle: current-cycle, remaining: dx })))
    ;; mint pool token and send to tx-sender
    (as-contract (try! (contract-call? .auto-alex-v3-1 mint-fixed new-supply sender)))
    (print { notification: "position-added", payload: { new-supply: new-supply } })
    (rebase)))
(define-public (upgrade (dx uint))
  (let (
      (end-cycle-v2 (contract-call? .auto-alex-v2 get-end-cycle))
      (current-cycle (try! (rebase)))
      (intrinsic-dx (mul-down dx (try! (contract-call? .auto-alex-v2 get-intrinsic))))
      (new-supply (get-tokens-to-shares intrinsic-dx))
      (sender tx-sender))
    (asserts! (> intrinsic-dx u0) ERR-INVALID-LIQUIDITY)
    (asserts! (not (is-create-paused)) ERR-PAUSED)
    (asserts! (< end-cycle-v2 (+ current-cycle u32)) ERR-END-CYCLE-V2) ;; auto-alex-v2 is not configured correctly
    ;; transfer dx to contract to stake for max cycles
    (try! (contract-call? .auto-alex-v2 transfer-fixed dx sender .auto-alex-v3-1 none))
    (and (< end-cycle-v2 current-cycle) (begin (as-contract (try! (reduce-position-v2))) true))
    ;; mint pool token and send to tx-sender
    (as-contract (try! (contract-call? .auto-alex-v3-1 mint-fixed new-supply sender)))
    (print { notification: "upgrade-position-added", payload: { new-supply: new-supply } })
    (rebase)))
(define-public (claim-and-mint (reward-cycles (list 200 uint)))
  (let (
      (claimed (unwrap-panic (contract-call? .staking-helper claim-staking-reward .age000-governance-token reward-cycles))))
    (try! (add-to-position (fold sum-claimed claimed u0)))
    (ok claimed)))
(define-public (claim-and-stake (reward-cycle uint))
  (let (
      (current-cycle (unwrap! (get-reward-cycle block-height) ERR-STAKING-NOT-AVAILABLE))
      (end-cycle-v2 (get-end-cycle-v2))
      ;; claim all that's available to claim for the reward-cycle
      (claimed (as-contract (try! (claim-staking-reward reward-cycle))))
      (claimed-v2 (if (< end-cycle-v2 current-cycle) (as-contract (try! (reduce-position-v2))) (begin (try! (claim-and-stake-v2 reward-cycle)) u0)))
      (tokens (+ (get to-return claimed) (get entitled-token claimed) claimed-v2))
      (previous-shares-to-tokens (try! (get-staked-cycle-shares-to-tokens-or-fail (- reward-cycle u1))))
      (redeeming (mul-down previous-shares-to-tokens (get-redeem-shares-per-cycle-or-default reward-cycle))))
    (asserts! (> current-cycle reward-cycle) ERR-REWARD-CYCLE-NOT-COMPLETED)
    (as-contract (try! (contract-call? .auto-alex-v3-1-registry set-staked-cycle reward-cycle true)))
    (as-contract (try! (contract-call? .auto-alex-v3-1-registry set-staked-cycle-shares-to-tokens reward-cycle (get-shares-to-tokens ONE_8))))
    (try! (fold stake-tokens-iter REWARD-CYCLE-INDEXES (ok { current-cycle: current-cycle, remaining: (- tokens redeeming) })))
    (print { notification: "claim-and-stake", payload: { redeeming: redeeming }})
    (as-contract (try! (contract-call? .auto-alex-v3-1-registry set-redeem-tokens-per-cycle reward-cycle redeeming)))
    (ok true)))
(define-public (request-redeem (amount uint))
  (let (
      (current-cycle (unwrap! (get-reward-cycle block-height) ERR-STAKING-NOT-AVAILABLE))
      (redeem-cycle (+ current-cycle redeem-delay-cycles))
      (request-details { requested-by: tx-sender, shares: amount, redeem-cycle: redeem-cycle, status: (get-pending) }))
    (asserts! (not (is-redeem-paused)) ERR-PAUSED)
    (try! (contract-call? .auto-alex-v3-1 transfer-fixed amount tx-sender .auto-alex-v3-1 none))
    (as-contract (try! (contract-call? .auto-alex-v3-1-registry set-redeem-shares-per-cycle redeem-cycle (+ (get-redeem-shares-per-cycle-or-default redeem-cycle) amount))))
    (print { notification: "redeem-request", payload: request-details })
    (as-contract (contract-call? .auto-alex-v3-1-registry set-redeem-request u0 request-details))))
(define-public (finalize-redeem (request-id uint))
  (let (
      (request-details (try! (get-redeem-request-or-fail request-id)))
      (redeem-cycle (get redeem-cycle request-details))
      (check-claim-and-stake (and (not (is-cycle-staked redeem-cycle)) (try! (claim-and-stake redeem-cycle))))
      (current-cycle (try! (rebase)))
      (redeem-tokens (div-down (mul-down (get shares request-details) (get-redeem-tokens-per-cycle-or-default redeem-cycle)) (get-redeem-shares-per-cycle-or-default redeem-cycle)))
      (updated-request-details (merge request-details { status: (get-finalized) })))
    (asserts! (not (is-redeem-paused)) ERR-PAUSED)
    (asserts! (is-eq (get-pending) (get status request-details)) ERR-REQUEST-FINALIZED-OR-REVOKED)
    (as-contract (try! (contract-call? .auto-alex-v3-1 transfer-token .age000-governance-token redeem-tokens (get requested-by request-details))))
    (as-contract (try! (contract-call? .auto-alex-v3-1 burn-fixed (get shares request-details) .auto-alex-v3-1)))
    (print { notification: "finalize-redeem", payload: updated-request-details })
    (as-contract (try! (contract-call? .auto-alex-v3-1-registry set-redeem-request request-id updated-request-details)))
    (rebase)))
(define-public (revoke-redeem (request-id uint))
  (let (
      (request-details (try! (get-redeem-request-or-fail request-id)))
      (redeem-cycle (get redeem-cycle request-details))
      (updated-request-details (merge request-details { status: (get-revoked) })))
    (asserts! (is-eq tx-sender (get requested-by request-details)) ERR-NOT-AUTHORIZED)
    (asserts! (not (is-cycle-staked redeem-cycle)) ERR-REWARD-CYCLE-NOT-COMPLETED)
    (asserts! (is-eq (get-pending) (get status request-details)) ERR-REQUEST-FINALIZED-OR-REVOKED)
    (as-contract (try! (contract-call? .auto-alex-v3-1 transfer-token .auto-alex-v3-1 (get shares request-details) (get requested-by request-details))))
    (as-contract (try! (contract-call? .auto-alex-v3-1-registry set-redeem-shares-per-cycle redeem-cycle (- (get-redeem-shares-per-cycle-or-default redeem-cycle) (get shares request-details)))))
    (print { notification: "revoke-redeem", payload: updated-request-details })
    (as-contract (contract-call? .auto-alex-v3-1-registry set-redeem-request request-id updated-request-details))))
(define-private (check-is-owner)
  (ok (asserts! (is-eq tx-sender (var-get contract-owner)) ERR-NOT-AUTHORIZED)))
(define-private (check-is-approved)
  (ok (asserts! (or (default-to false (map-get? approved-contracts tx-sender)) (is-ok (check-is-owner))) ERR-NOT-AUTHORIZED)))
(define-private (sum-claimed (claimed-response (response (tuple (entitled-token uint) (to-return uint)) uint)) (sum-so-far uint))
  (match claimed-response
    claimed (+ sum-so-far (get to-return claimed) (get entitled-token claimed))
    err sum-so-far))
(define-private (stake-tokens-iter (cycles-to-stake uint) (previous-response (response { current-cycle: uint, remaining: uint } uint)))
  (match previous-response
    ok-value
    (let (
      (reward-cycle (+ (get current-cycle ok-value) cycles-to-stake))
      (redeeming (get-shares-to-tokens (get-redeem-shares-per-cycle-or-default reward-cycle)))
      (returning (get to-return (get-staker-at-cycle reward-cycle)))
      (staking (if (is-eq cycles-to-stake u32)
        (get remaining ok-value)
        (if (> returning redeeming)
          u0
          (if (> (get remaining ok-value) (- redeeming returning))
            (- redeeming returning)
            (get remaining ok-value))))))
      (and (> staking u0) (as-contract (try! (stake-tokens staking cycles-to-stake))))
      (ok { current-cycle: (get current-cycle ok-value), remaining: (- (get remaining ok-value) staking) }))
    err-value previous-response))
(define-private (get-reward-cycle (stack-height uint))
  (contract-call? .alex-reserve-pool get-reward-cycle .age000-governance-token stack-height))
(define-private (get-staking-reward (reward-cycle uint))
  (contract-call? .alex-reserve-pool get-staking-reward .age000-governance-token (get-user-id) reward-cycle))
(define-private (get-staker-at-cycle (reward-cycle uint))
  (contract-call? .alex-reserve-pool get-staker-at-cycle-or-default .age000-governance-token reward-cycle (get-user-id)))
(define-private (get-user-id)
  (default-to u0 (contract-call? .alex-reserve-pool get-user-id .age000-governance-token .auto-alex-v3-1)))
(define-private (stake-tokens (amount-tokens uint) (lock-period uint))
  (contract-call? .auto-alex-v3-1 stake-tokens amount-tokens lock-period))
(define-private (claim-staking-reward (reward-cycle uint))
  (contract-call? .auto-alex-v3-1 claim-staking-reward reward-cycle))
(define-private (reduce-position-v2)
  (contract-call? .auto-alex-v3-1 reduce-position-v2))
(define-private (claim-and-stake-v2 (reward-cycle uint))
  (contract-call? .auto-alex-v2 claim-and-stake reward-cycle))
(define-private (get-end-cycle-v2)
  (contract-call? .auto-alex-v2 get-end-cycle))
(define-private (mul-down (a uint) (b uint))
    (/ (* a b) ONE_8))
(define-private (div-down (a uint) (b uint))
  (if (is-eq a u0) u0 (/ (* a ONE_8) b)))

Functions (43)

FunctionAccessArgs
reduce-position-v2private
get-contract-ownerread-only
get-pendingread-only
get-finalizedread-only
get-revokedread-only
get-start-cycleread-only
is-cycle-stakedread-onlyreward-cycle: uint
get-staked-cycle-shares-to-tokens-or-failread-onlyreward-cycle: uint
get-redeem-shares-per-cycle-or-defaultread-onlyreward-cycle: uint
get-redeem-tokens-per-cycle-or-defaultread-onlyreward-cycle: uint
get-redeem-request-or-failread-onlyrequest-id: uint
is-create-pausedread-only
is-redeem-pausedread-only
get-next-baseread-only
get-intrinsicread-only
get-shares-to-tokensread-onlydx: uint
get-tokens-to-sharesread-onlydx: uint
set-contract-ownerpublicowner: principal
set-approved-contractpublicowner: principal, approved: bool
pause-createpublicpause: bool
pause-redeempublicpause: bool
rebasepublic
add-to-positionpublicdx: uint
upgradepublicdx: uint
claim-and-mintpublicreward-cycles: (list 200 uint
claim-and-stakepublicreward-cycle: uint
request-redeempublicamount: uint
finalize-redeempublicrequest-id: uint
revoke-redeempublicrequest-id: uint
check-is-ownerprivate
check-is-approvedprivate
sum-claimedprivateclaimed-response: (response (tuple (entitled-token uint, to-return: uint
stake-tokens-iterprivatecycles-to-stake: uint, previous-response: (response { current-cycle: uint, remaining: uint } uint
get-reward-cycleprivatestack-height: uint
get-staking-rewardprivatereward-cycle: uint
get-staker-at-cycleprivatereward-cycle: uint
get-user-idprivate
stake-tokensprivateamount-tokens: uint, lock-period: uint
claim-staking-rewardprivatereward-cycle: uint
claim-and-stake-v2privatereward-cycle: uint
get-end-cycle-v2private
mul-downprivatea: uint, b: uint
div-downprivatea: uint, b: uint