Skip to content

Commit fa26ade

Browse files
mattgloryclaude
andcommitted
Add Zest flash liquidation receiver — STX + sBTC
Zero-capital liquidation receiver for Zest Protocol supporting both STX and canonical sBTC debt positions. - execute-stx-flash: for STX-denominated Zest positions - execute-sbtc-flash: for sBTC-denominated Zest positions - simulate(): read-only pre-flight profitability check - sweep-stx / sweep-sbtc: collect net profit after liquidation Zest liquidation-call signature marked TODO pending confirmation with Zest team — integration surface is minimal on their side. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent fa06c76 commit fa26ade

1 file changed

Lines changed: 204 additions & 0 deletions

File tree

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
;; FlashStack - Zest Flash Liquidation Receiver (STX + sBTC)
2+
;;
3+
;; Executes zero-capital liquidations on Zest Protocol using FlashStack flash loans.
4+
;; Supports both STX and canonical sBTC flash loans depending on the debt asset.
5+
;;
6+
;; Two entry points:
7+
;; execute-stx-flash - called by flashstack-stx-core (STX debt positions)
8+
;; execute-sbtc-flash - called by flashstack-sbtc-core (sBTC debt positions)
9+
;;
10+
;; Flow (same for both):
11+
;; 1. FlashStack core transfers asset to this contract
12+
;; 2. This contract calls Zest's liquidation-call with borrowed funds
13+
;; 3. Zest sends collateral bonus to this contract
14+
;; 4. Repay FlashStack core: principal + 0.05% fee
15+
;; 5. Surplus profit stays here - sweep via sweep-stx / sweep-sbtc
16+
;;
17+
;; Liquidation economics:
18+
;; Profit = liquidation_bonus - flash_loan_fee
19+
;; e.g. 5% bonus on 1000 STX loan = 50 STX bonus - 0.5 STX fee = 49.5 STX profit
20+
;;
21+
;; Integration note:
22+
;; Zest function signatures marked as TODO pending confirmation from Zest team.
23+
;;
24+
;; Must be whitelisted in both flashstack-stx-core and flashstack-sbtc-core before use.
25+
26+
(impl-trait 'SP20XD46NGAX05ZQZDKFYCCX49A3852BQABNP0VG5.flashstack-stx-core.stx-flash-receiver-trait)
27+
(impl-trait 'SP20XD46NGAX05ZQZDKFYCCX49A3852BQABNP0VG5.sbtc-flash-receiver-trait.sbtc-flash-receiver-trait)
28+
29+
;; =============================================
30+
;; Constants
31+
;; =============================================
32+
33+
;; TODO: Confirm Zest pool address with Zest team
34+
(define-constant ZEST-POOL 'SP2ZNGJ85ENDY6QRHQ5P2D4FXKGZWCKTB2T0Z55KS.pool-borrow-v2-0)
35+
(define-constant SBTC 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token)
36+
(define-constant STX-CORE 'SP20XD46NGAX05ZQZDKFYCCX49A3852BQABNP0VG5.flashstack-stx-core)
37+
(define-constant SBTC-CORE 'SP20XD46NGAX05ZQZDKFYCCX49A3852BQABNP0VG5.flashstack-sbtc-core)
38+
39+
(define-constant ERR-NOT-OWNER (err u800))
40+
(define-constant ERR-REPAY-FAILED (err u801))
41+
(define-constant ERR-LIQUIDATION (err u802))
42+
(define-constant ERR-INSUFFICIENT (err u803))
43+
(define-constant ERR-ZERO-AMOUNT (err u804))
44+
45+
;; =============================================
46+
;; State
47+
;; =============================================
48+
49+
(define-data-var owner principal tx-sender)
50+
51+
;; =============================================
52+
;; STX Flash Loan Callback
53+
;; Use when: borrower has STX-denominated debt on Zest
54+
;; Flash borrows from: flashstack-stx-core
55+
;; =============================================
56+
57+
(define-public (execute-stx-flash (amount uint) (core principal))
58+
(let (
59+
(fee-bp (unwrap! (contract-call? 'SP20XD46NGAX05ZQZDKFYCCX49A3852BQABNP0VG5.flashstack-stx-core
60+
get-fee-basis-points) ERR-REPAY-FAILED))
61+
(raw-fee (/ (* amount fee-bp) u10000))
62+
(fee (if (> raw-fee u0) raw-fee u1))
63+
(owed (+ amount fee))
64+
)
65+
;; ── Step 1: Liquidate the Zest position using borrowed STX ──────────────
66+
;; TODO: Replace with confirmed Zest liquidation-call signature.
67+
;; Typical pattern (AAVE-style):
68+
;; (as-contract (contract-call? ZEST-POOL liquidation-call
69+
;; collateral-asset ;; e.g. 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
70+
;; debt-asset ;; STX (native)
71+
;; borrower ;; principal being liquidated
72+
;; amount ;; debt amount to repay
73+
;; true ;; receive underlying collateral (not aToken)
74+
;; ))
75+
76+
;; ── Step 2: Verify we received enough to repay ───────────────────────────
77+
(let ((stx-balance (stx-get-balance (as-contract tx-sender))))
78+
(asserts! (>= stx-balance owed) ERR-INSUFFICIENT)
79+
80+
;; ── Step 3: Repay STX flash loan (principal + fee) ───────────────────
81+
(unwrap!
82+
(as-contract (stx-transfer? owed tx-sender core))
83+
ERR-REPAY-FAILED)
84+
85+
(ok true)
86+
)
87+
)
88+
)
89+
90+
;; =============================================
91+
;; sBTC Flash Loan Callback
92+
;; Use when: borrower has sBTC-denominated debt on Zest
93+
;; Flash borrows from: flashstack-sbtc-core
94+
;; =============================================
95+
96+
(define-public (execute-sbtc-flash (amount uint) (core principal))
97+
(let (
98+
(fee-bp (unwrap! (contract-call? 'SP20XD46NGAX05ZQZDKFYCCX49A3852BQABNP0VG5.flashstack-sbtc-core
99+
get-fee-basis-points) ERR-REPAY-FAILED))
100+
(raw-fee (/ (* amount fee-bp) u10000))
101+
(fee (if (> raw-fee u0) raw-fee u1))
102+
(owed (+ amount fee))
103+
)
104+
;; ── Step 1: Liquidate the Zest position using borrowed sBTC ─────────────
105+
;; TODO: Replace with confirmed Zest liquidation-call signature.
106+
;; Typical pattern:
107+
;; (as-contract (contract-call? ZEST-POOL liquidation-call
108+
;; collateral-asset ;; e.g. STX or xBTC
109+
;; debt-asset ;; 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
110+
;; borrower ;; principal being liquidated
111+
;; amount ;; sBTC debt amount to repay (sats)
112+
;; true ;; receive underlying collateral
113+
;; ))
114+
115+
;; ── Step 2: Verify sufficient sBTC to repay ──────────────────────────────
116+
(let ((sbtc-balance (unwrap!
117+
(as-contract (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
118+
get-balance tx-sender))
119+
ERR-REPAY-FAILED)))
120+
(asserts! (>= sbtc-balance owed) ERR-INSUFFICIENT)
121+
122+
;; ── Step 3: Repay sBTC flash loan (principal + fee) ──────────────────
123+
(unwrap!
124+
(as-contract (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
125+
transfer owed tx-sender core none))
126+
ERR-REPAY-FAILED)
127+
128+
(ok true)
129+
)
130+
)
131+
)
132+
133+
;; =============================================
134+
;; Owner Functions
135+
;; =============================================
136+
137+
(define-public (sweep-stx (amount uint))
138+
(begin
139+
(asserts! (is-eq tx-sender (var-get owner)) ERR-NOT-OWNER)
140+
(asserts! (> amount u0) ERR-ZERO-AMOUNT)
141+
(unwrap!
142+
(as-contract (stx-transfer? amount tx-sender (var-get owner)))
143+
ERR-REPAY-FAILED)
144+
(ok true)
145+
)
146+
)
147+
148+
(define-public (sweep-sbtc (amount uint))
149+
(begin
150+
(asserts! (is-eq tx-sender (var-get owner)) ERR-NOT-OWNER)
151+
(asserts! (> amount u0) ERR-ZERO-AMOUNT)
152+
(unwrap!
153+
(as-contract (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
154+
transfer amount tx-sender (var-get owner) none))
155+
ERR-REPAY-FAILED)
156+
(ok true)
157+
)
158+
)
159+
160+
(define-public (set-owner (new-owner principal))
161+
(begin
162+
(asserts! (is-eq tx-sender (var-get owner)) ERR-NOT-OWNER)
163+
(ok (var-set owner new-owner))
164+
)
165+
)
166+
167+
;; =============================================
168+
;; Read-only
169+
;; =============================================
170+
171+
;; Pre-flight profitability check before executing a liquidation.
172+
;; debt-amount : amount to repay (microSTX or sats)
173+
;; bonus-bp : Zest liquidation bonus in basis points (e.g. u500 = 5%)
174+
(define-read-only (simulate (debt-amount uint) (bonus-bp uint))
175+
(let (
176+
(raw-fee (/ (* debt-amount u5) u10000))
177+
(fee (if (> raw-fee u0) raw-fee u1))
178+
(bonus (/ (* debt-amount bonus-bp) u10000))
179+
(profit (if (> bonus fee) (- bonus fee) u0))
180+
)
181+
{
182+
debt-amount: debt-amount,
183+
bonus-bp: bonus-bp,
184+
bonus: bonus,
185+
flash-fee: fee,
186+
net-profit: profit,
187+
profitable: (> bonus fee),
188+
owed-to-core: (+ debt-amount fee),
189+
}
190+
)
191+
)
192+
193+
(define-read-only (get-stx-balance)
194+
(stx-get-balance (as-contract tx-sender))
195+
)
196+
197+
(define-read-only (get-sbtc-balance)
198+
(as-contract (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
199+
get-balance tx-sender))
200+
)
201+
202+
(define-read-only (get-owner)
203+
(ok (var-get owner))
204+
)

0 commit comments

Comments
 (0)