Sablier

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

SablierV2NFTDescriptor::generateAccentColor colors cannot equal to 100%

Summary

SablierV2NFTDescriptor::generateAccentColor generates the saturation and lightness for the stream NFTs. The comments state that both values are bounded to include 100, however in the current code it is not possible for either value to be equal to 100.

Vulnerability Details

SablierV2NFTDescriptor::generateAccentColor()

function generateAccentColor(address sablier, uint256 streamId) internal view returns (string memory) {
// The chain ID is part of the hash so that the generated color is different across chains.
uint256 chainId = block.chainid;
// Hash the parameters to generate a pseudo-random bit field, which will be used as entropy.
// | Hue | Saturation | Lightness | -> Roles
// | [31:16] | [15:8] | [7:0] | -> Bit positions
uint32 bitField = uint32(uint256(keccak256(abi.encodePacked(chainId, sablier, streamId))));
unchecked {
// The hue is a degree on a color wheel, so its range is [0, 360).
// Shifting 16 bits to the right means using the bits at positions [31:16].
>> uint256 hue = (bitField >> 16) % 360;
>> // The saturation is a percentage where 0% is grayscale and 100%, but here the range is bounded to [20,100]
// to make the colors more lively.
// Shifting 8 bits to the right and applying an 8-bit mask means using the bits at positions [15:8].
uint256 saturation = ((bitField >> 8) & 0xFF) % 80 + 20;
// The lightness is typically a percentage between 0% (black) and 100% (white), but here the range
>> // is bounded to [30,100] to avoid dark colors.
// Applying an 8-bit mask means using the bits at positions [7:0].
uint256 lightness = (bitField & 0xFF) % 70 + 30;
// Finally, concatenate the HSL values to form an SVG color string.
return string.concat("hsl(", hue.toString(), ",", saturation.toString(), "%,", lightness.toString(), "%)");
}
}

The two highlighted comments state that the color ranges are bound to [20, 100] and [30,100]. However neither of these colors can be equal to 100.
For saturation to be set to 100:
((bitField >> 8) & 0xFF) % 80 + 20 = 100
((bitField >> 8) & 0xFF) % 80 = 80

However it is not possible for any value when it has %80 applied to be equal to 80, the range is bound to [0,79]. Therefore the real range for saturation is [20,99] and for lightness it's [30,99]. Hue also cannot be equal to 360 and it's real range is [0,359]

Impact

The saturation and lightness bounds stated in the code comments are slightly off. It seems the intention was for the value to be able to reach 100 however in the current state this is not possible.

Risk: Low, as it only affects the visuals of the NFT without affecting funds or core functionality.

Tools Used

Manual Review

Recommendations

Change the code comments to revise the ranges to [20, 99], [30,99] and [0,359].

Updates

Lead Judging Commences

inallhonesty Lead Judge over 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

0xnevi Judge
over 1 year ago
inallhonesty Lead Judge
over 1 year ago
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.