# Incomplete Withdrawals Integration on Elixir Strategy

Jigsaw's ElixirStrategy only calls unstake(), which silently returns zero assets when Elixir's cooldown is disabled, blocking withdrawals.

- Payout: Contest reward
- Severity: medium
- Program: Jigsaw
- Credited: maptool
- Disclosed: 2025-08-11
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_jigsaw_june2025.pdf#3.2.7
- Library page: https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.2.7
- Tags: domain:web3 impact:funds-loss kind:contest platform:cantina sev:medium tech:evm tech:solidity technique:incomplete-fix technique:source-review vuln:business-logic vuln:misconfiguration

**Target:** ElixirStrategy.sol vault strategy integrating Elixir stdeUSD
**Root cause:** Strategy hardcodes ISdeUsdMin.unstake() for withdrawals, but stdeUSD only populates cooldowns via cooldownShares() when cooldownDuration > 0; with cooldown disabled, unstake() succeeds but withdraws zero assets.
**Steps:**
1. Admin calls `setCooldownDuration(0)` on stdeUSD, disabling cooldownShares/unstake and enabling ERC4626 withdraw/redeem.
2. Jigsaw strategy invokes `_genericCall({_contract: tokenOut, _call: abi.encodeCall(ISdeUsdMin.unstake, (address(this)))})`.
3. unstake() reads empty cooldowns mapping, assets=0, calls `silo.withdraw(receiver, 0)` and returns without reverting.
4. Strategy believes withdrawal succeeded but receives no assets; funds remain stuck.
**How found:** Code-reading of stdeUSD's cooldownShares/unstake/withdraw/redeem and the ensureCooldownOn/Off modifiers, noticing the strategy only integrates unstake() and never handles the ERC4626 path used when cooldownDuration==0.
**Exploitation:** Not an attacker-driven exploit; triggered by admin disabling cooldown, after which any strategy withdrawal silently yields zero assets, locking user funds in the strategy.
**Insight:** When integrating a vault that toggles between two withdrawal modes via an admin-set duration, check every branch of the target's modifiers (ensureCooldownOn/Off) and ensure the strategy handles both; a no-op success path is worse than a revert.
