Sablier

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

SablierV2MerkleLL & SablierV2MerkleLT can silently fail in deployment from the SablierV2MerkleLockupFactory causing loss of funds for deployer

Summary

When deploying a SablierV2MerkleLL contract via the SablierV2MerkleLockupFactory, if the deployment fails (e.g., due to out-of-gas errors or invalid constructor parameters), the deployer will lose the gas fees spent on the deployment attempt. This loss occurs because the factory contract does not handle failed deployments, leading to the consumption of gas without successfully deploying the contract.

Vulnerability Details

The createMerkleLL function in the SablierV2MerkleLockupFactory deploys a new SablierV2MerkleLL contract using
the new keyword. This deployment process involves the execution of the constructor of SablierV2MerkleLL,
which initializes various state variables and sets up token approvals.

function createMerkleLL(
MerkleLockup.ConstructorParams memory baseParams,
ISablierV2LockupLinear lockupLinear,
LockupLinear.Durations memory streamDurations,
uint256 aggregateAmount,
uint256 recipientCount
)
external returns (ISablierV2MerkleLL merkleLL) {
// Deploy the MerkleLockup contract with CREATE.
merkleLL = new SablierV2MerkleLL(baseParams, lockupLinear, streamDurations);
// Log the creation of the MerkleLockup contract, including some metadata that is not stored on-chain.
emit CreateMerkleLL(merkleLL, baseParams, lockupLinear, streamDurations, aggregateAmount, recipientCount);
}

However, if the deployment fails (e.g., due to out-of-gas errors or invalid constructor parameters), the transaction will revert. While this reversion ensures that no erroneous state changes occur, the gas used for the deployment attempt is still consumed and not refunded. As a result, the deployer incurs a financial loss in the form of gas fees.

Impact

The primary impact of a failed deployment is the loss of gas fees spent during the deployment attempt.
Since the factory contract does not handle deployment failures within a try/catch block, the deployer
must bear the full cost of the gas consumed.

Proof of Concept:

Consider the deployment scenario where the gas estimation is insufficient or constructor parameters are invalid.

function createMerkleLL(
MerkleLockup.ConstructorParams memory baseParams,
ISablierV2LockupLinear lockupLinear,
LockupLinear.Durations memory streamDurations,
uint256 aggregateAmount,
uint256 recipientCount
)
external returns (ISablierV2MerkleLL merkleLL) {
// Deploy the MerkleLockup contract with CREATE.
merkleLL = new SablierV2MerkleLL(baseParams, lockupLinear, streamDurations);
// Log the creation of the MerkleLockup contract, including some metadata that is not stored on-chain.
emit CreateMerkleLL(merkleLL, baseParams, lockupLinear, streamDurations, aggregateAmount, recipientCount);
}

If the deployment fails, the gas fees spent on the attempt are lost, and the deployer receives no refund for the consumed gas.

Tools Used

VS Code/Foundry

Recommendations

To mitigate the risk of losing gas fees during deployment failures, consider implementing the
deployment logic within a try/catch block. This approach will allow handling deployment failures
gracefully and potentially retrying the deployment or handling a failed deployment correctly.

function createMerkleLL(
MerkleLockup.ConstructorParams memory baseParams,
ISablierV2LockupLinear lockupLinear,
LockupLinear.Durations memory streamDurations,
uint256 aggregateAmount,
uint256 recipientCount
)
external returns (ISablierV2MerkleLL merkleLL) {
try new SablierV2MerkleLL(baseParams, lockupLinear, streamDurations) returns (ISablierV2MerkleLL deployedMerkleLL) {
merkleLL = deployedMerkleLL;
// Log the creation of the MerkleLockup contract, including some metadata that is not stored on-chain.
emit CreateMerkleLL(merkleLL, baseParams, lockupLinear, streamDurations, aggregateAmount, recipientCount);
} catch (bytes memory errorData) {
emit DeploymentFailed(baseParams, errorData);
revert("SablierV2MerkleLockupFactory: Deployment failed");
}
}
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.