(impl-trait .trait-ownable.ownable-trait)
(define-constant ERR-NOT-AUTHORIZED (err u1000))
(define-constant ERR-ALREADY-PROCESSED (err u1409))
(define-constant ERR-DISTRIBUTION (err u1410))
(define-constant ONE_8 (pow u10 u8))
(define-map distributed-per-cycle uint uint)
(define-map user-distributed-per-cycle { user: principal, cycle: uint } bool)
(define-map processed-batches { cycle: uint, batch: uint } bool)
(define-data-var contract-owner principal tx-sender)
(define-map approved-contracts principal bool)
(define-read-only (get-contract-owner)
(ok (var-get contract-owner))
)
(define-public (set-contract-owner (owner principal))
(begin
(try! (check-is-owner))
(ok (var-set contract-owner owner))
)
)
(define-public (add-approved-contract (new-approved-contract principal))
(begin
(try! (check-is-owner))
(ok (map-set approved-contracts new-approved-contract true))
)
)
(define-public (set-approved-contract (owner principal) (approved bool))
(begin
(try! (check-is-owner))
(ok (map-set approved-contracts owner approved))
)
)
(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! (default-to false (map-get? approved-contracts tx-sender)) ERR-NOT-AUTHORIZED))
)
(define-read-only (get-distributed-per-cycle-or-default (cycle uint))
(default-to u0 (map-get? distributed-per-cycle cycle))
)
(define-read-only (get-user-distributed-per-cycle-or-default (user principal) (cycle uint))
(default-to false (map-get? user-distributed-per-cycle { user: user, cycle: cycle }))
)
(define-private (distribute-iter (recipient principal) (prior (response { cycle: uint, atalex: uint, balance: uint, sum: uint } uint)))
(let
(
(prior-unwrapped (try! prior))
(cycle (get cycle prior-unwrapped))
(sum (get sum prior-unwrapped))
(atalex (get atalex prior-unwrapped))
(balance (get balance prior-unwrapped))
(shares (div-down (mul-down atalex (contract-call? .fwp-wstx-alex-tranched-64 get-user-balance-per-cycle-or-default recipient cycle)) balance))
)
(if (get-user-distributed-per-cycle-or-default recipient cycle)
;; if the user already received distribution, then skip
(ok { cycle: cycle, atalex: atalex, balance: balance, sum: sum })
(let
(
(alex (if (is-eq shares u0) u0 (try! (contract-call? .auto-alex get-token-given-position shares))))
(apower (if (is-eq alex u0) u0 (mul-down alex (contract-call? .alex-reserve-pool get-apower-multiplier-in-fixed-or-default .fwp-wstx-alex-50-50-v1-01))))
)
(and
(> apower u0)
(as-contract (try! (contract-call? .token-apower mint-fixed apower recipient)))
(as-contract (try! (contract-call? .token-apower burn-fixed apower .fwp-wstx-alex-tranched-64)))
)
(map-set user-distributed-per-cycle { user: recipient, cycle: cycle } true)
(ok { cycle: cycle, atalex: atalex, balance: balance, sum: (+ sum shares) })
)
)
)
)
(define-read-only (is-cycle-batch-processed (cycle uint) (batch uint))
(default-to
false
(map-get? processed-batches { cycle: cycle, batch: batch })
)
)
(define-public (distribute-apower-only (cycle uint) (batch uint) (recipients (list 200 principal)))
(let
(
(distributable-per-cycle (contract-call? .fwp-wstx-alex-tranched-64 get-distributable-per-cycle-or-default cycle))
)
(asserts! (or (is-ok (check-is-owner)) (is-ok (check-is-approved))) ERR-NOT-AUTHORIZED)
(asserts! (is-eq (is-cycle-batch-processed cycle batch) false) ERR-ALREADY-PROCESSED)
(asserts! (> distributable-per-cycle u0) ERR-DISTRIBUTION)
(let
(
(output (try! (fold distribute-iter recipients (ok { cycle: cycle, atalex: distributable-per-cycle, balance: (contract-call? .fwp-wstx-alex-tranched-64 get-total-balance-per-cycle-or-default cycle), sum: u0 }))))
)
(map-set processed-batches { cycle: cycle, batch: batch } true)
(map-set distributed-per-cycle cycle (+ (get-distributed-per-cycle-or-default cycle) (get sum output)))
(ok (get sum output))
)
)
)
(define-public (distribute (cycle uint) (batch uint) (recipients (list 200 principal)))
(begin
(try! (contract-call? .fwp-wstx-alex-tranched-64 distribute cycle batch recipients))
(distribute-apower-only cycle batch recipients)
)
)
(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)
)
)