# Reentrancy in PartialLiquidation and Repay Allows Unfair Liquidation and Arbitrary Mid-Liquidation Calls

PartialLiquidation disables reentrancy protection before repay, letting a repay hook re-enter liquidationCall and double-liquidate an already-solvent borrower.

- Payout: Contest reward
- Severity: medium
- Program: Silo
- Credited: ZC002
- Disclosed: 2025-03-19
- Write-up quality: 7/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_silo.pdf#3.2.9
- Library page: https://bugbountylibrary.com/r/cantina%3Asilo%3A3.2.9
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:cantina sev:medium tech:evm tech:solidity technique:chained technique:source-review vuln:business-logic vuln:liquidation vuln:reentrancy

**Target:** PartialLiquidation.liquidationCall / Silo.repay hook flow
**Root cause:** liquidationCall calls turnOffReentrancyProtection() before invoking repay(), and repay fires the beforeAction hook before re-enabling protection, so hooks can re-enter mid-liquidation while collateral was already seized but debt not yet repaid.
**Steps:**
1. Deploy a hook receiver whose beforeAction (Hook.REPAY) mints an NFT to the liquidator via _safeMint, triggering onERC721Received on the liquidator contract.
2. Borrower deposits 10e18 collateral, borrows 7.5e18 same asset; warp 50 days so position is liquidatable.
3. Liquidator calls `partialLiquidation.liquidationCall(token0, token0, BORROWER, 5e18, false)`.
4. Inside repay, beforeAction fires; NFT mint calls back into liquidator's `onERC721Received`.
5. In onERC721Received, re-enter `partialLiquidation.liquidationCall(token0, token0, BORROWER, 5e18, false)` while first liquidation is mid-flight.
6. Second liquidation succeeds despite borrower being solvent after first seizure, seizing extra collateral / duplicate fees.
**How found:** Code reading of PartialLiquidation.liquidationCall noticed turnOffReentrancyProtection() placed before repay(); tracing repay showed beforeAction hook fires before turnOnReentrancyProtection(), opening a reentrancy window even with a non-malicious hook.
**Exploitation:** Attacker becomes liquidator of a position; a benign repay hook (NFT mint) re-enters liquidationCall during the window where collateral was already forwarded but debt not yet repaid, executing a second liquidation on the same borrower in one tx to seize additional collateral and collect duplicate liquidation fees.
**Escalation:** Re-entry can also perform deposits, borrows, flash loans, collateral transitions or arbitrary Silo ops mid-liquidation, corrupting LTV/balance accounting.
**Insight:** When a guard is toggled off to let a callee re-enable it, check every external call and hook between the disable and the callee's re-enable; hooks like ERC721 _safeMint or ERC777 transfers are enough to re-enter even without malicious intent.
