Upgrade Compound II’s Oracle to UAV3

Abstract

This proposal is to upgrade the Compound II UniswapAnchoredView (UAV) Oracle. The upgrade will update the UAV’s reference prices from Uniswap V2 pools to Uniswap V3 pools.
Note that this proposal references the CIP-style format.

Motivation

A significant amount of liquidity on Uniswap V2 has shifted towards Uniswap V3 as liquidity providers capitalize on concentrated liquidity provisioning strategies. Compound’s UAV Oracle, which serves as a reference anchor mechanism for pricing data ingestion, must follow this shift of market liquidity to provide higher reliability and security assurances by reducing the risk of price manipulation or other issues related to low liquidity. This proposal aims to address this by updating the UAV to check the prices on Uniswap V3 instead of Uniswap V2.

Proposal Details

Below are details that have stayed the same from the original proposal.

  • The new UniswapAnchoredView (UAV) no longer records and keeps observations but instead queries the respective Uniswap V3 pool’s observe function to get a TWAP with the set anchor period when it’s needed (i.e., when a reporter calls validate on the UAV).
  • The price of an asset in Uniswap V3 is a function of the “tick” of the pool. The formula is price = 1.0001^tick. The math required for conversion between posted prices and the Uniswap V3 TWAP and the UAV representation has been modified to support this. Relevant libraries (TickMath and FullMath) have been included from the Uniswap V3 codebase.
  • The tests from the original UAV have been adapted to the new Uniswap V3 architecture - i.e., observations/TWAP tests were removed. Hardhat (+typechain) has been implemented so real Uniswap V3 pools can be used via forked mainnet in tests and eliminate the need for mocking Uniswap V3 pools.
  • Increased the Uniswap observation cardinality to 150 on pools that were below 150. “cardinality” in Uniswap is a term for the TWAP lookback history. It represents the state changes per block, so ten trades in a block get condensed and recorded as one update in the lookback. To save on gas costs, the cardinality starts at 2, and anyone can pay the gas cost for a deeper lookback. Therefore, increasing the cardinality to 150 ensures a safe minimum for the lookback history.

We note that a reduction in liquidity within Uniswap v3 pools can make the TWAP price in those pools easier to manipulate and may cause the Uniswap anchor to be less accurate than expected. However, this will not affect the accuracy of the primary Price Feeds from Chainlink.

Notably, the main change from the last implementation is to update the getUnderlyingPrice function to fetch the token configuration using the cToken address instead of calling the underlying function from the cToken. The reasoning is that getUnderlyingPrice fails when passing in the address of the cETH token as cETH does not implement the underlying function like other cTokens. The community can review this change in PR14 in Github.

The new UAV3 contract is deployed here, which matches the changes from PR14 outlined above. We encourage the community to inspect this instance and provide any feedback.

Rationale

The rationale behind the proposed design goes back to when the UAV was initially created. After the DAI liquidation event, in which the Coinbase oracle deviated from the market-wide price for DAI/USD, the Compound community came to a consensus to upgrade Compound II’s oracle system to use Chainlink Price Feeds. The community had also determined to develop a custom implementation using the Uniswap Anchored View (UAV) to have a “sanity check” to ensure data from Chainlink Price Feeds were within acceptable bounds of the time-weighted average price of the token/ETH pair on Uniswap v2. To learn more about the UAV’s architecture, please see the Compound Docs.

However, the custom implementation of the UAV is very different from how other protocols integrate Chainlink Price Feeds. These protocols, such as Compound III, use Chainlink Price Feeds directly to retrieve price data. For alternative considerations for this and future proposals, the direct integration method is the preferred route for a streamlined implementation while minimizing the potential for false positives from a reference anchor.

Expected Impact

The new UAV3 is deployed in the proposed state with Price Feed aggregator contracts pushing pricing data to it. Currently, the contract is functioning as expected and without issue. If an on-chain vote passes this proposal, the upgrade will immediately take effect to utilize Uniswap V3 prices in the reference anchor.

Security Considerations

As with any protocol enhancement, important security implications have been taken into serious consideration to avoid any unintended impact on the Compound II protocol, as the UAV influences its core markets. The original code was audited, and we have worked closely with the OpenZeppelin team to review the small code change and performed tests to ensure a smooth transition to the new UAV. This includes:

  • Querying the price directly with the new function to retrieve the correct value without reversion
  • Comparing the configuration for cETH with the params file and old versions of the same contract

Linked here, the community can review the result of a successful test that:

  • Compares the prices for cTokens with their addresses’ underlying prices
  • Compares the proposed UAV and production UAV

You can also run these tests by following the instructions here.

Lastly, any updates to Compound’s oracles will follow the same rigorous testing processes. As mentioned in @cylon’s post here, this includes:

  1. Proposal Simulations - comprehensive simulation testing before submission for a governance vote.
  2. Change management - ensuring that code deployed on-chain always matches the versions of the Compound protocol repository to maintain high quality and readability.

Next Steps

As discussed on the developer community call, we want to allow the community to review the updates before going to an on-chain vote this week. We will post an update once the proposal has been submitted on-chain so that the community can prepare to perform post-deployment checks to ensure everything is working correctly.

We look forward to completing the UAV upgrade and invite the Compound community to share their feedback.

Copyright

Copyright and related rights waived via CC0.

This contribution is offered “as is” without warranty of any kind.

4 Likes

Thanks @CL_Michael for the detailed post and overview of these changes. I can confirm that the OpenZeppelin team worked with ChainLink to ensure that the fix and simulations were in order.

I also appreciate this example of how the CIP format can be utilized for protocol changes without needing to be submitted as a CIP.

In this case, we had discussed on the last community call that this change did not require a CIP due to the fact that these changes have already been accepted by long-standing community consensus in the forum and that the security issues have been addressed through a thorough review. That being said, we would always appreciate additional eyes on this from other community members to be sure.

3 Likes

Thanks – this proposal makes sense to me, and I support it.

2 Likes

The post on the governance dashboard says there were no integration tests. Compound.


I reviewed the PR and I could not find any integration tests. Fetch underlying price using ctoken by cds95 · Pull Request #14 · smartcontractkit/open-oracle · GitHub

I also reviewed both the open and closed pull requests on the compound v2 main repo where I did not find any integration tests. Pull requests · compound-finance/compound-protocol · GitHub

This is a protocol that manages billions of other people’s money. Please do the responsible thing and prove the protocol works after the upgrade with an integration test.

7 Likes

Hi @elliot , thank you for reviewing.

What you’ve highlighted in the submission states that GFX has not simulated it, but you can find the successful tests in a separate PR here in the open-oracle repo. Further explanation from the original post:

The test suite contained in the PR was run on a mainnet fork by our team to ensure they work correctly with the live contracts deployed. The deployed implementation can also have its functions called directly to confirm that price reporting works successfully on all existing markets.

Additionally, you can review the previous tests in the open-oracle repo and this integration test in another PR. This test also called the current live UAV, and our live proposed UAV then compared the results for all the markets. All prices matched without reverting.

OpenZeppelin also confirmed the simulations here:

To be more comprehensive, we have merged another PR with further test coverage. It includes a forked mainnet test and a script to hit mainnet directly and compare the output.

We encourage community members to run the test suite or do their simulations to validate our findings.

5 Likes

To follow up on what @CL_Michael has shared, OpenZeppelin performed our own separate simulations using Foundry to confirm that the fix was successful and the price reporting works as expected.

While we don’t normally publish the testing scripts used in our security reviews, I’ve had our auditors make an exception in this case given the past incident. This should serve as additional validation of the upgrade’s safety on top of the more comprehensive tests that ChainLink has already run and published. Community members are welcome to review and run the scripts themselves in the repo below.

8 Likes

Thanks for the details @CL_Michael @cylon, this is reassuring. By the way, why aren’t the tests that are written for each proposal published ? I think that this is very valuable for the community.

In the meantime, we (Morpho Labs) also did some quick integration testing of the new oracle contract, that you can find here: GitHub - morpho-labs/compound-UAV3-integration-test

4 Likes

I too have concerns about proposals without corresponding simulations, so I’ve started to create some (example) scenarios that can be used for testing v2 proposals:

Some basic v2 scenarios by jflatow · Pull Request #660 · compound-finance/comet · GitHub.

This only covers half the actions in the top 4 markets, it would be nice to have these be a bit more sophisticated, but the cool thing is that using the Comet scenario framework, we can trivially run any scenarios written like this against any future or pending proposals. My hope is we can add to this optional v2 scenario suite, and also make v2 proposals using this framework (Compound Labs is already doing this for all proposals), in order to increase confidence.

4 Likes

It’s great to see the tests published for the community to see!

One final item that seems like it needs to be completed before this proposal executes is the ownership of the new oracle needs to be transferred from the EOA that deployed it to the Compound Community Multisig.

UniswapAnchoredView | Address 0x50ce56a3239671ab62f185704caedf626352741e | Etherscan is owned by the deployer Address 0x61E5E1ea8fF9Dc840e0A549c752FA7BDe9224e99 | Etherscan

2 Likes

Thank you to everyone who reviewed and supported the proposal. The vote has passed, and we have initiated the transfer of ownership of the UAV for the Compound Community Multisig to accept.

Tagging the current multisig signers for visibility: @TennisBowling @arr00 @blck @jared @brendan_dharma & Gauntlet (@pauljlei)

2 Likes

I’ll try to get this through the multisig asap

1 Like

Thank you to everyone who supported the UAV3 upgrade and helped ensure a smooth transition.

Now that it has been successfully running for over a week on Compound V2, we plan to deprecate the old UAV. Please be advised that we are targeting the shutdown for Friday, Jan 27. If any other protocols or users still reference the old UAV contract, please migrate to the current UAV contract to avoid any issues.

3 Likes