Skip to content

Commit

Permalink
Merge pull request #173 from fei-protocol/feat/v2-e2e
Browse files Browse the repository at this point in the history
E2E Tests
  • Loading branch information
Joeysantoro committed Sep 13, 2021
2 parents d9bf115 + 4ba1e6e commit 334306d
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 9 deletions.
6 changes: 3 additions & 3 deletions contracts/pcv/balancer/BalancerLBPSwapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ contract BalancerLBPSwapper is IPCVSwapper, OracleRef, Timed, WeightedBalancerPo
}
// 2. Reset weights to 99:1
// Using current block time triggers immediate weight reset
updateWeightsGradually(
_updateWeightsGradually(
pool,
block.timestamp,
block.timestamp,
Expand Down Expand Up @@ -263,7 +263,7 @@ contract BalancerLBPSwapper is IPCVSwapper, OracleRef, Timed, WeightedBalancerPo
);

// 4. Kick off new auction ending after `duration` seconds
updateWeightsGradually(
_updateWeightsGradually(
pool,
block.timestamp,
block.timestamp + duration,
Expand Down Expand Up @@ -358,7 +358,7 @@ contract BalancerLBPSwapper is IPCVSwapper, OracleRef, Timed, WeightedBalancerPo
);

// Kick off the first auction
updateWeightsGradually(
_updateWeightsGradually(
pool,
block.timestamp,
block.timestamp + duration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ abstract contract WeightedBalancerPoolManager is IWeightedBalancerPoolManager, B
uint256 endTime,
uint256[] memory endWeights
) public override onlyGovernorOrAdmin {
_updateWeightsGradually(pool, startTime, endTime, endWeights);
}

function _updateWeightsGradually(
IWeightedPool pool,
uint256 startTime,
uint256 endTime,
uint256[] memory endWeights
) internal {
pool.updateWeightsGradually(startTime, endTime, endWeights);
}
}
1 change: 1 addition & 0 deletions deploy/v2Phase1.js
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ async function deploy(deployAddress, addresses, logging = false) {
tribeSplitter,
feiTribeLBPSwapper,
pcvEquityMinter,
staticPcvDepositWrapper,
};
}

Expand Down
156 changes: 151 additions & 5 deletions end-to-end/e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import hre, { artifacts, expect, web3 } from 'hardhat'
import { time } from '@openzeppelin/test-helpers';
import { TestEndtoEndCoordinator } from './setup';
import { syncPool } from '../scripts/utils/syncPool'
import { MainnetContractAddresses, MainnetContracts } from './setup/types';
import { getPeg, getPrice, forceEth } from './setup/utils'
import { BN, expectApprox, expectRevert, expectEvent } from '../test/helpers'
import { forceEth } from './setup/utils'
import { BN, expectApprox, expectEvent } from '../test/helpers'
import proposals from './proposals_config.json'

const ERC20 = artifacts.require("ERC20");
const FToken = artifacts.require("contracts/external/CToken.sol:CToken");
const uintMax = '115792089237316195423570985008687907853269984665640564039457584007913129639935';

const { toBN } = web3.utils;
Expand Down Expand Up @@ -43,6 +40,155 @@ describe('e2e', function () {
await contracts.uniswapPCVDeposit.deposit()
})

describe('Collateralization Oracle', async function () {
it('exempting an address removes from PCV stats', async function () {
const {collateralizationOracle, compoundEthPCVDeposit } = contracts;

const beforeBalance = await compoundEthPCVDeposit.balance();

const beforeStats = await collateralizationOracle.pcvStats();
await collateralizationOracle.setDepositExclusion(compoundEthPCVDeposit.address, true);
const afterStats = await collateralizationOracle.pcvStats();

expectApprox(afterStats[0], beforeStats[0].sub(beforeBalance));
expectApprox(afterStats[1], afterStats[1]);
expectApprox(afterStats[2], beforeStats[2].sub(beforeBalance));
});
});

describe('Collateralization Oracle Keeper', async function () {
it('can only call when deviation or time met', async function () {
const { staticPcvDepositWrapper, collateralizationOracleWrapper, collateralizationOracleKeeper, fei } = contracts;

const beforeBalance = await fei.balanceOf(deployAddress);

await collateralizationOracleWrapper.update();

// After updating everything should be up to date
expect(await collateralizationOracleWrapper.isOutdatedOrExceededDeviationThreshold()).to.be.false;

// After time increase, should be outdated
await time.increase(await collateralizationOracleWrapper.remainingTime());

expect(await collateralizationOracleWrapper.isOutdatedOrExceededDeviationThreshold()).to.be.true;
expect(await collateralizationOracleWrapper.isOutdated()).to.be.true;
expect(await collateralizationOracleWrapper.isExceededDeviationThreshold()).to.be.false;

// UpdateIfOutdated succeeds
await collateralizationOracleWrapper.updateIfOutdated({from: deployAddress});

expect(await collateralizationOracleWrapper.isOutdatedOrExceededDeviationThreshold()).to.be.false;

// Increase PCV balance to exceed deviation threshold
const pcvStats = await collateralizationOracleWrapper.pcvStats();
await staticPcvDepositWrapper.setBalance(pcvStats[0]);

expect(await collateralizationOracleWrapper.isOutdatedOrExceededDeviationThreshold()).to.be.true;
expect(await collateralizationOracleWrapper.isOutdated()).to.be.false;
expect(await collateralizationOracleWrapper.isExceededDeviationThreshold()).to.be.true;

// Keeper is incentivized to update oracle
await time.increase(await collateralizationOracleKeeper.MIN_MINT_FREQUENCY());
await collateralizationOracleKeeper.mint({from: deployAddress});

const incentive = await collateralizationOracleKeeper.incentiveAmount();
expect(beforeBalance.add(incentive)).to.be.bignumber.equal(await fei.balanceOf(deployAddress));

expect(await collateralizationOracleWrapper.isOutdatedOrExceededDeviationThreshold()).to.be.false;
});
});

describe('TribeReserveStabilizer', async function() {
it('mint TRIBE', async function () {
const { tribeReserveStabilizer, tribe } = contracts;
const tribeSupply = await tribe.totalSupply();
const balanceBefore = await tribe.balanceOf(deployAddress);

await tribeReserveStabilizer.mint(deployAddress, '100000');

// Minting increases total supply and target balance
expect(balanceBefore.add(new BN('100000'))).to.be.bignumber.equal(await tribe.balanceOf(deployAddress));
expect(tribeSupply.add(new BN('100000'))).to.be.bignumber.equal(await tribe.totalSupply());
});

it('exchangeFei', async function () {
const { fei, staticPcvDepositWrapper, tribe, tribeReserveStabilizer, collateralizationOracleWrapper } = contracts;

await fei.mint(deployAddress, tenPow18.mul(tenPow18).mul(toBN(4)));
await collateralizationOracleWrapper.update();

const userFeiBalanceBefore = toBN(await fei.balanceOf(deployAddress));
const userTribeBalanceBefore = await tribe.balanceOf(deployAddress);

const feiTokensExchange = toBN(40000000000000)
await tribeReserveStabilizer.updateOracle();
const expectedAmountOut = await tribeReserveStabilizer.getAmountOut(feiTokensExchange);
await tribeReserveStabilizer.exchangeFei(feiTokensExchange);

const userFeiBalanceAfter = toBN(await fei.balanceOf(deployAddress))
const userTribeBalanceAfter = await tribe.balanceOf(deployAddress);

expect(userTribeBalanceAfter.sub(toBN(expectedAmountOut))).to.be.bignumber.equal(userTribeBalanceBefore);
expect(userFeiBalanceAfter).to.be.bignumber.equal(userFeiBalanceBefore.sub(feiTokensExchange));

await staticPcvDepositWrapper.setBalance(tenPow18.mul(tenPow18).mul(toBN(10)));
await collateralizationOracleWrapper.update();
expect(await tribeReserveStabilizer.isCollateralizationBelowThreshold()).to.be.false;
});
});

describe('PCV Equity Minter + LBP', async function() {
it('mints appropriate amount and swaps', async function() {
const { pcvEquityMinter, collateralizationOracleWrapper, staticPcvDepositWrapper, feiTribeLBPSwapper, tribe, tribeSplitter } = contracts;

await time.increase(await pcvEquityMinter.remainingTime());

const pcvStats = await collateralizationOracleWrapper.pcvStats();
await staticPcvDepositWrapper.setBalance(pcvStats[0]);
await collateralizationOracleWrapper.update();

const mintAmount = await pcvEquityMinter.mintAmount();

const balancesBefore = await feiTribeLBPSwapper.getReserves();

const splitterBalanceBefore = await tribe.balanceOf(tribeSplitter.address);

await pcvEquityMinter.mint();

const balancesAfter = await feiTribeLBPSwapper.getReserves();

expectApprox(balancesBefore[0].add(mintAmount), balancesAfter[0]);
expect(await feiTribeLBPSwapper.swapEndTime()).to.be.bignumber.greaterThan(toBN(await time.latest()));

await time.increase(await pcvEquityMinter.duration());
await pcvEquityMinter.mint();

expect(await tribe.balanceOf(tribeSplitter.address)).to.be.bignumber.greaterThan(splitterBalanceBefore);
});
});

describe('TRIBE Splitter', async function () {
it('splits TRIBE 3 ways', async function () {
const { tribeSplitter, tribeReserveStabilizer, tribe, erc20Dripper, core } = contracts;

await core.allocateTribe(tribeSplitter.address, '1000000');

const beforeBalanceStabilizer = await tribe.balanceOf(tribeReserveStabilizer.address);
const beforeBalanceDripper = await tribe.balanceOf(erc20Dripper.address);
const beforeBalanceCore = await tribe.balanceOf(core.address);

await tribeSplitter.allocate();

const afterBalanceStabilizer = await tribe.balanceOf(tribeReserveStabilizer.address);
const afterBalanceDripper = await tribe.balanceOf(erc20Dripper.address);
const afterBalanceCore = await tribe.balanceOf(core.address);

expectApprox(beforeBalanceStabilizer, afterBalanceStabilizer.sub(new BN('600000')));
expectApprox(beforeBalanceDripper, afterBalanceDripper.sub(new BN('200000')));
expectApprox(beforeBalanceCore, afterBalanceCore.sub(new BN('200000')));
});
});

describe('BondingCurve', async () => {
describe('ETH', async function () {
beforeEach(async function () {
Expand Down
8 changes: 8 additions & 0 deletions end-to-end/setup/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ export type MainnetContracts = {
curve3Metapool: typeof Contract,
erc20Dripper: typeof Contract,
tribalChiefOptimisticTimelock: typeof Contract,
staticPcvDepositWrapper: typeof Contract,
collateralizationOracle: typeof Contract,
collateralizationOracleWrapper: typeof Contract,
collateralizationOracleKeeper: typeof Contract,
tribeReserveStabilizerAddress: typeof Contract,
pcvEquityMinter: typeof Contract,
tribeSplitter: typeof Contract,
feiTribeLBPSwapper: typeof Contract,
}

export type MainnetContractAddresses = {
Expand Down
7 changes: 6 additions & 1 deletion proposals/dao/v2Phase1.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const { constants: { MAX_UINT256 } } = require('@openzeppelin/test-helpers');
const { expect } = require('../../test/helpers');

const e18 = '000000000000000000';

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

/*
Expand All @@ -16,7 +18,7 @@ V2 Phase 1 Upgrade Steps
9. Set ETH Bonding Curve Minting Cap Max
10. Move PCV from old ETH Uni PCV Deposit to new
11. Move PCV from old DPI Uni PCV Deposit to new
12. TODO: Seed TRIBE to LBP Swapper
12. Seed TRIBE to LBP Swapper
*/
async function run(addresses, oldContracts, contracts, logging = false) {
const {
Expand All @@ -31,6 +33,7 @@ async function run(addresses, oldContracts, contracts, logging = false) {
ratioPCVController,
pcvEquityMinter,
collateralizationOracleKeeper,
feiTribeLBPSwapper,
core,
tribe
} = contracts;
Expand Down Expand Up @@ -68,6 +71,8 @@ async function run(addresses, oldContracts, contracts, logging = false) {
await oldRatioPCVController.withdrawRatio(oldContracts.uniswapPCVDeposit.address, uniswapPCVDeposit.address, '10000'); // move 100% of PCV from old -> new

await ratioPCVController.withdrawRatio(oldContracts.dpiUniswapPCVDeposit.address, dpiUniswapPCVDeposit.address, '10000'); // move 100% of PCV from old -> new

await core.allocateTribe(feiTribeLBPSwapper.address, `1000000${e18}`);
}

/// / --------------------- NOT RUN ON CHAIN ----------------------
Expand Down

0 comments on commit 334306d

Please sign in to comment.