In the _dripsRange function of the Drips.sol contract variable end is declared as of type uint40. After the arithmetic operations and conditional checks have been performed, the end variable is returned as uint32(end) thus down casting it unsafely.
Proof of Concept
If the uint40 end variable has a value which is more than 2^32 - 1, at the time of down casting, then the uint32(end) will truncate the most significant 8 bits of the end variable. This will trigger unwanted data loss and unexpected behaviour of the protocol.
function _dripsRange(
DripsReceiver memory receiver,
uint32 updateTime,
uint32 maxEnd,
uint32 startCap,
uint32 endCap
) private pure returns (uint32 start, uint32 end_) {
start = receiver.config.start();
// slither-disable-start timestamp
if (start == 0) {
start = updateTime;
}
uint40 end = uint40(start) + receiver.config.duration();
// slither-disable-next-line incorrect-equality
if (end == start || end > maxEnd) {
end = maxEnd;
}
if (start < startCap) {
start = startCap;
}
if (end > endCap) {
end = endCap;
}
if (end < start) {
end = start;
}
// slither-disable-end timestamp
return (start, uint32(end));
}
For example if the uint40 end variable is stored with value 2^32, which means the 33rd bit will be set to "1". Due to unsafe down casting of uint32(end) the return value will be equal to "0" since most significant 8 bits are truncated. This will return an erroneous value, thus breaking the protocol.
Similar issue can be found in the _balanceAt function of the Drips.sol contract as well. Here uint256 return value is unsafely down cast to uint128 value.
Lines of code
https://github.com/code-423n4/2023-01-drips/blob/main/src/Drips.sol#L985-L1013 https://github.com/code-423n4/2023-01-drips/blob/main/src/Drips.sol#L572
Vulnerability details
Impact
In the
_dripsRange
function of theDrips.sol
contract variableend
is declared as of typeuint40
. After the arithmetic operations and conditional checks have been performed, theend
variable is returned asuint32(end)
thus down casting it unsafely.Proof of Concept
If the
uint40 end
variable has a value which is more than 2^32 - 1, at the time of down casting, then theuint32(end)
will truncate the most significant 8 bits of theend
variable. This will trigger unwanted data loss and unexpected behaviour of the protocol.https://github.com/code-423n4/2023-01-drips/blob/main/src/Drips.sol#L985-L1013
For example if the
uint40 end
variable is stored with value 2^32, which means the 33rd bit will be set to "1". Due to unsafe down casting ofuint32(end)
the return value will be equal to "0" since most significant 8 bits are truncated. This will return an erroneous value, thus breaking the protocol.Similar issue can be found in the
_balanceAt
function of theDrips.sol
contract as well. Here uint256 return value is unsafely down cast to uint128 value.https://github.com/code-423n4/2023-01-drips/blob/main/src/Drips.sol#L572
Tools Used
Manual and VS Code.
Recommended Mitigation Steps
Import Openzeppelin safeCast.sol library into the contract and use its
toUint32()
function to safely down cast touint32(end)
.