Skip to content

Commit

Permalink
Merge pull request #96 from fei-protocol/Fixed-Cadence-Reweights
Browse files Browse the repository at this point in the history
Fixed Reweight Cadence
  • Loading branch information
Joeysantoro committed May 23, 2021
2 parents e2934af + 3ed9cc8 commit 00731e4
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 18 deletions.
28 changes: 23 additions & 5 deletions contracts/pcv/EthUniswapPCVController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ import "@openzeppelin/contracts/math/Math.sol";
import "./IUniswapPCVController.sol";
import "../refs/UniRef.sol";
import "../external/UniswapV2Library.sol";
import "../utils/Timed.sol";

/// @title a IUniswapPCVController implementation for ETH
/// @author Fei Protocol
contract EthUniswapPCVController is IUniswapPCVController, UniRef {
contract EthUniswapPCVController is IUniswapPCVController, UniRef, Timed {
using Decimal for Decimal.D256;
using SafeMathCopy for uint256;

uint256 public override reweightWithdrawBPs = 9900;

uint256 internal _reweightDuration = 4 hours;

uint256 internal constant BASIS_POINTS_GRANULARITY = 10000;

/// @notice returns the linked pcv deposit contract
Expand All @@ -40,24 +43,27 @@ contract EthUniswapPCVController is IUniswapPCVController, UniRef {
uint256 _minDistanceForReweightBPs,
address _pair,
address _router
) public UniRef(_core, _pair, _router, _oracle) {
) public UniRef(_core, _pair, _router, _oracle) Timed(_reweightDuration) {
pcvDeposit = IPCVDeposit(_pcvDeposit);

reweightIncentiveAmount = _incentiveAmount;
_minDistanceForReweight = Decimal.ratio(
_minDistanceForReweightBPs,
BASIS_POINTS_GRANULARITY
);

// start timer
_initTimed();
}

receive() external payable {}

/// @notice reweights the linked PCV Deposit to the peg price. Needs to be reweight eligible
function reweight() external override postGenesis whenNotPaused nonContract {
function reweight() external override whenNotPaused {
updateOracle();
require(
reweightEligible(),
"EthUniswapPCVController: Not at incentive parity or not at min distance"
"EthUniswapPCVController: Not passed reweight time or not at min distance"
);
_reweight();
_incentivize();
Expand Down Expand Up @@ -108,12 +114,21 @@ contract EthUniswapPCVController is IUniswapPCVController, UniRef {
emit ReweightMinDistanceUpdate(basisPoints);
}

/// @notice sets the reweight duration
function setDuration(uint256 _duration)
external
override
onlyGovernor
{
_setDuration(_duration);
}

/// @notice signal whether the reweight is available. Must have incentive parity and minimum distance from peg
function reweightEligible() public view override returns (bool) {
bool magnitude =
_getDistanceToPeg().greaterThan(_minDistanceForReweight);
// incentive parity is achieved after a certain time relative to distance from peg
bool time = incentiveContract().isIncentiveParity();
bool time = isTimeEnded();
return magnitude && time;
}

Expand Down Expand Up @@ -146,6 +161,9 @@ contract EthUniswapPCVController is IUniswapPCVController, UniRef {

_burnFeiHeld();

// reset timer
_initTimed();

emit Reweight(msg.sender);
}

Expand Down
2 changes: 2 additions & 0 deletions contracts/pcv/IUniswapPCVController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ interface IUniswapPCVController {

function setPCVDeposit(address _pcvDeposit) external;

function setDuration(uint256 _duration) external;

function setReweightIncentive(uint256 amount) external;

function setReweightMinDistance(uint256 basisPoints) external;
Expand Down
46 changes: 33 additions & 13 deletions test/pcv/EthUniswapPCVController.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ const {
expectEvent,
expectRevert,
balance,
time,
expect,
EthUniswapPCVController,
Fei,
MockBot,
MockPCVDeposit,
MockOracle,
MockPair,
Expand Down Expand Up @@ -150,35 +150,55 @@ describe('EthUniswapPCVController', function () {
});
});

describe('From Contract', function() {
it('reverts', async function() {
let bot = await MockBot.new();
await expectRevert(bot.controllerReweight(this.pcvController.address), "CoreRef: Caller is a contract");
describe('Not yet at time', function () {
beforeEach(async function() {
await this.pair.set(100000, 51000000, LIQUIDITY_INCREMENT, {from: userAddress, value: 100000}); // 510:1 FEI/ETH with 10k liquidity
});
});

describe('Not at incentive parity', function () {
it('reverts', async function() {
await this.pair.set(100000, 51000000, LIQUIDITY_INCREMENT, {from: userAddress, value: 100000}); // 510:1 FEI/ETH with 10k liquidity
expect(await this.pcvController.isTimeEnded()).to.be.equal(false);
expect(await this.pcvController.reweightEligible()).to.be.equal(false);
await expectRevert(this.pcvController.reweight(), "EthUniswapPCVController: Not at incentive parity or not at min distance");
await expectRevert(this.pcvController.reweight(), "EthUniswapPCVController: Not passed reweight time or not at min distance");
})

describe('After time period passes', function() {
beforeEach(async function() {
await time.increase(new BN('14400'));
});

it('Reweight eligible', async function() {
expect(await this.pcvController.isTimeEnded()).to.be.equal(true);
expect(await this.pcvController.reweightEligible()).to.be.equal(true);
});

describe('After Reweight', function() {
beforeEach(async function() {
await this.pcvDeposit.deposit(100000, {value: 100000}); // deposit LP
await this.pcvController.reweight({from: userAddress});
});
it('timer resets', async function() {
expect(await this.pcvController.isTimeEnded()).to.be.equal(false);
expect(await this.pcvController.reweightEligible()).to.be.equal(false);
});
});
});
});

describe('Not at min distance', function () {
it('reverts', async function() {
await this.pair.set(100000, 50400000, LIQUIDITY_INCREMENT, {from: userAddress, value: 100000}); // 504:1 FEI/ETH with 10k liquidity
await this.incentive.setIncentiveParity(true);
await time.increase(new BN('14400'));

expect(await this.pcvController.reweightEligible()).to.be.equal(false);
await expectRevert(this.pcvController.reweight(), "EthUniswapPCVController: Not at incentive parity or not at min distance");
await expectRevert(this.pcvController.reweight(), "EthUniswapPCVController: Not passed reweight time or not at min distance");
})
});

describe('No incentive for caller if controller not minter', function() {
beforeEach(async function() {
await this.pair.set(100000, 51000000, LIQUIDITY_INCREMENT, {from: userAddress, value: 100000}); // 510:1 FEI/ETH with 10k liquidity
await this.pcvDeposit.deposit(100000, {value: 100000}); // deposit LP
await this.incentive.setIncentiveParity(true);
await time.increase(new BN('14400'));
expect(await this.pcvController.reweightEligible()).to.be.equal(true);
await this.pcvController.reweight({from: userAddress});
});
Expand All @@ -199,7 +219,7 @@ describe('EthUniswapPCVController', function () {
beforeEach(async function() {
await this.pair.set(100000, 51000000, LIQUIDITY_INCREMENT, {from: userAddress, value: 100000}); // 490:1 FEI/ETH with 10k liquidity
await this.pcvDeposit.deposit(100000, {value: 100000}); // deposit LP
await this.incentive.setIncentiveParity(true);
await time.increase(new BN('14400'));
await this.core.grantMinter(this.pcvController.address, {from: governorAddress});
expect(await this.pcvController.reweightEligible()).to.be.equal(true);
await this.pcvController.reweight({from: userAddress});
Expand Down

0 comments on commit 00731e4

Please sign in to comment.