# Yield, Swivel, Element, APWine and Sense lend() are subject to reentracy resulting in Illuminate PT over-mint

Illuminate Lender's lend() functions for Yield, Swivel, Element, APWine and Sense lack reentrancy guards, letting a malicious pool reenter and over-mint Illuminate PTs, stealing other users' funds.

- Payout: Contest reward
- Severity: high
- Program: Illuminate
- Credited: Jeiwan
- Disclosed: 2022-10-15
- Write-up quality: 8/10
- Original: https://github.com/sherlock-audit/2022-10-illuminate-judging/issues/179
- Library page: https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AH-8
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:accounting-error vuln:business-logic vuln:reentrancy

**Target:** Lender.sol lend()/yield()/elementSwap() swap helpers
**Root cause:** lend() computes PTs minted from a balance difference around a call to a user-supplied pool contract, without a reentrancy guard, so nested lend() calls inflate the recorded balance delta.
**Steps:**
1. Deploy attacker contract `y` implementing the Yield pool interface (fyToken(), sellBasePreview(), sellBase()).
2. In `y`, before forwarding to the real pool, call `Lender.lend(p,u,m,a2,y,...)` recursively with the same params but a different amount.
3. Nest 2-3 calls with amounts e.g. `10 DAI`, `100 DAI`, `10^6 DAI`; each inner call's PT balance increase is counted by the outer lend()'s `balanceOf` delta.
4. Outer lend() mints `1*10^6 + 1*10^2 + 1*10^1` PTs, middle mints `10^6+10^2`, inner mints `10^6`, total `3*10^6+2*10^2+10` PTs for `10^6+10^2+10` DAI.
5. Redeem the over-minted Illuminate PTs before other users to drain the underlying.
**How found:** Code review: noticed lend() variants use `balanceOf` before/after around a call to a user-supplied pool address, and that no nonReentrant modifier exists, so a malicious pool can reenter the same lend() and have its PT gain double-counted.
**Exploitation:** Attacker supplies a malicious pool contract to lend(); it reenters lend() with the same PT market so each nested swap's PT gain is counted multiple times by the outer balance-difference accounting, minting far more Illuminate PTs than underlying deposited. Attacker then redeems first to take the whole underlying backing.
**Escalation:** Recursion depth and amount sizing amplify over-mint; redeeming first converts inflated PTs into full underlying drain of other lenders.
**Insight:** When a function mints shares/tokens based on a `balanceOf` delta around an external call to an address the caller controls, that delta is reentrancy-exploitable even without a classic state-update ordering bug — check every user-supplied pool/router argument for a guard.
