(define-constant O tx-sender)
(define-constant E1 (err u860))
(define-constant E2 (err u861))
(define-constant E3 (err u862))
(define-data-var reward-rate uint u100)
(define-map stakes principal {amount: uint, since: uint, rewards-claimed: uint})
(define-public (stake-tokens (amt uint))
(begin (asserts! (> amt u0) E2)
(try! (stx-transfer? amt tx-sender (as-contract tx-sender)))
(let ((s (default-to {amount: u0, since: stacks-block-height, rewards-claimed: u0}
(map-get? stakes tx-sender))))
(ok (map-set stakes tx-sender
{amount: (+ (get amount s) amt),
since: stacks-block-height,
rewards-claimed: (get rewards-claimed s)})))))
(define-public (unstake (amt uint))
(let ((s (unwrap! (map-get? stakes tx-sender) E3)))
(asserts! (<= amt (get amount s)) E2)
(try! (as-contract (stx-transfer? amt tx-sender contract-caller)))
(ok (map-set stakes tx-sender
(merge s {amount: (- (get amount s) amt)})))))
(define-read-only (get-stake (u principal))
(default-to {amount: u0, since: u0, rewards-claimed: u0}
(map-get? stakes u)))
(define-read-only (get-pending-reward (u principal))
(let ((s (default-to {amount: u0, since: u0, rewards-claimed: u0}
(map-get? stakes u))))
(if (is-eq (get amount s) u0) u0
(/ (* (get amount s) (- stacks-block-height (get since s)) (var-get reward-rate)) u1000000))))
(define-public (set-reward-rate (r uint))
(begin (asserts! (is-eq tx-sender O) E1) (ok (var-set reward-rate r))))