# Fully repaying a loan will result in debt payment being lost

Cooler.repay deletes the loan storage struct before reading loan.lender, so full repayment sends debt tokens to address(0), losing the lender's funds.

- Payout: Contest reward
- Severity: high
- Program: Cooler
- Credited: 0x52
- Disclosed: 2023-01-16
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-01-cooler-judging/issues/33
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-01-cooler%3AH-3
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:accounting-error

**Target:** Solidity lending contract repay() function
**Root cause:** `loan` is a storage reference to `loans[loanID]`; deleting `loans[loanID]` zeroes the struct, so the subsequent `loan.lender` read returns address(0).
**Steps:**
1. Call `repay(loanID, repaid)` with `repaid == loan.amount`
2. `delete loans[loanID]` executes, zeroing the storage struct referenced by `loan`
3. `debt.transferFrom(msg.sender, loan.lender, repaid)` reads `loan.lender` as `address(0)`
4. Tokens are transferred to address(0) and lost (or revert for tokens that block zero-address transfers)
**How found:** Code reading of repay(): noticed the storage-reference aliasing between `loan` and `loans[loanID]` and that `delete` precedes the `loan.lender` read.
**Exploitation:** Any borrower fully repaying a loan triggers the bug; the debt tokens are sent to address(0) instead of the lender, permanently losing the lender's principal.
**Insight:** When a function holds a `storage` pointer and then deletes the underlying mapping entry, every later field read on that pointer returns zero — check ordering of delete vs. field access in repay/withdraw/liquidate flows.
