Sablier

Sablier
DeFiFoundry
53,440 USDC
View results
Submission Details
Severity: medium
Invalid

hardcoded grace period will be incompatible with cliff campaigns

Description

The grace period is defined as a period of 7 days starting from the first time a claim has been made inside a campaign:

/// @notice Returns a flag indicating whether the grace period has passed.
/// @dev The grace period is 7 days after the first claim.
function _hasGracePeriodPassed() internal view returns (bool) {
return _firstClaimTime > 0 && block.timestamp > _firstClaimTime + 7 days;
}

inside this period, the Admin can call clawback to retrieve unclaimed funds. This is crucial in situations where there is an issue with the campaign that can lead to all sorts of undesired behaviours. The Admin can call clawback if no claim has been made, or during the grace period, or when the campaign has ended.

function clawback(address to, uint128 amount) external override onlyAdmin {
// Check: current timestamp is over the grace period and the campaign has not expired.
if (_hasGracePeriodPassed() && !hasExpired()) {
revert Errors.SablierV2MerkleLockup_ClawbackNotAllowed({
blockTimestamp: block.timestamp,
expiration: EXPIRATION,
firstClaimTime: _firstClaimTime
});
}
// Effect: transfer the tokens to the provided address.
ASSET.safeTransfer(to, amount);
// Log the clawback.
emit Clawback(admin, to, amount);
}

Ultimately ,clawback just transfers the asset amounts to the Admin's provided address and by doing so retrieving the funds.

The team confirmed through the Discord (Sablier Channel) that soon, support for creating cliff stream campaigns will be available. Additionally, they mentioned that the following campaign structure can be configured:

// Q: hi, is it possible to create a campaign where a recipient will start having his amount streamed x amount of days after claiming instead of directly after claiming ?
// A: Well, you could create a an Airstream campaign with a cliff stream, which is coming very soon. Currently we only support linear streams for Airstreams.

Thus, a campaign can be configured as such that when a recipient calls claim, the streaming does not begin immediately as it does in a linear stream. Instead, the recipient must wait for a specified number of days before their amount begins streaming, and they can then initiate their first withdrawal.

This is problematic due to the hardcoded 7-day grace period, the Admin has only a 7 day time window to determine if recipients are able to withdraw their funds, but due to the nature of the cliff streams it can be designed in such a way where a recipient might have to wait 14 days before being able to even call withdraw.

I will illustrate this with an example:

  • Bob creates a cliff campaign, designed where recipient calls claim, recipient has to wait 2 weeks before amount starts being streamed, 2 weeks have passed, recipient can now start withdrawing

  • Alice is the first user to call claim, _firstClaimTime is triggered

  • Alice has to wait 2 weeks before her amount starts being streamed

  • After two weeks, Alice attempts to withdraw, but encounters an issue preventing her from doing so. This could be due to a problem with the merkle tree, which, according to the docs can result in potentially leading to unclaimable assets or unexpected behavior.

  • Admin notices this and calls clawback, however this will fail since it is hardcoded to 7 days.

Why MEDIUM instead of HIGH:

  • This situation will only work if the campaign is not cancellable

  • at the end of the campaign, clawback can be called again.

This implies that recipients involved in a non-cancellable campaign must wait until the campaign's end to retrieve their funds. First of all, this defeats the purpose of a cliff stream, which is intended to allow users to withdraw at regular intervals. Secondly, cliffs typically span long durations, ranging from months to a year. Consequently, users may have to wait months or even up to a year before receiving their refunded funds.

Tools Used

Manual Review

Recommendation

This can easily be mitigated. Simply remove the grace period, this way the Admin can always call clawback whenever needed.

Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.