@0x/contracts-staking: Remove LibFeeMath and just put _cobbDouglas() in MixinExchangeFees.
`@0x/contracts-staking`: Update `LibFixedMath` to existing naming conventions. `@0x/contracts-staking`: Add `cobbDouglasAlphaNumerator` and `cobbDouglasAlphaDenominator` to `Mixinstorage`. `@0x/contracts-staking`: Add external `setCobbDouglasAlpha()` function to `MixinExchnageFees` `@0x/contracts-staking`: Update `_cobbDouglas()` to use the new `LibFixedMath` voodoo. `@0x/contracts-staking`: In reward calculations, use only delegated stake by pool owner as opposed to both delegated and active stake to compute stake totals.
This commit is contained in:
committed by
Lawrence Forman
parent
c1fc454d19
commit
a09cd03ce6
@@ -22,6 +22,7 @@ import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
import "../libs/LibFeeMath.sol";
|
||||
import "../libs/LibStakingRichErrors.sol";
|
||||
import "../libs/LibFixedMath.sol";
|
||||
import "../immutable/MixinStorage.sol";
|
||||
import "../immutable/MixinConstants.sol";
|
||||
import "../interfaces/IStakingEvents.sol";
|
||||
@@ -56,6 +57,26 @@ contract MixinExchangeFees is
|
||||
{
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
/// @dev Set the cobb douglas alpha value used when calculating rewards.
|
||||
/// Valid inputs: 0 <= `numerator` / `denominator` <= 1.0
|
||||
/// @param numerator The alpha numerator.
|
||||
/// @param denominator The alpha denominator.
|
||||
function setCobbDouglasAlpha(
|
||||
uint256 numerator,
|
||||
uint256 denominator
|
||||
)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
if (int256(numerator) < 0 ||
|
||||
int256(denominator) <= 0 ||
|
||||
numerator > denominator) {
|
||||
revert("INVALID_ALPHA");
|
||||
}
|
||||
cobbDouglasAlphaNumerator = numerator;
|
||||
cobbDouglasAlphaDenomintor = denominator;
|
||||
}
|
||||
|
||||
/// TODO(jalextowle): Add WETH to protocol fees. Should this be unwrapped?
|
||||
/// @dev Pays a protocol fee in ETH.
|
||||
/// Only a known 0x exchange can call this method. See (MixinExchangeManager).
|
||||
@@ -71,10 +92,19 @@ contract MixinExchangeFees is
|
||||
{
|
||||
uint256 amount = msg.value;
|
||||
bytes32 poolId = getStakingPoolIdOfMaker(makerAddress);
|
||||
uint256 _feesCollectedThisEpoch = protocolFeesThisEpochByPool[poolId];
|
||||
protocolFeesThisEpochByPool[poolId] = _feesCollectedThisEpoch.safeAdd(amount);
|
||||
if (_feesCollectedThisEpoch == 0) {
|
||||
activePoolsThisEpoch.push(poolId);
|
||||
if (poolId != 0x0) {
|
||||
// There is a pool associated with `makerAddress`.
|
||||
// TODO(dorothy-zbornak): When we have epoch locks on delegating, we could
|
||||
// preclude pools that have no delegated stake, since they will never have
|
||||
// stake in this epoch.
|
||||
uint256 _feesCollectedThisEpoch = protocolFeesThisEpochByPool[poolId];
|
||||
protocolFeesThisEpochByPool[poolId] = _feesCollectedThisEpoch.safeAdd(amount);
|
||||
if (_feesCollectedThisEpoch == 0) {
|
||||
activePoolsThisEpoch.push(poolId);
|
||||
}
|
||||
} else {
|
||||
// No pool associated with `makerAddress`. Refund the fee.
|
||||
msg.sender.transfer(amount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +155,7 @@ contract MixinExchangeFees is
|
||||
}
|
||||
|
||||
/// @dev Pays rewards to market making pools that were active this epoch.
|
||||
/// Each pool receives a portion of the fees generated this epoch (see LibFeeMath) that is
|
||||
/// Each pool receives a portion of the fees generated this epoch (see _cobbDouglas) that is
|
||||
/// proportional to (i) the fee volume attributed to their pool over the epoch, and
|
||||
/// (ii) the amount of stake provided by the maker and their delegators. Rebates are paid
|
||||
/// into the Reward Vault (see MixinStakingPoolRewardVault) where they can be withdraw by makers and
|
||||
@@ -176,7 +206,7 @@ contract MixinExchangeFees is
|
||||
|
||||
// compute weighted stake
|
||||
uint256 totalStakeDelegatedToPool = getTotalStakeDelegatedToPool(poolId);
|
||||
uint256 stakeHeldByPoolOperator = getActivatedAndUndelegatedStake(getStakingPoolOperator(poolId));
|
||||
uint256 stakeHeldByPoolOperator = getStakeDelegatedToPoolByOwner(getStakingPoolOperator(poolId), poolId);
|
||||
uint256 weightedStake = stakeHeldByPoolOperator.safeAdd(
|
||||
totalStakeDelegatedToPool
|
||||
.safeMul(REWARD_PAYOUT_DELEGATED_STAKE_PERCENT_VALUE)
|
||||
@@ -209,12 +239,14 @@ contract MixinExchangeFees is
|
||||
// step 2/3 - record reward for each pool
|
||||
for (uint256 i = 0; i != totalActivePools; i++) {
|
||||
// compute reward using cobb-douglas formula
|
||||
uint256 reward = LibFeeMath._cobbDouglasSuperSimplified(
|
||||
uint256 reward = _cobbDouglas(
|
||||
initialContractBalance,
|
||||
activePools[i].feesCollected,
|
||||
totalFeesCollected,
|
||||
activePools[i].weightedStake,
|
||||
totalWeightedStake
|
||||
totalWeightedStake,
|
||||
cobbDouglasAlphaNumerator,
|
||||
cobbDouglasAlphaDenomintor
|
||||
);
|
||||
|
||||
// record reward in vault
|
||||
@@ -250,4 +282,54 @@ contract MixinExchangeFees is
|
||||
finalContractBalance
|
||||
);
|
||||
}
|
||||
|
||||
/// @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 ownerRewards Rewards for the owner.
|
||||
function _cobbDouglas(
|
||||
uint256 totalRewards,
|
||||
uint256 ownerFees,
|
||||
uint256 totalFees,
|
||||
uint256 ownerStake,
|
||||
uint256 totalStake,
|
||||
uint256 alphaNumerator,
|
||||
uint256 alphaDenominator
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 ownerRewards)
|
||||
{
|
||||
assert(ownerFees <= totalFees);
|
||||
assert(ownerStake <= totalStake);
|
||||
assert(alphaNumerator <= alphaDenominator);
|
||||
int256 feeRatio = LibFixedMath._toFixed(ownerFees, totalFees);
|
||||
int256 stakeRatio = LibFixedMath._toFixed(ownerStake, totalStake);
|
||||
int256 alpha = LibFixedMath._toFixed(alphaNumerator, alphaDenominator);
|
||||
|
||||
// The cobb-doublas function has the form:
|
||||
// totalRewards * feeRatio ^ alpha * stakeRatio ^ (1-alpha)
|
||||
// We instead use:
|
||||
// totalRewards * stakeRatio * e^(alpha * (ln(feeRatio) - ln(stakeRatio)))
|
||||
|
||||
// Compute e^(alpha * (ln(feeRatio) - ln(stakeRatio)))
|
||||
int256 n = LibFixedMath._exp(
|
||||
LibFixedMath._mul(
|
||||
alpha,
|
||||
LibFixedMath._ln(feeRatio) - LibFixedMath._ln(stakeRatio)
|
||||
)
|
||||
);
|
||||
// Multiply the above with totalRewards * stakeRatio
|
||||
ownerRewards = LibFixedMath._uintMul(
|
||||
LibFixedMath._mul(n, stakeRatio),
|
||||
totalRewards
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,4 +106,10 @@ contract MixinStorage is
|
||||
|
||||
// Rebate Vault
|
||||
IStakingPoolRewardVault internal rewardVault;
|
||||
|
||||
// Numerator for cobb douglas alpha factor.
|
||||
uint256 internal cobbDouglasAlphaNumerator = 1;
|
||||
|
||||
// Denominator for cobb douglas alpha factor.
|
||||
uint256 internal cobbDouglasAlphaDenomintor = 6;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,14 @@ interface IStakingEvents {
|
||||
uint256 earliestEndTimeInSeconds
|
||||
);
|
||||
|
||||
/// @dev Emitted by MixinExchangeFees when the cobb douglas alpha is updated.
|
||||
/// @param numerator The alpha numerator.
|
||||
/// @param denominator The alpha denominator.
|
||||
event CobbDouglasAlphaChanged(
|
||||
uint256 numerator,
|
||||
uint256 denominator
|
||||
);
|
||||
|
||||
/// @dev Emitted by MixinScheduler when the timeLock period is changed.
|
||||
/// @param timeLockPeriod The timeLock period we changed to.
|
||||
/// @param startEpoch The epoch this period started.
|
||||
|
||||
@@ -1,315 +0,0 @@
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
/// @dev This library implements math helpers for fee computation.
|
||||
/// *** READ MixinExchangeFees BEFORE CONTINUING ***
|
||||
/// To do - Optimization / Precision / SafeMath.
|
||||
/// To do - Once better nth root - choose a value that is not a divisor of 18, like 7.
|
||||
/// To do - 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.
|
||||
library LibFeeMath {
|
||||
|
||||
// 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
|
||||
returns (uint256 root)
|
||||
{
|
||||
assembly {
|
||||
///// Implements Newton's Approximation, derived from Newton's nth Root Algorithm /////
|
||||
///// See https://en.wikipedia.org/wiki/Nth_root#nth_root_algorithm
|
||||
|
||||
// 1. Find greatest power-of-2 <= `value`
|
||||
let nearestPowerOf2 := 0x100000000000000000000000000000000
|
||||
let m := 128
|
||||
for {let p := 64}
|
||||
gt(p, 0)
|
||||
{ p := div(p, 2) }
|
||||
{
|
||||
|
||||
switch gt(nearestPowerOf2, base)
|
||||
case 1 {
|
||||
nearestPowerOf2 := shr(p, nearestPowerOf2)
|
||||
m := sub(m, p)
|
||||
}
|
||||
case 0 {
|
||||
switch lt(nearestPowerOf2, base)
|
||||
case 1 {
|
||||
nearestPowerOf2 := shl(p, nearestPowerOf2)
|
||||
m := add(m, p)
|
||||
}
|
||||
case 0 {
|
||||
p := 0
|
||||
}
|
||||
}
|
||||
}
|
||||
if gt(nearestPowerOf2, base) {
|
||||
nearestPowerOf2 := shr(1, nearestPowerOf2)
|
||||
m := sub(m, 1)
|
||||
}
|
||||
|
||||
|
||||
// 2. Find greatest power-of-2 that, when raised to the power of `n`,
|
||||
// is <= `value`
|
||||
let x := exp(2, div(m, n))
|
||||
|
||||
// 3. Find y such that `x` + `y` = `base`
|
||||
let y := sub(base, exp2(x, n))
|
||||
|
||||
// 4. Run Newton's Approximation to approximate the root
|
||||
let denominator := mul(n, exp2(x, sub(n, 1)))
|
||||
root := add(x, div(y, denominator))
|
||||
|
||||
// 5. Run Newton's nth Root Algorithm
|
||||
let delta := 1 // run at least once
|
||||
// solhint-disable no-empty-blocks
|
||||
for {}
|
||||
gt(delta, 0)
|
||||
{}
|
||||
{
|
||||
// compute lhs
|
||||
let lhsDenominator := exp2(root, sub(n, 1))
|
||||
let lhs := div(base, lhsDenominator)
|
||||
|
||||
// check for overlow
|
||||
switch lt(lhs, root)
|
||||
case 0 {
|
||||
// underestimate
|
||||
delta := div(sub(lhs, root), n)
|
||||
root := add(root, delta)
|
||||
}
|
||||
case 1 {
|
||||
// overestimate
|
||||
delta := div(sub(root, lhs), n)
|
||||
root := sub(root, delta)
|
||||
}
|
||||
}
|
||||
|
||||
// @HACK(hysz) - ganache core workaround (issue #430)
|
||||
function exp2(b, p) -> z {
|
||||
z := b
|
||||
for {p := sub(p, 1)}
|
||||
gt(p, 0)
|
||||
{p := sub(p, 1)}
|
||||
{
|
||||
z := mul(z, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @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
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 root)
|
||||
{
|
||||
uint256 scalar = 10**18;
|
||||
uint256 numerator = _nthRoot(base, n);
|
||||
uint256 denominator = _nthRoot(scalar, n);
|
||||
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
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 root)
|
||||
{
|
||||
uint256 numerator = _nthRoot(base, COBB_DOUGLAS_ALPHA_DENOMINATOR);
|
||||
root = (TOKEN_MULTIPLIER * numerator) / NTH_ROOT_OF_TOKEN_MULTIPLIER;
|
||||
return root;
|
||||
}
|
||||
|
||||
/// @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
|
||||
returns (uint256 result)
|
||||
{
|
||||
result = (numerator * scalar) / denominator;
|
||||
for (power = power - 1; power > 0; power -= 1) {
|
||||
result = (result * numerator) / denominator;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @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,
|
||||
uint256 totalFees,
|
||||
uint256 ownerStake,
|
||||
uint256 totalStake,
|
||||
uint8 alphaNumerator,
|
||||
uint8 alphaDenominator
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return _exp(_nthRootFixedPoint(ownerFees * totalStake, alphaDenominator),
|
||||
((totalRewards * ownerStake) / totalStake),
|
||||
_nthRootFixedPoint(totalFees * ownerStake, alphaDenominator),
|
||||
alphaNumerator
|
||||
);
|
||||
}
|
||||
|
||||
/// @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,
|
||||
uint256 totalFees,
|
||||
uint256 ownerStake,
|
||||
uint256 totalStake,
|
||||
uint8 alphaDenominator
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return (_nthRootFixedPoint(ownerFees * totalStake, alphaDenominator) * totalRewards * ownerStake) /
|
||||
(_nthRootFixedPoint(totalFees * ownerStake, alphaDenominator) * totalStake);
|
||||
}
|
||||
|
||||
/// @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,
|
||||
uint256 totalFees,
|
||||
uint256 ownerStake,
|
||||
uint256 totalStake,
|
||||
uint8 alphaDenominator
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return (_nthRootFixedPoint(ownerStake * totalFees, alphaDenominator) * totalRewards * ownerFees) /
|
||||
(_nthRootFixedPoint(totalStake * ownerFees, alphaDenominator) * totalFees);
|
||||
}
|
||||
|
||||
/// @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,
|
||||
uint256 totalFees,
|
||||
uint256 ownerStake,
|
||||
uint256 totalStake
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return (_nthRootFixedPointFixedN(ownerFees * totalStake) * totalRewards * ownerStake) /
|
||||
(_nthRootFixedPointFixedN(totalFees * ownerStake) * totalStake);
|
||||
}
|
||||
|
||||
/// @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,
|
||||
uint256 totalFees,
|
||||
uint256 ownerStake,
|
||||
uint256 totalStake
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return (_nthRootFixedPointFixedN(ownerStake * totalFees) * totalRewards * ownerFees) /
|
||||
(_nthRootFixedPointFixedN(totalStake * ownerFees) * totalFees);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@ pragma solidity ^0.5.9;
|
||||
|
||||
/// @dev Signed, fixed-point, 127-bit precision math library.
|
||||
library LibFixedMath {
|
||||
|
||||
// 1
|
||||
int256 private constant FIXED_1 = int256(0x0000000000000000000000000000000080000000000000000000000000000000);
|
||||
|
||||
// 1
|
||||
@@ -28,29 +30,35 @@ library LibFixedMath {
|
||||
// -69.07755278982137043720332303294494434957608235919531845909733017243007692132225692604324818191230406
|
||||
int256 private constant EXP_MIN_VAL = int256(0xffffffffffffffffffffffffffffffdd7612c00c0077ada1b83518e8cafc0e90);
|
||||
|
||||
/// @dev Get one as a fixed-point number.
|
||||
function _one() internal pure returns (int256 c) {
|
||||
c = FIXED_1;
|
||||
}
|
||||
|
||||
/// @dev Returns the multiplication of two fixed point numbers, reverting on overflow.
|
||||
function mul(int256 a, int256 b) internal pure returns (int256 c) {
|
||||
c = _mul(a, b) / FIXED_1;
|
||||
function _mul(int256 a, int256 b) internal pure returns (int256 c) {
|
||||
c = __mul(a, b) / FIXED_1;
|
||||
}
|
||||
|
||||
/// @dev Returns the division of two fixed point numbers.
|
||||
function div(int256 a, int256 b) internal pure returns (int256 c) {
|
||||
c = _div(_mul(a, FIXED_1), b);
|
||||
function _div(int256 a, int256 b) internal pure returns (int256 c) {
|
||||
c = __div(__mul(a, FIXED_1), b);
|
||||
}
|
||||
|
||||
/// @dev Returns the unsigned integer result of multiplying a fixed-point
|
||||
/// number with an integer, reverting if the multiplication overflows.
|
||||
/// Negative results are clamped to zero.
|
||||
function uintMul(int256 a, int256 b) internal pure returns (uint256) {
|
||||
int256 c = _mul(a, b);
|
||||
function _uintMul(int256 f, uint256 u) internal pure returns (uint256) {
|
||||
require(int256(u) >= int256(0), "FIXED_MATH_INTEGER_TOO_LARGE");
|
||||
int256 c = __mul(f, int256(u));
|
||||
if (c <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return uint256(c) >> 127;
|
||||
return uint256(uint256(c) >> 127);
|
||||
}
|
||||
|
||||
/// @dev Returns the absolute value of a fixed point number.
|
||||
function abs(int256 a) internal pure returns (int256 c) {
|
||||
function _abs(int256 a) internal pure returns (int256 c) {
|
||||
if (a >= 0) {
|
||||
c = a;
|
||||
} else {
|
||||
@@ -58,23 +66,37 @@ library LibFixedMath {
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Convert `n` / 1 to a fixed-point number.
|
||||
function toFixed(int256 n) internal pure returns (int256 f) {
|
||||
f = _mul(n, FIXED_1);
|
||||
/// @dev Convert signed `n` / 1 to a fixed-point number.
|
||||
function _toFixed(int256 n) internal pure returns (int256 f) {
|
||||
f = __mul(n, FIXED_1);
|
||||
}
|
||||
|
||||
/// @dev Convert `n` / `d` to a fixed-point number.
|
||||
function toFixed(int256 n, int256 d) internal pure returns (int256 f) {
|
||||
f = _div(_mul(n, FIXED_1), d);
|
||||
/// @dev Convert signed `n` / `d` to a fixed-point number.
|
||||
function _toFixed(int256 n, int256 d) internal pure returns (int256 f) {
|
||||
f = __div(__mul(n, FIXED_1), d);
|
||||
}
|
||||
|
||||
/// @dev Convert unsigned `n` / 1 to a fixed-point number.
|
||||
/// Reverts if `n` is too large to fit in a fixed-point number.
|
||||
function _toFixed(uint256 n) internal pure returns (int256 f) {
|
||||
require(int256(n) >= 0, "FIXED_MATH_INTEGER_TOO_LARGE");
|
||||
f = __mul(int256(n), FIXED_1);
|
||||
}
|
||||
|
||||
/// @dev Convert unsigned `n` / `d` to a fixed-point number.
|
||||
/// Reverts if `n` / `d` is too large to fit in a fixed-point number.
|
||||
function _toFixed(uint256 n, uint256 d) internal pure returns (int256 f) {
|
||||
require(int256(n) >= 0 && int256(d) >= 0, "FIXED_MATH_INTEGER_TOO_LARGE");
|
||||
f = __div(__mul(int256(n), FIXED_1), int256(d));
|
||||
}
|
||||
|
||||
/// @dev Convert a fixed-point number to an integer.
|
||||
function toInteger(int256 f) internal pure returns (int256 n) {
|
||||
function _toInteger(int256 f) internal pure returns (int256 n) {
|
||||
return f >> 127;
|
||||
}
|
||||
|
||||
/// @dev Get the natural logarithm of a fixed-point number 0 < `x` <= LN_MAX_VAL
|
||||
function ln(int256 x) internal pure returns (int256 r) {
|
||||
function _ln(int256 x) internal pure returns (int256 r) {
|
||||
if (x == FIXED_1) {
|
||||
return 0;
|
||||
}
|
||||
@@ -147,7 +169,7 @@ library LibFixedMath {
|
||||
}
|
||||
|
||||
/// @dev Compute the natural exponent for a fixed-point number EXP_MIN_VAL <= `x` <= 1
|
||||
function exp(int256 x) internal pure returns (int256 r) {
|
||||
function _exp(int256 x) internal pure returns (int256 r) {
|
||||
if (x <= EXP_MIN_VAL) {
|
||||
// Saturate to zero below EXP_MIN_VAL.
|
||||
return 0;
|
||||
@@ -242,7 +264,7 @@ library LibFixedMath {
|
||||
}
|
||||
|
||||
/// @dev Returns the multiplication two numbers, reverting on overflow.
|
||||
function _mul(int256 a, int256 b) private pure returns (int256 c) {
|
||||
function __mul(int256 a, int256 b) private pure returns (int256 c) {
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -251,7 +273,7 @@ library LibFixedMath {
|
||||
}
|
||||
|
||||
/// @dev Returns the division of two numbers, reverting on division by zero.
|
||||
function _div(int256 a, int256 b) private pure returns (int256 c) {
|
||||
function __div(int256 a, int256 b) private pure returns (int256 c) {
|
||||
require(b != 0, "FIXED_MATH_DIVISION_BY_ZERO");
|
||||
c = a / b;
|
||||
}
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.5;
|
||||
|
||||
import "../src/libs/LibFeeMath.sol";
|
||||
|
||||
|
||||
contract LibFeeMathTest {
|
||||
|
||||
function nthRoot(uint256 base, uint256 n) public pure returns (uint256 root) {
|
||||
return LibFeeMath._nthRoot(base, n);
|
||||
}
|
||||
|
||||
function nthRootFixedPoint(
|
||||
uint256 base,
|
||||
uint256 n
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (uint256 root)
|
||||
{
|
||||
return LibFeeMath._nthRootFixedPoint(base, n);
|
||||
}
|
||||
|
||||
function cobbDouglas(
|
||||
uint256 totalRewards,
|
||||
uint256 ownerFees,
|
||||
uint256 totalFees,
|
||||
uint256 ownerStake,
|
||||
uint256 totalStake,
|
||||
uint8 alphaNumerator,
|
||||
uint8 alphaDenominator
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return LibFeeMath._cobbDouglas(
|
||||
totalRewards,
|
||||
ownerFees,
|
||||
totalFees,
|
||||
ownerStake,
|
||||
totalStake,
|
||||
alphaNumerator,
|
||||
alphaDenominator
|
||||
);
|
||||
}
|
||||
|
||||
function cobbDouglasSimplified(
|
||||
uint256 totalRewards,
|
||||
uint256 ownerFees,
|
||||
uint256 totalFees,
|
||||
uint256 ownerStake,
|
||||
uint256 totalStake,
|
||||
uint8 alphaDenominator
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (uint256)
|
||||
{
|
||||
return LibFeeMath._cobbDouglasSimplified(
|
||||
totalRewards,
|
||||
ownerFees,
|
||||
totalFees,
|
||||
ownerStake,
|
||||
totalStake,
|
||||
alphaDenominator
|
||||
);
|
||||
}
|
||||
|
||||
function cobbDouglasSimplifiedInverse(
|
||||
uint256 totalRewards,
|
||||
uint256 ownerFees,
|
||||
uint256 totalFees,
|
||||
uint256 ownerStake,
|
||||
uint256 totalStake,
|
||||
uint8 alphaDenominator
|
||||
)
|
||||
public
|
||||
// pure
|
||||
returns (uint256)
|
||||
{
|
||||
return LibFeeMath._cobbDouglasSimplifiedInverse(
|
||||
totalRewards,
|
||||
ownerFees,
|
||||
totalFees,
|
||||
ownerStake,
|
||||
totalStake,
|
||||
alphaDenominator
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"compile:truffle": "truffle compile"
|
||||
},
|
||||
"config": {
|
||||
"abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingPoolRewardVault|IStakingProxy|IStructs|IVaultCore|IWallet|IZrxVault|LibEIP712Hash|LibFeeMath|LibFeeMathTest|LibRewardMath|LibSafeDowncast|LibSignatureValidator|LibStakingRichErrors|MixinConstants|MixinDelegatedStake|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakingPool|MixinStakingPoolRewardVault|MixinStakingPoolRewards|MixinStorage|MixinTimeLockedStake|MixinVaultCore|MixinZrxVault|Staking|StakingPoolRewardVault|StakingProxy|TestStorageLayout|ZrxVault).json",
|
||||
"abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingPoolRewardVault|IStakingProxy|IStructs|IVaultCore|IWallet|IZrxVault|LibEIP712Hash|LibFixedMath|LibRewardMath|LibSafeMath|LibSafeMath64|LibSafeMath96|LibSignatureValidator|LibStakingRichErrors|MixinConstants|MixinDelegatedStake|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinOwnable|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakingPool|MixinStakingPoolRewardVault|MixinStakingPoolRewards|MixinStorage|MixinTimeLockedStake|MixinVaultCore|MixinZrxVault|Staking|StakingPoolRewardVault|StakingProxy|ZrxVault).json",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||
},
|
||||
"repository": {
|
||||
|
||||
@@ -14,8 +14,7 @@ import * as IVaultCore from '../generated-artifacts/IVaultCore.json';
|
||||
import * as IWallet from '../generated-artifacts/IWallet.json';
|
||||
import * as IZrxVault from '../generated-artifacts/IZrxVault.json';
|
||||
import * as LibEIP712Hash from '../generated-artifacts/LibEIP712Hash.json';
|
||||
import * as LibFeeMath from '../generated-artifacts/LibFeeMath.json';
|
||||
import * as LibFeeMathTest from '../generated-artifacts/LibFeeMathTest.json';
|
||||
import * as LibFixedMath from '../generated-artifacts/LibFixedMath.json';
|
||||
import * as LibRewardMath from '../generated-artifacts/LibRewardMath.json';
|
||||
import * as LibSafeDowncast from '../generated-artifacts/LibSafeDowncast.json';
|
||||
import * as LibSignatureValidator from '../generated-artifacts/LibSignatureValidator.json';
|
||||
@@ -29,8 +28,8 @@ import * as MixinScheduler from '../generated-artifacts/MixinScheduler.json';
|
||||
import * as MixinStake from '../generated-artifacts/MixinStake.json';
|
||||
import * as MixinStakeBalances from '../generated-artifacts/MixinStakeBalances.json';
|
||||
import * as MixinStakingPool from '../generated-artifacts/MixinStakingPool.json';
|
||||
import * as MixinStakingPoolRewards from '../generated-artifacts/MixinStakingPoolRewards.json';
|
||||
import * as MixinStakingPoolRewardVault from '../generated-artifacts/MixinStakingPoolRewardVault.json';
|
||||
import * as MixinStakingPoolRewards from '../generated-artifacts/MixinStakingPoolRewards.json';
|
||||
import * as MixinStorage from '../generated-artifacts/MixinStorage.json';
|
||||
import * as MixinTimeLockedStake from '../generated-artifacts/MixinTimeLockedStake.json';
|
||||
import * as MixinVaultCore from '../generated-artifacts/MixinVaultCore.json';
|
||||
@@ -57,7 +56,7 @@ export const artifacts = {
|
||||
IWallet: IWallet as ContractArtifact,
|
||||
IZrxVault: IZrxVault as ContractArtifact,
|
||||
LibEIP712Hash: LibEIP712Hash as ContractArtifact,
|
||||
LibFeeMath: LibFeeMath as ContractArtifact,
|
||||
LibFixedMath: LibFixedMath as ContractArtifact,
|
||||
LibRewardMath: LibRewardMath as ContractArtifact,
|
||||
LibSafeDowncast: LibSafeDowncast as ContractArtifact,
|
||||
LibSignatureValidator: LibSignatureValidator as ContractArtifact,
|
||||
|
||||
@@ -12,8 +12,7 @@ export * from '../generated-wrappers/i_vault_core';
|
||||
export * from '../generated-wrappers/i_wallet';
|
||||
export * from '../generated-wrappers/i_zrx_vault';
|
||||
export * from '../generated-wrappers/lib_e_i_p712_hash';
|
||||
export * from '../generated-wrappers/lib_fee_math';
|
||||
export * from '../generated-wrappers/lib_fee_math_test';
|
||||
export * from '../generated-wrappers/lib_fixed_math';
|
||||
export * from '../generated-wrappers/lib_reward_math';
|
||||
export * from '../generated-wrappers/lib_safe_downcast';
|
||||
export * from '../generated-wrappers/lib_signature_validator';
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
"generated-artifacts/IWallet.json",
|
||||
"generated-artifacts/IZrxVault.json",
|
||||
"generated-artifacts/LibEIP712Hash.json",
|
||||
"generated-artifacts/LibFeeMath.json",
|
||||
"generated-artifacts/LibFeeMathTest.json",
|
||||
"generated-artifacts/LibFixedMath.json",
|
||||
"generated-artifacts/LibRewardMath.json",
|
||||
"generated-artifacts/LibSafeDowncast.json",
|
||||
"generated-artifacts/LibSignatureValidator.json",
|
||||
|
||||
Reference in New Issue
Block a user