# Borrowers lose funds if they call repayAndCloseLoan instead of closeLoan

repayAndCloseLoan on unmatched loans doesn't revert, transferring inflated interest plus minLoanAmount from borrower to a nonexistent lender, losing borrower funds.

- Payout: Audit contest
- Severity: medium
- Program: Backed Protocol
- Credited: cmichel
- Disclosed: 2022-04-21
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-04-backed-findings/issues/27
- Library page: https://bugbountylibrary.com/r/c4%3A2022-04-backed%3AM-05
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** NFTLoanFacilitator.sol repayAndCloseLoan / closeLoan
**Root cause:** repayAndCloseLoan lacks a check that a lender actually matched the loan (lastAccumulatedTimestamp > 0); interest accrues from timestamp 0 and loanAmount is the minLoanAmount, so a transfer is attempted for an unmatched loan.
**Steps:**
1. Borrower calls `createLoan` setting `minLoanAmount` and approves facilitator for the ERC20 loan asset.
2. No lender ever calls `lend`, so `lastAccumulatedTimestamp` stays 0 and no ownerOf/lender exists.
3. Borrower mistakenly calls `repayAndCloseLoan` instead of `closeLoan`.
4. Contract executes `ERC20(loanAsset).safeTransferFrom(msg.sender, lender, interest + loan.loanAmount)` with interest accumulated from timestamp 0 and loanAmount = minLoanAmount.
5. Borrower's approved funds are pulled and lost.
**How found:** Code review of repayAndCloseLoan: noticed it does not revert when no lender matched the loan, unlike closeLoan, and traced the safeTransferFrom using interest accumulated from timestamp 0 plus minLoanAmount. Sponsor initially thought ownerOf would revert, then discovered solmate's non-standard ownerOf did not revert, confirming the issue.
**Exploitation:** Not an attack: requires the borrower to have approved the facilitator for the ERC20 and to call the wrong function (repayAndCloseLoan) on an unmatched loan; funds are then transferred out based on inflated interest plus minLoanAmount.
**Insight:** When two functions close out the same state (closeLoan vs repayAndCloseLoan), check each for missing precondition guards; also verify whether library helpers like solmate ownerOf actually revert on nonexistent tokens, since assumed reverts can mask fund-loss paths.
