Sablier

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

`EXPIRATION` can be set in the past, preventing anyone from claiming airstreams

Summary

EXPIRATION can be set in the past, preventing anyone from claiming airstreams.

Vulnerability Details

EXPIRATION can be set in the past in SablierV2MerkleLockup.sol as there is no check to prevent this. When recipient tries to claim the airstream using claim function in the SablierV2MerkleLL contract, the stream will not be created because the stream campaign has already expired due to the _checkClaim and hasExpired functions :

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;
}

Impact

Due to the aforementioned issue, both the SablierV2MerkleLL and SablierV2MerkleLT contracts are affected. A malicious creator can set EXPIRATION to a past date when deploying either of these contracts, preventing users from claiming any airdrops.

Since there is no condition in the abstract base contract SablierV2MerkleLockup that checks for this, both the SablierV2MerkleLL and SablierV2MerkleLT contracts can be deployed on the blockchain without any restrictions.

This allows the malicious creator to mislead recipients and users into believing they can receive airdrop tokens from the SablierMerkleLockup contracts when, in reality, they cannot.

Tools Used

Manual Review

Recommendations

Add these lines in SablierV2MerkleLockup.sol file :

constructor(MerkleLockup.ConstructorParams memory params) {
// Check: the campaign name is not greater than 32 bytes
if (bytes(params.name).length > 32) {
revert Errors.SablierV2MerkleLockup_CampaignNameTooLong({ nameLength: bytes(params.name).length, maxLength: 32 });
}
++ if (params.expiration <= block.timestamp) revert ();
admin = params.initialAdmin;
ASSET = params.asset;
CANCELABLE = params.cancelable;
EXPIRATION = params.expiration;
ipfsCID = params.ipfsCID;
MERKLE_ROOT = params.merkleRoot;
NAME = bytes32(abi.encodePacked(params.name));
TRANSFERABLE = params.transferable;
}
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.