Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DIP-16: Moving main LP pool and oracle from Uniswap to Sushiswap 🍣 #2

Merged
merged 14 commits into from Mar 31, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
@@ -0,0 +1,2 @@
INFURA_KEY=
MNEMONIC=
8 changes: 8 additions & 0 deletions README.md
Expand Up @@ -5,6 +5,14 @@
- `yarn install`
- `yarn compile`

## deploy

copy .env and add own env variables

- `cp .env.example .env`

run deployment script
- `yarn deploy:[network]`
## test

- `yarn test`
Expand Down
38 changes: 17 additions & 21 deletions contracts/Constants.sol
Expand Up @@ -53,7 +53,7 @@ library Constants {
uint256 private constant GOVERNANCE_EMERGENCY_DELAY = 6; // 6 epochs

/* DAO */
uint256 private constant ADVANCE_INCENTIVE = 150e18; // 150 DSD
uint256 private constant ADVANCE_INCENTIVE_PREMIUM = 125e16; // pay out 25% more than tx fee value
uint256 private constant DAO_EXIT_LOCKUP_EPOCHS = 36; // 36 epochs fluid

/* Pool */
Expand All @@ -77,7 +77,7 @@ library Constants {
/* Deployed */
address private constant DAO_ADDRESS = address(0x6Bf977ED1A09214E6209F4EA5f525261f1A2690a);
address private constant DOLLAR_ADDRESS = address(0xBD2F0Cd039E0BFcf88901C98c0bFAc5ab27566e3);
address private constant PAIR_ADDRESS = address(0x66e33d2605c5fB25eBb7cd7528E7997b0afA55E8);
address private constant PAIR_ADDRESS = address(0x26d8151e631608570F3c28bec769C3AfEE0d73a3); // SushiSwap pair
address private constant TREASURY_ADDRESS = address(0xC7DA8087b8BA11f0892f1B0BFacfD44C116B303e);

/**
Expand All @@ -92,11 +92,7 @@ library Constants {
}

function getEpochStrategy() internal pure returns (EpochStrategy memory) {
return EpochStrategy({
offset: EPOCH_OFFSET,
start: EPOCH_START,
period: EPOCH_PERIOD
});
return EpochStrategy({ offset: EPOCH_OFFSET, start: EPOCH_START, period: EPOCH_PERIOD });
}

function getInitialStakeMultiple() internal pure returns (uint256) {
Expand All @@ -108,31 +104,31 @@ library Constants {
}

function getBootstrappingPrice() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: BOOTSTRAPPING_PRICE});
return Decimal.D256({ value: BOOTSTRAPPING_PRICE });
}

function getGovernancePeriod() internal pure returns (uint256) {
return GOVERNANCE_PERIOD;
}

function getGovernanceQuorum() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: GOVERNANCE_QUORUM});
return Decimal.D256({ value: GOVERNANCE_QUORUM });
}

function getGovernanceProposalThreshold() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: GOVERNANCE_PROPOSAL_THRESHOLD});
return Decimal.D256({ value: GOVERNANCE_PROPOSAL_THRESHOLD });
}

function getGovernanceSuperMajority() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: GOVERNANCE_SUPER_MAJORITY});
return Decimal.D256({ value: GOVERNANCE_SUPER_MAJORITY });
}

function getGovernanceEmergencyDelay() internal pure returns (uint256) {
return GOVERNANCE_EMERGENCY_DELAY;
}

function getAdvanceIncentive() internal pure returns (uint256) {
return ADVANCE_INCENTIVE;
function getAdvanceIncentivePremium() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({ value: ADVANCE_INCENTIVE_PREMIUM });
}

function getDAOExitLockupEpochs() internal pure returns (uint256) {
Expand All @@ -148,35 +144,35 @@ library Constants {
}

function getDebtRatioCap() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: DEBT_RATIO_CAP});
return Decimal.D256({ value: DEBT_RATIO_CAP });
}

function getInitialCouponRedemptionPenalty() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: INITIAL_COUPON_REDEMPTION_PENALTY});
return Decimal.D256({ value: INITIAL_COUPON_REDEMPTION_PENALTY });
}

function getCouponRedemptionPenaltyDecay() internal pure returns (uint256) {
return COUPON_REDEMPTION_PENALTY_DECAY;
}

function getSupplyChangeLimit() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: SUPPLY_CHANGE_LIMIT});
return Decimal.D256({ value: SUPPLY_CHANGE_LIMIT });
}

function getSupplyChangeDivisor() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: SUPPLY_CHANGE_DIVISOR});
return Decimal.D256({ value: SUPPLY_CHANGE_DIVISOR });
}

function getCouponSupplyChangeLimit() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: COUPON_SUPPLY_CHANGE_LIMIT});
return Decimal.D256({ value: COUPON_SUPPLY_CHANGE_LIMIT });
}

function getCouponSupplyChangeDivisor() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: COUPON_SUPPLY_CHANGE_DIVISOR});
return Decimal.D256({ value: COUPON_SUPPLY_CHANGE_DIVISOR });
}

function getNegativeSupplyChangeDivisor() internal pure returns (Decimal.D256 memory) {
return Decimal.D256({value: NEGATIVE_SUPPLY_CHANGE_DIVISOR});
return Decimal.D256({ value: NEGATIVE_SUPPLY_CHANGE_DIVISOR });
}

function getOraclePoolRatio() internal pure returns (uint256) {
Expand Down
57 changes: 0 additions & 57 deletions contracts/dao/Deployer.sol

This file was deleted.

18 changes: 10 additions & 8 deletions contracts/dao/Getters.sol
Expand Up @@ -64,7 +64,11 @@ contract Getters is State {
}

function oracle() public view returns (IOracle) {
return _state.provider.oracle;
if (epoch() < _state16.epochStartForSushiswapPool) {
return _state16.legacyOracle;
} else {
return _state.provider.oracle;
}
}

function pool() public view returns (address) {
Expand Down Expand Up @@ -99,6 +103,10 @@ contract Getters is State {
return dollar().totalSupply().sub(totalDebt());
}

function getPrice() public view returns (Decimal.D256 memory price) {
return _state13.price;
}

/**
* Account
*/
Expand All @@ -116,9 +124,6 @@ contract Getters is State {
}

function balanceOfCoupons(address account, uint256 epoch) public view returns (uint256) {
if (outstandingCoupons(epoch) == 0) {
return 0;
}
return _state.accounts[account].coupons[epoch];
}

Expand Down Expand Up @@ -161,10 +166,7 @@ contract Getters is State {
}

function epochTimeWithStrategy(Constants.EpochStrategy memory strategy) private view returns (uint256) {
return blockTimestamp()
.sub(strategy.start)
.div(strategy.period)
.add(strategy.offset);
return blockTimestamp().sub(strategy.start).div(strategy.period).add(strategy.offset);
}

// Overridable for testing
Expand Down
2 changes: 1 addition & 1 deletion contracts/dao/Govern.sol
Expand Up @@ -102,7 +102,7 @@ contract Govern is Setters, Permission, Upgradeable {
Require.that(
Decimal.ratio(votesFor(candidate), totalBondedAt(endsAfter)).greaterThan(Constants.getGovernanceQuorum()),
FILE,
"Must have quorom"
"Must have quorum"
);

Require.that(
Expand Down
48 changes: 39 additions & 9 deletions contracts/dao/Implementation.sol
Expand Up @@ -23,19 +23,27 @@ import "./Regulator.sol";
import "./Bonding.sol";
import "./Govern.sol";
import "../Constants.sol";
import "../external/AggregatorV3Interface.sol";

contract Implementation is State, Bonding, Market, Regulator, Govern {
using SafeMath for uint256;

event Advance(uint256 indexed epoch, uint256 block, uint256 timestamp);
event Incentivization(address indexed account, uint256 amount);

function initialize() initializer public {
// committer reward:
mintToAccount(msg.sender, 150e18); // 150 DSD to committer
// contributor rewards:
mintToAccount(0xF414CFf71eCC35320Df0BB577E3Bc9B69c9E1f07, 1000e18); // 1000 DSD to devnull
function initialize() public initializer {
_state16.epochStartForSushiswapPool = epoch() + 2;
_state16.legacyOracle = _state.provider.oracle; // legacy uniswap pool oracle

_state.provider.oracle = IOracle(address(0xb79E640B59062382c450D2F60f845C050cDd2986)); // new sushiswap oracle
_state.provider.oracle.setup(); // setup oracle
_state.provider.oracle.capture(); // capture for pool price on sushi pool

_state.provider.pool = address(0xf929fc6eC25850ce00e457c4F28cDE88A94415D8); // new sushiswap LP staking pool

mintToAccount(0x437cb43D08F64AF2aA64AD2525FE1074E282EC19, 2000e18); // 2000 DSD to gus
mintToAccount(0x35F32d099fb9E08b706A6fa41D639EEB69F8A906, 2000e18); // 2000 DSD to degendegen9
mintToAccount(0xF414CFf71eCC35320Df0BB577E3Bc9B69c9E1f07, 2000e18); // 2000 DSD to devnull
}

function advance() external incentivized {
Expand All @@ -47,10 +55,32 @@ contract Implementation is State, Bonding, Market, Regulator, Govern {
}

modifier incentivized {
// Mint advance reward to sender
uint256 incentive = Constants.getAdvanceIncentive();
mintToAccount(msg.sender, incentive);
emit Incentivization(msg.sender, incentive);
// run incentivisation after advancing, so we use the updated price
uint256 startGas = gasleft();
_;
// fetch gasPrice & ETH price from Chainlink
(, int256 ethPrice, , , ) = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419).latestRoundData();
(, int256 fastGasPrice, , , ) =
AggregatorV3Interface(0x169E633A2D1E6c10dD91238Ba11c4A708dfEF37C).latestRoundData();

// Calculate DSD cost
Decimal.D256 memory ethSpent =
Decimal.D256({
value: (startGas - gasleft() + 41000).mul(uint256(fastGasPrice)) // approximate used gas for tx
});
Decimal.D256 memory usdCost =
ethSpent.mul(
Decimal.D256({
value: uint256(ethPrice).mul(1e10) // chainlink ETH price has 8 decimals
})
);
Decimal.D256 memory dsdCost = usdCost.div(getPrice());

// Add incentive
Decimal.D256 memory incentive = dsdCost.mul(Constants.getAdvanceIncentivePremium());

// Mint advance reward to sender
mintToAccount(msg.sender, incentive.value);
emit Incentivization(msg.sender, incentive.value);
}
}
37 changes: 33 additions & 4 deletions contracts/dao/Market.sol
Expand Up @@ -146,8 +146,18 @@ contract Market is Comptroller, Curve {
require(epoch().sub(couponEpoch) >= 2, "Market: Too early to redeem");
require(amount != 0, "Market: Amount too low");

uint256 couponAmount = balanceOfCoupons(msg.sender, couponEpoch)
.mul(amount).div(balanceOfCouponUnderlying(msg.sender, couponEpoch), "Market: No underlying");
uint256 underlying = balanceOfCouponUnderlying(msg.sender, couponEpoch);
require(underlying >= amount, "Market: Insufficient coupon underlying balance");

uint256 couponAmount;
if (outstandingCoupons(couponEpoch) == 0) {
// coupons have expired
_state.accounts[msg.sender].coupons[couponEpoch] = 0;
} else {
// coupons have not expired
couponAmount = _state.accounts[msg.sender].coupons[couponEpoch]
.mul(amount).div(underlying, "Market: No underlying");
}

uint256 totalAmount = couponAmount.add(amount);

Expand Down Expand Up @@ -192,9 +202,28 @@ contract Market is Comptroller, Curve {
function transferCoupons(address sender, address recipient, uint256 epoch, uint256 amount) external {
require(sender != address(0), "Market: Coupon transfer from the zero address");
require(recipient != address(0), "Market: Coupon transfer to the zero address");
require(amount != 0, "Market: Amount too low");

uint256 underlying = balanceOfCouponUnderlying(sender, epoch);
require(underlying >= amount, "Market: Insufficient coupon underlying balance");

decrementBalanceOfCoupons(sender, epoch, amount, "Market: Insufficient coupon balance");
incrementBalanceOfCoupons(recipient, epoch, amount);
uint256 couponAmount;
if (outstandingCoupons(epoch) == 0) {
// coupons have expired
_state.accounts[sender].coupons[epoch] = 0;
} else {
// coupons have not expired
couponAmount = _state.accounts[sender].coupons[epoch]
.mul(amount).div(underlying, "Market: No underlying");
}

decrementBalanceOfCouponUnderlying(sender, epoch, amount, "Market: Insufficient coupon underlying balance");
incrementBalanceOfCouponUnderlying(recipient, epoch, amount);

if (couponAmount != 0) {
decrementBalanceOfCoupons(sender, epoch, couponAmount, "Market: Insufficient coupon balance");
incrementBalanceOfCoupons(recipient, epoch, couponAmount);
}

if (msg.sender != sender && allowanceCoupons(sender, msg.sender) != uint256(-1)) {
decrementAllowanceCoupons(sender, msg.sender, amount, "Market: Insufficient coupon approval");
Expand Down