In SablierV2MerkleLockup::_checkClaim, if _firstClaimTime = 0, then _firstClaimTime = uint40(block.timestamp). After the first call to _checkClaim, _firstClaimTime is set to the timestamp of the block at that moment. This causes _firstClaimTime to remain unchanged to the timestamp of the first call in subsequent invocations and will not be modified again.
After a user calls SablierV2MerkleLT::claim or SablierV2MerkleLL::claim, they will continue to call its internal function SablierV2MerkleLockup::_checkClaim.
When user A, with _firstClaimTime = 0, makes the first call to SablierV2MerkleLT::claim, the _firstClaimTime is set to the current block timestamp at that moment.
When user B makes a second call to SablierV2MerkleLT::claim, the _firstClaimTime will remain the timestamp from the first call and will not be modified again. Note: Because _firstClaimTime has already been set and is no longer equal to 0, it will not enter the logic block for setting the timestamp again.
Since _firstClaimTime is only set to the current timestamp during the initial claim, once it's set, it won't be modified again. Therefore, subsequent calls to the _checkClaim function by any user won't alter this value, and I believe this affects the conditional checks in the hasGracePeriodPassed and clawback functions.
Manual Review
It is suggested to perform another _firstClaimTime = uint40(block.timestamp) setting for the case where _firstClaimTime > 0. This ensures that in any subsequent calls, the value of _firstClaimTime reflects the current block timestamp when the user calls the _checkClaim function, rather than retaining the timestamp from the first call.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.