Source Code

;; IMMORTAL DCA
;; The simplest unstoppable economic entity.
;; No owner. No admin. No governance. No kill switch.

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

(define-constant HEARTBEAT_INTERVAL u144)
(define-constant MIN_BALANCE u100000)
(define-constant TRIGGER_REWARD_BPS u100)
(define-constant MAX_REWARD u100000)

(define-constant ERR_TOO_SOON (err u1001))
(define-constant ERR_NO_FUNDS (err u1002))

;; ============================================
;; STATE
;; ============================================

(define-data-var last-heartbeat uint u0)
(define-data-var total-heartbeats uint u0)
(define-data-var total-rewards-paid uint u0)
(define-data-var balance uint u0)

;; ============================================
;; HELPERS
;; ============================================

(define-private (min-uint (a uint) (b uint))
  (if (<= a b) a b))

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

(define-read-only (get-balance)
  (var-get balance))

(define-read-only (get-blocks-until-next)
  (let (
    (last (var-get last-heartbeat))
    (now block-height)
    (next (+ last HEARTBEAT_INTERVAL))
  )
    (if (>= now next) u0 (- next now))))

(define-read-only (can-trigger)
  (and
    (is-eq (get-blocks-until-next) u0)
    (>= (get-balance) MIN_BALANCE)))

(define-read-only (get-stats)
  {
    balance: (get-balance),
    last-heartbeat: (var-get last-heartbeat),
    blocks-until-next: (get-blocks-until-next),
    total-heartbeats: (var-get total-heartbeats),
    total-rewards-paid: (var-get total-rewards-paid),
    can-trigger: (can-trigger)
  })

;; ============================================
;; PUBLIC
;; ============================================

;; Anyone can deposit STX
(define-public (deposit (amount uint))
  (begin
    (try! (stx-transfer? amount tx-sender (as-contract tx-sender)))
    (var-set balance (+ (var-get balance) amount))
    (ok amount)))

;; THE HEARTBEAT
(define-public (trigger)
  (let (
    (now block-height)
    (current-balance (var-get balance))
    (caller tx-sender)
  )
    (asserts! (>= now (+ (var-get last-heartbeat) HEARTBEAT_INTERVAL)) ERR_TOO_SOON)
    (asserts! (>= current-balance MIN_BALANCE) ERR_NO_FUNDS)

    (let (
      (raw-reward (/ (* current-balance TRIGGER_REWARD_BPS) u10000))
      (reward (min-uint raw-reward MAX_REWARD))
    )
      (try! (as-contract (stx-transfer? reward tx-sender caller)))

      (var-set balance (- current-balance reward))
      (var-set last-heartbeat now)
      (var-set total-heartbeats (+ (var-get total-heartbeats) u1))
      (var-set total-rewards-paid (+ (var-get total-rewards-paid) reward))

      (ok {
        heartbeat: (var-get total-heartbeats),
        reward: reward,
        triggered-by: caller,
        block: now
      })
    )))

Functions (7)

FunctionAccessArgs
min-uintprivatea: uint, b: uint
get-balanceread-only
get-blocks-until-nextread-only
can-triggerread-only
get-statsread-only
depositpublicamount: uint
triggerpublic