Closed code423n4 closed 1 year ago
GalloDaSballo marked the issue as primary issue
[dispute validity]
This is an expected and documented behavior which must be accounted for when using Drips
contract in a protocol. It simplifies the code and reduces gas cost on overflow checks. See the docs of Drips
:
/// @notice Drips can keep track of at most `type(int128).max`
/// which is `2 ^ 127 - 1` units of each asset.
/// It's up to the caller to guarantee that this limit is never exceeded,
/// failing to do so may result in a total protocol collapse.
The attack you've described relies on amtDelta.thisCycle + amtDelta.nextCycle
overflowing int128
, but it's not possible without putting more than type(int128).max
tokens into the protocol. While it's reproduceable in the test environment by misusing the contract, it's impossible to pull of in the real world, because DripsHub
tracks the total amount of each ERC-20 in the protocol:
[Drips.sol]
uint256 internal constant _MAX_TOTAL_DRIPS_BALANCE = uint128(type(int128).max);
[DripsHub.sol]
uint256 public constant MAX_TOTAL_BALANCE = _MAX_TOTAL_DRIPS_BALANCE;
...
require(totalBalances[erc20] + amt <= MAX_TOTAL_BALANCE, "Total balance too high");
CodeSandwich marked the issue as sponsor disputed
Closing per the Sponsor's dispute
GalloDaSballo marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2023-01-drips/blob/9fd776b50f4be23ca038b1d0426e63a69c7a511d/src/Drips.sol#L287-L291
Vulnerability details
Impact
In
_receiveDripsResult()
, the type cast of uint128 could underflow, and result in wrongreceivedAmt
. The impacts could be:Proof of Concept
amtDelta.thisCycle
andamtDelta.nextCycle
can both be negative in function_addDelta()
, ifamtPerSec
is less than 0:Imagine there is only 1 cycle to iterate in the for loop, and the
thisCycle
is -10,000e18, less than 0. Then in line 289, thereveiveAmt
will be increased by uint128(-10,000e18) = 340282366920938453463374607431768211456.Then when
receiveDrips()
is called, the wrong amount ofreceivedAmt
of 340282366920938453463374607431768211456 would be transferred, if the balance is enough, the fund in the protocol could be drained.Or in other cases, the amount returned from
_receiveDripsResult()
will be inaccurate, the actual transferred amount will be wrong, some users could receive undeserved fund, and on the other hand, some users could loss fund due to the wrong amount.Tools Used
Manual analysis.
Recommended Mitigation Steps
Calculate the sum of all the
amtDeltas
and add toreceivedAmt
only if the total is greater than 0: