# A payment made towards multiple liens causes the borrower to lose funds to the payee

Bulk makePayment over multiple liens sends the entire paymentAmount to the first lien's payee, leaving remaining liens unpaid and borrower funds lost.

- Payout: Contest reward
- Severity: high
- Program: Astaria
- Credited: 0xRajeev
- Disclosed: 2022-11-07
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2022-10-astaria-judging/issues/190
- Library page: https://bugbountylibrary.com/r/sherlock%3A2022-10-astaria%3AH-13
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** LienToken.sol makePayment/_payment lien repayment loop
**Root cause:** _makePayment passes the full totalCapitalAvailable as paymentAmount to _payment on the first iteration; _payment transfers the entire amount to the payee even when it exceeds lien.amount, returning capitalSpent equal to the full amount, so subsequent iterations get paymentAmount=0.
**Steps:**
1. Borrower has multiple open liens on one collateralId.
2. Call `makePayment(collateralId, paymentAmount)` with paymentAmount covering more than the first lien.
3. `_makePayment` loops liens, calling `_payment(lien, paymentAmount)` with the full amount on iteration 1.
4. `_payment` transfers the full paymentAmount to the first lien's payee, exceeding lien.amount.
5. capitalSpent = full amount returned; next iteration paymentAmount = 0, remaining liens unpaid.
**How found:** Manual code review of the _makePayment loop and _payment transfer logic, noticing the full paymentAmount is forwarded on the first iteration and returned as capitalSpent, zeroing subsequent iterations.
**Exploitation:** Borrower intending to repay multiple liens loses the excess to the first payee while other liens stay open; no attacker needed, loss occurs on legitimate bulk payment.
**Insight:** In multi-item repayment loops, check whether the per-iteration amount is decremented by the amount actually consumed; a function returning 'spent' equal to the full input on the first item silently starves later iterations.
