Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions contract-addresses/mainnetAddresses.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
"uniswapPCVControllerAddress": { "artifact": "UniswapPCVController", "address": "0x0760dfe09bd6d04d0df9a60c51f01ecedceb5132"},
"bondingCurveAddress": { "artifact": "BondingCurve", "address": "0xe1578B4a32Eaefcd563a9E6d0dc02a4213f673B7"},
"dpiBondingCurveAddress": { "artifact": "BondingCurve", "address": "0xBf5721c5E1C370f6F1A3E21b3972E0AcE93A1E84"},
"daiBondingCurveAddress": { "artifact": "BondingCurve", "address": "0xC0afe0E649e32528666F993ce63822c3840e941a"},
"compositeOracleAddress": { "artifact": "CompositeOracle", "address": "0x8721f9EAba0B9081069970bCBce38763D3D4f28E"},
"chainlinkEthUsdOracleWrapperAddress": { "artifact": "ChainlinkOracleWrapper", "address": "0xCd3c40AE1256922BA16C7872229385E20Bc8351e"},
"chainlinkFeiEthOracleWrapperAddress": { "artifact": "ChainlinkOracleWrapper", "address": "0x060Be7B51F78DFFd04749332fd306BA1228e7444"},
"chainlinkDpiUsdOracleWrapperAddress": { "artifact": "ChainlinkOracleWrapper", "address": "0xB594d2bd55Ede471e16b92AE6F7651648DA871c3"},
"chainlinkDaiUsdOracleWrapperAddress": { "artifact": "ChainlinkOracleWrapper", "address": "0x231aDa12E273eDf3fA54CbD90c5C1a73129D5bb9"},
"ethReserveStabilizerAddress": { "artifact": "EthReserveStabilizer", "address": "0xa08A721dFB595753FFf335636674D76C455B275C"},
"ratioPCVControllerAddress": { "artifact": "RatioPCVController", "address": "0xfC1aD6eb84351597cD3b9B65179633697d65B920"},
"uniswapOracleAddress": { "artifact": "UniswapOracle", "address": "0x087F35bd241e41Fc28E43f0E8C58d283DD55bD65"},
Expand All @@ -36,11 +38,14 @@
"indexDelegatorAddress" : { "artifact": "SnapshotDelegatorPCVDeposit", "address": "0x0ee81df08B20e4f9E0F534e50da437D24491c4ee" },
"defiPulseOTCAddress" : { "address" : "0x673d140eed36385cb784e279f8759f495c97cf03" },
"compoundEthAddress" : { "address" : "0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5" },
"compoundDaiAddress" : { "address" : "0x5d3a536e4d6dbd6114cc1ead35777bab948e3643"},
"compoundEthPCVDepositAddress" : { "artifact" : "EthCompoundPCVDeposit", "address" : "0x4fCB1435fD42CE7ce7Af3cB2e98289F79d2962b3" },
"compoundDaiPCVDepositAddress" : { "artifact": "ERC20CompoundPCVDeposit", "address" : "0xe0f73b8d76D2Ad33492F995af218b03564b8Ce20"},
"communalFarmAddress" : { "address": "0x0639076265e9f88542C91DCdEda65127974A5CA5"},
"uniswapRouterAddress": { "address": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"},
"sushiswapRouterAddress" : { "address": "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F"},
"chainlinkDpiUsdOracleAddress": { "address": "0xD2A593BF7594aCE1faD597adb697b5645d5edDB2"},
"chainlinkDaiUsdOracleAddress": { "address": "0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9"},
"chainlinkEthUsdOracleAddress": { "address": "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"},
"chainlinkFeiEthOracleAddress": { "address": "0x7F0D2c2838c6AC24443d13e23d99490017bDe370"},
"rariPool8ComptrollerAddress": { "address": "0xc54172e34046c1653d1920d40333dd358c7a1af4"},
Expand All @@ -61,6 +66,7 @@
"creamFeiPCVDepositAddress" : { "artifact" : "ERC20CompoundPCVDeposit", "address": "0x243C601CC5DaA3Ac250B14509804188347bd2aFB" },
"poolPartyFeiPCVDepositAddress" : { "artifact" : "ERC20CompoundPCVDeposit", "address": "0x5A8CB4556e5D5935Af06beab8292905f48131479" },
"dpiAddress" : {"artifact" : "IERC20", "address" : "0x1494CA1F11D487c2bBe4543E90080AeBa4BA3C2b"},
"daiAddress" : {"artifact" : "IERC20", "address" : "0x6B175474E89094C44Da98b954EedeAC495271d0F"},
"sushiswapDpiFeiAddress" : {"artifact" : "IUniswapV2Pair", "address": "0x8775aE5e83BC5D926b6277579c2B0d40c7D9b528" },
"indexCoopFusePoolDpiAddress" : {"artifact" : "CErc20Delegator", "address" : "0xf06f65a6b7d2c401fcb8b3273d036d21fe2a5963"},
"indexCoopFusePoolDpiPCVDepositAddress" : { "artifact" : "ERC20CompoundPCVDeposit", "address" : "0x3dD3d945C4253bAc5B4Cc326a001B7d3f9C4DD66" },
Expand Down
1 change: 1 addition & 0 deletions contract-addresses/permissions.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"timelockAddress",
"pcvDripControllerAddress",
"dpiBondingCurveAddress",
"daiBondingCurveAddress",
"dpiUniswapPCVDepositAddress"
],
"burner": [
Expand Down
60 changes: 60 additions & 0 deletions deploy/fip_10a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const ChainlinkOracleWrapper = artifacts.require('ChainlinkOracleWrapper');
const ERC20CompoundPCVDeposit = artifacts.require('ERC20CompoundPCVDeposit');
const BondingCurve = artifacts.require('BondingCurve');

const e18 = '000000000000000000';

async function deploy(deployAddress, addresses, logging = false) {
const {
coreAddress,
chainlinkDaiUsdOracleAddress,
daiAddress,
compoundDaiAddress,
} = addresses;

if (
!coreAddress || !chainlinkDaiUsdOracleAddress || !daiAddress || !compoundDaiAddress
) {
throw new Error('An environment variable contract address is not set');
}

const chainlinkDaiUsdOracleWrapper = await ChainlinkOracleWrapper.new(
coreAddress,
chainlinkDaiUsdOracleAddress,
{ from: deployAddress }
);

logging ? console.log('DAI Oracle Wrapper deployed to: ', chainlinkDaiUsdOracleWrapper.address) : undefined;

const compoundDaiPCVDeposit = await ERC20CompoundPCVDeposit.new(
coreAddress,
compoundDaiAddress,
daiAddress,
{ from: deployAddress }
);

logging ? console.log('DAI ERC20CompoundPCVDeposit deployed to: ', compoundDaiPCVDeposit.address) : undefined;

const daiBondingCurve = await BondingCurve.new(
coreAddress,
chainlinkDaiUsdOracleWrapper.address,
chainlinkDaiUsdOracleWrapper.address,
`50000000${e18}`, // 50M Scale
[compoundDaiPCVDeposit.address],
[10000], // 100% to compound
604800, // 1 week between incentives
`100${e18}`, // 100 FEI reward
daiAddress,
30, // pre-scale discount .30%
100 // post-scale buffer 1%
);
logging ? console.log('DAI Bonding Curve deployed to: ', daiBondingCurve.address) : undefined;

return {
chainlinkDaiUsdOracleWrapper,
compoundDaiPCVDeposit,
daiBondingCurve,
};
}

module.exports = { deploy };
52 changes: 52 additions & 0 deletions end-to-end/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,58 @@ describe('e2e', function () {
await expectApprox(fuseBalanceAfter.sub(fuseBalanceBefore), allocatedDpi.div(toBN(10)), '100')
})
});

describe('DAI', async function () {
beforeEach(async function () {
// Acquire DAI
await hre.network.provider.request({
method: 'hardhat_impersonateAccount',
params: [contractAddresses.compoundDaiAddress]
});
const daiSeedAmount = tenPow18.mul(toBN(1000000)); // 1M DAI
await forceEth(contractAddresses.compoundDaiAddress);
await contracts.dai.transfer(deployAddress, daiSeedAmount, {from: contractAddresses.compoundDaiAddress});
})

it('should allow purchase of Fei through bonding curve', async function () {
const bondingCurve = contracts.daiBondingCurve;
const fei = contracts.fei;
const feiBalanceBefore = await fei.balanceOf(deployAddress);

const daiAmount = tenPow18.mul(toBN(1000000));; // 1M DAI
const oraclePrice = toBN((await bondingCurve.readOracle())[0]);
const currentPrice = toBN((await bondingCurve.getCurrentPrice())[0]);

// expected = amountIn * oracle * price (Note: there is an edge case when crossing scale where this is not true)
const expected = daiAmount.mul(oraclePrice).mul(currentPrice).div(tenPow18).div(tenPow18);

await contracts.dai.approve(bondingCurve.address, daiAmount);
await bondingCurve.purchase(deployAddress, daiAmount);

const feiBalanceAfter = await fei.balanceOf(deployAddress);
const expectedFinalBalance = feiBalanceBefore.add(expected);
expect(feiBalanceAfter).to.be.bignumber.equal(expectedFinalBalance);
})

it('should transfer allocation from bonding curve to the compound deposit', async function () {
const bondingCurve = contracts.daiBondingCurve;
const compoundPCVDeposit = contracts.compoundDaiPCVDeposit;

const pcvAllocations = await bondingCurve.getAllocation();
expect(pcvAllocations[0].length).to.be.equal(1);

const pcvDepositBefore = await compoundPCVDeposit.balance();

const allocatedDai = await bondingCurve.balance();
await bondingCurve.allocate();

const curveBalanceAfter = await bondingCurve.balance();
await expectApprox(curveBalanceAfter, toBN(0), '100')

const pcvDepositAfter = await compoundPCVDeposit.balance();
await expectApprox(pcvDepositAfter.sub(pcvDepositBefore), allocatedDai, '100');
})
});
});

it('should be able to redeem Fei from stabiliser', async function () {
Expand Down
4 changes: 4 additions & 0 deletions end-to-end/setup/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@ export type MainnetContracts = {
rariPool8FeiPCVDeposit: typeof Contract,
rariPool8EthPCVDeposit: typeof Contract,
compoundEthPCVDeposit: typeof Contract,
compoundDaiPCVDeposit: typeof Contract,
aaveEthPCVDeposit: typeof Contract,
stAAVE: typeof Contract,
dpiBondingCurve: typeof Contract,
daiBondingCurve: typeof Contract,
dpi: typeof Contract,
dai: typeof Contract,
chainlinkDpiUsdOracleWrapper: typeof Contract,
dpiUniswapPCVDeposit: typeof Contract,
indexCoopFusePoolDpiPCVDeposit: typeof Contract,
Expand All @@ -58,6 +61,7 @@ export type MainnetContractAddresses = {
chainlinkEthUsdOracleAddress: string,
chainlinkFeiEthOracleAddress: string,
compositeOracleAddress: string
compoundDaiAddress: string,
ethReserveStabilizerAddress: string,
ratioPCVControllerAddress: string,
wethAddress: string,
Expand Down
2 changes: 1 addition & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const config: HardhatUserConfig = {
chainId: 5777, // Any network (default: none)
forking: {
url: `https://eth-mainnet.alchemyapi.io/v2/${mainnetAlchemyApiKey}`,
blockNumber: 13019420
blockNumber: 13051100
}
},
localhost: {
Expand Down
16 changes: 8 additions & 8 deletions proposals/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
"proposerAddress" : "",
"voterAddress" : ""
},
"indexOTC" : {
"aavePcvDeposit" : {
"deploy" : true,
"validate" : false,
"exec" : false
},
"fip_10a" : {
"deploy" : false,
"validate" : true,
"validate" : false,
"exec" : true,
"proposerAddress" : "0xe0ac4559739bD36f0913FB0A3f5bFC19BCBaCD52",
"proposerAddress" : "0x6ef71ca9cd708883e129559f5edbfb9d9d5c6148",
"voterAddress" : "0xB8f482539F2d3Ae2C9ea6076894df36D1f632775",
"proposal_calldata" : ""
},
"aavePCVDeposit" : {
"deploy" : true,
"exec" : false,
"validate" : false
}
}
25 changes: 25 additions & 0 deletions proposals/dao/fip_10a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const { web3 } = require('hardhat');

const e18 = '000000000000000000';

async function setup(addresses, oldContracts, contracts, logging) {}

/*
1. Make DAI bonding curve a minter
*/
async function run(addresses, oldContracts, contracts, logging = false) {
const {
core,
daiBondingCurve
} = contracts;

core.grantMinter(daiBondingCurve.address);
}

async function teardown(addresses, oldContracts, contracts, logging) {}

async function validate(addresses, oldContracts, contracts) {}

module.exports = {
setup, run, teardown, validate
};
16 changes: 16 additions & 0 deletions proposals/description/fip_10a.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"proposal_title": "FIP-10a: Add DAI Bonding Curve",
"proposal_description_link": "",
"proposal_commands": [
{
"address": "0x8d5ED43dCa8C2F7dFB20CF7b53CC7E593635d7b9",
"values": "0",
"method": "grantMinter(address)",
"arguments": [
"0xC0afe0E649e32528666F993ce63822c3840e941a"
],
"description": "Grant Minter to DAI Bonding Curve"
}
],
"proposal_calldata": "0xda95691a00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000008d5ed43dca8c2f7dfb20cf7b53cc7e593635d7b9000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000146772616e744d696e746572286164647265737329000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000c0afe0e649e32528666f993ce63822c3840e941a000000000000000000000000000000000000000000000000000000000000057b4649502d3130613a2044414920426f6e64696e67204375727665200a4649502d3130610a0a54686520666f6c6c6f77696e6720697320612070726f706f73616c20746f206f70656e206120626f6e64696e6720637572766520666f72204441492c2077697468206120746172676574207363616c6520616e6420636170206f662035304d204645492c206174206120646973636f756e74206f6620302e33252e205468697320776f756c6420616464207e34392e38354d2044414920746f20746865205043562c20616e642072656c6561736520757020746f2035304d2046454920696e746f2063697263756c6174696f6e2e0a0a506f737369626c6520696e74656e64656420667574757265206465706c6f796d656e74202870656e64696e672063757272656e7420262066757475726520636f646520646576656c6f706d656e7420616e64206120766f74652920666f7220746869732044414920617265203a0a2d2050726f766964696e67206c697175696469747920696e2074686520437572766520464549206d657461706f6f6c0a2d2050726f766964696e67206c6971756964697479206f6e20556e697377617020763320616761696e7374204441490a2d204465706c6f79696e672044414920746f20416176652c2074686520466569526172692c206f72206c656176696e6720697420696e20436f6d706f756e640a0a5468657365206465706c6f796d656e74732077696c6c206861766520746f20626520617070726f76656420696e20612073657061726174652070726f706f73616c2c206f6e636520776520686176652061637175697265642044414920696e20746865205043562e20546869732070726f706f73616c20697320612070726572657175697369746520746f20616e792050435620616374696f6e20696e766f6c76696e67204441492e2057616974696e6720666f7220746865206e65787420766f74652873292c20746865204441492061637175697265642077696c6c2062652074656d706f726172696c79206465706f7369746564206f6e20436f6d706f756e642c207969656c64696e672061726f756e64207e336b2044414920706572206461792c20706c7573207e312e356b24206f6620434f4d5020706572206461792061742063757272656e742072617465732e0a0a426f6e64696e6720637572766520706172616d6574657273203a0a2d205363616c653a2035304d204645490a2d204d696e744361703a2035304d204645490a2d205072652d7363616c6520646973636f756e743a20302e33250a2d20506f73742d7363616c65207072656d69756d3a2031250a2d204f7261636c653a20436861696e6c696e6b204441492d5553442028322520646576696174696f6e207468726573686f6c64290a2d204b656570657220696e63656e7469766520616d6f756e743a20313030204645490a2d204b656570657220696e63656e74697665206672657175656e63793a2036303438303073202831207765656b290a2d20416c6c206f66207468652044414920504356207261697365642077696c6c206265206465706f7369746564206f6e20436f6d706f756e640a0a536e617073686f74203a2068747470733a2f2f736e617073686f742e6f72672f232f6665692e6574682f70726f706f73616c2f516d546a35636e4b623467754d646a51534e70587175355644746935526563526672324c76794d55686a6f6b79700a466f72756d203a2068747470733a2f2f74726962652e6665692e6d6f6e65792f742f6669702d31302d63757276652d696e746567726174696f6e2f333334322f32360a50756c6c2072657175657374203a2068747470733a2f2f6769746875622e636f6d2f6665692d70726f746f636f6c2f6665692d70726f746f636f6c2d636f72652f70756c6c2f3133310000000000"
}