### Example call to price-multi-resolve with three assets Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/oracle.md Shows an example invocation of price-multi-resolve with three asset entries and corresponding aids, returning a list of prices in the same order. ```clarity (price-multi-resolve (list {type: 0x00, ident: STX_FEED, callcode: none} {type: 0x00, ident: BTC_FEED, callcode: none} {type: 0x00, ident: USDC_FEED, callcode: (some 0x04)}) (list u0 u1 u3)) → Returns: (list 100000000 3000000000000 110000000) ``` -------------------------------- ### Setup commands: cd, pnpm install, pnpm clarigen Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/README.md Commands to install dependencies and generate TypeScript types using Clarigen. Requires Node.js v18+, pnpm, and Clarity version 6 with epoch 4.0. ```bash cd local-testing pnpm install pnpm clarigen # Generate TypeScript types ``` -------------------------------- ### Example walkthrough of egroup resolution Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/egroups.md Illustrates the resolution algorithm with a concrete example: user holds assets 0 and 2 (mask 0b0101), and available egroups with different masks. Shows how the algorithm finds the exact match first. ```text User has: Assets 0, 2 → mask = 0b0101 → popcount = 2 Available egroups: - ID 1: mask 0b0101, popcount 2 (exact match) - ID 2: mask 0b0111, popcount 3 (superset) - ID 3: mask 0b1111, popcount 4 (superset) Resolution: 1. min_pop = 2 2. Check bucket 2 first (popcount 2) 3. Find ID 1 (0b0101) - user mask is subset ✓ 4. Return ID 1 parameters ``` -------------------------------- ### Example of zststx dual transformation Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/oracle.md Shows the dual transformation for zststx: starting from STX price $1.00, apply the ststx ratio (1.05) to get $1.05, then apply the liquidity index (1.10) to get $1.155. ```text STX price: $1.00 → Apply ststx ratio (1.05) → $1.05 → Apply liquidity index (1.10) → $1.155 ``` -------------------------------- ### Pyth price normalization example Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/oracle.md Shows how Pyth prices with varying exponents are normalized to 8 decimals. The example uses price=123 and expo=-8, resulting in 123. ```text Target: 8 decimals (e.g., $1.23 = 123000000) Example: Pyth returns: price=123, expo=-8 Adjustment: expo + 8 = -8 + 8 = 0 Result: 123 / 10^0 = 123 (already 8 decimals) ``` -------------------------------- ### STX Registration Example Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/oracle.md Registers STX with a Pyth oracle, no transformation. Uses type 0x00, a placeholder feed ID, and callcode none for direct price. ```clarity (insert .wstx { type: 0x00, // Pyth oracle ident: 0x..., // STX/USD feed ID callcode: none // Direct price, no transformation }) ``` -------------------------------- ### Liquidity Index Example Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/vaults.md Shows how the liquidity index tracks accumulated interest on deposits. Demonstrates a deposit of 100 USDC, the index rising to 1.10, and the redemption value calculation. ```text Initial: index = 1.0 Supply: user deposits 100 USDC, gets 100 zUSDC Time passes... Current: index = 1.10 Redemption value: 100 × 1.10 = 110 USDC ``` -------------------------------- ### Borrow Index Example Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/vaults.md Illustrates how the borrow index tracks accumulated interest on debt. Shows initial index of 1.0, a borrow of 100 USDC, and the calculation of actual debt when the index rises to 1.15. ```text Initial: index = 1.0 Borrow: user owes 100 USDC at index 1.0 Time passes... Current: index = 1.15 Actual debt: 100 × (1.15 / 1.0) = 115 USDC ``` -------------------------------- ### zUSDC Registration Example with Liquidity Index Transformation Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/oracle.md Registers zUSDC with a Pyth oracle for USDC price and applies a liquidity index transformation via callcode (some 0x04). ```clarity (insert .vault-usdc { type: 0x00, // Pyth oracle (for USDC price) ident: 0x..., // USDC/USD feed ID callcode: (some 0x04) // CALLCODE-ZUSDC: apply liquidity index }) ``` -------------------------------- ### ststx Registration Example with Staking Ratio Transformation Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/oracle.md Registers ststx with a Pyth oracle for STX price and applies a staking ratio transformation via callcode (some 0x00). ```clarity (insert .ststx { type: 0x00, // Pyth oracle (for STX price) ident: 0x..., // STX/USD feed ID callcode: (some 0x00) // CALLCODE-STSTX: apply staking ratio }) ``` -------------------------------- ### Example of zUSDC price transformation Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/oracle.md Shows a concrete example for zUSDC: base USDC price of $1.00 (100000000) with a liquidity index of 1.10 (110000000) yields a vault token price of $1.10 (110000000). ```text Base USDC price: $1.00 = 100000000 Liquidity index: 1.10 (110000000) = 10% interest accrued Vault token price: $1.10 = 110000000 ``` -------------------------------- ### as-contract? with and without with-stx allowance example Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/references/sip-033-clarity4.md Shows two public functions. foo uses as-contract? with no allowances and attempts to transfer u1000000 uSTX, returning (err u128) because no allowance is granted. bar uses as-contract? with a with-stx u1000000 allowance and succeeds, returning (ok true). ```clarity (define-public (foo) (as-contract? () (try! (stx-transfer? u1000000 tx-sender recipient)) ) ) ;; Returns (err u128) (define-public (bar) (as-contract? ((with-stx u1000000)) (try! (stx-transfer? u1000000 tx-sender recipient)) ) ) ;; Returns (ok true) ``` -------------------------------- ### restrict-assets? basic example with stx-transfer? Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/references/sip-033-clarity4.md Shows restrict-assets? with no allowances: a stx-transfer? of u1000000 returns (err u128) because no allowance was granted, while a simple addition returns (ok u3). ```clarity (define-public (foo) (restrict-assets? tx-sender () (try! (stx-transfer? u1000000 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM)) ) ) ;; Returns (err u128) (define-public (bar) (restrict-assets? tx-sender () (+ u1 u2) ) ) ;; Returns (ok u3) ``` -------------------------------- ### with-stx allowance example Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/references/sip-033-clarity4.md Demonstrates with-stx granting an allowance of u1000000 uSTX. A transfer of u2000000 fails with (err u0), while a transfer of u1000000 succeeds with (ok true). ```clarity (restrict-assets? tx-sender ((with-stx u1000000)) (try! (stx-transfer? u2000000 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM)) ) ;; Returns (err u0) (restrict-assets? tx-sender ((with-stx u1000000)) (try! (stx-transfer? u1000000 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM)) ) ;; Returns (ok true) ``` -------------------------------- ### restrict-assets? with with-stacking allowance example Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/references/sip-033-clarity4.md Shows two calls to restrict-assets? with a with-stacking allowance. The first delegates u1100000000000 uSTX, exceeding the u1000000000000 allowance, and returns (err u0). The second delegates u900000000000, within the allowance, and returns (ok true). ```clarity (restrict-assets? tx-sender ((with-stacking u1000000000000)) (try! (contract-call? 'SP000000000000000000002Q6VF78.pox-4 delegate-stx u1100000000000 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM none none )) ) ;; Returns (err u0) (restrict-assets? tx-sender ((with-stacking u1000000000000)) (try! (contract-call? 'SP000000000000000000002Q6VF78.pox-4 delegate-stx u900000000000 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM none none )) ) ;; Returns (ok true) ``` -------------------------------- ### with-nft allowance example Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/references/sip-033-clarity4.md Demonstrates with-nft granting an allowance for NFT identifier u123. A transfer of u4 fails with (err u0), while a transfer of u123 succeeds with (ok true). ```clarity (restrict-assets? tx-sender ((with-nft (contract-of nft-trait) "stackaroo" (list u123))) (try! (contract-call? nft-trait transfer u4 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM)) ) ;; Returns (err u0) (restrict-assets? tx-sender ((with-nft (contract-of nft-trait) "stackaroo" (list u123))) (try! (contract-call? nft-trait transfer u123 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM)) ) ;; Returns (ok true) ``` -------------------------------- ### get-user-borrows: Retrieve all borrows for a user Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/protocol-data.md Returns all borrows for a user with detailed debt information. The function calls .assets get-bitmap to get the enabled mask, then .market-vault get-position to fetch the position. If no position exists, it returns an empty borrows list. The enriched debt entries include scaled debt, current borrow index, actual debt, and interest accrued. ```clarity (define-read-only (get-user-borrows (account principal)) (let ((enabled-mask (contract-call? .assets get-bitmap))) (match (contract-call? .market-vault get-position account enabled-mask) position (let ((debt-list (get debt position)) ;; Map each debt entry to enriched format with actual balances (enriched-debts (map build-debt-entry debt-list))) (ok { account: account, borrows: enriched-debts })) err-code ;; No position exists (ok { account: account, borrows: (list) })))) ``` -------------------------------- ### as-contract? with current-contract pattern Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/references/sip-033-clarity4.md Shows the pattern for getting the current contract principal using as-contract? and tx-sender, which is described as ugly. The new current-contract keyword is introduced to avoid this pattern. ```clarity (unwrap-panic (as-contract? () tx-sender)) ``` -------------------------------- ### contract-hash? example Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/references/sip-033-clarity4.md Returns the SHA-512/256 hash of the code body of the given contract principal. On success returns (ok 0x); returns (err u1) if the principal is not a contract principal, or (err u2) if the contract does not exist. ```clarity (contract-hash? 'SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF.BNS-V2) ;; Returns (ok 0x9f8104ff869aba1205cd5e15f6404dd05675f4c3fe0817c623c425588d981c2f) ``` -------------------------------- ### init Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/dao-multisig.md Initializes the multisig with a list of signers and a threshold. Only callable once by the deployer, and requires the threshold to be greater than zero and no greater than the number of signers. ```clarity (define-public (init (signer-list (list 20 principal)) (new-threshold uint)) (begin (asserts! (and (is-eq DEPLOYER tx-sender) (> new-threshold u0) (<= new-threshold (len signer-list)) (is-eq (var-get threshold) u0)) ERR-SANITY-SIGNER) (map set-signer signer-list) (var-set threshold new-threshold) (var-set signer-count (len signer-list)) (ok true))) ``` -------------------------------- ### Example of ststx price transformation Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/oracle.md Shows a concrete example of the ststx price transformation: base STX price of $1.00 (100000000) with a ratio of 1.05 yields a final price of $1.05 (105000000). ```text Base STX price: $1.00 = 100000000 (8 decimals) ststx ratio: 1.05 (1 ststx = 1.05 STX) Final price: $1.05 = 105000000 ``` -------------------------------- ### initialize Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-stx.md Public function that initializes the vault. ```APIDOC ## initialize ### Description Initializes the vault by setting the initialized flag and depositing the minimum liquidity. ### Method PUBLIC ### Endpoint initialize ### Parameters None ### Response Returns `(ok bool)` on success or `(err uint)` on failure. ``` -------------------------------- ### ubalance: Get vault USDC balance Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-usdc.md Private function to get the vault's USDC balance. The mainnet version is commented out, indicating it would use unwrap-panic with a contract call to get-balance. ```clarity (define-private (ubalance) ;; @mainnet: (unwrap-panic (contract-call? 'SP120SBRBQJ00MCWS7TM5R8WJNTTKD5K0HFRC2CNE.usdcx get-balance current-contract))) ``` -------------------------------- ### total-assets-preview private function Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-ststx.md Calculates total assets preview using debt-preview instead of total-debt. ```clarity (define-private (total-assets-preview) (let ((current-assets (var-get assets)) (debt (debt-preview)) (borrowed (var-get total-borrowed)) (interest (if (> debt borrowed) (- debt borrowed) u0))) (+ current-assets interest))) ``` -------------------------------- ### decode-u128 decode 16-byte big-endian uint Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/flashloan-liquidator.md Decodes a u128 from 16 bytes big-endian starting at a given position. Uses slice and as-max-len? with unwrap-panic, assuming the buffer has at least 16 bytes from start. ```clarity (define-private (decode-u128 (data (buff 4096)) (start uint)) (let ( (end (+ start u16)) (segment (default-to 0x (slice? data start end))) ) ;; Convert to u128, handling case where slice might be shorter than 16 bytes (buff-to-uint-be (unwrap-panic (as-max-len? segment u16))))) ``` -------------------------------- ### initialize public function Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-ststx.md Initializes the vault by setting the initialized flag and depositing minimum liquidity. Emits a print event and returns true. ```clarity (define-public (initialize) (begin (asserts! (not (var-get initialized)) ERR-ALREADY-INITIALIZED) (var-set initialized true) (try! (deposit MINIMUM-LIQUIDITY u0 NULL-ADDRESS)) (print { action: "vault-initialize", caller: contract-caller, data: { vault: UNDERLYING, minimum-liquidity: MINIMUM-LIQUIDITY } }) (ok true))) ``` -------------------------------- ### get-price Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/pyth-storage-v4.md Read-only function to get a price feed entry by identifier. ```APIDOC ## get-price ### Description Read-only function that returns the current price entry for a given price identifier. Similar to `read`, but read-only. ### Method Read-only function ### Parameters - **price-identifier** (buff 32) - Required - The price feed identifier. ### Return Value Returns a response containing the price entry tuple (with `conf`, `ema-conf`, `ema-price`, `expo`, `prev-publish-time`, `price`, `publish-time`) or an error code (uint). ### Source Code ```clarity (define-read-only (get-price (price-identifier (buff 32))) (let ((entry (unwrap! (map-get? prices price-identifier) ERR_PRICE_FEED_NOT_FOUND))) (ok entry))) ``` ``` -------------------------------- ### init public function Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/dao-executor.md Public function that initializes the impl variable. Only allowed once and only by the DEPLOYER; fails with ERR-INIT if called by anyone else or if impl is already set. ```clarity (define-public (init (new-impl principal)) (begin (asserts! (is-eq contract-caller DEPLOYER) ERR-INIT) (asserts! (is-none (var-get impl)) ERR-INIT) (var-set impl (some new-impl)) (ok true) )) ``` -------------------------------- ### handle-swap - flashloan callback routing to execute-sbtc-usdc-swap Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/flashloan-liquidator.md Handles the flashloan callback for swaps. Decodes parameters (borrower, coll-aid, debt-aid, min-coll, min-swap-out, dex-route) from the data buffer, calculates total repayment as amount + fee, and routes only for sBTC collateral and USDC debt (ids u2 and u6), calling execute-sbtc-usdc-swap or returning ERR-INVALID-ASSET-ID. ```clarity (define-private (handle-swap (amount uint) (fee uint) (data (buff 4096)) (caller principal)) (let ( (borrower (decode-principal data u1)) (coll-aid (get-u8 data u22)) (debt-aid (get-u8 data u23)) (min-coll (decode-u128 data u24)) (min-swap-out (decode-u128 data u40)) (dex-route (get-u8 data u56)) (total-repayment (+ amount fee)) ) ;; Route: sBTC collateral, USDC debt -> liquidate, swap to USDC (if (and (is-eq coll-aid u2) (is-eq debt-aid u6)) (execute-sbtc-usdc-swap borrower amount min-coll min-swap-out total-repayment caller) ERR-INVALID-ASSET-ID))) ``` -------------------------------- ### read-price-with-staleness-check Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/pyth-storage-v4.md Read-only function to get a price feed entry with a staleness check. ```APIDOC ## read-price-with-staleness-check ### Description Read-only function that returns a price feed entry only if it is not stale. It checks the price's publish-time against the current Stacks block time and a staleness threshold retrieved from the governance contract. ### Method Read-only function ### Parameters - **price-identifier** (buff 32) - Required - The price feed identifier. ### Return Value Returns a response containing the price entry tuple (with `conf`, `ema-conf`, `ema-price`, `expo`, `prev-publish-time`, `price`, `publish-time`) or an error code (uint) if the price is not found or is stale. ### Source Code ```clarity (define-read-only (read-price-with-staleness-check (price-identifier (buff 32))) (let ((entry (unwrap! (map-get? prices price-identifier) ERR_PRICE_FEED_NOT_FOUND)) (stale-price-threshold (contract-call? .pyth-governance-v3 get-stale-price-threshold)) (latest-stacks-timestamp (unwrap! (get-stacks-block-info? time (- stacks-block-height u1)) ERR_STALE_PRICE))) (asserts! (>= (get publish-time entry) (+ (- latest-stacks-timestamp stale-price-threshold) STACKS_BLOCK_TIME)) ERR_STALE_PRICE) (ok entry))) ``` ``` -------------------------------- ### ubalance: Get USDH balance of contract Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-usdh.md Private function that returns the USDH balance of the current contract. The mainnet version is commented out. ```clarity (define-private (ubalance) ;; @mainnet: (unwrap-panic (contract-call? 'SPN5AKG35QZSK2M8GAMR4AFX45659RJHDW353HSG.usdh-token-v1 get-balance current-contract))) ``` -------------------------------- ### ERR-ALREADY-INITIALIZED constant Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-ststx.md Error code for already initialized, value 802003. ```clarity (define-constant ERR-ALREADY-INITIALIZED (err u802003)) ``` -------------------------------- ### ERR-INIT constant Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-ststx.md Error code for initialization failures, value 802002. ```clarity (define-constant ERR-INIT (err u802002)) ``` -------------------------------- ### get-active-guardian-set: Get the active guardian set Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/wormhole-core-v4.md Read-only function that returns the active guardian set and its ID. Panics if the guardian set is not found. ```clarity (define-read-only (get-active-guardian-set) (let ((set-id (var-get active-guardian-set-id)) (guardians (unwrap-panic (map-get? guardian-sets set-id)))) (ok {set-id: set-id, guardians: guardians}))) ``` -------------------------------- ### set-price public function Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/mock-oracle.md Sets a price for a key, deployer only. Can be called directly in simnet. Emits a print event with action 'mock-oracle-set-price'. ```clarity (define-public (set-price (key (string-ascii 32)) (value uint)) (begin (asserts! (is-eq tx-sender (var-get deployer)) ERR-NOT-AUTHORIZED) (map-set prices key { value: value, timestamp: stacks-block-time }) (print { action: "mock-oracle-set-price", key: key, value: value, timestamp: stacks-block-time }) (ok true))) ``` -------------------------------- ### Execute sBTC to USDC Swap Liquidation (execute-sbtc-usdc-swap) Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/flashloan-liquidator.md Executes a flashloan liquidation by calling the market contract to liquidate sBTC collateral with USDC debt, swapping the received sBTC for USDC via mock-dex, and transferring the USDC to the caller for repayment and profit. Requires specific parameters: borrower, debt-amount, min-collateral, min-swap-out, total-repayment, and caller. Expects success (ok) or throws an error (err) from the called contracts. ```clarity (define-private (execute-sbtc-usdc-swap (borrower principal) (debt-amount uint) (min-collateral uint) (min-swap-out uint) (total-repayment uint) (caller principal)) (ok (try! (as-contract? ((with-all-assets-unsafe)) (begin ;; Step 1: Liquidate sBTC collateral with USDC debt (let ( (liq-result (try! (contract-call? .market liquidate borrower .sbtc .usdc debt-amount min-collateral none none))) (collateral-received (get collateral liq-result)) ) ;; Step 2: Swap sBTC -> USDC via mock-dex (let ( (swap-result (try! (contract-call? .mock-dex swap .sbtc .usdc collateral-received min-swap-out))) (usdc-received swap-result) ) ;; Step 3: Transfer USDC to caller for flashloan repayment and profit (try! (contract-call? .usdc transfer usdc-received tx-sender caller none)) (print { action: "flashloan-liquidation-swap", borrower: borrower, collateral-received: collateral-received, usdc-received: usdc-received, total-repayment: total-repayment, caller: caller }) true))))))) ``` -------------------------------- ### Get Market Pause Liquidation Status (get-market-pause-liquidation) Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/flashloan-liquidator.md Read-only function that calls the market contract to check if liquidation is paused. Direct reference to market for deployment ordering. ```clarity (define-read-only (get-market-pause-liquidation) (contract-call? .market get-pause-liquidation)) ``` -------------------------------- ### total-supply-preview Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-ststx.md Returns the total supply including the treasury LP preview. ```clarity (define-private (total-supply-preview) (let ((current-supply (total-supply)) (treasury-lp (calc-treasury-lp-preview))) (+ current-supply treasury-lp))) ``` -------------------------------- ### Get Operation Code for Swap Liquidation (get-op-swap) Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/flashloan-liquidator.md Returns the operation code for swap liquidation (OP-LIQUIDATE-SWAP). Used to identify the liquidation operation type. This is a read-only function. ```clarity (define-read-only (get-op-swap) OP-LIQUIDATE-SWAP) ``` -------------------------------- ### flashloan implementation Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-usdh.md The full implementation of the flashloan function, including reentrancy guard, whitelist check, fee calculation, and callback execution. ```clarity (define-public (flashloan (amount uint) (funds-receiver (optional principal)) (fc ) (data (optional (buff 4096)))) (let ((states (var-get pause-states)) (u (try! (accrue))) (funds-provider contract-caller) (funds-receiver-resolved (match funds-receiver recv recv contract-caller)) (permissions (get-flashloan-permissions funds-provider)) (can-flashloan (get can-flashloan permissions)) (fee-exempt (get fee-exempt permissions)) (fee-percentage (if fee-exempt u0 (var-get fee-flash))) (contract-balance (ubalance)) (fee (mul-div-up amount fee-percentage BPS))) (asserts! (not (get flashloan states)) ERR-PAUSED) (asserts! (not (var-get in-flashloan)) ERR-REENTRANCY) ;; Whitelist check (asserts! can-flashloan ERR-FLASHLOAN-UNAUTHORIZED) (asserts! (is-standard funds-receiver-resolved) ERR-INVALID-ADDRESS) ;; Check liquidity (asserts! (<= amount contract-balance) ERR-INSUFFICIENT-FLASHLOAN-LIQUIDITY) ;; Set reentrancy guard (var-set in-flashloan true) ;; Send funds to receiver (try! (send-underlying amount funds-receiver-resolved)) ;; Execute callback (try! (contract-call? fc callback amount fee data)) ;; Pull back amount + fee from provider (try! (receive-underlying (+ amount fee) funds-provider)) ;; Send fee to treasury if fee > 0 (if (> fee u0) (try! (send-underlying fee .dao-treasury)) false) ;; Clear reentrancy guard (var-set in-flashloan false) (print { action: "flashloan", caller: contract-caller, data: { funds-provider: funds-provider, funds-receiver: funds-receiver-resolved, amount: amount, fee: fee, assets: (var-get assets) } }) (ok true))) ``` -------------------------------- ### Get Operation Code for Redeem-Swap Liquidation (get-op-redeem-swap) Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/flashloan-liquidator.md Returns the operation code for redeem-swap liquidation (OP-LIQUIDATE-REDEEM-SWAP). Used to identify the liquidation operation type. This is a read-only function. ```clarity (define-read-only (get-op-redeem-swap) OP-LIQUIDATE-REDEEM-SWAP) ``` -------------------------------- ### Get Operation Code for Redeem Liquidation (get-op-redeem) Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/flashloan-liquidator.md Returns the operation code for redeem liquidation (OP-LIQUIDATE-REDEEM). Used to identify the liquidation operation type. This is a read-only function. ```clarity (define-read-only (get-op-redeem) OP-LIQUIDATE-REDEEM) ``` -------------------------------- ### set-flashloan-permissions public function Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-ststx.md Sets flashloan permissions for an account. Requires DAO auth and emits a print event. ```clarity (define-public (set-flashloan-permissions (account principal) (can-flashloan bool) (fee-exempt bool)) (begin (try! (check-dao-auth)) (print { action: "vault-set-flashloan-permissions", caller: tx-sender, data: { vault: UNDERLYING, account: account, can-flashloan: can-flashloan, fee-exempt: fee-exempt } }) (ok (map-set flashloan-permissions account { can-flashloan: can-flashloan, fee-exempt: fee-exempt })))) ``` -------------------------------- ### Get Operation Code for Same-Asset Liquidation (get-op-same-asset) Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/flashloan-liquidator.md Returns the operation code for same-asset liquidation (OP-LIQUIDATE-SAME-ASSET). Used to identify the liquidation operation type. This is a read-only function. ```clarity (define-read-only (get-op-same-asset) OP-LIQUIDATE-SAME-ASSET) ``` -------------------------------- ### Flash loan workflow steps Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/docs/vaults.md Outlines the four-step flash loan process for whitelisted partners: borrow, execute callback, repay principal, and complete or revert. Flash loans are not public and are restricted to DAO-approved addresses for market health operations. ```text 1. Whitelisted contract borrows from vault 2. Executes callback logic 3. Repays principal before transaction ends 4. Transaction completes (or reverts if repayment fails) ``` -------------------------------- ### principal-construct-from-version-and-hash principal builder Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/flashloan-liquidator.md Constructs a principal from a version uint and a 20-byte hash. Supports mainnet (0x16), testnet (0x1a), contract (0x14), and multi-sig versions (0x15, 0x19), defaulting to testnet standard. ```clarity (define-private (principal-construct-from-version-and-hash (version uint) (hash (buff 20))) (if (is-eq version u22) ;; 0x16 = mainnet standard principal (unwrap-panic (principal-construct? 0x16 hash)) (if (is-eq version u26) ;; 0x1a = testnet standard principal (unwrap-panic (principal-construct? 0x1a hash)) (if (is-eq version u20) ;; 0x14 = mainnet contract principal (unwrap-panic (principal-construct? 0x14 hash)) (if (is-eq version u21) ;; 0x15 = mainnet multi-sig (unwrap-panic (principal-construct? 0x15 hash)) (if (is-eq version u25) ;; 0x19 = testnet multi-sig (unwrap-panic (principal-construct? 0x19 hash)) ;; Default to testnet standard (unwrap-panic (principal-construct? 0x1a hash)))))))) ``` -------------------------------- ### ubalance: Get vault ststxbtc balance Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-ststxbtc.md Private helper that returns the vault's balance of the underlying ststxbtc token. The mainnet variant is commented out; the local implementation is not shown. ```clarity (define-private (ubalance) ;; @mainnet: (unwrap-panic (contract-call? 'SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.ststxbtc-token-v2 get-balance current-contract))) ``` -------------------------------- ### Constant ERR-ALREADY-INITIALIZED: duplicate init error Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-sbtc.md Error constant for when initialization is attempted more than once, with code 801003. ```clarity (define-constant ERR-ALREADY-INITIALIZED (err u801003)) ``` -------------------------------- ### Initialize Market-Vault and Configure Vaults and eGroups Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/proposal-protocol-init.md This Clarity code initializes the market-vault, sets supply and debt caps for each vault, authorizes the market contract, and inserts eGroups with predefined masks and LTV parameters. It is part of the protocol initialization process. ```clarity ;; STEP 2: INITIALIZE MARKET-VAULT (try! (contract-call? .market-vault set-impl .market)) ;; STEP 3: CONFIGURE VAULTS ;; Set vault caps (try! (contract-call? .vault-stx set-cap-supply CAP-STX-SUPPLY)) (try! (contract-call? .vault-stx set-cap-debt CAP-STX-DEBT)) (try! (contract-call? .vault-sbtc set-cap-supply CAP-SBTC-SUPPLY)) (try! (contract-call? .vault-sbtc set-cap-debt CAP-SBTC-DEBT)) (try! (contract-call? .vault-ststx set-cap-supply CAP-STSTX-SUPPLY)) (try! (contract-call? .vault-ststx set-cap-debt CAP-STSTX-DEBT)) (try! (contract-call? .vault-usdc set-cap-supply CAP-USDC-SUPPLY)) (try! (contract-call? .vault-usdc set-cap-debt CAP-USDC-DEBT)) (try! (contract-call? .vault-usdh set-cap-supply CAP-USDH-SUPPLY)) (try! (contract-call? .vault-usdh set-cap-debt CAP-USDH-DEBT)) (try! (contract-call? .vault-ststxbtc set-cap-supply CAP-STSTXBTC-SUPPLY)) (try! (contract-call? .vault-ststxbtc set-cap-debt CAP-STSTXBTC-DEBT)) ;; Authorize market contract in all vaults (try! (contract-call? .vault-stx set-authorized-contract .market true)) (try! (contract-call? .vault-sbtc set-authorized-contract .market true)) (try! (contract-call? .vault-ststx set-authorized-contract .market true)) (try! (contract-call? .vault-usdc set-authorized-contract .market true)) (try! (contract-call? .vault-usdh set-authorized-contract .market true)) (try! (contract-call? .vault-ststxbtc set-authorized-contract .market true)) ;; STEP 4: CREATE EGROUPS ;; Asset IDs (Paired system: underlying_id, vault_id = underlying_id + 1): ;; wstx: 0, zSTX: 1, sbtc: 2, zsBTC: 3, ststx: 4, zstSTX: 5, usdc: 6, zUSDC: 7, usdh: 8, zUSDH: 9, ststxbtc: 10, zstSTXbtc: 11 ;; Collateral bits: 0-63 (same as asset ID) ;; Debt bits: 64-127 (asset ID + 64) ;; Bit values: wstx=2^0=1, zSTX=2^1=2, sbtc=2^2=4, zsBTC=2^3=8, ststx=2^4=16, zstSTX=2^5=32, usdc=2^6=64, zUSDC=2^7=128, usdh=2^8=256, zUSDH=2^9=512, ststxbtc=2^10=1024, zstSTXbtc=2^11=2048 ;; Debt bits: wstx=2^64, sbtc=2^66, ststx=2^68, usdc=2^70, usdh=2^72 ;; Egroup 1: sBTC collateral + USDC+USDh debt (70% LTV) ;; MASK = 2^2 + 2^70 + 2^72 = 4 + 1180591620717411303424 + 4722366482869645213696 = 5902958103587056517124 (try! (contract-call? .egroup insert { BORROW-DISABLED-MASK: u0, MASK: u5902958103587056517124, LIQ-CURVE-EXP: u10000, LIQ-PENALTY-MIN: u500, LIQ-PENALTY-MAX: u1000, LTV-BORROW: u7000, LTV-LIQ-PARTIAL: u8500, LTV-LIQ-FULL: u9000 })) ;; Egroup 2: sBTC collateral + STX+sBTC+stSTX+USDC+USDh debt (30% LTV) ;; MASK = 2^2 + 2^64 + 2^66 + 2^68 + 2^70 + 2^72 = 4 + 6290339728780957101056 = 6290339728780957101060 (try! (contract-call? .egroup insert { BORROW-DISABLED-MASK: u0, MASK: u6290339728780957101060, LIQ-CURVE-EXP: u10000, LIQ-PENALTY-MIN: u500, LIQ-PENALTY-MAX: u1000, LTV-BORROW: u3000, LTV-LIQ-PARTIAL: u4000, LTV-LIQ-FULL: u5500 })) ;; Egroup 3: sBTC collateral + sBTC debt (80% LTV) ;; MASK = 2^2 + 2^66 = 4 + 73786976294838206464 = 73786976294838206468 (try! (contract-call? .egroup insert { BORROW-DISABLED-MASK: u0, MASK: u73786976294838206468, LIQ-CURVE-EXP: u10000, LIQ-PENALTY-MIN: u500, LIQ-PENALTY-MAX: u1000, LTV-BORROW: u8000, LTV-LIQ-PARTIAL: u9000, LTV-LIQ-FULL: u9500 })) ;; Egroup 4: zsBTC collateral + USDC+USDh debt (70% LTV) ;; MASK = 2^3 + 2^70 + 2^72 = 8 + 5902958103587056517120 = 5902958103587056517128 (try! (contract-call? .egroup insert { BORROW-DISABLED-MASK: u0, MASK: u5902958103587056517128, LIQ-CURVE-EXP: u10000, LIQ-PENALTY-MIN: u500, LIQ-PENALTY-MAX: u1000, LTV-BORROW: u7000, LTV-LIQ-PARTIAL: u8500, LTV-LIQ-FULL: u9000 })) ;; Egroup 5: zSTX collateral + USDC+USDh debt (40% LTV) ;; MASK = 2^1 + 2^70 + 2^72 = 2 + 5902958103587056517120 = 5902958103587056517122 (try! (contract-call? .egroup insert { BORROW-DISABLED-MASK: u0, MASK: u5902958103587056517122, LIQ-CURVE-EXP: u10000, LIQ-PENALTY-MIN: u500, LIQ-PENALTY-MAX: u1000, LTV-BORROW: u4000, LTV-LIQ-PARTIAL: u6000, LTV-LIQ-FULL: u7500 })) ;; Egroup 6: zstSTX collateral + USDC+USDh debt (40% LTV) ;; MASK = 2^5 + 2^70 + 2^72 = 32 + 5902958103587056517120 = 5902958103587056517152 (try! (contract-call? .egroup insert { BORROW-DISABLED-MASK: u0, MASK: u5902958103587056517152, LIQ-CURVE-EXP: u10000, LIQ-PENALTY-MIN: u500, LIQ-PENALTY-MAX: u1000, LTV-BORROW: u4000, LTV-LIQ-PARTIAL: u6000, LTV-LIQ-FULL: u7500 })) ;; Egroup 7: zUSDC collateral + STX debt (30% LTV) ;; MASK = 2^7 + 2^64 = 128 + 18446744073709551616 = 18446744073709551744 (try! (contract-call? .egroup insert { BORROW-DISABLED-MASK: u0, MASK: u18446744073709551744, LIQ-CURVE-EXP: u10000, LIQ-PENALTY-MIN: u500, LIQ-PENALTY-MAX: u1000, LTV-BORROW: u3000, LTV-LIQ-PARTIAL: u5000, LTV-LIQ-FULL: u6500 })) ;; Egroup 8: zsBTC collateral + STX+sBTC+stSTX+USDC+USDh debt (30% LTV) ``` -------------------------------- ### check-proof: Verify Merkle proof Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/pyth-pnau-decoder-v3.md Verifies a Merkle proof by folding the path with hash-path starting from the leaf hash, then comparing to the root hash. Returns true if the proof is valid. ```clarity (define-private (check-proof (root-hash (buff 20)) (leaf (buff 255)) (path (list 255 (buff 20)))) (is-eq root-hash (fold hash-path path (hash-leaf leaf)))) ``` -------------------------------- ### get-vault-available-liquidity: Get available liquidity for vault Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/protocol-data.md Private function that takes a vault ID (vid) and returns the available assets from the corresponding vault contract. Unknown IDs return 0. ```clarity (define-private (get-vault-available-liquidity (vid uint)) (if (is-eq vid STX) (contract-call? .vault-stx get-available-assets) (if (is-eq vid sBTC) (contract-call? .vault-sbtc get-available-assets) (if (is-eq vid stSTX) (contract-call? .vault-ststx get-available-assets) (if (is-eq vid USDC) (contract-call? .vault-usdc get-available-assets) (if (is-eq vid USDH) (contract-call? .vault-usdh get-available-assets) (if (is-eq vid stSTXbtc) (contract-call? .vault-ststxbtc get-available-assets) u0))))))) ``` -------------------------------- ### get-default-flashloan-permissions read-only function Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/vault-ststx.md Returns the default flashloan permissions tuple as a response. ```clarity (define-read-only (get-default-flashloan-permissions) (ok (var-get default-flashloan-permissions))) ``` -------------------------------- ### ERR_VERSION_MIN constant Source: https://github.com/zest-protocol/zest-v2-contracts/blob/main/local-testing/docs/clarigen/pyth-pnau-decoder-v3.md Error code (u2003) returned when the minor version in the header does not match PYTHNET_MINOR_VERSION. ```clarity (define-constant ERR_VERSION_MIN (err u2003)) ```