Source Code

;; STX Faucet Smart Contract - Clarity 3/4 compatible
;; Dispenses 0.05 STX once every 144 Bitcoin blocks (24 hours)

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

;; Hardcoded Contract Owner
(define-constant CONTRACT_OWNER 'SP267C6MQJHPR7297033Z8VSKTJM7M62V375BRHHP)

;; Error codes
(define-constant ERR_UNAUTHORIZED (err u100))
(define-constant ERR_ALREADY_CLAIMED (err u101))
(define-constant ERR_INSUFFICIENT_BALANCE (err u102))
(define-constant ERR_INVALID_AMOUNT (err u103))
(define-constant ERR_FAUCET_INACTIVE (err u104))
(define-constant ERR_INVALID_RECIPIENT (err u105))

;; Rate limiting (144 Bitcoin blocks = 24 hours)
(define-constant BLOCKS_PER_DAY u144)

;; Default drip amounts (0.05 STX = 50,000 microSTX)
(define-constant DEFAULT_DRIP u50000)

;; =============================================================================
;; DATA STORAGE
;; =============================================================================

(define-map last-claims principal uint)
(define-data-var drip-amount uint DEFAULT_DRIP)
(define-data-var is-active bool true)

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

(define-read-only (get-last-claim (user principal))
  (map-get? last-claims user)
)

(define-read-only (is-eligible (user principal))
  (let (
    (last-claim-height (default-to u0 (map-get? last-claims user)))
  )
    (if (is-eq last-claim-height u0)
      true
      (>= burn-block-height (+ last-claim-height BLOCKS_PER_DAY))
    )
  )
)

(define-read-only (get-faucet-balance)
  (stx-get-balance (as-contract tx-sender))
)

(define-read-only (get-blocks-remaining (user principal))
  (let (
    (last-claim-height (default-to u0 (map-get? last-claims user)))
  )
    (if (or (is-eq last-claim-height u0) (>= burn-block-height (+ last-claim-height BLOCKS_PER_DAY)))
      u0
      (- BLOCKS_PER_DAY (- burn-block-height last-claim-height))
    )
  )
)

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

(define-public (claim-stx)
  (let (
    (claimer tx-sender)
    (amount (var-get drip-amount))
  )
    (asserts! (var-get is-active) ERR_FAUCET_INACTIVE)
    (asserts! (is-eligible claimer) ERR_ALREADY_CLAIMED)
    (asserts! (>= (stx-get-balance (as-contract tx-sender)) amount) ERR_INSUFFICIENT_BALANCE)
    
    (map-set last-claims claimer burn-block-height)

    ;; Transfer from contract to user
    (try! (as-contract (stx-transfer? amount tx-sender claimer)))
    
    (ok amount)
  )
)

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

(define-public (set-drip-amount (new-amount uint))
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    (asserts! (> new-amount u0) ERR_INVALID_AMOUNT)
    (var-set drip-amount new-amount)
    (ok new-amount)
  )
)

(define-public (toggle-active)
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    (var-set is-active (not (var-get is-active)))
    (ok (var-get is-active))
  )
)

(define-public (fund-faucet (amount uint))
  (stx-transfer? amount tx-sender (as-contract tx-sender))
)

(define-public (withdraw (amount uint) (recipient principal))
  (begin
    ;; 1. Authority Check
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_UNAUTHORIZED)
    
    ;; 2. Basic Recipient Check (Silences the "unchecked data" warning)
    (asserts! (not (is-eq recipient (as-contract tx-sender))) ERR_INVALID_RECIPIENT)
    
    ;; 3. Balance Check
    (asserts! (>= (stx-get-balance (as-contract tx-sender)) amount) ERR_INSUFFICIENT_BALANCE)
    
    ;; 4. Execution
    (try! (as-contract (stx-transfer? amount tx-sender recipient)))
    
    (ok amount)
  )
)

Functions (9)

FunctionAccessArgs
get-last-claimread-onlyuser: principal
is-eligibleread-onlyuser: principal
get-faucet-balanceread-only
get-blocks-remainingread-onlyuser: principal
claim-stxpublic
set-drip-amountpublicnew-amount: uint
toggle-activepublic
fund-faucetpublicamount: uint
withdrawpublicamount: uint, recipient: principal