Skip to content

Feature : Collateralization oracle#94

Closed
eswak wants to merge 6 commits intofei-protocol:masterfrom
eswak:feature/CollateralizationOracle
Closed

Feature : Collateralization oracle#94
eswak wants to merge 6 commits intofei-protocol:masterfrom
eswak:feature/CollateralizationOracle

Conversation

@eswak
Copy link
Contributor

@eswak eswak commented Apr 11, 2021

Hi,

Here is a pull request to add a Collateralization Oracle as discussed on the governance forums.

This contract is pretty straightforward & mainly composed of pure functions :

  • It interacts with EthUniswapPCVDeposit to get the totalValue() and getReserves().
  • Circulating FEI supply is defined as FEI totalSupply() minus FEI in the Uniswap pool owned by EthUniswapPCVDeposit.
  • UniswapOracle is used for the ETH/USD current price.
  • UniswapOracle is used for the ETH/FEI current price (234b68f).
  • It should be upgraded as PCV is deployed elsewhere in the future (as in FIP-2 #95).

I also implemented a small test suite inspired from the one of UniswapOracle :
Can be run with npm run test -- -g CollateralizationOracle
image

Also tested on a local mainnet fork, with results consistent with what's observed on https://app.fei.money/analytics (see comments below)

Best,

Copy link
Contributor

@Joeysantoro Joeysantoro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome thanks for coding it up so fast!

One final note is it is good to reduce the number of external contract calls as much as possible to save on gas. One call to read should only hit every external call once in the entire flow.

Rationale from Joey's review :
"Using the spot reserves of Uniswap would be vulnerable to flash manipulation. I'd suggest using an ETH-FEI TWAP oracle and then back out manipulation resistant numbers for the reserves"

Also add :
- collateralizationRatio() view function
- overCollateralized() view function
- associated tests
@eswak
Copy link
Contributor Author

eswak commented Apr 12, 2021

I changed the implementation of _collateralizationRatio() to make the external calls only once.

But since we introduced the ethFeiPriceOracle, there are still 5 external calls to get the collateral ratio. Should we have an internal variable to keep the last value, and rely more on update() calls ?

On a related topic : is the code of the webapp (https://app.fei.money/analytics) available somewhere ? The analytics page could be updated to read the oracle.

@eswak eswak marked this pull request as draft April 12, 2021 10:02
@Joeysantoro
Copy link
Contributor

On a related topic : is the code of the webapp (https://app.fei.money/analytics) available somewhere ? The analytics page could be updated to read the oracle.

The webapp code is not available but we could update it! Have you tested this oracle on a mainnet fork?

@eswak
Copy link
Contributor Author

eswak commented Apr 21, 2021

Note : to be updated after #95 is merged (EthReserveStabilizer and EthPCVDripper will have non-zero balance of ETH that must be counted as part of the PCV).

@eswak
Copy link
Contributor Author

eswak commented Apr 22, 2021

Have you tested this oracle on a mainnet fork?

I did not until now, and it helped me to find an overflow error... good call.

I'm not sure I should commit this test script anywhere, but now the oracle works on a local mainnet fork :

// truffle test collateralizationOracleMainnet.js
// npm run test -- -g CollateralizationOracle

// mainnet addresses
const core = '0x8d5ED43dCa8C2F7dFB20CF7b53CC7E593635d7b9';
const ethUsdPriceOracle = '0x087F35bd241e41Fc28E43f0E8C58d283DD55bD65';
const ethFeiPriceOracle = '0xB58cbCb1e98c7F3771847cc2D730bF9589b534e4';
const ethUniswapPCVDeposit = '0x9b0C6299D08fe823f2C0598d97A1141507e4ad86';

const CollateralizationOracle = artifacts.require('CollateralizationOracle');

contract('CollateralizationOracle', async (accounts) => {
  it('should print pure function results', async () => {
    const oracle = await CollateralizationOracle.new(core, ethUsdPriceOracle, ethFeiPriceOracle, ethUniswapPCVDeposit);
    console.log('isOutdated:', await oracle.isOutdated());
    console.log('circulatingFei:', await oracle.circulatingFei() / 1e18);
    console.log('ethPcv:', await oracle.ethPcv()  / 1e18);
    console.log('ethUsd:', await oracle.ethUsd() / 1e18);
    const ethFeiInPool = await oracle.ethFeiInPool();
    console.log('ethFeiInPool.ethInPool:', ethFeiInPool[0] / 1e18);
    console.log('ethFeiInPool.feiInPool:', ethFeiInPool[1] / 1e18);
    console.log('ethFeiInPool.validity:', ethFeiInPool[2]);
    console.log('collateralizationRatio:', await oracle.collateralizationRatio() / 1e18);
    console.log('overCollateralized:', await oracle.overCollateralized());
    console.log('update...');
    await oracle.update();
    console.log('... updated !');
  });
});

Results are consistent with what is displayed on the analytics page :
image

@eswak eswak closed this Aug 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments