Uniswap / v3-periphery

🦄 🦄 🦄 Peripheral smart contracts for interacting with Uniswap v3
https://uniswap.org
GNU General Public License v2.0
1.17k stars 1.09k forks source link

Running OracleLibrary consult on pools with only one observation #246

Open JasperTimm opened 2 years ago

JasperTimm commented 2 years ago

Hey there,

I'm playing around with a fork of mainnet on a local chain and using UniswapV3 to test some swap functionality. When using the OracleLibrary to get prices via consult(), I've found it tricky when using a lesser known token with only one observation stored. Each time a swap occurs the one observation is then overwritten with the timestamp of when this happened. This means when running a consult soon after, the secondsAgo needs to be no more than the last timestamp for the latest swap otherwise running into this revert: https://github.com/Uniswap/v3-core/blob/main/contracts/libraries/Oracle.sol#L226

At the moment I check getOldestObservationSecondsAgo() > secondsAgo before calling, and if not I need to call slot0() on the pool directly and grab the latest tick. I feel like this could be handled within the OracleLibrary a little better though, perhaps consult could implement this itself but I'm open to other ideas.

I also considered using getBlockStartingTickAndLiquidity in the OracleLibrary but there's a check here ( https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/OracleLibrary.sol#L97 ) that there's at least 2 observations. However the next block simply returns the pools slot0() observation anyway... regardless of the above, it feels like the require should move below this block anyway?

Happy to look at PRs if helpful. Just getting thoughts on this first as I assume you folks know the code far better than me.