Skip to content

Commit

Permalink
Merge f77c2c6 into 5cad7f9
Browse files Browse the repository at this point in the history
  • Loading branch information
Jerry Smith committed Jan 9, 2021
2 parents 5cad7f9 + f77c2c6 commit 42f2c01
Show file tree
Hide file tree
Showing 9 changed files with 445 additions and 30 deletions.
47 changes: 23 additions & 24 deletions contracts/Treasury.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
import '@openzeppelin/contracts/utils/ReentrancyGuard.sol';

import './interfaces/IOracle.sol';
import './interfaces/IBoardroom.sol';
import './interfaces/IBasisAsset.sol';
import './interfaces/ISimpleERCFund.sol';
import './lib/Babylonian.sol';
import './lib/FixedPoint.sol';
import './lib/Safe112.sol';
import './owner/Operator.sol';
import './utils/Epoch.sol';
import './utils/ContractGuard.sol';
import {ICurve} from './curve/Curve.sol';
import {IOracle} from './interfaces/IOracle.sol';
import {IBoardroom} from './interfaces/IBoardroom.sol';
import {IBasisAsset} from './interfaces/IBasisAsset.sol';
import {ISimpleERCFund} from './interfaces/ISimpleERCFund.sol';
import {Babylonian} from './lib/Babylonian.sol';
import {FixedPoint} from './lib/FixedPoint.sol';
import {Safe112} from './lib/Safe112.sol';
import {Operator} from './owner/Operator.sol';
import {Epoch} from './utils/Epoch.sol';
import {ContractGuard} from './utils/ContractGuard.sol';

/**
* @title Basis Cash Treasury contract
Expand All @@ -39,14 +40,14 @@ contract Treasury is ContractGuard, Epoch {
address public cash;
address public bond;
address public share;
address public curve;
address public boardroom;

address public bondOracle;
address public seigniorageOracle;

// ========== PARAMS
uint256 public cashPriceOne;
uint256 public cashPriceCeiling;

uint256 private accumulatedSeigniorage = 0;
uint256 private lastBondOracleEpoch = 0;
Expand All @@ -64,19 +65,20 @@ contract Treasury is ContractGuard, Epoch {
address _seigniorageOracle,
address _boardroom,
address _fund,
address _curve,
uint256 _startTime
) public Epoch(1 days, _startTime, 0) {
cash = _cash;
bond = _bond;
share = _share;
curve = _curve;
bondOracle = _bondOracle;
seigniorageOracle = _seigniorageOracle;

boardroom = _boardroom;
fund = _fund;

cashPriceOne = 10**18;
cashPriceCeiling = uint256(105).mul(cashPriceOne).div(10**2);
}

/* =================== Modifier =================== */
Expand Down Expand Up @@ -139,9 +141,6 @@ contract Treasury is ContractGuard, Epoch {
function initialize() public checkOperator {
require(!initialized, 'Treasury: initialized');

// burn all of it's balance
IBasisAsset(cash).burn(IERC20(cash).balanceOf(address(this)));

// set accumulatedSeigniorage to it's balance
accumulatedSeigniorage = IERC20(cash).balanceOf(address(this));

Expand Down Expand Up @@ -198,10 +197,10 @@ contract Treasury is ContractGuard, Epoch {
}

// TWEAK
function setCashPriceCeiling(uint256 newCeiling) public onlyOperator {
uint256 oldCeiling = cashPriceCeiling;
cashPriceCeiling = newCeiling;
emit CashPriceCeilingChanged(msg.sender, oldCeiling, newCeiling);
function setCeilingCurve(address newCurve) public onlyOperator {
address oldCurve = newCurve;
curve = newCurve;
emit CeilingCurveChanged(msg.sender, oldCurve, newCurve);
}

/* ========== MUTABLE FUNCTIONS ========== */
Expand Down Expand Up @@ -276,7 +275,7 @@ contract Treasury is ContractGuard, Epoch {
uint256 cashPrice = _getCashPrice(bondOracle);
require(cashPrice == targetPrice, 'Treasury: cash price moved');
require(
cashPrice > cashPriceCeiling, // price > $1.05
cashPrice > ICurve(curve).calcCeiling(circulatingSupply()), // price > $1.05
'Treasury: cashPrice not eligible for bond purchase'
);
require(
Expand Down Expand Up @@ -304,7 +303,7 @@ contract Treasury is ContractGuard, Epoch {
{
_updateCashPrice();
uint256 cashPrice = _getCashPrice(seigniorageOracle);
if (cashPrice <= cashPriceCeiling) {
if (cashPrice <= ICurve(curve).calcCeiling(circulatingSupply())) {
return; // just advance epoch instead revert
}

Expand Down Expand Up @@ -374,10 +373,10 @@ contract Treasury is ContractGuard, Epoch {
address oldOracle,
address newOracle
);
event CashPriceCeilingChanged(
event CeilingCurveChanged(
address indexed operator,
uint256 oldCeiling,
uint256 newCeiling
address oldCurve,
address newCurve
);

// CORE
Expand Down
82 changes: 82 additions & 0 deletions contracts/curve/Curve.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
pragma solidity ^0.6.0;

interface ICurve {
function minSupply() external view returns (uint256);

function maxSupply() external view returns (uint256);

function minCeiling() external view returns (uint256);

function maxCeiling() external view returns (uint256);

function calcCeiling(uint256 _supply) external view returns (uint256);
}

abstract contract Curve is ICurve {
/* ========== EVENTS ========== */

event MinSupplyChanged(
address indexed operator,
uint256 _old,
uint256 _new
);

event MaxSupplyChanged(
address indexed operator,
uint256 _old,
uint256 _new
);

event MinCeilingChanged(
address indexed operator,
uint256 _old,
uint256 _new
);

event MaxCeilingChanged(
address indexed operator,
uint256 _old,
uint256 _new
);

/* ========== STATE VARIABLES ========== */

uint256 public override minSupply;
uint256 public override maxSupply;

uint256 public override minCeiling;
uint256 public override maxCeiling;

/* ========== GOVERNANCE ========== */

function setMinSupply(uint256 _newMinSupply) public virtual {
uint256 oldMinSupply = minSupply;
minSupply = _newMinSupply;
emit MinSupplyChanged(msg.sender, oldMinSupply, _newMinSupply);
}

function setMaxSupply(uint256 _newMaxSupply) public virtual {
uint256 oldMaxSupply = maxSupply;
maxSupply = _newMaxSupply;
emit MaxSupplyChanged(msg.sender, oldMaxSupply, _newMaxSupply);
}

function setMinCeiling(uint256 _newMinCeiling) public virtual {
uint256 oldMinCeiling = _newMinCeiling;
minCeiling = _newMinCeiling;
emit MinCeilingChanged(msg.sender, oldMinCeiling, _newMinCeiling);
}

function setMaxCeiling(uint256 _newMaxCeiling) public virtual {
uint256 oldMaxCeiling = _newMaxCeiling;
maxCeiling = _newMaxCeiling;
emit MaxCeilingChanged(msg.sender, oldMaxCeiling, _newMaxCeiling);
}

function calcCeiling(uint256 _supply)
external
view
virtual
override
returns (uint256);
}
73 changes: 73 additions & 0 deletions contracts/curve/Linear.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
pragma solidity ^0.6.0;

import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';

import {Operator} from '../owner/Operator.sol';
import {Curve} from './Curve.sol';

contract LinearThreshold is Operator, Curve {
using SafeMath for uint256;

/* ========== CONSTRUCTOR ========== */

constructor(
uint256 _minSupply,
uint256 _maxSupply,
uint256 _minCeiling,
uint256 _maxCeiling
) public {
minSupply = _minSupply;
maxSupply = _maxSupply;
minCeiling = _minCeiling;
maxCeiling = _maxCeiling;
}

/* ========== GOVERNANCE ========== */

function setMinSupply(uint256 _newMinSupply) public override onlyOperator {
super.setMinSupply(_newMinSupply);
}

function setMaxSupply(uint256 _newMaxSupply) public override onlyOperator {
super.setMaxSupply(_newMaxSupply);
}

function setMinCeiling(uint256 _newMinCeiling)
public
override
onlyOperator
{
super.setMinCeiling(_newMinCeiling);
}

function setMaxCeiling(uint256 _newMaxCeiling)
public
override
onlyOperator
{
super.setMaxCeiling(_newMaxCeiling);
}

/* ========== VIEW FUNCTIONS ========== */

function calcCeiling(uint256 _supply)
public
view
override
returns (uint256)
{
if (_supply <= minSupply) {
return maxCeiling;
}
if (_supply >= maxSupply) {
return minCeiling;
}

uint256 slope =
maxCeiling.sub(minCeiling).mul(1e18).div(maxSupply.sub(minSupply));
uint256 ceiling =
maxCeiling.sub(slope.mul(_supply.sub(minSupply)).div(1e18));

return ceiling;
}
}
114 changes: 114 additions & 0 deletions contracts/curve/Sigmoid.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
pragma solidity ^0.6.0;

import {Math} from '@openzeppelin/contracts/math/Math.sol';
import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';

import {Operator} from '../owner/Operator.sol';
import {Curve} from './Curve.sol';

contract SigmoidThreshold is Operator, Curve {
using SafeMath for uint256;

/* ========== STATE VARIABLES ========== */

uint256[23] private slots;

/* ========== CONSTRUCTOR ========== */

constructor(
uint256 _minSupply,
uint256 _maxSupply,
uint256 _minCeiling,
uint256 _maxCeiling
) public {
minSupply = _minSupply;
maxSupply = _maxSupply;
minCeiling = _minCeiling;
maxCeiling = _maxCeiling;

slots[0] = 1000000000000000000;
slots[1] = 994907149075715143;
slots[2] = 988513057369406817;
slots[3] = 982013790037908452;
slots[4] = 970687769248643639;
slots[5] = 952574126822433143;
slots[6] = 924141819978756551;
slots[7] = 880797077977882314;
slots[8] = 817574476193643651;
slots[9] = 731058578630004896;
slots[10] = 622459331201854593;
slots[11] = 500000000000000000;
slots[12] = 377540668798145407;
slots[13] = 268941421369995104;
slots[14] = 182425523806356349;
slots[15] = 119202922022117574;
slots[16] = 75858180021243560;
slots[17] = 47425873177566788;
slots[18] = 29312230751356326;
slots[19] = 17986209962091562;
slots[20] = 11486942630593183;
slots[21] = 5092850924284857;
slots[22] = 0;
}

/* ========== GOVERNANCE ========== */

function setMinSupply(uint256 _newMinSupply) public override onlyOperator {
super.setMinSupply(_newMinSupply);
}

function setMaxSupply(uint256 _newMaxSupply) public override onlyOperator {
super.setMaxSupply(_newMaxSupply);
}

function setMinCeiling(uint256 _newMinCeiling)
public
override
onlyOperator
{
super.setMinCeiling(_newMinCeiling);
}

function setMaxCeiling(uint256 _newMaxCeiling)
public
override
onlyOperator
{
super.setMaxCeiling(_newMaxCeiling);
}

/* ========== VIEW FUNCTIONS ========== */

function calcCeiling(uint256 _supply)
public
view
override
returns (uint256)
{
if (_supply <= minSupply) {
return maxCeiling;
}
if (_supply >= maxSupply) {
return minCeiling;
}

uint256 slotWidth = maxSupply.sub(minSupply).div(slots.length);
uint256 xa = _supply.sub(minSupply).div(slotWidth);
uint256 xb = Math.min(xa.add(1), slots.length.sub(1));

uint256 slope = slots[xa].sub(slots[xb]).mul(1e18).div(slotWidth);
uint256 wy = slots[xa].add(slope.mul(slotWidth.mul(xa)).div(1e18));

uint256 percentage = 0;
if (wy > slope.mul(_supply).div(1e18)) {
percentage = wy.sub(slope.mul(_supply).div(1e18));
} else {
percentage = slope.mul(_supply).div(1e18).sub(wy);
}

return
minCeiling.add(
maxCeiling.sub(minCeiling).mul(percentage).div(1e18)
);
}
}

0 comments on commit 42f2c01

Please sign in to comment.