# Wrong parameter when retrieving causes a complete DoS of the protocol

CouncilMember._retrieve passes the Sablier proxy target instead of the lockup stream as the withdrawMax lockup param, reverting all withdrawals and DoSing the protocol.

- Payout: Contest reward
- Severity: high
- Program: Telcoin
- Credited: 0xadrii
- Disclosed: 2024-01-04
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2024-01-telcoin-judging/issues/139
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-01-telcoin%3AH-2
- Tags: domain:web3 impact:dos kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:dos vuln:misconfiguration

**Target:** CouncilMember.sol _retrieve() Sablier integration
**Root cause:** _retrieve() encodes _target (the SablierV2ProxyTarget) as the lockup argument to withdrawMax instead of the actual SablierV2LockupLinear stream address, which is never stored in the contract.
**Steps:**
1. Deploy real Sablier V2 core (LockupLinear) plus PRBProxy and ProxyTarget periphery contracts.
2. Create a stream via PRBProxy.execute(target, createWithDurations(...)) so the proxy owns streamId 1.
3. Initialize CouncilMember with stream_=PRBProxy, target_=ProxyTarget, id_=1.
4. Mint a council NFT, warp 1 day, then call mint()/burn()/removeFromOffice() which invoke _retrieve().
5. Observe revert PRBProxy_ExecutionReverted() because withdrawMax is called with the proxy target as lockup.
**How found:** Researcher read the _retrieve() encodeWithSelector call and noticed the first argument after the selector was _target rather than the lockup stream, then confirmed the real Sablier lockup address is never stored in CouncilMember; existing tests used a TestStream mock that masked the bug.
**Exploitation:** No attacker action needed; the misconfiguration makes every _retrieve() call revert, so mint, burn and removeFromOffice are permanently bricked. Only redeployment fixes it.
**Insight:** When a contract integrates a proxy/periphery pattern (PRBProxy + ProxyTarget), verify each argument against the periphery function signature; mocks that collapse the proxy and stream into one contract hide wrong-address bugs, so PoC against the real periphery.
