# Lender may not be able to close loan or get back lending token.

TellerV2 sets bid.lender to USING_LENDER_MANAGER on NFT claim, so lenderCloseLoan's sender==bid.lender check fails and NFT owner receives escrowed funds.

- Payout: Contest reward
- Severity: high
- Program: Teller
- Credited: 0xadrii
- Disclosed: 2024-04-18
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2024-04-teller-finance-judging/issues/11
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-04-teller-finance%3AH-1
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** TellerV2 lending contract (claimLoanNFT / lenderCloseLoan / _sendOrEscrowFunds)
**Root cause:** claimLoanNFT overwrites bid.lender with the USING_LENDER_MANAGER sentinel, but lenderCloseLoan and setRepaymentListenerForBid still compare sender to bid.lender directly instead of resolving via getLoanLender.
**Steps:**
1. Lender calls `claimLoanNFT(_bidId)`; bid.lender becomes USING_LENDER_MANAGER and lenderManager mints NFT to lender.
2. Lender calls `lenderCloseLoan(_bidId)` after default; `require(sender == bid.lender)` fails because bid.lender is the sentinel, reverting.
3. Same failure occurs in `setRepaymentListenerForBid`.
4. On PAID/LIQUIDATED, `_sendOrEscrowFunds` resolves lender via `getLoanLender` -> `lenderManager.ownerOf(_bidId)`, so funds go to whoever currently holds the NFT, not the original lender.
**How found:** Code reading of claimLoanNFT's sentinel assignment and tracing every place bid.lender is used directly versus via getLoanLender, spotting the inconsistent resolution.
**Exploitation:** A lender who claimed the NFT and later transferred or sold it (or had it stolen) loses the ability to close the loan and the escrowed repayment/collateral flows to the new NFT owner.
**Insight:** When a contract uses a sentinel address to signal indirection (e.g. USING_LENDER_MANAGER), grep every read of that storage slot for direct comparisons; any check not routed through the resolver function is a latent auth/ownership bug.
