# The provide() function does not reset withdrawal requests, allowing an attacker to bypass risk-free yield tactics protection

Opus absorber's provide() fails to reset withdrawal request timestamps, letting an attacker pre-stage valid requests across accounts and exit immediately after profitable absorptions.

- Payout: Contest reward
- Severity: medium
- Program: Opus
- Credited: minhquanym
- Disclosed: 2024-03-08
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-01-opus-findings/issues/116
- Library page: https://bugbountylibrary.com/r/c4%3A2024-01-opus%3AM-04
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:business-logic vuln:race-condition

**Target:** Absorber stability pool contract (provide/remove/request-withdraw)
**Root cause:** provide() does not reset the account's pending withdrawal request timestamp, so a previously queued request remains valid after new yin is supplied, defeating the timelock meant to prevent risk-free yield frontrunning.
**Steps:**
1. Deposit small yin into many accounts (e.g. 100).
2. Stagger requestWithdrawal calls across accounts spaced by REQUEST_VALIDITY_PERIOD so at least one request is always valid within [REQUEST_BASE_TIMELOCK, REQUEST_BASE_TIMELOCK+REQUEST_VALIDITY_PERIOD].
3. When a profitable absorption is imminent, call `provide(largeYin)` on the account holding a valid request.
4. Immediately call `remove()` on the same account to withdraw principal plus yield share.
**How found:** Noticed the protocol's request-withdraw timelock was designed to stop risk-free yield frontrunning, then observed provide() never clears the stored request timestamp, so a stale-but-valid request survives new deposits.
**Exploitation:** Attacker maintains a rotating set of accounts with valid withdrawal authorizations; on a profitable absorption they supply large yin via provide() and instantly remove() to capture a disproportionate share of the yang collateral, avoiding the intended lockup.
**Insight:** When a protocol adds a timelock to block frontrunning, check every state-changing entry point that should invalidate the pending request (deposit/provide) — a single missing reset re-enables the exact attack the timelock was built to stop.
