Closed sherlock-admin closed 8 months ago
1 comment(s) were left on this issue during the judging contest.
takarez commented:
valid because {This is a valid issue because the watson explain a scenario close to the one in issue 051 thus making it a dupp of it }
Arz
high
The CouncilMember contract will be completely broken because the Sablier stream reverts when withdrawing 0 amounts
Summary
If
withdrawMax()
is called and the withdrawable amount is 0 the Sablier contract will revert. This will DOS most functions inCouncilMember.sol
because_retrieve()
is sometimes called 2 times(for example inburn()
, it gets called inupdate()
the second time) and the withdrawable amount will be 0 once_retrieve()
is called the second time.Vulnerability Detail
If
withdrawMax()
in the Sablier contract is called and the withdrawable amount is 0 the call will revert because there is a 0 amount check. See here.This will be a big problem for:
Functions where
_retrieve()
is called 2 times -mint()
,burn()
andremoveFromOffice()
._retrieve()
is first called in the function and then its called the second time inERC721.update()
which will fail because we already withdrew the max . This applies to any stream typesDynamic stream types for example vesting with periodic unlocks where the withdrawable amount will be 0 for some time.
This will completely break the contract and
mint()
,burn()
andremoveFromOffice()
will be DoSed right after the first mint. If a stream is used where the withdrawable amount is 0 for some time, council members will be unable to claim their allocated amounts because withdrawing 0 will revert so callingclaim()
will fail.Impact
The contract will be completely unusable and council member can fail to receive their allocated amounts of TEL.
Code Snippet
https://github.com/sablier-labs/v2-core/blob/b0016437ef3cc8606e1100965dd911d7e658b40b/src/abstracts/SablierV2Lockup.sol#L270
As you can see in the Sablier contracts when
withdrawMax()
is called and the amount is 0, the tx reverts.When we call
mint()
,_retrieve()
is first called in the function and then_mint()
calls_update()
_update()
will then call_retrieve()
again but this time the withdrawable amount will be 0 and the tx will revert.Tool used
Manual Review
Recommendation
Before calling withdraw check if the withdrawable amount is 0.
Duplicate of #47