Documented libraries and removed unnecessary interface, IMixinScheduler

This commit is contained in:
Greg Hysen
2019-06-28 17:02:38 -07:00
parent 6da70cfa0d
commit 3922d02910
13 changed files with 149 additions and 245 deletions

View File

@@ -33,7 +33,6 @@ import "./staking_pools/MixinStakingPoolRewards.sol";
contract Staking is
IMixinScheduler,
IStaking,
IStakingEvents,
MixinDeploymentConstants,

View File

@@ -32,7 +32,6 @@ import "./MixinExchangeManager.sol";
contract MixinExchangeFees is
IMixinScheduler,
IStakingEvents,
MixinDeploymentConstants,
MixinConstants,

View File

@@ -23,14 +23,30 @@ pragma solidity ^0.5.5;
library LibFeeMath {
// @TODO Once better nth root - choose a value that is not a divisor of 18, like 7.
// @TODO Update these values for deployment
/// @dev This library implements math helpers for fee computation.
/// *** READ MixinExchangeFees BEFORE CONTINUING ***
/// @TODO - Optimization / Precision / SafeMath.
/// @TODO Once better nth root - choose a value that is not a divisor of 18, like 7.
/// @TODO Update these values for deployment.
/// There may be better, more efficient ways of implementing these functions.
/// This works well enough to test the end-to-system, but it would be really
/// good to get some math experts in here to check out this code. We should also
/// look at existing projects, in case similar functionality exists and has been
/// audited by a third-party.
// Denominator of alpha in cobb-douglas function
uint256 constant internal COBB_DOUGLAS_ALPHA_DENOMINATOR = 6;
// Reflects number of decimal places in a token amount
uint256 constant internal TOKEN_MULTIPLIER = 1000000000000000000;
// The divisor for finding the nth root of token amounts.
uint256 constant internal NTH_ROOT_OF_TOKEN_MULTIPLIER = 1000;
/// @dev Computes the nth root of a number.
/// @param base to compute the root.
/// @param n nth root.
/// @return nth root of base.
function _nthRoot(uint256 base, uint256 n)
internal
pure
@@ -79,14 +95,6 @@ library LibFeeMath {
// 4. Run Newton's Approximation to approximate the root
let denominator := mul(n, exp2(x, sub(n, 1)))
// -- playing with turning root into fixed point to retain decimals --
//let numerator := y
//let fixedPointScaleFactor := exp2(10, 18)
//let fixedPointNumerator := mul(y, fixedPointScaleFactor)
//let fixedPointX := mul(x, fixedPointScaleFactor)
//let fixedPointRoot := add(fixedPointX, div(fixedPointNumerator, denominator))
root := add(x, div(y, denominator))
// 5. Run Newton's nth Root Algorithm
@@ -114,7 +122,7 @@ library LibFeeMath {
}
}
// ganache core workaround (issue #430)
// @HACK(hysz) - ganache core workaround (issue #430)
function exp2(b, p) -> z {
z := b
for {p := sub(p, 1)}
@@ -127,6 +135,10 @@ library LibFeeMath {
}
}
/// @dev Computes the nth root of a fixed point value.
/// @param base to compute the root.
/// @param n nth root.
/// @return nth root of base.
function _nthRootFixedPoint(
uint256 base,
uint256 n
@@ -141,6 +153,10 @@ library LibFeeMath {
root = (scalar * numerator) / denominator;
}
/// @dev Computes the nth root of a fixed point value, where the
/// number of decimal places is known before hand (hardcoded above).
/// @param base to compute the root.
/// @return nth root of base.
function _nthRootFixedPointFixedN(
uint256 base
)
@@ -153,7 +169,12 @@ library LibFeeMath {
return root;
}
// scalar gets multiplied by once at the beginning
/// @dev Computes an exponent of a value in the form (ab)/c, minimizing loss of precision.
/// @param numerator of fraction
/// @param scalar to be multiplied by the numerator
/// @param denominator of fraction
/// @param power to raise value to
/// @return Exponent of input value.
function _exp(uint256 numerator, uint256 scalar, uint256 denominator, uint256 power)
internal
pure
@@ -166,9 +187,17 @@ library LibFeeMath {
return result;
}
// cobb-douglas using the nth root fixed point algorithm above
// no limitation on alpha. We tend to get better rounding
// on the simplified versions below.
/// @dev The cobb-douglas function used to compute fee-based rewards for staking pools in a given epoch.
/// Note that in this function there is no limitation on alpha; we tend to get better rounding
/// on the simplified versions below.
/// @param totalRewards collected over an epoch.
/// @param ownerFees Fees attributed to the owner of the staking pool.
/// @param totalFees collected across all active staking pools in the epoch.
/// @param ownerStake Stake attributed to the owner of the staking pool.
/// @param totalStake collected across all active staking pools in the epoch.
/// @param alphaNumerator Numerator of `alpha` in the cobb-dougles function.
/// @param alphaDenominator Denominator of `alpha` in the cobb-douglas function.
/// @return Result of computing the cobb-douglas function.
function _cobbDouglas(
uint256 totalRewards,
uint256 ownerFees,
@@ -189,7 +218,15 @@ library LibFeeMath {
);
}
// alpha = 1/x
/// @dev The cobb-douglas function used to compute fee-based rewards for staking pools in a given epoch.
/// Note - we assume that alpha = 1/x
/// @param totalRewards collected over an epoch.
/// @param ownerFees Fees attributed to the owner of the staking pool.
/// @param totalFees collected across all active staking pools in the epoch.
/// @param ownerStake Stake attributed to the owner of the staking pool.
/// @param totalStake collected across all active staking pools in the epoch.
/// @param alphaDenominator Denominator of `alpha` in the cobb-douglas function.
/// @return Result of computing the cobb-douglas function.
function _cobbDouglasSimplified(
uint256 totalRewards,
uint256 ownerFees,
@@ -206,7 +243,15 @@ library LibFeeMath {
(_nthRootFixedPoint(totalFees * ownerStake, alphaDenominator) * totalStake);
}
// (1 - alpha) = 1/x
/// @dev The cobb-douglas function used to compute fee-based rewards for staking pools in a given epoch.
/// Note - we assume that (1 - alpha) = 1/x
/// @param totalRewards collected over an epoch.
/// @param ownerFees Fees attributed to the owner of the staking pool.
/// @param totalFees collected across all active staking pools in the epoch.
/// @param ownerStake Stake attributed to the owner of the staking pool.
/// @param totalStake collected across all active staking pools in the epoch.
/// @param alphaDenominator Denominator of `alpha` in the cobb-douglas function.
/// @return Result of computing the cobb-douglas function.
function _cobbDouglasSimplifiedInverse(
uint256 totalRewards,
uint256 ownerFees,
@@ -223,9 +268,14 @@ library LibFeeMath {
(_nthRootFixedPoint(totalStake * ownerFees, alphaDenominator) * totalFees);
}
// alpha = 1/x, where x is known
// x is defined in `MixinConstants.COBB_DOUGLAS_ALPHA_DENOMINATOR`
// Currently set to 6.
/// @dev The cobb-douglas function used to compute fee-based rewards for staking pools in a given epoch.
/// Note - we assume that alpha = 1/x, where x is defined by `COBB_DOUGLAS_ALPHA_DENOMINATOR`
/// @param totalRewards collected over an epoch.
/// @param ownerFees Fees attributed to the owner of the staking pool.
/// @param totalFees collected across all active staking pools in the epoch.
/// @param ownerStake Stake attributed to the owner of the staking pool.
/// @param totalStake collected across all active staking pools in the epoch.
/// @return Result of computing the cobb-douglas function.
function _cobbDouglasSuperSimplified(
uint256 totalRewards,
uint256 ownerFees,
@@ -241,9 +291,14 @@ library LibFeeMath {
(_nthRootFixedPointFixedN(totalFees * ownerStake) * totalStake);
}
// (1 - alpha) = 1/x, where x is known
// x is defined in `MixinConstants.COBB_DOUGLAS_ALPHA_DENOMINATOR`
// Currently set to 6.
/// @dev The cobb-douglas function used to compute fee-based rewards for staking pools in a given epoch.
/// Note - we assume that (1 - alpha) = 1/x, where x is defined by `COBB_DOUGLAS_ALPHA_DENOMINATOR`
/// @param totalRewards collected over an epoch.
/// @param ownerFees Fees attributed to the owner of the staking pool.
/// @param totalFees collected across all active staking pools in the epoch.
/// @param ownerStake Stake attributed to the owner of the staking pool.
/// @param totalStake collected across all active staking pools in the epoch.
/// @return Result of computing the cobb-douglas function.
function _cobbDouglasSuperSimplifiedInverse(
uint256 totalRewards,
uint256 ownerFees,
@@ -258,6 +313,4 @@ library LibFeeMath {
return (_nthRootFixedPointFixedN(ownerStake * totalFees) * totalRewards * ownerFees) /
(_nthRootFixedPointFixedN(totalStake * ownerFees) * totalFees);
}
}

View File

@@ -23,8 +23,19 @@ import "./LibSafeMath.sol";
library LibRewardMath {
/// @dev This library contains logic for computing the reward balances of staking pool members.
/// *** READ MixinStakingPoolRewards BEFORE CONTINUING ***
using LibSafeMath for uint256;
/// @dev Computes a member's payout denominated in the real asset (ETH).
/// Use this function when a member is liquidating their position in the pool (undelegating all their stake);
/// their shadow balance must be reset to zero so there is no need to compute it here.
/// @param amountDelegatedByOwner Amount of Stake delegated by the member to the staking pool.
/// @param totalAmountDelegated Total amount of Stake delegated by all members of the staking pool.
/// @param amountOfShadowAssetHeldByOwner The shadow balance of the member.
/// @param totalAmountOfShadowAsset The sum total of shadow balances across all members of the pool.
/// @param totalAmountOfRealAsset The total amount of ETH shared by members of the pool.
function _computePayoutDenominatedInRealAsset(
uint256 amountDelegatedByOwner,
uint256 totalAmountDelegated,
@@ -50,6 +61,15 @@ library LibRewardMath {
return payoutInRealAsset;
}
/// @dev Computes a member's payout denominated in the real asset (ETH).
/// Use this function when a member is undelegating a portion (but not all) of their stake.
/// @param partialAmountDelegatedByOwner Amount of Stake being undelegated by the member to the staking pool.
/// @param amountDelegatedByOwner Amount of Stake delegated by the member to the staking pool.
/// This includes `partialAmountDelegatedByOwner`.
/// @param totalAmountDelegated Total amount of Stake delegated by all members of the staking pool.
/// @param amountOfShadowAssetHeldByOwner The shadow balance of the member.
/// @param totalAmountOfShadowAsset The sum total of shadow balances across all members of the pool.
/// @param totalAmountOfRealAsset The total amount of ETH shared by members of the pool.
function _computePartialPayout(
uint256 partialAmountDelegatedByOwner,
uint256 amountDelegatedByOwner,
@@ -79,6 +99,13 @@ library LibRewardMath {
return (payoutInRealAsset, payoutInShadowAsset);
}
/// @dev Computes how much shadow asset to mint a member who wants to
/// join (or delegate more stake to) a staking pool.
/// @param amountToDelegateByOwner Amount of Stake the new member would delegate.
/// @param totalAmountDelegated Total amount currently delegated to the pool.
/// This does *not* include `amountToDelegateByOwner`.
/// @param totalAmountOfShadowAsset The sum total of shadow balances across all members of the pool.
/// @param totalAmountOfRealAsset The total amount of ETH shared by members of the pool.
function _computeBuyInDenominatedInShadowAsset(
uint256 amountToDelegateByOwner,
uint256 totalAmountDelegated,

View File

@@ -22,49 +22,28 @@ pragma solidity ^0.5.5;
library LibSafeMath {
uint256 constant internal MAX_UINT_96 = 79228162514264337593543950335; // 2**96-1
uint256 constant internal MAX_UINT_64 = 18446744073709551615; // 2**64-1
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
/// @dev Returns the addition of two unsigned integers, reverting on overflow.
/// Note that this reverts on overflow.
function _add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
require(c >= a, "OVERFLOW");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
/// @dev Returns the subtraction of two unsigned integers.
/// Note that this reverts on underflow.
function _sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
require(b <= a, "UNDEROVERFLOW");
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
/// @dev Returns the multiplication of two unsigned integers, reverting on overflow.
/// Note that this reverts on overflow.
function _mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
@@ -79,46 +58,16 @@ library LibSafeMath {
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
/// @dev Returns the integer division of two unsigned integers.
/// Note that this reverts on division by zero. The result is rounded towards zero.
function _div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, "SafeMath: division by zero");
require(b > 0, "DIVISION_BY_ZERO");
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function _mod(uint256 a, uint256 b)
internal
pure
returns (uint256)
{
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
/// @dev Safely downcasts to a uint96
/// Note that this reverts if the input value is too large.
function _downcastToUint96(uint256 a)
internal
pure
@@ -131,6 +80,8 @@ library LibSafeMath {
return uint96(a);
}
/// @dev Safely downcasts to a uint64
/// Note that this reverts if the input value is too large.
function _downcastToUint64(uint256 a)
internal
pure

View File

@@ -21,47 +21,25 @@ pragma solidity ^0.5.5;
library LibSafeMath64 {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
/// @dev Returns the addition of two unsigned integers, reverting on overflow.
/// Note that this reverts on overflow.
function _add(uint64 a, uint64 b) internal pure returns (uint64) {
uint64 c = a + b;
require(c >= a, "SafeMath: addition overflow");
require(c >= a, "OVERFLOW");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
/// @dev Returns the subtraction of two unsigned integers.
/// Note that this reverts on underflow.
function _sub(uint64 a, uint64 b) internal pure returns (uint64) {
require(b <= a, "SafeMath: subtraction overflow");
require(b <= a, "UNDEROVERFLOW");
uint64 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
/// @dev Returns the multiplication of two unsigned integers, reverting on overflow.
/// Note that this reverts on overflow.
function _mul(uint64 a, uint64 b) internal pure returns (uint64) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
@@ -76,57 +54,11 @@ library LibSafeMath64 {
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
/// @dev Returns the integer division of two unsigned integers.
/// Note that this reverts on division by zero. The result is rounded towards zero.
function _div(uint64 a, uint64 b) internal pure returns (uint64) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, "SafeMath: division by zero");
require(b > 0, "DIVISION_BY_ZERO");
uint64 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function _mod(uint64 a, uint64 b)
internal
pure
returns (uint64)
{
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
function _computePercentageCeil(uint64 value, uint8 numerator)
internal
pure
returns (uint64)
{
uint64 scaledNumerator = _mul(value, numerator);
uint64 ceilScalar = uint64(99);
uint64 denominator = uint64(100);
return _div(
_add(scaledNumerator, ceilScalar),
denominator
);
}
}

View File

@@ -21,47 +21,25 @@ pragma solidity ^0.5.5;
library LibSafeMath96 {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
/// @dev Returns the addition of two unsigned integers, reverting on overflow.
/// Note that this reverts on overflow.
function _add(uint96 a, uint96 b) internal pure returns (uint96) {
uint96 c = a + b;
require(c >= a, "SafeMath: addition overflow");
require(c >= a, "OVERFLOW");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
/// @dev Returns the subtraction of two unsigned integers.
/// Note that this reverts on underflow.
function _sub(uint96 a, uint96 b) internal pure returns (uint96) {
require(b <= a, "SafeMath: subtraction overflow");
require(b <= a, "UNDEROVERFLOW");
uint96 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
/// @dev Returns the multiplication of two unsigned integers, reverting on overflow.
/// Note that this reverts on overflow.
function _mul(uint96 a, uint96 b) internal pure returns (uint96) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
@@ -76,52 +54,24 @@ library LibSafeMath96 {
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
/// @dev Returns the integer division of two unsigned integers.
/// Note that this reverts on division by zero. The result is rounded towards zero.
function _div(uint96 a, uint96 b) internal pure returns (uint96) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, "SafeMath: division by zero");
require(b > 0, "DIVISION_BY_ZERO");
uint96 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function _mod(uint96 a, uint96 b)
/// @dev Computes the percentage `numerator` is of `value`.
/// @param value The whole amount.
/// @param slice A slice of `value`.
/// @return The percentage `slice` is of `value`
function _computePercentageCeil(uint96 value, uint8 slice)
internal
pure
returns (uint96)
{
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
function _computePercentageCeil(uint96 value, uint8 numerator)
internal
pure
returns (uint96)
{
uint96 scaledNumerator = _mul(value, numerator);
uint96 scaledNumerator = _mul(value, slice);
uint96 ceilScalar = uint96(99);
uint96 denominator = uint96(100);
return _div(

View File

@@ -32,7 +32,6 @@ import "../staking_pools/MixinStakingPoolRewards.sol";
contract MixinDelegatedStake is
IMixinScheduler,
IStakingEvents,
MixinDeploymentConstants,
MixinConstants,

View File

@@ -31,7 +31,6 @@ import "./MixinTimelockedStake.sol";
contract MixinStake is
IMixinScheduler,
IStakingEvents,
MixinDeploymentConstants,
MixinConstants,

View File

@@ -28,7 +28,6 @@ import "./MixinTimelockedStake.sol";
contract MixinStakeBalances is
IMixinScheduler,
IStakingEvents,
MixinDeploymentConstants,
MixinConstants,

View File

@@ -27,7 +27,6 @@ import "../sys/MixinScheduler.sol";
contract MixinTimelockedStake is
IMixinScheduler,
IStakingEvents,
MixinDeploymentConstants,
MixinConstants,

View File

@@ -28,7 +28,6 @@ import "./MixinStakingPool.sol";
contract MixinStakingPoolRewards is
IMixinScheduler,
IStakingEvents,
MixinDeploymentConstants,
MixinConstants,

View File

@@ -18,7 +18,6 @@
pragma solidity ^0.5.5;
import "../core_interfaces/IMixinScheduler.sol";
import "../libs/LibSafeMath.sol";
import "../libs/LibSafeMath64.sol";
import "../immutable/MixinConstants.sol";
@@ -28,7 +27,6 @@ import "../interfaces/IStakingEvents.sol";
contract MixinScheduler is
IMixinScheduler,
IStakingEvents,
MixinDeploymentConstants,
MixinConstants,