The LibUsdOracle
is used inside LibWell.getRationsAndBeanIndex
which is the principal function to get the price of non-bean assets for the protocol. Beanstalk relies heavily on this function to keep its peg mechanism. i.e.: convert, sunrise, caseId & temperature, pods/soil, everything is affected by the price of non-bean assets.
The problem here is that the Convert/LibDeltaB use LibWell.getRatiosAndBeanIndex(tokens)
with a 0
lookback.
when using the Uniswap Oracle(encodeType == 0x02) for a token and the LibWell.getRationsAndBeanIndex
calls LibUsdOracle.getUsdPrice
it will a lookback 0
. The following will happen:
the function getTokenPriceFromExternal
will add a lookback
of 15 minutes for the Uniswap Price:
Now: uniswap price * chainlink price / 6.
Notice that here we have the following scenario:
Uniswap will return the TWAP price of 15min
Chainlink can return the current price** OR** the price from 4/3/2/hours ago
This will lead Beanstalk to consume the incorrect price. i.e:
tokenPrice = WBTC = 50k
USD
chainlinkTokenPrice = FRAX 0.95
USD
But chainlinkTokenPrice 4 hours ago was 0.99
USD
As shown above, using different limits for fetching assets' prices will** very often **lead the protocol to consume the incorrect price, because they are being fetched in different moments.
When using Convert:
users can exploit this to buy assets for a cheaper price or sell assets for a higher price.
Users can unfairly pay penalty fees due to the miscalculation of the deltaB
Users can skip penalty fees due to the miscalculation of the deltaB
When sunrise is called
It can miscalculate the deltaB and put the protocol in a situation that doesn't reflect the current state. I.e set abovePeg
when in fact is under the peg.
Miscalculate the caseId
, hence several components like temperature, pod rate, soil issuance, etc.
Minting more beans than it should.
Issuing more debt than it should
Manual Review
In a previous report, I recommended adding an oracleTimeout
parameter for each oracle instead of using hardcoded values. Considering this recommendation implemented, we can now implement the 2nd part:
Set a threshold to compare the time from Chainlink/Uniswap. If the time is within the limit, the price can be used otherwise return 0.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.