Closed code423n4 closed 1 year ago
[dispute validity]
The current behavior is correct. Calling _addDeltaRange(state, cycleStart, cycleStart + 1, -int256(amt * _AMT_PER_SEC_MULTIPLIER));
does apply dripping at a per-second rate of -amt
, but it does so on a time range of cycleStart, cycleStart + 1,
, which is 1 second long, so the "undripped" amount is amt
. Applying your fix breaks 18 tests.
CodeSandwich marked the issue as sponsor disputed
I agree with @CodeSandwich
Looks to me like this is already accounted here: https://github.com/code-423n4/2023-01-drips/blob/9fd776b50f4be23ca038b1d0426e63a69c7a511d/src/Drips.sol#L1045-L1046
int256 fullCycle = (int256(uint256(_cycleSecs)) * amtPerSec) / amtPerSecMultiplier;
Feel free to follow up with an instance of the issue @chaduke3730 but for now am closing as invalid
GalloDaSballo marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2023-01-drips/blob/9fd776b50f4be23ca038b1d0426e63a69c7a511d/src/Drips.sol#L366
Vulnerability details
Impact
Detailed description of the impact of this finding.
_squeezeDrips()
passes the amount argument in place ofamtPerSec
for its callee_addDeltaRange
in the following line https://github.com/code-423n4/2023-01-drips/blob/9fd776b50f4be23ca038b1d0426e63a69c7a511d/src/Drips.sol#L366-L1053The last argument should be the dripping speed, not dripping amount. Because of this bug, it will cause either underflow, which reverts the _squeezeDrips() function, or much higher future dripping speed and thus the losing of fund for the sender.
Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
We show why using the wrong argument for
_addDeltaRange
will cause underflow/revert, or the losing of fund for the sender below:1) Alice calls
DripsHub.squeezeDrips()
, which callsDrips._squeezeDrips()
.2)
Drips._squeezeDrips()
calls_squeezeDripsResult()
to calculate the squeezed amount,amt
.3) Suppose
amt
= 3600, andcycleSecs_ = 3600
, that is each cycle is 1 hour.4)
Drips._squeezeDrips()
will call_addDeltaRange()
to adjust the dripping speed at both ends:cycleStart
andcycleStart+1
. Note a negative speed is used here since we already squeezed the amount out, so a negative speed need to take effect for the current cycle.5) Unfortunately, instead of using the dripping speed of amt/cycleSecs_ = 3600/3600 = 1/sec, it uses
amt
as the dripping speed (with a multiplication factor of _AMT_PER_SEC_MULTIPLIER). As a result, the dripping speed is mistakenly 3600X of the correct speed argument that should be passed toaddDeltaRange()
- passing(-3600*_AMT_PER_SEC_MULTIPLIER)
instead of(-1*_AMT_PER_SEC_MULTIPLIER)
for our example.6)
_addDeltaRange()
calls_addDelta()
at both ends to adjust the speed.7) The first
_addDelta()
will be called, since we had a negative speed, bothfullCycle
andnextCycle
will take negative values below. Depending on which value is bigger,might underflow, since we are mistakenly subtracting a much larger wrong number (3600X of it is supposed to be) from
amtDelta.thisCycle
(which might not be that big) instead of the original correct number. Similarly,might also underflow as well due to a much larger number of nextCycle (3600X of it is supposed to be). If these two underflows will not happen, then the second
_addDelta()
will result the losing of fund, which we show below.8) If there is no underflow, then the second _addDelta() will be executed: https://github.com/code-423n4/2023-01-drips/blob/9fd776b50f4be23ca038b1d0426e63a69c7a511d/src/Drips.sol#L1029:
9) Here we are adjusting with a positive speed (since the original speed argument is negative). Since
-amtPerSec
is 3600X is what is supposed to be._addDelta()
will cause the increase of 3600X speed adjustments of it is supposed to be for bothamtDelta.thisCycle
andamtDelta.nextCycle
.10) As a result, the receiver will steal a lot of funding from the sender, the sender is losing fund!
Tools Used
Remix
Recommended Mitigation Steps
We need to pass the correct argument to as follows: