# get_supply_ratio() compares raw shares to normal tokens without exchange price conversion, over-allocating yield to with-interest suppliers, leading to insolvency

Jupiter Lend's get_supply_ratio compares raw shares against normal tokens without exchange-price conversion, over-allocating yield to with-interest suppliers and creating an insolvency gap.

- Payout: Contest reward
- Severity: medium
- Program: Jupiter Lend
- Credited: hackhack
- Disclosed: 2026-07-11
- Write-up quality: 7/10
- Original: https://code4rena.com/reports/2026-02-jupiter-lend#m-03
- Library page: https://bugbountylibrary.com/r/c4%3A2026-02-jupiter-lend%3AM-03
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:rust tech:solana technique:source-review vuln:accounting-error vuln:reward-distribution

**Target:** Solana lending program state (token_reserve.rs, user_supply_position.rs)
**Root cause:** get_supply_ratio() and get_borrow_ratio() pass raw shares (amount*EXCHANGE_PRICES_PRECISION/exchange_price) into get_with_interest_vs_free_ratio alongside interest-free amounts in normal token units, unlike every other consumer which converts shares to normal tokens first.
**Steps:**
1. Observe with-interest supply stored as raw shares while interest-free supply stored as normal tokens in user_supply_position.rs.
2. Note get_supply_with_interest_normal_ceil(), get_borrow_with_interest_normal(), calc_utilization() all convert shares to normal; get_supply_ratio()/get_borrow_ratio() do not.
3. At deployment exchange_price=1e12 so units coincide; as exchange_price grows, with-interest side appears smaller than reality.
4. calculate_exchange_prices() uses the skewed ratio to set supply_rate too high, inflating supply_exchange_price beyond actual borrower yield.
5. With-interest suppliers withdraw excess tokens from reserve balance, compounding each operate/supply/borrow/withdraw call; at 36% drift with 50/50 split supply_rate is ~15% too high.
**How found:** Code review comparing unit conventions across consumers of get_total_supply_with_interest(); noticed only the ratio helpers skipped the raw-share-to-normal conversion that all other callers perform.
**Exploitation:** Any with-interest supplier repeatedly supplies/withdraws to trigger calculate_exchange_prices() and withdraw inflated share value, draining reserve balance; interest-free depositors and last withdrawers absorb the shortfall.
**Escalation:** Error compounds on every calculate_exchange_prices() call, growing the insolvency gap over time.
**Insight:** When a value has multiple consumers, audit each for consistent unit conversion — a single consumer skipping the shares-to-tokens conversion (while siblings convert) is a strong signal of a unit-mismatch bug, especially when the developer's worked example only validates at the 1:1 price point.
