# Drips that end after the current cycle but before its creation can allow users to profit from squeezing

Drip created with start/end before creation time yields zero dripped amount on removal, yet receiver can still squeeze full amount, draining contract assets.

- Payout: Contest reward
- Severity: high
- Program: Drips Protocol
- Credited: evan
- Disclosed: 2023-03-10
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2023-01-drips-findings/issues/315
- Library page: https://bugbountylibrary.com/r/c4%3A2023-01-drips%3AH-01
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** DripsHub.sol setDrips/squeezeDrips
**Root cause:** setDrips computes dripped amount from elapsed time between start and end; a drip whose end precedes creation drips 0 so sender withdraws full balance, but squeezeDrips caps only by cycle start, not updateTime, so receiver still squeezes the full amount.
**Steps:**
1. Set cycle length 10s; at second 5 call `setDrips(user, erc20, currReceivers, +2, receivers, 0, 0)` with receiver config start=block.timestamp, amtPerSec=1*AMT_PER_SEC_MULTIPLIER, end=2 (drip ends before creation).
2. At second 6 call `setDrips(user, erc20, receivers, -2, emptyReceivers, 0, 0)` to remove drip; dripped amount is 0 so full balance returns to sender.
3. Call `squeezeDrips(receiver, erc20, user, 0, history)` with history of both updates; squeezeStartCap=_currCycleStart()=0, squeezeEndCap=6, returns full 2 units.
4. Point receiver at sender-controlled address to drain arbitrary asset from contract.
**How found:** Reasoned about mismatch between setDrips' dripped-amount calculation (bounded by start/end) and squeezeDrips' cap logic (bounded only by cycle start), hypothesizing a drip ending before creation yields zero cost but nonzero squeeze.
**Exploitation:** Sender creates a backdated short drip, immediately removes it recovering full balance, then squeezes via controlled receiver to extract funds the contract never received, repeatable to drain arbitrary ERC20 balance.
**Insight:** When a protocol has separate accounting for deposit/withdraw vs. claim/squeeze, check whether the claim path's time caps use the same updateTime/start bounds as the accounting path; a drip whose end < creation time is a classic zero-cost-but-claimable state.
