Summary
In case of relatively frequent reserves update the capped reserves changing can be faster than expected due to the difference between short time passed and specified capInterval
.
Vulnerability Details
The MultiFlowPump.update
lets specify capInterval
which is used for periods number calculation and CapReservesParameters
which determine maximum changing in a period (capInterval
).
function update(uint256[] calldata reserves, bytes calldata data) external {
(bytes16 alpha, uint256 capInterval, CapReservesParameters memory crp) =
abi.decode(data, (bytes16, uint256, CapReservesParameters));
<...>
bytes16 alphaN;
bytes16 deltaTimestampBytes;
uint256 capExponent;
{
uint256 deltaTimestamp = _getDeltaTimestamp(pumpState.lastTimestamp);
if (deltaTimestamp == 0) return;
alphaN = alpha.powu(deltaTimestamp);
deltaTimestampBytes = deltaTimestamp.fromUInt();
>> capExponent = calcCapExponent(deltaTimestamp, capInterval);
}
pumpState.lastReserves = _capReserves(msg.sender, pumpState.lastReserves, reserves, capExponent, crp);
As mentions in the comment before calcCapExponent
function invoke at least one interval will be accounted. But there are no CapReservesParameters
adjustment for the decreased interval in the contract logic, they are used as is instead.
function _capReserves(
address well,
uint256[] memory lastReserves,
uint256[] memory reserves,
uint256 capExponent,
>> CapReservesParameters memory crp
) internal view returns (uint256[] memory cappedReserves) {
if (reserves.length != 2) {
revert TooManyTokens();
}
Call memory wf = IWell(well).wellFunction();
IMultiFlowPumpWellFunction mfpWf = IMultiFlowPumpWellFunction(wf.target);
>> cappedReserves = _capLpTokenSupply(lastReserves, reserves, capExponent, crp, mfpWf, wf.data, true);
if (cappedReserves.length == 0) {
>> cappedReserves = _capRates(lastReserves, reserves, capExponent, crp, mfpWf, wf.data);
>> cappedReserves = _capLpTokenSupply(lastReserves, cappedReserves, capExponent, crp, mfpWf, wf.data, false);
} else {
>> cappedReserves = _capRates(lastReserves, cappedReserves, capExponent, crp, mfpWf, wf.data);
}
}
Impact
Unexpected fast capped reserves changing can break a Well logic, lost of precision
Tools used
Manual Review
Recommendations
Consider using a unified 1 second capInterval
for all Wells or implementing a logic of CapReservesParameters
params adjustment as ratio between actual time passed and capInterval
.