Platform: Code4rena
Start Date: 07/03/2024
Pot Size: $63,000 USDC
Total HM: 20
Participants: 36
Period: 5 days
Judge: cccz
Total Solo HM: 11
Id: 349
League: BLAST
Rank: 17/36
Findings: 1
Award: $377.05
🌟 Selected for report: 1
🚀 Solo Findings: 0
🌟 Selected for report: 0xAadi
Also found by: 0x11singh99, bareli, hihen
377.0529 USDC - $377.05
The MagicLpAggregator
contract contains a flaw within the _getReserves
function where it fails to return the reserve values fetched from the pair
contract. This oversight results in the latestAnswer
function always returning zero, which can have severe implications for any systems that depend on this contract for accurate liquidity pool pricing data.
The missing return statement in the _getReserves
function leads to the latestAnswer
function always returning zero. This affects any dependent systems or contracts that rely on accurate price data from the MagicLpAggregator
contract, as they will receive incorrect information, potentially leading to financial loss or system failure.
The _getReserves
function in the provided code snippet does not return the fetched reserves:
33: function _getReserves() internal view virtual returns (uint256, uint256) { 34: (uint256 baseReserve, uint256 quoteReserve) = pair.getReserves(); 35: }
Due to the missing return statement, the latestAnswer function uses uninitialized variables for baseReserve
and quoteReserve
, which default to zero:
function latestAnswer() public view override returns (int256) { // ... (uint256 baseReserve, uint256 quoteReserve) = _getReserves(); baseReserve = baseReserve * (10 ** (WAD - baseDecimals)); // baseReserve defaults to 0 quoteReserve = quoteReserve * (10 ** (WAD - quoteDecimals)); // quoteReserve defaults to 0 // ... }
Manual Review
Update _getReserves()
- function _getReserves() internal view virtual returns (uint256, uint256) { + function _getReserves() internal view virtual returns (uint256 baseReserve, uint256 quoteReserve) { - (uint256 baseReserve, uint256 quoteReserve) = pair.getReserves(); + (baseReserve, quoteReserve) = pair.getReserves(); }
Other
#0 - 0xm3rlin
2024-03-15T00:56:04Z
confirmed
#1 - c4-pre-sort
2024-03-15T12:22:50Z
141345 marked the issue as primary issue
#2 - c4-pre-sort
2024-03-15T12:23:27Z
141345 marked the issue as sufficient quality report
#3 - 0xCalibur
2024-03-17T04:31:13Z
Fixed main branch, meanwhile this contest was happenning
https://github.com/Abracadabra-money/abracadabra-money-contracts
#4 - c4-sponsor
2024-03-17T04:31:16Z
0xCalibur (sponsor) confirmed
#5 - c4-judge
2024-03-29T13:37:07Z
thereksfour marked the issue as satisfactory
#6 - c4-judge
2024-03-31T06:48:00Z
thereksfour marked the issue as selected for report
#7 - c4-judge
2024-03-31T06:51:14Z
thereksfour changed the severity to 3 (High Risk)
#8 - trust1995
2024-04-02T14:00:22Z
Hi,
The impact is that oracle ALWAYS returns price = 0. I argue that this is in line with Medium severity (like 3/4 dups submitted it) because:
@0xCalibur if you can weight in on any assumptions of integration with the Oracle setup it would be helpful.
#9 - 0xCalibur
2024-04-04T13:02:42Z
There was a mistake, not returning the value in _getReserves. We turned on "error on warnings" during compilation on Foundry config to avoid such issues in the future. This could have been avoided easily.
#10 - thereksfour
2024-04-05T11:12:56Z
This fact reduces the severity of this issue, will downgrade it to M
A price of 0 is considered invalid in Chainlink and most other feeds, the assumed behavior would be to revert. Admin can replace the feed at that time. Loss of funds seems very unlikely, it would have to be that the first time the issue is discovered it is when price of 0 is assumed legitimate and used to handle funds - is that in line with required likelihood for High?
#11 - c4-judge
2024-04-05T11:13:06Z
thereksfour changed the severity to 2 (Med Risk)