Source Code

;; Aegis Withdrawals v3 - Withdrawal Contract
;; Handles normal and emergency withdrawals
;; Part of the Aegis Vault split architecture

;; ============================================
;; CONSTANTS
;; ============================================

(define-constant CONTRACT-OWNER tx-sender)

;; Error codes
(define-constant ERR-NOT-AUTHORIZED (err u5001))
(define-constant ERR-NO-STAKE-FOUND (err u5002))
(define-constant ERR-STAKE-STILL-LOCKED (err u5003))
(define-constant ERR-STAKE-INACTIVE (err u5004))
(define-constant ERR-CONTRACT-PAUSED (err u5005))
(define-constant ERR-STAKING-CONTRACT-NOT-SET (err u5006))
(define-constant ERR-TREASURY-NOT-SET (err u5007))

;; Withdrawal parameters
(define-constant PENALTY-PERCENT u2)         ;; 2% emergency withdrawal penalty
(define-constant PENALTY-DENOMINATOR u100)

;; ============================================
;; DATA VARIABLES
;; ============================================

(define-data-var contract-paused bool false)
(define-data-var staking-contract principal CONTRACT-OWNER)
(define-data-var treasury-contract principal CONTRACT-OWNER)
(define-data-var total-withdrawals uint u0)
(define-data-var total-penalties uint u0)

;; ============================================
;; ADMIN FUNCTIONS
;; ============================================

(define-public (set-paused (paused bool))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (var-set contract-paused paused)
    (ok true)
  )
)

(define-public (set-staking-contract (contract principal))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (var-set staking-contract contract)
    (ok true)
  )
)

(define-public (set-treasury-contract (contract principal))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (var-set treasury-contract contract)
    (ok true)
  )
)

;; ============================================
;; PRIVATE HELPERS
;; ============================================

(define-private (calculate-penalty (amount uint))
  (/ (* amount PENALTY-PERCENT) PENALTY-DENOMINATOR)
)

;; ============================================
;; PUBLIC FUNCTIONS
;; ============================================

;; Normal withdrawal (after lock period expires)
(define-public (withdraw (stake-id uint))
  (let
    (
      (staker tx-sender)
      (staking (var-get staking-contract))
      (stake-data (unwrap! (contract-call? .aegis-staking-v2-15 get-stake staker stake-id) ERR-NO-STAKE-FOUND))
      (amount (get amount stake-data))
      (is-unlocked (contract-call? .aegis-staking-v2-15 is-stake-unlocked staker stake-id))
    )
    ;; Validations
    (asserts! (not (var-get contract-paused)) ERR-CONTRACT-PAUSED)
    (asserts! (get is-active stake-data) ERR-STAKE-INACTIVE)
    (asserts! is-unlocked ERR-STAKE-STILL-LOCKED)
    
    ;; Deactivate stake in staking contract
    (try! (contract-call? .aegis-staking-v2-15 deactivate-stake staker stake-id amount))
    
    ;; Transfer full amount back to staker
    (try! (contract-call? .aegis-staking-v2-15 transfer-stx staker amount))
    
    ;; Update stats
    (var-set total-withdrawals (+ (var-get total-withdrawals) u1))
    
    (print { 
      event: "withdraw",
      staker: staker,
      stake-id: stake-id,
      amount: amount,
      penalty: u0
    })
    
    (ok { amount: amount, penalty: u0 })
  )
)

;; Emergency withdrawal (before lock expires, with 2% penalty)
(define-public (emergency-withdraw (stake-id uint))
  (let
    (
      (staker tx-sender)
      (stake-data (unwrap! (contract-call? .aegis-staking-v2-15 get-stake staker stake-id) ERR-NO-STAKE-FOUND))
      (amount (get amount stake-data))
      (penalty (calculate-penalty amount))
      (return-amount (- amount penalty))
      (treasury (var-get treasury-contract))
    )
    ;; Validations
    (asserts! (not (var-get contract-paused)) ERR-CONTRACT-PAUSED)
    (asserts! (get is-active stake-data) ERR-STAKE-INACTIVE)
    
    ;; Deactivate stake in staking contract
    (try! (contract-call? .aegis-staking-v2-15 deactivate-stake staker stake-id amount))
    
    ;; Transfer 98% back to staker
    (try! (contract-call? .aegis-staking-v2-15 transfer-stx staker return-amount))
    
    ;; Transfer 2% penalty to treasury
    (try! (contract-call? .aegis-staking-v2-15 transfer-stx treasury penalty))
    
    ;; Update stats
    (var-set total-withdrawals (+ (var-get total-withdrawals) u1))
    (var-set total-penalties (+ (var-get total-penalties) penalty))
    
    (print { 
      event: "emergency-withdraw",
      staker: staker,
      stake-id: stake-id,
      original-amount: amount,
      penalty: penalty,
      returned: return-amount
    })
    
    (ok { returned: return-amount, penalty: penalty })
  )
)

;; ============================================
;; READ-ONLY FUNCTIONS
;; ============================================

(define-read-only (get-withdrawal-stats)
  {
    total-withdrawals: (var-get total-withdrawals),
    total-penalties: (var-get total-penalties),
    penalty-percent: PENALTY-PERCENT,
    is-paused: (var-get contract-paused)
  }
)

(define-read-only (get-staking-contract)
  (var-get staking-contract)
)

(define-read-only (get-treasury-contract)
  (var-get treasury-contract)
)

(define-read-only (preview-emergency-withdraw (amount uint))
  {
    penalty: (calculate-penalty amount),
    returned: (- amount (calculate-penalty amount))
  }
)

Functions (10)

FunctionAccessArgs
set-pausedpublicpaused: bool
set-staking-contractpubliccontract: principal
set-treasury-contractpubliccontract: principal
calculate-penaltyprivateamount: uint
withdrawpublicstake-id: uint
emergency-withdrawpublicstake-id: uint
get-withdrawal-statsread-only
get-staking-contractread-only
get-treasury-contractread-only
preview-emergency-withdrawread-onlyamount: uint