Sablier

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

Non Critical issues (1-10) of 73

NC001 - Constants should be defined rather than using magic numbers:

Even assembly can benefit from using readable constants instead of hex/numeric literals.

Click to show 4 findings
File: v2-core/src/SablierV2NFTDescriptor.sol
146 } else if (truncatedAmount >= 1e15) {
150 string[5] memory suffixes = ["", "K", "M", "B", "T"];
156 while (truncatedAmount >= 1000) {
157 fractionalAmount = (truncatedAmount / 10) % 100; // keep the first two digits after the decimal point
158 truncatedAmount /= 1000;
180 } else if (durationInDays > 9999) {
200 return streamedAmount * 10_000 / depositedAmount;
218 uint256 hue = (bitField >> 16) % 360;
223 uint256 saturation = ((bitField >> 8) & 0xFF) % 80 + 20;
228 uint256 lightness = (bitField & 0xFF) % 70 + 30;
324 if (success && returnData.length == 32) {
338 if (!success || returnData.length <= 64) {
346 if (bytes(symbol).length > 30) {
374 string memory fractionalPart = stringifyFractionalAmount(percentage % 100);
377 string memory wholePart = (percentage / 100).toString();

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2NFTDescriptor.sol#L0:0

File: v2-core/src/libraries/NFTSVG.sol
72 vars.amountWidth + vars.durationWidth + vars.progressWidth + vars.statusWidth + CARD_MARGIN * 3;
79 vars.progressXPosition = (1000 - vars.cardsWidth) / 2;

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/libraries/NFTSVG.sol#L0:0

File: v2-core/src/libraries/SVGElements.sol
94 width = 144; // 2 * 20 (margins) + 8 * 13 (charWidth)
96 width = 208; // 3 * 20 (margins) + 8 * 13 (charWidth) + 44 (diameter)
106 width = Math.max(captionWidth, contentWidth) + 40;
217 (10_000 - progressNumerical).toString(),
240 uint256 charWidth = largeFont ? 16 : 13;

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/libraries/SVGElements.sol#L0:0

File: v2-periphery/src/abstracts/SablierV2MerkleLockup.sol
61 if (bytes(params.name).length > 32) {
64 maxLength: 32
157 return _firstClaimTime > 0 && block.timestamp > _firstClaimTime + 7 days;

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/abstracts/SablierV2MerkleLockup.sol#L0:0

NC002 - Use scientific notation (e.g. 1e18) rather than exponentiation (e.g. 10**18):

While the compiler knows to optimize away the exponentiation, it's still better coding practice to use idioms that do not require compiler optimization, if they exist.

File: v2-core/src/SablierV2NFTDescriptor.sol
140 truncatedAmount = decimals == 0 ? amount : amount / 10 ** decimals;

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2NFTDescriptor.sol#L0:0

NC003 - Function ordering does not follow the Solidity style guide:

According to the Solidity style guide, functions should be laid out in the following order :constructor(), receive(), fallback(), external, public, internal, private, but the cases below do not follow this pattern.

File: v2-core/src/abstracts/SablierV2Lockup.sol
/// @auditbase public functions should not come before external functions
function wasCanceled(uint256 streamId) external view override notNull(streamId) returns (bool result) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/abstracts/SablierV2Lockup.sol#L218:218

File: v2-periphery/src/abstracts/SablierV2MerkleLockup.sol
/// @auditbase public functions should not come before external functions
function name() external view override returns (string memory) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/abstracts/SablierV2MerkleLockup.sol#L98:98

NC004 - Imports could be organized more systematically:

This issue arises when the contract's interface is not imported first, followed by each of the interfaces it uses, followed by all other files.

Click to show 11 findings
File: v2-core/src/SablierV2LockupDynamic.sol
12 import { ISablierV2LockupDynamic } from "./interfaces/ISablierV2LockupDynamic.sol";

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupDynamic.sol#L0:0

File: v2-core/src/SablierV2LockupLinear.sol
11 import { ISablierV2LockupLinear } from "./interfaces/ISablierV2LockupLinear.sol";

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupLinear.sol#L0:0

File: v2-core/src/SablierV2LockupTranched.sol
9 import { ISablierV2LockupTranched } from "./interfaces/ISablierV2LockupTranched.sol";

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupTranched.sol#L0:0

File: v2-core/src/SablierV2NFTDescriptor.sol
10 import { ISablierV2Lockup } from "./interfaces/ISablierV2Lockup.sol";

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2NFTDescriptor.sol#L0:0

File: v2-core/src/abstracts/SablierV2Lockup.sol
8 import { IERC721Metadata } from "hot/node_modules/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/abstracts/SablierV2Lockup.sol#L0:0

File: v2-periphery/src/SablierV2BatchLockup.sol
6 import { ISablierV2LockupDynamic } from "hot/@sablier/v2-core/src/interfaces/ISablierV2LockupDynamic.sol";

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/SablierV2BatchLockup.sol#L0:0

File: v2-periphery/src/SablierV2MerkleLL.sol
5 import { IERC20 } from "hot/node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol";

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/SablierV2MerkleLL.sol#L0:0

File: v2-periphery/src/SablierV2MerkleLT.sol
5 import { IERC20 } from "hot/node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol";

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/SablierV2MerkleLT.sol#L0:0

File: v2-periphery/src/SablierV2MerkleLockupFactory.sol
5 import { ISablierV2LockupLinear } from "hot/@sablier/v2-core/src/interfaces/ISablierV2LockupLinear.sol";

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/SablierV2MerkleLockupFactory.sol#L0:0

File: v2-periphery/src/abstracts/SablierV2MerkleLockup.sol
10 import { ISablierV2MerkleLockup } from "../interfaces/ISablierV2MerkleLockup.sol";

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/abstracts/SablierV2MerkleLockup.sol#L0:0

File: v2-periphery/src/types/DataTypes.sol
6 import { ISablierV2Lockup } from "hot/@sablier/v2-core/src/interfaces/ISablierV2Lockup.sol";

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/types/DataTypes.sol#L0:0

NC005 - Constants in comparisons should appear on the left side:

This issue arises when constants in comparisons appear on the right side, which can lead to typo bugs.

Click to show 9 findings
File: v2-core/src/SablierV2LockupDynamic.sol
204 if (_segments[streamId].length > 1) {
243 if (index == 0) {
360 if (createAmounts.brokerFee > 0) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupDynamic.sol#L0:0

File: v2-core/src/SablierV2LockupLinear.sol
141 if (params.durations.cliff > 0) {
263 if (params.timestamps.cliff > 0) {
280 if (createAmounts.brokerFee > 0) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupLinear.sol#L0:0

File: v2-core/src/SablierV2LockupTranched.sol
264 if (createAmounts.brokerFee > 0) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupTranched.sol#L0:0

File: v2-core/src/SablierV2NFTDescriptor.sol
134 if (amount == 0) {
140 truncatedAmount = decimals == 0 ? amount : amount / 10 ** decimals;
144 if (truncatedAmount < 1) {
146 } else if (truncatedAmount >= 1e15) {
156 while (truncatedAmount >= 1000) {
178 if (durationInDays == 0) {
180 } else if (durationInDays > 9999) {
184 string memory suffix = durationInDays == 1 ? " Day" : " Days";
324 if (success && returnData.length == 32) {
338 if (!success || returnData.length <= 64) {
346 if (bytes(symbol).length > 30) {
357 if (fractionalAmount == 0) {
361 else if (fractionalAmount < 10) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2NFTDescriptor.sol#L0:0

File: v2-core/src/abstracts/SablierV2Lockup.sol
309 if (recipient.code.length > 0) {
354 if (amount == 0) {
382 if (msg.sender != recipient && recipient.code.length > 0) {
394 if (msg.sender != sender && sender.code.length > 0 && sender != recipient) {
427 if (withdrawableAmount > 0) {
584 if (recipientAmount == 0) {
609 if (recipient.code.length > 0) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/abstracts/SablierV2Lockup.sol#L0:0

File: v2-core/src/libraries/Helpers.sol
90 if (totalAmount == 0) {
121 if (depositAmount == 0) {
126 if (startTime == 0) {
132 if (segmentCount == 0) {
148 if (depositAmount == 0) {
153 if (timestamps.start == 0) {
158 if (timestamps.cliff > 0) {
193 if (depositAmount == 0) {
198 if (startTime == 0) {
204 if (trancheCount == 0) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/libraries/Helpers.sol#L0:0

File: v2-core/src/libraries/SVGElements.sol
206 if (progressNumerical == 0) {
235 if (length == 0) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/libraries/SVGElements.sol#L0:0

File: v2-periphery/src/SablierV2BatchLockup.sol
36 if (batchSize == 0) {
84 if (batchSize == 0) {
137 if (batchSize == 0) {
185 if (batchSize == 0) {
237 if (batchSize == 0) {
285 if (batchSize == 0) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/SablierV2BatchLockup.sol#L0:0

File: v2-periphery/src/abstracts/SablierV2MerkleLockup.sol
61 if (bytes(params.name).length > 32) {
94 return EXPIRATION > 0 && EXPIRATION <= block.timestamp;
149 if (_firstClaimTime == 0) {
157 return _firstClaimTime > 0 && block.timestamp > _firstClaimTime + 7 days;

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/abstracts/SablierV2MerkleLockup.sol#L0:0

NC006 - else-block not required:

One level of nesting can be removed by not having an else block when the if-block returns

Click to show 4 findings
File: v2-core/src/SablierV2LockupDynamic.sol
204 if (_segments[streamId].length > 1) {
205 // If there is more than one segment, it may be required to iterate over all of them.
206 return _calculateStreamedAmountForMultipleSegments(streamId);
207 } else {
208 // Otherwise, there is only one segment, and the calculation is simpler.
209 return _calculateStreamedAmountForOneSegment(streamId);
210 }

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupDynamic.sol#L0:0

File: v2-core/src/SablierV2NFTDescriptor.sol
144 if (truncatedAmount < 1) {
145 return string.concat(SVGElements.SIGN_LT, " 1");
146 } else if (truncatedAmount >= 1e15) {
147 return string.concat(SVGElements.SIGN_GT, " 999.99T");
148 }
178 if (durationInDays == 0) {
179 return string.concat(SVGElements.SIGN_LT, " 1 Day");
180 } else if (durationInDays > 9999) {
181 return string.concat(SVGElements.SIGN_GT, " 9999 Days");
182 }
309 if (symbol.equal("SAB-V2-LOCKUP-LIN")) {
310 return "Lockup Linear";
311 } else if (symbol.equal("SAB-V2-LOCKUP-DYN")) {
312 return "Lockup Dynamic";
313 } else if (symbol.equal("SAB-V2-LOCKUP-TRA")) {
314 return "Lockup Tranched";
315 } else {
316 revert Errors.SablierV2NFTDescriptor_UnknownNFT(sablier, symbol);
317 }
311 } else if (symbol.equal("SAB-V2-LOCKUP-DYN")) {
312 return "Lockup Dynamic";
313 } else if (symbol.equal("SAB-V2-LOCKUP-TRA")) {
314 return "Lockup Tranched";
315 } else {
316 revert Errors.SablierV2NFTDescriptor_UnknownNFT(sablier, symbol);
317 }
313 } else if (symbol.equal("SAB-V2-LOCKUP-TRA")) {
314 return "Lockup Tranched";
315 } else {
316 revert Errors.SablierV2NFTDescriptor_UnknownNFT(sablier, symbol);
317 }
324 if (success && returnData.length == 32) {
325 return abi.decode(returnData, (uint8));
326 } else {
327 return 0;
328 }
346 if (bytes(symbol).length > 30) {
347 return "Long Symbol";
348 } else {
349 return symbol;
350 }
357 if (fractionalAmount == 0) {
358 return "";
359 }
360 // Add a leading zero if the fractional part is less than 10, e.g. for "1", this function returns ".01%".
361 else if (fractionalAmount < 10) {
362 return string.concat(".0", fractionalAmount.toString());
363 }
364 // Otherwise, stringify the fractional amount simply.
365 else {
366 return string.concat(".", fractionalAmount.toString());
367 }
361 else if (fractionalAmount < 10) {
362 return string.concat(".0", fractionalAmount.toString());
363 }
364 // Otherwise, stringify the fractional amount simply.
365 else {
366 return string.concat(".", fractionalAmount.toString());
367 }
385 if (status == Lockup.Status.DEPLETED) {
386 return "Depleted";
387 } else if (status == Lockup.Status.CANCELED) {
388 return "Canceled";
389 } else if (status == Lockup.Status.STREAMING) {
390 return "Streaming";
391 } else if (status == Lockup.Status.SETTLED) {
392 return "Settled";
393 } else {
394 return "Pending";
395 }
387 } else if (status == Lockup.Status.CANCELED) {
388 return "Canceled";
389 } else if (status == Lockup.Status.STREAMING) {
390 return "Streaming";
391 } else if (status == Lockup.Status.SETTLED) {
392 return "Settled";
393 } else {
394 return "Pending";
395 }
389 } else if (status == Lockup.Status.STREAMING) {
390 return "Streaming";
391 } else if (status == Lockup.Status.SETTLED) {
392 return "Settled";
393 } else {
394 return "Pending";
395 }
391 } else if (status == Lockup.Status.SETTLED) {
392 return "Settled";
393 } else {
394 return "Pending";
395 }

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2NFTDescriptor.sol#L0:0

File: v2-core/src/abstracts/SablierV2Lockup.sol
482 if (_streams[streamId].isDepleted) {
483 return Lockup.Status.DEPLETED;
484 } else if (_streams[streamId].wasCanceled) {
485 return Lockup.Status.CANCELED;
486 }
492 if (_calculateStreamedAmount(streamId) < _streams[streamId].amounts.deposited) {
493 return Lockup.Status.STREAMING;
494 } else {
495 return Lockup.Status.SETTLED;
496 }
503 if (_streams[streamId].isDepleted) {
504 return amounts.withdrawn;
505 } else if (_streams[streamId].wasCanceled) {
506 return amounts.deposited - amounts.refunded;
507 }

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/abstracts/SablierV2Lockup.sol#L0:0

File: v2-core/src/libraries/SVGElements.sol
256 if (cardType == CardType.PROGRESS) {
257 return "Progress";
258 } else if (cardType == CardType.STATUS) {
259 return "Status";
260 } else if (cardType == CardType.AMOUNT) {
261 return "Amount";
262 } else {
263 return "Duration";
264 }
258 } else if (cardType == CardType.STATUS) {
259 return "Status";
260 } else if (cardType == CardType.AMOUNT) {
261 return "Amount";
262 } else {
263 return "Duration";
264 }
260 } else if (cardType == CardType.AMOUNT) {
261 return "Amount";
262 } else {
263 return "Duration";
264 }

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/libraries/SVGElements.sol#L0:0

NC007 - Events may be emitted out of order due to reentrancy:

Ensure that events follow the best practice of check-effects-interaction, and are emitted before external calls

Click to show 7 findings
File: v2-core/src/SablierV2LockupDynamic.sol
/// @audit safeTransferFrom() called before event
365 emit ISablierV2LockupDynamic.CreateLockupDynamicStream({
366 streamId: streamId,
367 funder: msg.sender,
368 sender: params.sender,
369 recipient: params.recipient,
370 amounts: createAmounts,
371 asset: params.asset,
372 cancelable: params.cancelable,
373 transferable: params.transferable,
374 segments: params.segments,
375 timestamps: LockupDynamic.Timestamps({ start: stream.startTime, end: stream.endTime }),
376 broker: params.broker.account
377 });

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupDynamic.sol#L365:377

File: v2-core/src/SablierV2LockupLinear.sol
/// @audit safeTransferFrom() called before event
285 emit ISablierV2LockupLinear.CreateLockupLinearStream({
286 streamId: streamId,
287 funder: msg.sender,
288 sender: params.sender,
289 recipient: params.recipient,
290 amounts: createAmounts,
291 asset: params.asset,
292 cancelable: params.cancelable,
293 transferable: params.transferable,
294 timestamps: params.timestamps,
295 broker: params.broker.account
296 });

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupLinear.sol#L285:296

File: v2-core/src/SablierV2LockupTranched.sol
/// @audit safeTransferFrom() called before event
269 emit ISablierV2LockupTranched.CreateLockupTranchedStream({
270 streamId: streamId,
271 funder: msg.sender,
272 sender: params.sender,
273 recipient: params.recipient,
274 amounts: createAmounts,
275 asset: params.asset,
276 cancelable: params.cancelable,
277 transferable: params.transferable,
278 tranches: params.tranches,
279 timestamps: LockupTranched.Timestamps({ start: stream.startTime, end: stream.endTime }),
280 broker: params.broker.account
281 });

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupTranched.sol#L269:281

File: v2-core/src/abstracts/SablierV2Lockup.sol
/// @audit safeTransfer() called before event
602 emit ISablierV2Lockup.CancelLockupStream(streamId, sender, recipient, asset, senderAmount, recipientAmount);
/// @audit safeTransfer() called before event
655 emit ISablierV2Lockup.WithdrawFromLockupStream(streamId, to, asset, amount);
/// @audit safeTransfer() called before event
605 emit MetadataUpdate({ _tokenId: streamId });

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/abstracts/SablierV2Lockup.sol#L605:605

File: v2-periphery/src/abstracts/SablierV2MerkleLockup.sol
/// @audit safeTransfer() called before event
121 emit Clawback(admin, to, amount);

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/abstracts/SablierV2MerkleLockup.sol#L121:121

NC008 - If-statement can be converted to a ternary:

The code can be made more compact while also increasing readability by converting the following if-statements to ternaries (e.g. foo += (x > y) ? a : b)

Click to show 4 findings
File: v2-core/src/SablierV2LockupDynamic.sol
204 if (_segments[streamId].length > 1) {
205 // If there is more than one segment, it may be required to iterate over all of them.
206 return _calculateStreamedAmountForMultipleSegments(streamId);
207 } else {
208 // Otherwise, there is only one segment, and the calculation is simpler.
209 return _calculateStreamedAmountForOneSegment(streamId);
210 }
243 if (index == 0) {
244 // When the current segment's index is equal to 0, the current segment is the first, so use the start
245 // time as the previous timestamp.
246 previousTimestamp = stream.startTime;
247 } else {
248 // Otherwise, when the current segment's index is greater than zero, it means that the segment is not
249 // the first. In this case, use the previous segment's timestamp.
250 previousTimestamp = segments[index - 1].timestamp;
251 }

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupDynamic.sol#L0:0

File: v2-core/src/SablierV2NFTDescriptor.sol
324 if (success && returnData.length == 32) {
325 return abi.decode(returnData, (uint8));
326 } else {
327 return 0;
328 }
346 if (bytes(symbol).length > 30) {
347 return "Long Symbol";
348 } else {
349 return symbol;
350 }
361 else if (fractionalAmount < 10) {
362 return string.concat(".0", fractionalAmount.toString());
363 }
364 // Otherwise, stringify the fractional amount simply.
365 else {
366 return string.concat(".", fractionalAmount.toString());
367 }
391 } else if (status == Lockup.Status.SETTLED) {
392 return "Settled";
393 } else {
394 return "Pending";
395 }

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2NFTDescriptor.sol#L0:0

File: v2-core/src/abstracts/SablierV2Lockup.sol
492 if (_calculateStreamedAmount(streamId) < _streams[streamId].amounts.deposited) {
493 return Lockup.Status.STREAMING;
494 } else {
495 return Lockup.Status.SETTLED;
496 }

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/abstracts/SablierV2Lockup.sol#L0:0

File: v2-core/src/libraries/SVGElements.sol
260 } else if (cardType == CardType.AMOUNT) {
261 return "Amount";
262 } else {
263 return "Duration";
264 }

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/libraries/SVGElements.sol#L0:0

NC009 - Public functions not called by the contract should be declared external instead:

Contracts are allowed to override their parents' functions and change the visibility from external to public.

File: v2-core/src/abstracts/SablierV2Lockup.sol
198 function streamedAmountOf(uint256 streamId)
199 public
200 view
201 override
202 notNull(streamId)
203 returns (uint128 streamedAmount)
204 {
205 streamedAmount = _streamedAmountOf(streamId);
206 }

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/abstracts/SablierV2Lockup.sol#L0:0

File: v2-periphery/src/abstracts/SablierV2MerkleLockup.sol
88 function hasClaimed(uint256 index) public view override returns (bool) {
89 return _claimedBitMap.get(index);
90 }

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/src/abstracts/SablierV2MerkleLockup.sol#L0:0

NC010 - Variables need not be initialized to zero:

The default value for variables is zero, so initializing them to zero is superfluous.

Click to show 7 findings
File: v2-core/src/SablierV2LockupDynamic.sol
344 for (uint256 i = 0; i < segmentCount; ++i) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupDynamic.sol#L0:0

File: v2-core/src/SablierV2LockupTranched.sol
248 for (uint256 i = 0; i < trancheCount; ++i) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/SablierV2LockupTranched.sol#L0:0

File: v2-core/src/abstracts/SablierV2Lockup.sol
277 for (uint256 i = 0; i < count; ++i) {
452 for (uint256 i = 0; i < streamIdsCount; ++i) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/abstracts/SablierV2Lockup.sol#L0:0

File: v2-core/src/libraries/Helpers.sol
252 for (uint256 index = 0; index < count; ++index) {
315 for (uint256 index = 0; index < count; ++index) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/libraries/Helpers.sol#L0:0

File: v2-core/src/libraries/SVGElements.sol
242 for (uint256 i = 0; i < length; ++i) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-core/src/libraries/SVGElements.sol#L0:0

File: v2-periphery/src/SablierV2MerkleLT.sol
52 for (uint256 i = 0; i < count; ++i) {
135 for (uint256 i = 0; i < trancheCount; ++i) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/v2-core/src/SablierV2MerkleLT.sol#L0:0

File: v2-periphery/src/SablierV2MerkleLockupFactory.sol
56 for (uint256 i = 0; i < tranchesWithPercentages.length; ++i) {

https://github.com/Cyfrin/2024-05-Sablier/tree/main/v2-periphery/v2-core/src/SablierV2MerkleLockupFactory.sol#L0:0

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.