Sablier

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

Discrepancy in `clawback` Function Logic in `SablierV2MerkleLockup` Contract

Summary

The clawback function in the SablierV2MerkleLockup contract has a logical flaw that contradicts the requirements specified in the ISablierV2MerkleLockup interface which it inherits. The current implementation is more restrictive than intended, potentially preventing legitimate clawback operations.

Vulnerability details

The clawback function in the SablierV2MerkleLockup contract checks if the grace period has passed AND if the campaign has not expired. If both conditions are true, it reverts the transaction. This logic contradicts the interface documentation, which specifies that the clawback should be allowed if any of the following conditions are met:

  • No claim has been made.

  • The current timestamp is within 7 days after the first claim.

  • The campaign has expired.

Interface Definition

https://github.com/Cyfrin/2024-05-Sablier/blob/43d7e752a68bba2a1d73d3d6466c3059079ed0c6/v2-periphery/src/interfaces/ISablierV2MerkleLockup.sol#L68-L81

/// @notice Claws back the unclaimed tokens from the campaign.
///
/// @dev Emits a {Clawback} event.
///
/// Requirements:
/// - The caller must be the admin.
/// - No claim must be made, OR
/// The current timestamp must not exceed 7 days after the first claim, OR
/// The campaign must be expired.
///
/// @param to The address to receive the tokens.
/// @param amount The amount of tokens to claw back.
function clawback(address to, uint128 amount) external;
}

But the implementation doesn't follow that:

https://github.com/Cyfrin/2024-05-Sablier/blob/43d7e752a68bba2a1d73d3d6466c3059079ed0c6/v2-periphery/src/abstracts/SablierV2MerkleLockup.sol#L109

function clawback(address to, uint128 amount) external override onlyAdmin {
if (_hasGracePeriodPassed() && !hasExpired()) {
revert Errors.SablierV2MerkleLockup_ClawbackNotAllowed({
blockTimestamp: block.timestamp,
expiration: EXPIRATION,
firstClaimTime: _firstClaimTime
});
}
ASSET.safeTransfer(to, amount);
emit Clawback(admin, to, amount);
}

Impact

The restrictive logic in the clawback function may prevent legitimate clawback operations, potentially locking funds that should be reclaimable under the conditions specified in the interface documentation. The current implementation only allows clawback if the grace period has not passed or the campaign has expired, which is more restrictive than the interface requirements.

Tools Used

Manual review

Recommendations

Update the clawback function logic to align with the interface documentation.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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