# User can evade liquidation by depositing the minimum of tokens and gain time to not be liquidated

Salty.IO borrower front-runs liquidation with a dust deposit, resetting cooldownExpiration so liquidateUser reverts, letting underwater positions evade liquidation.

- Payout: Contest reward
- Severity: high
- Program: Salty.IO
- Credited: 0xbepresent
- Disclosed: 2024-04-19
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-01-salty-findings/issues/312
- Library page: https://bugbountylibrary.com/r/c4%3A2024-01-salty%3AH-05
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:liquidation vuln:race-condition

**Target:** CollateralAndLiquidity / StakingRewards stablecoin lending contract
**Root cause:** depositCollateralAndIncreaseShare calls _increaseUserShare with useCooldown=true, which sets user.cooldownExpiration = block.timestamp + modificationCooldown. liquidateUser later calls _decreaseUserShare with useCooldown=true, which requires block.timestamp >= cooldownExpiration, so any fresh deposit blocks liquidation.
**Steps:**
1. Alice deposits collateral and borrows max USDS.
2. Collateral price crashes making Alice liquidatable.
3. Alice front-runs liquidation: `collateralAndLiquidity.depositCollateralAndIncreaseShare(PoolUtils.DUST + 1, PoolUtils.DUST + 1, 0, block.timestamp, false)`
4. This sets user.cooldownExpiration = now + modificationCooldown.
5. Liquidator calls `liquidateUser(alice)`; _decreaseUserShare(wallet, collateralPoolID, amount, true) reverts with 'Must wait for the cooldown to expire'.
6. Alice repeats the dust deposit each time the cooldown nears expiry to stay unliquidated.
**How found:** Code reading of _increaseUserShare/_decreaseUserShare cooldown logic: noticed both deposit and liquidation paths share the same cooldownExpiration gate, so a deposit can block the liquidation decrease.
**Exploitation:** Attacker holding an underwater position watches the mempool for liquidateUser calls and submits a minimal DUST+1 collateral deposit ahead of it. The deposit resets the cooldown, causing the liquidation's _decreaseUserShare to revert. Repeating the dust deposit indefinitely keeps the bad debt unliquidated while the attacker retains borrowed USDS.
**Insight:** When a cooldown/timelock is applied symmetrically to both increase and decrease of a share, check whether an attacker-controlled increase can gate a privileged decrease (liquidation, withdrawal, slashing) and grief it.
