# JUSD borrow fee rate is less than it should be

JUSDBank's getTRate() borrow fee math divides by an inflated rate, so borrowers pay ~9.1% instead of the intended 10% fee, shorting protocol revenue.

- Payout: Contest reward
- Severity: medium
- Program: Jojo
- Credited: BenRai
- Disclosed: 2023-04-11
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-04-jojo-judging/issues/73
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-04-jojo%3AM-1
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:fee-bypass

**Target:** JUSDBank.sol borrow accounting / getTRate()
**Root cause:** t0Rate is initialized to 1e18 and getTRate() adds borrowFeeRate*time/SECONDS_PER_YEAR, then _borrow divides tAmount by tRate, so the stored t0Amount shrinks by tRate rather than by the intended fee fraction.
**Steps:**
1. Observe getTRate() returns t0Rate + borrowFeeRate*timeDifference/SECONDS_PER_YEAR with t0Rate=1e18.
2. After one year at 10% fee, getTRate()=1.1e18.
3. Borrow 1 JUSD (1e6): t0Amount = 1e6*1e18/1.1e18 ≈ 909091.
4. Repay later: debt reflects ~9.1% fee instead of 10%, undercharging the borrower.
**How found:** Code review of the interest-rate accumulator: noticed t0Rate seeded at 1e18 and that _borrow divides by tRate, then computed the one-year example to show the fee fraction is inverted.
**Exploitation:** Borrowers repeatedly borrow JUSD and repay after time accrues, paying a lower effective fee than the configured borrowFeeRate, reducing protocol fee revenue.
**Insight:** When a rate accumulator is seeded at 1e18 and used as a divisor, check whether the intended fee is applied as a fraction (tAmount - tAmount*rate) rather than dividing by (1+rate); the two diverge as time accrues.
