Skip to content

Commit

Permalink
Merge pull request #38 from fei-protocol/FIP-8-Chainlink-Integration
Browse files Browse the repository at this point in the history
FIP-8: Chainlink Upgrade
  • Loading branch information
Joeysantoro committed Jun 16, 2021
2 parents ca1531d + 2f5111d commit 7f6cbd9
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 10 deletions.
44 changes: 44 additions & 0 deletions proposals/fip_8.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"proposal_title": "FIP-8: Use Chainlink Oracle",
"proposal_description_link": "https://docs.google.com/document/d/1bKLdC0k79Wh5sbdFWZTiC_tI6HSZg64uAd_qrkRzvm0",
"proposal_commands": [
{
"address": "0xa08A721dFB595753FFf335636674D76C455B275C",
"values": "0",
"method": "setOracle(address)",
"arguments": [
"0xCd3c40AE1256922BA16C7872229385E20Bc8351e"
],
"description": "Set oracle on EthReserveStabilizer"
},
{
"address": "0x5d6446880fcd004c851ea8920a628c70ca101117",
"values": "0",
"method": "setOracle(address)",
"arguments": [
"0xCd3c40AE1256922BA16C7872229385E20Bc8351e"
],
"description": "Set oracle on EthUniswapPCVDeposit"
},
{
"address": "0x0760dfe09bd6d04d0df9a60c51f01ecedceb5132",
"values": "0",
"method": "setOracle(address)",
"arguments": [
"0xCd3c40AE1256922BA16C7872229385E20Bc8351e"
],
"description": "Set oracle on EthUniswapPCVController"
},
{
"address": "0xe1578B4a32Eaefcd563a9E6d0dc02a4213f673B7",
"values": "0",
"method": "setOracle(address)",
"arguments": [
"0xCd3c40AE1256922BA16C7872229385E20Bc8351e"
],
"description": "Set oracle on EthBondingCurve"
}
],
"proposal_calldata": "0xda95691a00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000a08a721dfb595753fff335636674d76c455b275c0000000000000000000000005d6446880fcd004c851ea8920a628c70ca1011170000000000000000000000000760dfe09bd6d04d0df9a60c51f01ecedceb5132000000000000000000000000e1578b4a32eaefcd563a9e6d0dc02a4213f673b7000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000127365744f7261636c65286164647265737329000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000127365744f7261636c65286164647265737329000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000127365744f7261636c65286164647265737329000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000127365744f7261636c6528616464726573732900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cd3c40ae1256922ba16c7872229385e20bc8351e0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cd3c40ae1256922ba16c7872229385e20bc8351e0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cd3c40ae1256922ba16c7872229385e20bc8351e0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cd3c40ae1256922ba16c7872229385e20bc8351e00000000000000000000000000000000000000000000000000000000000004e84649502d383a2055736520436861696e6c696e6b204f7261636c65200a546869732070726f706f73616c20737769746368657320746865207072696d617279204554482d555344206f7261636c6520746f20436861696e6c696e6b2066726f6d20746865204554482d5553444320545741502063757272656e746c7920757365642e205468697320776f756c6420656e68616e63652061636375726163792c20726564756365206d616e6970756c6174696f6e20726573697374616e636520616e64207265647563652072656c69616e6365206f6e20555344432e0a0a436861696e6c696e6b20686173206120726f62757374206f7261636c65206e6574776f726b2c207768696368206c657665726167657320646174612066726f6d20626f7468206f6e2d20616e64206f66662d636861696e20736f75726365732e204d616e79206f7468657220457468657265756d2070726f6a656374732075736520616e6420636f6c6c6563746976656c7920737570706f72742074686520436861696e6c696e6b204554482f555344206f7261636c652c20696e636c7564696e672053796e7468657469782c20416176652c205365742050726f746f636f6c2c204c6f6f7072696e672c20616e64206d616e79206d6f72652e0a0a426563617573652069742075736573206120353062707320646576696174696f6e207468726573686f6c64206173207472696767657220726174686572207468616e20612073746174696320545741502c2074686520436861696e6c696e6b206f7261636c6520726573706f6e64732066617374657220746f206d61726b657420766f6c6174696c6974792e205468697320776f756c642068656c7020656e68616e6365207468652070656720616e642070726f746f636f6c206d656368616e69736d732e0a0a43757272656e746c79207468652070726f746f636f6c20757365206f7261636c657320696e2064657465726d696e696e673a0a54686520626f6e64696e6720637572766520707572636861736520707269636520666f72204645490a54686520726573657276652073746162696c697a65722073616c6520707269636520666f72204645490a54686520707269636520746f20726577656967687420746f0a54686520736c69707061676520746f6c6572616e6365206f6e20556e697377617020737761707320616e64206c69717569646974792070726f766973696f6e0a0a4164646974696f6e616c6c792c20757067726164696e6720746f20636861696e6c696e6b20776f756c6420736176652067617320666f7220757365727320647572696e67206f7261636c65207570646174657320696e20464549207377617073206f6e20556e697377617020616e64206f746865722070726f746f636f6c20666c6f77732e200a0a546865206f7261636c6520746f20626520757365642069732074686520436861696e6c696e6b4f7261636c6557726170706572207772697474656e2062792040657377616b20686572653a2068747470733a2f2f6769746875622e636f6d2f6665692d70726f746f636f6c2f6665692d70726f746f636f6c2d636f72652f70756c6c2f313030200a466f72756d2044697363757373696f6e3a2068747470733a2f2f74726962652e6665692e6d6f6e65792f742f636861696e6c696e6b2d6f7261636c652d696e746567726174696f6e2d64697363757373696f6e2f33333136000000000000000000000000000000000000000000000000"
}

75 changes: 75 additions & 0 deletions scripts/dao/fip_8.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const EthReserveStabilizer = artifacts.require('EthReserveStabilizer');
const EthBondingCurve = artifacts.require('EthBondingCurve');
const UniswapPCVController = artifacts.require('UniswapPCVController');
const UniswapPCVDeposit = artifacts.require('UniswapPCVDeposit');

const { getAddresses } = require('../utils/helpers');
const { sudo } = require('../utils/sudo');

const {
chainlinkEthUsdOracleWrapper,
ethBondingCurveAddress,
ethReserveStabilizerAddress,
ethUniswapPCVDepositAddress,
ethUniswapPCVControllerAddress
} = getAddresses();

/*
DAO Proposal Steps
1. Set oracle to chainlink on EthBondingCurve
2. Set oracle to chainlink on EthReserveStabilizer
3. Set oracle to chainlink on EthUniswapPCVDeposit
4. Set oracle to chainlink on EthUniswapPCVController
*/

// The steps that don't form part of the proposal but need to be mocked up
async function setup() {
await sudo();
}

// The actual steps in the proposal
async function runProposalSteps() {
const ethBondingCurve = await EthBondingCurve.at(ethBondingCurveAddress);
const ethReserveStabilizer = await EthReserveStabilizer.at(ethReserveStabilizerAddress);
const ethUniswapPCVDeposit = await UniswapPCVDeposit.at(ethUniswapPCVDepositAddress);
const ethUniswapPCVController = await UniswapPCVController.at(ethUniswapPCVControllerAddress);

// 1. Set oracle to chainlink on EthBondingCurve
console.log('Setting oracle on EthBondingCurve');
await ethBondingCurve.setOracle(chainlinkEthUsdOracleWrapper);

// 2. Set oracle to chainlink on EthReserveStabilizer
console.log('Setting oracle on EthReserveStabilizer');
await ethReserveStabilizer.setOracle(chainlinkEthUsdOracleWrapper);

// 3. Set oracle to chainlink on EthUniswapPCVDeposit
console.log('Setting oracle on EthUniswapPCVDeposit');
await ethUniswapPCVDeposit.setOracle(chainlinkEthUsdOracleWrapper);

// 4. Set oracle to chainlink on EthUniswapPCVController
console.log('Setting oracle on EthUniswapPCVController');
await ethUniswapPCVController.setOracle(chainlinkEthUsdOracleWrapper);
}

async function main() {
await setup();
await runProposalSteps();
}

module.exports = { main };

// Run setup
// setup()
// .then(() => process.exit(0))
// .catch((error) => {
// console.error(error);
// process.exit(1);
// });

// Run full script
// main()
// .then(() => process.exit(0))
// .catch((error) => {
// console.error(error);
// process.exit(1);
// });
17 changes: 15 additions & 2 deletions scripts/utils/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ function check(flag, message) {
}
}

// The current version of the contracts in the repo uses readOracle as the api
// The old api was peg(), so the currently deployed contracts need manual calling until the upgrade
async function readOracle(oracleRef, web3) {
const data = await web3.eth.call({to: oracleRef.address, data: web3.eth.abi.encodeFunctionSignature('peg()')});
return (web3.eth.abi.decodeParameter({ Decimal: {value: 'uint256' }}, data))[0];
}

function getAddresses() {
let feiAddress;
let ethUniswapPCVDepositAddress;
Expand All @@ -29,6 +36,8 @@ function getAddresses() {
let wethAddress;
let uniswapRouterAddress;
let uniswapOracleAddress;
let chainlinkEthUsdOracleWrapperAddress;

if (process.env.TESTNET_MODE) {
feiAddress = process.env.RINKEBY_FEI;
ethUniswapPCVDepositAddress = process.env.RINKEBY_ETH_UNISWAP_PCV_DEPOSIT;
Expand All @@ -50,6 +59,7 @@ function getAddresses() {
wethAddress = process.env.RINKEBY_WETH;
uniswapOracleAddress = process.env.RINKEBY_UNISWAP_ORACLE;
uniswapRouterAddress = process.env.RINKEBY_UNISWAP_ROUTER;
chainlinkEthUsdOracleWrapperAddress = process.env.RINKEBY_ETH_USD_CHAINLINK_WRAPPER;
} else {
feiAddress = process.env.MAINNET_FEI;
ethUniswapPCVDepositAddress = process.env.MAINNET_ETH_UNISWAP_PCV_DEPOSIT;
Expand All @@ -71,6 +81,7 @@ function getAddresses() {
wethAddress = process.env.MAINNET_WETH;
uniswapOracleAddress = process.env.MAINNET_UNISWAP_ORACLE;
uniswapRouterAddress = process.env.MAINNET_UNISWAP_ROUTER;
chainlinkEthUsdOracleWrapperAddress = process.env.MAINNET_ETH_USD_CHAINLINK_WRAPPER;
}

return {
Expand All @@ -93,11 +104,13 @@ function getAddresses() {
pcvDripControllerAddress,
wethAddress,
uniswapRouterAddress,
uniswapOracleAddress
uniswapOracleAddress,
chainlinkEthUsdOracleWrapperAddress
};
}

module.exports = {
check,
getAddresses
getAddresses,
readOracle
};
18 changes: 10 additions & 8 deletions scripts/utils/sudo.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const { getAddresses } = require('./helpers');

// Grants Governor, Minter, Burner, and PCVController access to accounts[0]
// Also mints a large amount of FEI to accounts[0]
async function main() {
async function sudo() {
const { coreAddress, feiAddress, timelockAddress } = getAddresses();

// Impersonate the Timelock which has Governor access on-chain
Expand All @@ -28,7 +28,7 @@ async function main() {

// Force ETH to the Timelock to send txs on its behalf
console.log('Deploying ForceEth');
const forceEth = await ForceEth.new({value: '1000000000000000000000'});
const forceEth = await ForceEth.new({value: '1000000000000000000'});

console.log('Forcing ETH to timelock');
await forceEth.forceEth(timelockAddress);
Expand All @@ -44,9 +44,11 @@ async function main() {
await fei.mint(accounts[0], new BN('10000000000000000000000000000000000'));
}

main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
// sudo()
// .then(() => process.exit(0))
// .catch((error) => {
// console.error(error);
// process.exit(1);
// });

module.exports = { sudo };
116 changes: 116 additions & 0 deletions scripts/validation/fip_8.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
const { web3 } = require('hardhat');
const fipEight = require('../dao/fip_8');

const EthReserveStabilizer = artifacts.require('EthReserveStabilizer');
const EthBondingCurve = artifacts.require('EthBondingCurve');
const UniswapPCVController = artifacts.require('UniswapPCVController');
const UniswapPCVDeposit = artifacts.require('UniswapPCVDeposit');
const ChainlinkOracleWrapper = artifacts.require('ChainlinkOracleWrapper');

const { check, getAddresses, readOracle } = require('../utils/helpers');

const {
chainlinkEthUsdOracleWrapperAddress,
ethBondingCurveAddress,
ethReserveStabilizerAddress,
ethUniswapPCVDepositAddress,
ethUniswapPCVControllerAddress
} = getAddresses();

async function getState() {
const chainlinkEthUsdOracleWrapper = await ChainlinkOracleWrapper.at(
chainlinkEthUsdOracleWrapperAddress
);
const ethBondingCurve = await EthBondingCurve.at(ethBondingCurveAddress);
const ethReserveStabilizer = await EthReserveStabilizer.at(ethReserveStabilizerAddress);
const ethUniswapPCVDeposit = await UniswapPCVDeposit.at(ethUniswapPCVDepositAddress);
const ethUniswapPCVController = await UniswapPCVController.at(ethUniswapPCVControllerAddress);

const bondingCurveOracle = await ethBondingCurve.oracle();
const bondingCurveOracleValue = await readOracle(ethBondingCurve, web3);
const stabilizerOracle = await ethReserveStabilizer.oracle();
const stabilizerOracleValue = await readOracle(ethReserveStabilizer, web3);
const uniswapPCVDepositOracle = await ethUniswapPCVDeposit.oracle();
const uniwapPCVDepositOracleValue = await readOracle(ethUniswapPCVDeposit, web3);
const uniswapPCVControllerOracle = await ethUniswapPCVController.oracle();
const uniswapPCVControllerValue = await readOracle(ethUniswapPCVController, web3);

const chainlinkOracleValue = (await chainlinkEthUsdOracleWrapper.read())[0][0];
const chainlinkOracleValid = (await chainlinkEthUsdOracleWrapper.read())[1];
return {
chainlinkOracleValid,
chainlinkOracleValue,
bondingCurveOracle,
bondingCurveOracleValue,
stabilizerOracle,
stabilizerOracleValue,
uniswapPCVDepositOracle,
uniwapPCVDepositOracleValue,
uniswapPCVControllerOracle,
uniswapPCVControllerValue,
};
}

async function validateState(newState) {
const {
chainlinkOracleValid,
chainlinkOracleValue,
bondingCurveOracle,
bondingCurveOracleValue,
stabilizerOracle,
stabilizerOracleValue,
uniswapPCVDepositOracle,
uniwapPCVDepositOracleValue,
uniswapPCVControllerOracle,
uniswapPCVControllerValue,
} = newState;

check(chainlinkOracleValid, 'Chainlink oracle returning invalid');

check(bondingCurveOracle === chainlinkEthUsdOracleWrapperAddress, 'Bonding curve oracle unchanged');
check(stabilizerOracle === chainlinkEthUsdOracleWrapperAddress, 'Stabilizer oracle unchanged');
check(uniswapPCVDepositOracle === chainlinkEthUsdOracleWrapperAddress, 'PCV deposit oracle unchanged');
check(uniswapPCVControllerOracle === chainlinkEthUsdOracleWrapperAddress, 'PCV controller oracle unchanged');

check(bondingCurveOracleValue === chainlinkOracleValue, 'Bonding curve oracle value mismatch');
check(stabilizerOracleValue === chainlinkOracleValue, 'Stabilizer oracle value mismatch');
check(uniwapPCVDepositOracleValue === chainlinkOracleValue, 'PCV deposit oracle value mismatch');
check(uniswapPCVControllerValue === chainlinkOracleValue, 'PCV controller oracle value mismatch');
}

// Runs the fip-8 script with before+after validation
async function fullLocalValidation() { // eslint-disable-line
const stateBeforeFipEight = await getState();
console.log('State before FIP-8:', JSON.stringify(stateBeforeFipEight, null, 2));

console.log('Running FIP-8 execution script...');
await fipEight.main();
console.log('Finished running FIP-8 execution script.');

const stateAfterFipEight = await getState();
console.log('State after FIP-8:', JSON.stringify(stateAfterFipEight, null, 2), '\n');

await validateState(stateAfterFipEight);
}

// Runs validation assuming fip-8 has already been executed
async function postFipValidation() { // eslint-disable-line
const stateAfterFipEight = await getState();
console.log('State after FIP-8:', JSON.stringify(stateAfterFipEight, null, 2), '\n');

await validateState(stateAfterFipEight);
}

// fullLocalValidation()
// .then(() => process.exit(0))
// .catch((error) => {
// console.error(error);
// process.exit(1);
// });

// postFipValidation()
// .then(() => process.exit(0))
// .catch((error) => {
// console.error(error);
// process.exit(1);
// });

0 comments on commit 7f6cbd9

Please sign in to comment.