Precision calculation error in PendlePTOracle::_calculateBaseToQuote causing erroneous price reports
Summary
PendlePTOracle is expected to provide a result in rateDecimals (10^18) but instead provides the result in different decimals (depending on PTToken decimals) due to a calculation error. As a result, reported pricing can diverge from real price by orders of magnitude.
Vulnerability Detail
In PendlePTOracle::_calculateBaseToQuote the calculation providing the answer is this:
This calculation assumes that the ptRate returned from PENDLE_ORACLE is given in ptDecimals (which is why the formula divides by ptDecimals). However this is incorrect. In fact the Pendle oracle returns ptRate in fixed 10^18 decimals (regardless of the PT Token decimals): This can be seen in Pendle's oracle code here, note that when getPtToAssetRateRaw returns a value of 1 (in the case that expiry time has passed) PMath.ONE (which is 10^18) is used. An example can be seen in the aUSDC pendle market on Arbitrum where the PT token decimals are 6 but when calling the Pendle Oracle getPtToAssetRate function with the aUSDC market (0x875F154f4eC93255bEAEA9367c3AdF71Cdcb4Cc0) the result is given in 10^18 precision.
The result is that for any pendle market where the PT token decimals are different than 10^18 the oracle returns a result that is orders of magnitude different than the true result (which is expected to be in 10^18 decimals). The distorted price will have an effect system wide, whenever the ptOracle is consulted for price for the purpose of calculations.
root cause
Dividing by ptDecimals in the answer formula instead of by the pendle oracle precision of 10^18.
Impact
The resulting price deviation (in the example of aUSDC the result will be in 10^30 decimals instead of 10^18) will cause price reporting to be orders of magnitude different than the expected result. The result is used in TradingMudule::getOraclePrice causing it to potentially report prices that are way off.
Impact includes:
A. Erroneous health checks and collateralization rate calculations leading to increased bad debt risk (over-evaluation) or unnecessary liquidations causing loss to users (under-evaluation).
B. Trade module malfunctioning due to wrong calculation of trade limits, causing trades to either fail, or conversely performing trades that should have been reverted due to excessive slippage.
nirohgo
High
Precision calculation error in PendlePTOracle::_calculateBaseToQuote causing erroneous price reports
Summary
PendlePTOracle is expected to provide a result in rateDecimals (10^18) but instead provides the result in different decimals (depending on PTToken decimals) due to a calculation error. As a result, reported pricing can diverge from real price by orders of magnitude.
Vulnerability Detail
In PendlePTOracle::_calculateBaseToQuote the calculation providing the answer is this:
This calculation assumes that the ptRate returned from PENDLE_ORACLE is given in ptDecimals (which is why the formula divides by ptDecimals). However this is incorrect. In fact the Pendle oracle returns ptRate in fixed 10^18 decimals (regardless of the PT Token decimals): This can be seen in Pendle's oracle code here, note that when getPtToAssetRateRaw returns a value of 1 (in the case that expiry time has passed) PMath.ONE (which is 10^18) is used. An example can be seen in the aUSDC pendle market on Arbitrum where the PT token decimals are 6 but when calling the Pendle Oracle getPtToAssetRate function with the aUSDC market (0x875F154f4eC93255bEAEA9367c3AdF71Cdcb4Cc0) the result is given in 10^18 precision.
The result is that for any pendle market where the PT token decimals are different than 10^18 the oracle returns a result that is orders of magnitude different than the true result (which is expected to be in 10^18 decimals). The distorted price will have an effect system wide, whenever the ptOracle is consulted for price for the purpose of calculations.
root cause
Dividing by ptDecimals in the answer formula instead of by the pendle oracle precision of 10^18.
Impact
The resulting price deviation (in the example of aUSDC the result will be in 10^30 decimals instead of 10^18) will cause price reporting to be orders of magnitude different than the expected result. The result is used in TradingMudule::getOraclePrice causing it to potentially report prices that are way off.
Impact includes:
A. Erroneous health checks and collateralization rate calculations leading to increased bad debt risk (over-evaluation) or unnecessary liquidations causing loss to users (under-evaluation).
B. Trade module malfunctioning due to wrong calculation of trade limits, causing trades to either fail, or conversely performing trades that should have been reverted due to excessive slippage.
Code Snippet
https://github.com/sherlock-audit/2024-06-leveraged-vaults/blob/14d3eaf0445c251c52c86ce88a84a3f5b9dfad94/leveraged-vaults-private/contracts/oracles/PendlePTOracle.sol#L117
Tool used
Manual Review
Recommendation
Correct the formula by dividing by the Pendle Oracle fixed precision (10^18) instead of the pt token decimals.
Duplicate of #66