diff --git a/contracts/borrower-v1.clar b/contracts/borrower-v1.clar index 718d96e..c75af64 100644 --- a/contracts/borrower-v1.clar +++ b/contracts/borrower-v1.clar @@ -97,7 +97,7 @@ (lp-open-interest-without-principal (contract-call? .math-v1 safe-sub (get lp-open-interest interest-params) total-borrowed-amount)) (lp-part (contract-call? .math-v1 safe-div (* interest-part lp-open-interest-without-principal) open-interest-without-principal)) (protocol-part (contract-call? .math-v1 safe-div (* interest-part (get protocol-open-interest interest-params)) open-interest-without-principal)) - (staked-part (contract-call? .math-v1 safe-div (* interest-part (get staked-open-interest interest-params)) open-interest-without-principal)) + (staked-part (contract-call? .math-v1 safe-sub interest-part (+ lp-part protocol-part))) (asset-params (contract-call? .state-v1 get-lp-params)) (staked-lp-tokens (contract-call? .math-v1 convert-to-shares asset-params staked-part false)) (total-user-debt-shares (unwrap! (contract-call? .math-v1 sub (get debt-shares position) shares) ERR-NOT-ENOUGH-SHARES)) diff --git a/contracts/liquidator-v1.clar b/contracts/liquidator-v1.clar index 347e772..4f77d3c 100644 --- a/contracts/liquidator-v1.clar +++ b/contracts/liquidator-v1.clar @@ -10,8 +10,8 @@ (define-constant PRICE-SCALING-FACTOR (contract-call? .constants-v2 get-price-scaling-factor)) ;; Must have the same precision as SCALING-FACTOR (define-constant MINIMUM_HEALTH_RATIO u100000000) -;; Liquidation buffer of 0.50% -(define-constant LIQUIDATION-BUFFER u500000) +;; Liquidation buffer of 2.00% +(define-constant LIQUIDATION-BUFFER u2000000) ;; ERROR VALUES (define-constant ERR-DIVIDE-BY-ZERO (err u30000)) @@ -25,8 +25,9 @@ (define-constant ERR-INVALID-ORACLE-PRICE (err u30008)) (define-constant ERR-MISSING-MARKET-PRICE (err u30009)) (define-constant ERR-NON-ZERO-REPAY-AMOUNT (err u30010)) +(define-constant ERR-LIQUIDATION-NOT-ALLOWED (err u30011)) -;; PUBLIC FUNCTIONS +;; PUBLIC FUNCTIONS (define-public (batch-liquidate (pyth-price-feed-data (optional (buff 8192))) (collateral ) (batch (list 20 (optional { user: principal, liquidator-repay-amount: uint, @@ -251,7 +252,10 @@ (define-private (execute-liquidation (user principal) (collateral ) (liquidator-repay-amount uint) (min-collateral-expected uint)) (let ( - (collateral-token (contract-of collateral)) + (collateral-token (contract-of collateral)) + ;; L-36: enforce minimum 6-block gap between borrowing and liquidation + (user-position-data (contract-call? .state-v1 get-borrow-repay-params user)) + (position-for-block-check (unwrap! (get user-position user-position-data) ERR-NO-POSITION)) ;; get liquidation info for the user (liquidation-res (try! (get-liquidation-info user collateral liquidator-repay-amount none none none none))) (liquidation-info (get liquidation-info liquidation-res)) @@ -283,7 +287,7 @@ ;; calculate liquidity provider and protocol debt repaid (lp-part (contract-call? .math-v1 safe-div (* interest-part lp-open-interest-without-principal) open-interest-without-principal)) (protocol-part (contract-call? .math-v1 safe-div (* interest-part (get protocol-open-interest open-interest-info)) open-interest-without-principal)) - (staked-part (contract-call? .math-v1 safe-div (* interest-part (get staked-open-interest open-interest-info)) open-interest-without-principal)) + (staked-part (contract-call? .math-v1 safe-sub interest-part (+ lp-part protocol-part))) (asset-params (contract-call? .state-v1 get-lp-params)) (staked-lp-tokens (contract-call? .math-v1 convert-to-shares asset-params staked-part false)) (updated-borrowed-amount (contract-call? .math-v1 safe-sub user-borrowed-amount principal-part)) @@ -294,6 +298,8 @@ (get collaterals position-data) )) ) + ;; L-36: require at least 6 blocks (~1 min) between borrowing and liquidation + (asserts! (>= stacks-block-height (+ (get borrowed-block position-for-block-check) u6)) ERR-LIQUIDATION-NOT-ALLOWED) (try! (ensure-non-zero-repay-amount liquidator-repay-amount collateral-price)) ;; update state (try! (contract-call? .state-v1 update-liquidate-collateral-state collateral { @@ -369,7 +375,7 @@ ) (let ( - (denominator (- + (denominator (contract-call? .math-v1 safe-sub SCALING-FACTOR (try! (safe-div (* (+ SCALING-FACTOR liquidation-discount) collateral-liquid-ltv) SCALING-FACTOR)) )) @@ -532,9 +538,10 @@ (interest-part (get interest-part interest-portion)) (open-interest-without-principal (contract-call? .math-v1 safe-sub total-open-interest total-borrowed-amount)) (lp-open-interest-without-principal (contract-call? .math-v1 safe-sub lp-open-interest-val total-borrowed-amount)) - (lp-part (+ principal-part (contract-call? .math-v1 safe-div (* interest-part lp-open-interest-without-principal) open-interest-without-principal))) + (lp-interest-part (contract-call? .math-v1 safe-div (* interest-part lp-open-interest-without-principal) open-interest-without-principal)) (protocol-part (contract-call? .math-v1 safe-div (* interest-part protocol-open-interest-val) open-interest-without-principal)) - (staked-part (contract-call? .math-v1 safe-div (* interest-part staked-open-interest-val) open-interest-without-principal)) + (staked-part (contract-call? .math-v1 safe-sub interest-part (+ lp-interest-part protocol-part))) + (lp-part (+ principal-part lp-interest-part)) (updated-total-borrowed-amount (contract-call? .math-v1 safe-sub total-borrowed-amount principal-part)) (staked-lp-tokens (contract-call? .staking-v1 get-total-staked-lp-tokens)) (burned-staking-lp-tokens (try! (contract-call? .state-v1 socialize-user-bad-debt user remaining-debt lp-part staked-part protocol-part updated-total-borrowed-amount .staking-v1 staked-lp-tokens))) @@ -549,7 +556,7 @@ updated-total-borrowed-amount: updated-total-borrowed-amount, burned-staking-lp-tokens: burned-staking-lp-tokens }) - (asserts! (<= burned-staking-lp-tokens u0) (contract-call? .staking-v1 slash-total-staked-lp-tokens burned-staking-lp-tokens)) + (if (> burned-staking-lp-tokens u0) (try! (contract-call? .staking-v1 slash-total-staked-lp-tokens burned-staking-lp-tokens)) true) SUCCESS )) ) diff --git a/contracts/lp-incentives-v2.clar b/contracts/lp-incentives-v2.clar index 8cfad79..807d011 100644 --- a/contracts/lp-incentives-v2.clar +++ b/contracts/lp-incentives-v2.clar @@ -51,6 +51,7 @@ (define-constant ERR-USER-REWARDS-CLAIMED (err u100009)) (define-constant ERR-REWARDS-NOT-CLAIMED (err u100010)) (define-constant ERR-INVALID-SNAPSHOT-TIME (err u100011)) +(define-constant ERR-NOT-AUTHORIZED (err u100012)) ;; Read-only functions (define-read-only (get-epoch-details) @@ -121,6 +122,7 @@ (define-public (claim-rewards (on-behalf-of (optional principal))) (let ( (user (default-to contract-caller on-behalf-of)) + (auth-check (asserts! (or (is-eq contract-caller user) (is-none on-behalf-of)) ERR-NOT-AUTHORIZED)) (rewards (unwrap! (map-get? user-rewards user) ERR-NO-USER-REWARDS)) (reward-amount (get earned-rewards rewards)) ) diff --git a/contracts/modules/linear-kinked-ir-v1.clar b/contracts/modules/linear-kinked-ir-v1.clar index da8bcef..cd865c7 100644 --- a/contracts/modules/linear-kinked-ir-v1.clar +++ b/contracts/modules/linear-kinked-ir-v1.clar @@ -10,6 +10,8 @@ (define-constant ERR-NOT-INITIALIZED (err u70002)) (define-constant ERR-NOT-GOVERNANCE (err u70003)) (define-constant ERR-INVALID-UTILIZATION-KINK (err u70004)) +(define-constant ERR-INVALID-IR-PARAMS (err u70005)) +(define-constant ERR-TAYLOR-INPUT-TOO-LARGE (err u70006)) ;; CONSTANTS (define-constant one-8 u100000000) @@ -20,6 +22,8 @@ (define-constant fact_5 u120000000000000) (define-constant fact_6 u720000000000000) (define-constant seconds-in-year u31536000) +(define-constant MAX-IR-PARAM u100000000000000) +(define-constant MAX-TAYLOR-INPUT u2000000000000) (define-constant STACKS_BLOCK_TIME (contract-call? .constants-v1 get-stacks-block-time )) ;; DATA-VARS @@ -47,6 +51,9 @@ ) (asserts! (< utilization-kink-val one-12) ERR-INVALID-UTILIZATION-KINK) + (asserts! (<= ir-slope-1-val MAX-IR-PARAM) ERR-INVALID-IR-PARAMS) + (asserts! (<= ir-slope-2-val MAX-IR-PARAM) ERR-INVALID-IR-PARAMS) + (asserts! (<= base-ir-val MAX-IR-PARAM) ERR-INVALID-IR-PARAMS) (print { old-ir-slope-1: (var-get ir-slope-1), new-ir-slope-1: ir-slope-1-val, @@ -126,7 +133,10 @@ (define-read-only (compounded-interest (current-interest-rate uint) (elapsed-block-time uint)) (begin (asserts! (var-get is-initialized) ERR-NOT-INITIALIZED) - (ok (taylor-6 (get-rt-by-block current-interest-rate elapsed-block-time))) + (let ((rt (get-rt-by-block current-interest-rate elapsed-block-time))) + (asserts! (<= rt MAX-TAYLOR-INPUT) ERR-TAYLOR-INPUT-TOO-LARGE) + (ok (taylor-6 rt)) + ) )) (define-read-only (get-ir-params) @@ -171,7 +181,7 @@ )) (define-private (mul (x uint) (y uint)) - (/ (+ (* x y) (/ one-12 u2)) one-12) + (/ (* x y) one-12) ) (define-private (div (x uint) (y uint)) @@ -181,7 +191,7 @@ ;; rate in 12-fixed ;; n-blocks (define-read-only (get-rt-by-block (rate uint) (elapsed-block-time uint)) - (/ (* rate (/ (* elapsed-block-time one-12) seconds-in-year)) one-12) + (/ (* rate elapsed-block-time) seconds-in-year) ) ;; taylor series expansion to the 6th degree to estimate e^x diff --git a/contracts/modules/withdrawal-caps-v1.clar b/contracts/modules/withdrawal-caps-v1.clar index 91cc3a7..556a623 100644 --- a/contracts/modules/withdrawal-caps-v1.clar +++ b/contracts/modules/withdrawal-caps-v1.clar @@ -20,6 +20,7 @@ (define-constant ERR-INVALID-CAP-FACTOR (err u120005)) (define-constant ERR-NOT-AUTHORIZED (err u120006)) (define-constant ERR-SYNC-FAILED (err u120007)) +(define-constant ERR-BLOCK-INFO (err u120008)) ;; VARIABLES @@ -67,7 +68,7 @@ ;; PRIVATE FUNCTIONS (define-private (get-time-now) - (unwrap-panic (get-stacks-block-info? time (- stacks-block-height u1))) + (ok (unwrap! (get-stacks-block-info? time (- stacks-block-height u1)) ERR-BLOCK-INFO)) ) (define-private (refill-bucket-amount (last-updated-at uint) (time-now uint) (max-bucket uint) (current-bucket uint) (inflow uint)) @@ -84,7 +85,7 @@ (let ( (extra-bucket-amount (- current-bucket max-bucket)) (decay-window (get-decay-time-window)) - (elapsed (if (is-eq last-updated-at u0) decay-window (- time-now last-updated-at))) + (elapsed (if (is-eq last-updated-at u0) decay-window (if (> time-now last-updated-at) (- time-now last-updated-at) u0))) (decayed-amount (if (>= elapsed decay-window) extra-bucket-amount (/ (* extra-bucket-amount elapsed) decay-window))) (new-bucket (- current-bucket decayed-amount)) ) @@ -94,7 +95,7 @@ (define-private (sync-lp-bucket (inflow uint)) (let ( - (time-now (get-time-now)) + (time-now (try! (get-time-now))) (last-ts (var-get last-lp-bucket-update)) (total-liquidity (unwrap! (contract-call? .mock-usdc get-balance .state-v1) ERR-FAILED-TO-GET-BALANCE)) (max-lp-bucket (/ (* total-liquidity (var-get lp-cap-factor)) SCALING-FACTOR)) @@ -120,7 +121,7 @@ (define-private (sync-debt-bucket (inflow uint)) (let ( - (time-now (get-time-now)) + (time-now (try! (get-time-now))) (last-ts (var-get last-debt-bucket-update)) (total-liquidity (contract-call? .state-v1 get-borrowable-balance)) (max-debt-bucket (/ (* total-liquidity (var-get debt-cap-factor)) SCALING-FACTOR)) @@ -145,7 +146,7 @@ (define-private (sync-collateral-bucket (collateral ) (inflow uint)) (let ( - (time-now (get-time-now)) + (time-now (try! (get-time-now))) (collateral-token (contract-of collateral)) (last-ts (default-to u0 (map-get? last-collateral-bucket-update collateral-token))) (total-liquidity (unwrap! (contract-call? collateral get-balance .state-v1) ERR-FAILED-TO-GET-BALANCE)) diff --git a/contracts/staking-v1.clar b/contracts/staking-v1.clar index 4f069c7..bdb78ad 100644 --- a/contracts/staking-v1.clar +++ b/contracts/staking-v1.clar @@ -208,7 +208,7 @@ (active-staked-lp-tokens-to-slash (- lp-tokens withdrawal-lp-tokens-to-slash)) ) (try! (contract-call? .state-v1 is-allowed-contract contract-caller)) - (var-set total-lp-tokens-staked (- (var-get total-lp-tokens-staked) active-staked-lp-tokens-to-slash)) + (var-set total-lp-tokens-staked (contract-call? .math-v1 safe-sub (var-get total-lp-tokens-staked) active-staked-lp-tokens-to-slash)) (if (is-eq withdrawal-lp-tokens withdrawal-lp-tokens-to-slash) (var-set unfinalized-withdrawals { lp-tokens: u0, diff --git a/tests/borrower_flow.test.ts b/tests/borrower_flow.test.ts index 20c5bad..f479c95 100644 --- a/tests/borrower_flow.test.ts +++ b/tests/borrower_flow.test.ts @@ -403,6 +403,11 @@ describe("Borrower User flow tests", () => { ); expect(depositorBalance.result.value.value).toBe(5000n); + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -449,6 +454,11 @@ describe("Borrower User flow tests", () => { ); expect(userDebtShares.result.value.data["debt-shares"].value).toEqual(796n); + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", diff --git a/tests/liquidation.test.ts b/tests/liquidation.test.ts index 699a416..080d5c0 100644 --- a/tests/liquidation.test.ts +++ b/tests/liquidation.test.ts @@ -369,6 +369,7 @@ describe("liquidation tests", () => { ); mint_token("mock-usdc", 18181818181, depositor); + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -457,6 +458,7 @@ describe("liquidation tests", () => { borrower1 ).result.value.value; + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -552,7 +554,7 @@ describe("liquidation tests", () => { let length = block.length; block.forEach((txn, index) => { if (index == length - 1) { - expect(txn.result).toBeErr(Cl.uint(113)); // ERR-LIQUIDATION-NOT-ALLOWED + expect(txn.result).toBeErr(Cl.uint(30011)); // ERR-LIQUIDATION-TIME-LOCK } else { expect(txn.result).toBeOk(Cl.bool(true)); } @@ -627,6 +629,7 @@ describe("liquidation tests", () => { mint_token("mock-usdc", 17777777777, depositor); + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -759,6 +762,7 @@ describe("liquidation tests", () => { ); mint_token("mock-usdc", 18181818181, depositor); + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -841,6 +845,7 @@ describe("liquidation tests", () => { ); mint_token("mock-usdc", 39000013190, depositor); + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -978,6 +983,7 @@ describe("liquidation tests", () => { liquidateData2, ...new Array(18).fill(Cl.none()), ]; + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "liquidator-v1", "batch-liquidate", @@ -1077,6 +1083,7 @@ describe("liquidation tests", () => { ); mint_token("mock-usdc", 30000000000000, depositor); + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1098,7 +1105,7 @@ describe("liquidation tests", () => { deployer ); expect(accounthealthRes.result.value.data["position-health"]).toEqual( - Cl.uint(100001972n) + Cl.uint(100001973n) ); }); @@ -1152,6 +1159,7 @@ describe("liquidation tests", () => { ); mint_token("mock-usdc", 18181818181, depositor); + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1173,7 +1181,7 @@ describe("liquidation tests", () => { deployer ); expect(accounthealthRes.result.value.data["position-health"]).toEqual( - Cl.uint(100000002n) + Cl.uint(100000000n) ); }); @@ -1227,6 +1235,7 @@ describe("liquidation tests", () => { ); mint_token("mock-usdc", 18181818181, depositor); + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1302,6 +1311,7 @@ describe("liquidation tests", () => { ); mint_token("mock-usdc", 18181818181, depositor); + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1377,6 +1387,7 @@ describe("liquidation tests", () => { ); mint_token("mock-usdc", 18181818181, depositor); + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1492,6 +1503,7 @@ describe("liquidation tests", () => { ); state_set_governance_contract(deployer); + simnet.mineEmptyBlocks(6); let liquidate = simnet.callPublicFn( "mock-liquidator-with-flash-loan", "liquidate-collateral", diff --git a/tests/lp-incentives.test.ts b/tests/lp-incentives.test.ts index d3a8770..ac68f84 100644 --- a/tests/lp-incentives.test.ts +++ b/tests/lp-incentives.test.ts @@ -316,8 +316,8 @@ describe("LP incentives tests", () => { expectUserStxBalance(user2, 0n); expectUnclaimedUserCount(1n); - // claim user2 rewards through user1 - claimRewards(user1, user2); + // claim user2 rewards (L-30: must be claimed by user themselves) + claimRewards(user2); expectUserStxBalance(user1, 60n); expectUserStxBalance(user2, 40n); expectUnclaimedUserCount(0n); @@ -414,9 +414,9 @@ describe("LP incentives tests", () => { // claim user rewards claimRewards(user1); - claimRewards(user1, user2); + claimRewards(user2); claimRewards(user3); - claimRewards(user1, user4); + claimRewards(user4); claimRewards(user5); claimRewards(user6); @@ -552,9 +552,9 @@ describe("LP incentives tests", () => { // claim user rewards claimRewards(user1); - claimRewards(user1, user2); + claimRewards(user2); claimRewards(user3); - claimRewards(user1, user4); + claimRewards(user4); claimRewards(user5); claimRewards(user6); diff --git a/tests/modules/linear-kinked-ir.test.ts b/tests/modules/linear-kinked-ir.test.ts index 4924f8b..f54ea9c 100644 --- a/tests/modules/linear-kinked-ir.test.ts +++ b/tests/modules/linear-kinked-ir.test.ts @@ -420,7 +420,7 @@ describe("linear kinked interest rate module tests", () => { // (((1 + (0.15/365/24/60/60))^(30000)) - 1) * 100 = 0.01427042449% // ((1 + (0.15/365/24/60/60))^(30000)) * 10^8 = 10,00,14,270.4244869736 - expect(IR.result).toBeOk(Cl.uint(1000142704245)); + expect(IR.result).toBeOk(Cl.uint(1000142704244)); }); it("calculate interest accrual with 10000 elapsed blocks", () => { diff --git a/tests/poc-slash-underflow.test.ts b/tests/poc-slash-underflow.test.ts index baeabba..51128db 100644 --- a/tests/poc-slash-underflow.test.ts +++ b/tests/poc-slash-underflow.test.ts @@ -177,6 +177,12 @@ describe("PoC: slash-total-staked-lp-tokens underflow", () => { // ──────────────────────────────────────────────────────────── mint_token("mock-usdc", 20_000_000_000, liquidator); + // Advance past the 6-block time-lock between borrowing and liquidation + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 94n, deployer); + // After fix, liquidation should succeed (bad debt socialized correctly) const result = simnet.callPublicFn( "liquidator-v1", diff --git a/tests/staking.test.ts b/tests/staking.test.ts index 80d8fa7..4a52436 100644 --- a/tests/staking.test.ts +++ b/tests/staking.test.ts @@ -649,6 +649,11 @@ describe("staking tests", () => { ); expect(depositorBalance.result.value.value).toBe(5000n); + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -705,6 +710,11 @@ describe("staking tests", () => { ); expect(depositToReserve.result).toBeOk(Cl.bool(true)); + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -903,6 +913,11 @@ describe("staking tests", () => { ); expect(depositorBalance.result.value.value).toBe(5000n); + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -972,6 +987,11 @@ describe("staking tests", () => { ); expect(totalLpSupply.result).toBeOk(Cl.uint(2000)); + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1195,6 +1215,11 @@ describe("staking tests", () => { ); expect(depositorBalance.result.value.value).toBe(5000n); + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1264,6 +1289,11 @@ describe("staking tests", () => { ); expect(totalLpSupply.result).toBeOk(Cl.uint(2000)); + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1449,6 +1479,11 @@ describe("staking tests", () => { mint_token("mock-usdc", 5000, depositor1); // first liquidation + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1474,6 +1509,11 @@ describe("staking tests", () => { expect(depositToReserve.result).toBeOk(Cl.bool(true)); // second liquidation triggers full wipe-out + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1580,6 +1620,11 @@ describe("staking tests", () => { mint_token("mock-usdc", 5000, depositor1); // first liquidation + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1605,6 +1650,11 @@ describe("staking tests", () => { expect(depositToReserve.result).toBeOk(Cl.bool(true)); // second liquidation triggers full wipe-out + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1769,6 +1819,11 @@ describe("staking tests", () => { ); expect(depositorBalance.result.value.value).toBe(5000n); + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); let liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral", @@ -1846,6 +1901,11 @@ describe("staking tests", () => { ); expect(stakingStatus.result).toStrictEqual(Cl.bool(true)); + simnet.mineEmptyBlocks(6); + // refresh prices after mining blocks + await set_price("mock-usdc", 1n, deployer); + await set_price("mock-btc", 10n, deployer); + await set_price("mock-eth", 65n, deployer); liquidate = simnet.callPublicFn( "liquidator-v1", "liquidate-collateral",