(impl-trait .extension-trait.extension-trait)
(impl-trait .proposal-trait.proposal-trait)
(use-trait ft-trait .trait-sip-010.sip-010-trait)
(define-constant ERR-NOT-AUTHORIZED (err u1000))
(define-constant ERR-SCHEDULE-NOT-FOUND (err u1001))
(define-constant ERR-PAUSED (err u1002))
(define-constant ERR-UPDATE-CHECKPOINT-FAILED (err u1003))
(define-constant ERR-TOKEN-MISMATCH (err u1004))
(define-constant ERR-VESTING-NOT-STARTED (err u1005))
(define-constant ERR-INVALID-VESTING-DETAILS (err u1006))
(define-constant ERR-UPDATE-VESTING-FAILED (err u1007))
(define-constant ERR-UPDATE-PRINCIPAL-MAP-FAILED (err u1008))
(define-constant ERR-UPDATE-NFT-MAP-FAILED (err u1009))
(define-constant ERR-ALREADY-MINTED (err u1010))
(define-constant ERR-TREASURY-GRANT-NOT-PAUSED (err u1011))
(define-constant ERR-OWNER-NOT-FOUND (err u1012))
(define-constant ONE_8 u100000000)
(define-constant MAX_UINT u340282366920938463463374607431768211455)
(define-map nft-principal uint principal)
(define-map principal-nft principal uint)
(define-map vestings uint { stx: uint, alex: uint })
(define-map checkpoints uint uint)
(define-data-var paused bool true)
(define-read-only (is-dao-or-extension)
(ok (asserts! (or (is-eq tx-sender .executor-dao) (contract-call? .executor-dao is-extension contract-caller)) ERR-NOT-AUTHORIZED)))
(define-read-only (get-start-height)
(contract-call? .treasury-grant get-start-height))
(define-read-only (get-end-height)
(contract-call? .treasury-grant get-end-height))
(define-read-only (is-paused)
(var-get paused))
(define-read-only (get-nft-principal (token-id uint))
(map-get? nft-principal token-id))
(define-read-only (get-principal-nft (principal principal))
(map-get? principal-nft principal))
(define-read-only (get-vesting-or-fail (token-id uint))
(ok (unwrap! (map-get? vestings token-id) ERR-SCHEDULE-NOT-FOUND)))
(define-read-only (get-checkpoint-or-fail (token-id uint))
(let (
(vesting-details (try! (get-vesting-or-fail token-id))))
(match (map-get? checkpoints token-id)
some-value (ok some-value)
(ok (get-start-height)))))
(define-read-only (get-stats (token-id uint))
(let (
(vesting-details (try! (get-vesting-or-fail token-id)))
(vesting-per-block (/ (get alex vesting-details) (- (get-end-height) (get-start-height))))
(checkpoint (try! (get-checkpoint-or-fail token-id)))
(new-checkpoint (max (get-start-height) (min (get-end-height) burn-block-height)))
(vested-amount (* (- new-checkpoint checkpoint) vesting-per-block))
(claimed-amount (* (- checkpoint (get-start-height)) vesting-per-block)))
(ok {
available: vested-amount, claimed: claimed-amount, remaining: (- (get alex vesting-details) vested-amount claimed-amount),
checkpoint: checkpoint, new-checkpoint: new-checkpoint })))
(define-read-only (get-owner (token-id uint))
(contract-call? .token-recovery-nft get-owner token-id))
(define-public (pause (new-paused bool))
(begin
(try! (is-dao-or-extension))
(ok (var-set paused new-paused))))
(define-public (callback (sender principal) (payload (buff 2048)))
(ok true))
(define-public (execute (sender principal))
(begin
(try! (contract-call? .executor-dao set-extensions (list { extension: .treasury-grant-v2, enabled: true } )))
(try! (contract-call? .treasury-grant pause true))
(try! (pause false))
(ok true)))
(define-public (mint-certificate (user principal))
(let (
(alread-minted (asserts! (is-none (map-get? principal-nft user)) ERR-ALREADY-MINTED))
(token-id (try! (contract-call? .token-recovery-nft mint user)))
(vesting-details (try! (contract-call? .treasury-grant get-vesting-or-fail user)))
(checkpoint-details (try! (contract-call? .treasury-grant get-checkpoint-or-fail user))))
(asserts! (contract-call? .treasury-grant is-paused) ERR-TREASURY-GRANT-NOT-PAUSED)
(asserts! (map-insert principal-nft user token-id) ERR-UPDATE-PRINCIPAL-MAP-FAILED)
(asserts! (map-insert nft-principal token-id user) ERR-UPDATE-NFT-MAP-FAILED)
(asserts! (map-insert vestings token-id vesting-details) ERR-UPDATE-VESTING-FAILED)
(asserts! (map-insert checkpoints token-id checkpoint-details) ERR-UPDATE-CHECKPOINT-FAILED)
(ok token-id)))
(define-public (claim-stx (token-id uint))
(let (
(vesting-details (try! (get-vesting-or-fail token-id)))
(updated-details (merge vesting-details { stx: u0 }))
(owner (unwrap! (unwrap-panic (get-owner token-id)) ERR-OWNER-NOT-FOUND))
(sender tx-sender))
(asserts! (not (is-paused)) ERR-PAUSED)
(asserts! (is-eq sender owner) ERR-NOT-AUTHORIZED)
(asserts! (> burn-block-height (get-start-height)) ERR-VESTING-NOT-STARTED)
(asserts! (map-set vestings token-id updated-details) ERR-UPDATE-VESTING-FAILED)
(and (> (get stx vesting-details) u0) (as-contract (try! (contract-call? .treasury-grant transfer-fixed .token-wstx-v2 (get stx vesting-details) sender))))
(print { notification: "claim-stx", payload: { token-id: token-id, owner: sender, claimed: (get stx vesting-details), updated-details: updated-details }})
(ok true)))
(define-public (claim-alex (token-id uint))
(let (
(stats (try! (get-stats token-id)))
(owner (unwrap! (unwrap-panic (get-owner token-id)) ERR-OWNER-NOT-FOUND))
(sender tx-sender))
(asserts! (not (is-paused)) ERR-PAUSED)
(asserts! (is-eq sender owner) ERR-NOT-AUTHORIZED)
(asserts! (> burn-block-height (get-start-height)) ERR-VESTING-NOT-STARTED)
(asserts! (map-set checkpoints token-id (get new-checkpoint stats)) ERR-UPDATE-CHECKPOINT-FAILED)
(and (> (get available stats) u0) (as-contract (try! (contract-call? .treasury-grant transfer-fixed .token-alex (get available stats) sender))))
(print { notification: "claim-alex", payload: { token-id: token-id, owner: sender, claimed: (get available stats) }, claimed-so-far: (+ (get available stats) (get claimed stats)), remaining: (get remaining stats) })
(ok true)))
(define-public (claim (token-id uint))
(begin
(try! (claim-stx token-id))
(claim-alex token-id)))
(define-public (claim-many (token-ids (list 1000 uint)))
(ok (map claim token-ids)))
(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)))
(define-private (min (a uint) (b uint))
(if (<= a b) a b))
(define-private (max (a uint) (b uint))
(if (>= a b) a b))