Sablier

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

No expiration checks can lead to expiration date set in the past, making the campaign useless/unclaimable

Summary

There is no check of the expiration value when creating a new campaign through the SablierV2MerkleLockupFactory, making the campaign useless.

Vulnerability Details

A user can either intentionally or by accident set the expiration of a campaign/airdrop in the past. There are no checks in place to prevent that for happening.

Impact

The campaign is essentially rendered useless. No user can claim rewards, since there is a campaign expiration check when claiming:

SablierV2MerkleLockup.sol:
function _checkClaim(uint256 index, bytes32 leaf, bytes32[] calldata merkleProof) internal {
// Check: the campaign has not expired.
if (hasExpired()) {
revert Errors.SablierV2MerkleLockup_CampaignExpired({
blockTimestamp: block.timestamp,
expiration: EXPIRATION
});
}
.
.
}
function hasExpired() public view override returns (bool) {
return EXPIRATION > 0 && EXPIRATION <= block.timestamp;
}

Proof of Code

Place the following code in 2024-05-Sablier/v2-periphery/test/integration/merkle-lockup/factory/create-merkle-lt/createMerkleLT.t.sol test file.

function test_ExpirationSetInThePast() external {
MerkleLockup.ConstructorParams memory baseParams = defaults.baseParams();
uint256 aggregateAmount = defaults.AGGREGATE_AMOUNT();
uint256 recipientCount = defaults.RECIPIENT_COUNT();
MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages = defaults.tranchesWithPercentages();
// Set expiration in the past.
baseParams.expiration = uint40(block.timestamp) - 1;
assert(baseParams.expiration < block.timestamp);
merkleLockupFactory.createMerkleLT(
baseParams, lockupTranched, tranchesWithPercentages, aggregateAmount, recipientCount
);
}

Tools Used

Manual review

Recommendations

In SablierV2MerkleLockupFactory file include the following checks, they will make the above test fail:

function createMerkleLL(
MerkleLockup.ConstructorParams memory baseParams,
ISablierV2LockupLinear lockupLinear,
LockupLinear.Durations memory streamDurations,
uint256 aggregateAmount,
uint256 recipientCount
)
external
returns (ISablierV2MerkleLL merkleLL)
{
++ if (baseParams.expiration <= block.timestamp) {
++ revert();
++ }
.
.
}
function createMerkleLT(
MerkleLockup.ConstructorParams memory baseParams,
ISablierV2LockupTranched lockupTranched,
MerkleLT.TrancheWithPercentage[] memory tranchesWithPercentages,
uint256 aggregateAmount,
uint256 recipientCount
)
external
returns (ISablierV2MerkleLT merkleLT)
{
++ if (baseParams.expiration <= block.timestamp) {
++ revert();
++ }
.
.
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Info/Gas/Invalid as per Docs

https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity

Support

FAQs

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