# OCC_Modular::applyCombine will round APR down

OCC_Modular.applyCombine divides weighted APR by notional with floor rounding, letting a borrower shave 1 BIPS off combined loan APR.

- Payout: Contest reward
- Severity: medium
- Program: Zivoe
- Credited: cergyk
- Disclosed: 2024-03-19
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2024-03-zivoe-judging/issues/304
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-03-zivoe%3AM-12
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:business-logic vuln:precision-loss

**Target:** OCC_Modular loan-combination locker (Solidity)
**Root cause:** APR = APR / notional in applyCombine truncates the weighted-average APR because APR is expressed in BIPS with low precision, so the division floors in the borrower's favor.
**Steps:**
1. Combine Loan A (100 principal, 20 APR, 100 payments) and Loan B (100 principal, 50 APR, 100 payments): (50*100+20*100)/200 = 35 exactly.
2. After combine approval, borrower makes one repayment on Loan B: 99 principal, 99 payments.
3. Recompute: (50*99+20*100)/(100+99) = 34.7..., which floors to 34 BIPS.
4. Borrower accepts combine at 34 APR instead of 35, saving 1 BIPS of interest on the whole notional.
**How found:** Code reading of applyCombine's weighted-average APR computation; noticed integer division truncation and that a borrower can perturb inputs via repayment to force the floor.
**Exploitation:** Borrower waits for underwriter approval of a combine, then makes a small repayment on one loan to perturb the weighted average so the division floors down by 1 BIPS, then accepts the combine at the reduced APR.
**Insight:** When a weighted average is computed in low-precision integer units (BIPS), check whether a user-controlled input (e.g. a partial repayment) can shift the numerator/denominator so the truncation lands in their favor after admin approval.
