LOSS OF PRECISION RESULTING IN WRONG VALUE FOR PRICE RATIO #323
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
selected for report
This submission will be included/highlighted in the audit report
sponsor acknowledged
Technically the issue is correct, but we're not going to resolve it for XYZ reasons
Lines of code
https://github.com/code-423n4/2022-09-y2k-finance/blob/2175c044af98509261e4147edeb48e1036773771/src/oracles/PegOracle.sol#L46-L83
Vulnerability details
Impact
The project implements a price oracle in order to get the relative price between the pegged asset and the price of the original asset (example: stETH to ETH). If the ratio (the pegged asset divided by the original asset) is 1 the Token is pegged, otherwise is depegged.
Bellow is a code snippet from the PegOracle.sol function.
To fetch the ratio at any time, the
PegOracle.sol
performs some calculations; first the relative price is multiplied by 1e4 and then it returns the above calculation divided by 1e6.The Controller.sol file makes an external call to the PegOracle.sol oracle to get the relative price. After, the value returned, it is multiplied by
10**(18-(priceFeed.decimals())
and the result represents the relative price between the two assets.The result is converted to 18 decimal points in order to be compared with the Strike Price passed by the admin on
VaultFactory.sol
.Due to the fact that the first multiplication is first divided by
1e6
(PegOracle.sol#L78)( and then re-multiplied byuint256 decimals = 10**(18-(priceFeed.decimals()));
(Controller.sol#L299-L300) it leads to loss of precision. This behavior will make the relative price between the assets incorrect.Proof of Concept
Bellow is a test that illustrates the above issue for various oracle pairs. The calculated ratio is compared against a modified version of an example of different price denominator, provided by Chainlink.
Here is the output after running the with:
forge test --fork-url https://arb1.arbitrum.io/rpc -vv
:990500000000000000
990544616614592905
996300000000000000
1003669952945847834
996000000000000000
1003940775578783463
Tools Used
Manual Review
Recommended Mitigation Steps
Since the 2 assets are required to having the same amount of decimals a formula that transforms the relative price to 1e18 could be:
x * 1e18 / y
.An example that Chainlink implements, that includes a
scalePrice
function, in order to find a different price denominator could be found hereThe text was updated successfully, but these errors were encountered: