DeFiHardhat
12,000 USDC
View results
Submission Details
Severity: low
Invalid

An attacker can exploit the `try catch` to manipulate `MultiFlowPump` reserve values.

Summary

An attacker can exploit the try catch within the tryCalcReserveAtRatioSwap(), tryCalcLpTokenSupply() and tryCalcLPTokenUnderlying() functions to manipulate MultiFlowPump reserve values.

Vulnerability Details

MultiFlowPump.tryCalcReserveAtRatioSwap(), MultiFlowPump.tryCalcLpTokenSupply(), MultiFlowPump.tryCalcLPTokenUnderlying() make an incorrect assumption about the behavior of the code. In all of them there is a call one function from the WellFunction contract (calcReserveAtRatioSwap(), calcLpTokenSupply() and calcLPTokenUnderlying(), respectively) and if the function revert they catch the error and assume that the error comes from arithmetic overflow, thus setting their output to type(uint256).max. See the code snippet from MultiFlowPump.tryCalcReserveAtRatioSwap() as an example.

function tryCalcReserveAtRatioSwap(
IMultiFlowPumpWellFunction wf,
uint256[] memory reserves,
uint256 i,
uint256[] memory ratios,
bytes memory data
) internal view returns (uint256 reserve) {
try wf.calcReserveAtRatioSwap(reserves, i, ratios, data) returns (uint256 _reserve) {
reserve = _reserve;
} catch {
reserve = type(uint256).max;
}
}

However this assumption is wrong as all of the functions above can also revert due to out of gas error. As a result, the output will be set to max value even if the error does not come from overflow. This is problematic because an attacker can cause this out of gas error at will by restricting the gas limit from his transaction, triggering the out of gas error.

Currently on Ethereum and EVM-compatible chains, calls can consume at most 63/64 of the parent's call gas (See EIP-150). An attacker can exploit this to restrict the parent gas call limit (for example Well.swapTo() or any other Well function which calls _updatePumps()), making the child function fail (calcReserveAtRatioSwap(), calcLpTokenSupply() or calcLPTokenUnderlying()) and still leaving enough gas left (1/64) for the catch branch to be executed. Therefore he is able to set the output of the aforementioned functions to type(uint256).max outside the overflow conditions.

Impact

Under the situations described above, an attacker can exploit out of gas errors to manipulate the return values of tryCalcReserveAtRatioSwap(), tryCalcLpTokenSupply() or tryCalcLPTokenUnderlying(), resulting in incorrect reserves values stored in the MultiFlowPump.

Tools Used

Manual Review.

Recommendations

Consider better handling the possible errors in the try catch statement, catching only the arithmetic errors and reverting otherwise.

Updates

Lead Judging Commences

giovannidisiena Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

Informational/Invalid

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.