According to a comment in ParaSpaceOracle, a fallback oracle should be used when Chainlink returns negative prices:
* - If the returned price by a Chainlink aggregator is <= 0, the call is forwarded to a fallback oracle
However, this is currently not the case. The answer is first cast to a uint (from an int):
price = uint256(source.latestAnswer());
The fallback is then only used if the casted answer is 0. However, if source.latestAnswer() was smaller than 0, price will be a huge number (because of the casting) that will be wrongly used.
Proof Of Concept
Let's say source.latestAnswer() = -1. Then, price will be equal to type(uint256).max (i.e., a huge number) and this wrong price will be used by the system, leading to completely wrong valuations.
Recommended Mitigation Steps
Check that the latest answer is <= 0 before casting, use the fallback oracle in that case.
Lines of code
https://github.com/code-423n4/2022-11-paraspace/blob/c01a980e5d6e15b2993b912c3569ed8b5236ff33/paraspace-core/contracts/misc/ParaSpaceOracle.sol#L128
Vulnerability details
Impact
According to a comment in
ParaSpaceOracle
, a fallback oracle should be used when Chainlink returns negative prices:However, this is currently not the case. The answer is first cast to a uint (from an int):
The fallback is then only used if the casted answer is 0. However, if
source.latestAnswer()
was smaller than 0,price
will be a huge number (because of the casting) that will be wrongly used.Proof Of Concept
Let's say
source.latestAnswer() = -1
. Then,price
will be equal totype(uint256).max
(i.e., a huge number) and this wrong price will be used by the system, leading to completely wrong valuations.Recommended Mitigation Steps
Check that the latest answer is <= 0 before casting, use the fallback oracle in that case.