Merge pull request #2207 from 0xProject/fix/3.0/improve-readability
Improve readability, fix `_trySetCumulativeReward` logic
This commit is contained in:
commit
96c8da9fdd
@ -41,10 +41,10 @@ contract MixinStake is
|
|||||||
getZrxVault().depositFrom(staker, amount);
|
getZrxVault().depositFrom(staker, amount);
|
||||||
|
|
||||||
// mint stake
|
// mint stake
|
||||||
_incrementCurrentAndNextBalance(_activeStakeByOwner[staker], amount);
|
_increaseCurrentAndNextBalance(_activeStakeByOwner[staker], amount);
|
||||||
|
|
||||||
// update global total of active stake
|
// update global total of active stake
|
||||||
_incrementCurrentAndNextBalance(globalStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)], amount);
|
_increaseCurrentAndNextBalance(globalStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)], amount);
|
||||||
|
|
||||||
// notify
|
// notify
|
||||||
emit Stake(
|
emit Stake(
|
||||||
@ -74,10 +74,10 @@ contract MixinStake is
|
|||||||
}
|
}
|
||||||
|
|
||||||
// burn inactive stake
|
// burn inactive stake
|
||||||
_decrementCurrentAndNextBalance(_inactiveStakeByOwner[staker], amount);
|
_decreaseCurrentAndNextBalance(_inactiveStakeByOwner[staker], amount);
|
||||||
|
|
||||||
// update global total of inactive stake
|
// update global total of inactive stake
|
||||||
_decrementCurrentAndNextBalance(globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)], amount);
|
_decreaseCurrentAndNextBalance(globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)], amount);
|
||||||
|
|
||||||
// update withdrawable field
|
// update withdrawable field
|
||||||
_withdrawableStakeByOwner[staker] =
|
_withdrawableStakeByOwner[staker] =
|
||||||
@ -186,30 +186,19 @@ contract MixinStake is
|
|||||||
// Sanity check the pool we're delegating to exists.
|
// Sanity check the pool we're delegating to exists.
|
||||||
_assertStakingPoolExists(poolId);
|
_assertStakingPoolExists(poolId);
|
||||||
|
|
||||||
// Cache amount delegated to pool by staker.
|
_withdrawAndSyncDelegatorRewards(
|
||||||
IStructs.StoredBalance memory initDelegatedStakeToPoolByOwner =
|
poolId,
|
||||||
_loadUnsyncedBalance(_delegatedStakeToPoolByOwner[staker][poolId]);
|
staker
|
||||||
|
);
|
||||||
|
|
||||||
// Increment how much stake the staker has delegated to the input pool.
|
// Increment how much stake the staker has delegated to the input pool.
|
||||||
_incrementNextBalance(
|
_increaseNextBalance(
|
||||||
_delegatedStakeToPoolByOwner[staker][poolId],
|
_delegatedStakeToPoolByOwner[staker][poolId],
|
||||||
amount
|
amount
|
||||||
);
|
);
|
||||||
|
|
||||||
// Increment how much stake has been delegated to pool.
|
// Increment how much stake has been delegated to pool.
|
||||||
_incrementNextBalance(_delegatedStakeByPoolId[poolId], amount);
|
_increaseNextBalance(_delegatedStakeByPoolId[poolId], amount);
|
||||||
|
|
||||||
// Synchronizes reward state in the pool that the owner is delegating
|
|
||||||
// to.
|
|
||||||
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
|
|
||||||
_loadSyncedBalance(_delegatedStakeToPoolByOwner[staker][poolId]);
|
|
||||||
|
|
||||||
_withdrawAndSyncDelegatorRewards(
|
|
||||||
poolId,
|
|
||||||
staker,
|
|
||||||
initDelegatedStakeToPoolByOwner,
|
|
||||||
finalDelegatedStakeToPoolByOwner
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Un-Delegates a owners stake from a staking pool.
|
/// @dev Un-Delegates a owners stake from a staking pool.
|
||||||
@ -226,30 +215,19 @@ contract MixinStake is
|
|||||||
// sanity check the pool we're undelegating from exists
|
// sanity check the pool we're undelegating from exists
|
||||||
_assertStakingPoolExists(poolId);
|
_assertStakingPoolExists(poolId);
|
||||||
|
|
||||||
// cache amount delegated to pool by staker
|
_withdrawAndSyncDelegatorRewards(
|
||||||
IStructs.StoredBalance memory initDelegatedStakeToPoolByOwner =
|
poolId,
|
||||||
_loadUnsyncedBalance(_delegatedStakeToPoolByOwner[staker][poolId]);
|
staker
|
||||||
|
);
|
||||||
|
|
||||||
// decrement how much stake the staker has delegated to the input pool
|
// decrement how much stake the staker has delegated to the input pool
|
||||||
_decrementNextBalance(
|
_decreaseNextBalance(
|
||||||
_delegatedStakeToPoolByOwner[staker][poolId],
|
_delegatedStakeToPoolByOwner[staker][poolId],
|
||||||
amount
|
amount
|
||||||
);
|
);
|
||||||
|
|
||||||
// decrement how much stake has been delegated to pool
|
// decrement how much stake has been delegated to pool
|
||||||
_decrementNextBalance(_delegatedStakeByPoolId[poolId], amount);
|
_decreaseNextBalance(_delegatedStakeByPoolId[poolId], amount);
|
||||||
|
|
||||||
// synchronizes reward state in the pool that the owner is undelegating
|
|
||||||
// from
|
|
||||||
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
|
|
||||||
_loadSyncedBalance(_delegatedStakeToPoolByOwner[staker][poolId]);
|
|
||||||
|
|
||||||
_withdrawAndSyncDelegatorRewards(
|
|
||||||
poolId,
|
|
||||||
staker,
|
|
||||||
initDelegatedStakeToPoolByOwner,
|
|
||||||
finalDelegatedStakeToPoolByOwner
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Returns a storage pointer to a user's stake in a given status.
|
/// @dev Returns a storage pointer to a user's stake in a given status.
|
||||||
|
@ -111,7 +111,7 @@ contract MixinStakeStorage is
|
|||||||
/// @dev Increments both the `current` and `next` fields.
|
/// @dev Increments both the `current` and `next` fields.
|
||||||
/// @param balancePtr storage pointer to balance.
|
/// @param balancePtr storage pointer to balance.
|
||||||
/// @param amount to mint.
|
/// @param amount to mint.
|
||||||
function _incrementCurrentAndNextBalance(IStructs.StoredBalance storage balancePtr, uint256 amount)
|
function _increaseCurrentAndNextBalance(IStructs.StoredBalance storage balancePtr, uint256 amount)
|
||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
// Remove stake from balance
|
// Remove stake from balance
|
||||||
@ -126,7 +126,7 @@ contract MixinStakeStorage is
|
|||||||
/// @dev Decrements both the `current` and `next` fields.
|
/// @dev Decrements both the `current` and `next` fields.
|
||||||
/// @param balancePtr storage pointer to balance.
|
/// @param balancePtr storage pointer to balance.
|
||||||
/// @param amount to mint.
|
/// @param amount to mint.
|
||||||
function _decrementCurrentAndNextBalance(IStructs.StoredBalance storage balancePtr, uint256 amount)
|
function _decreaseCurrentAndNextBalance(IStructs.StoredBalance storage balancePtr, uint256 amount)
|
||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
// Remove stake from balance
|
// Remove stake from balance
|
||||||
@ -141,7 +141,7 @@ contract MixinStakeStorage is
|
|||||||
/// @dev Increments the `next` field (but not the `current` field).
|
/// @dev Increments the `next` field (but not the `current` field).
|
||||||
/// @param balancePtr storage pointer to balance.
|
/// @param balancePtr storage pointer to balance.
|
||||||
/// @param amount to increment by.
|
/// @param amount to increment by.
|
||||||
function _incrementNextBalance(IStructs.StoredBalance storage balancePtr, uint256 amount)
|
function _increaseNextBalance(IStructs.StoredBalance storage balancePtr, uint256 amount)
|
||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
// Add stake to balance
|
// Add stake to balance
|
||||||
@ -155,7 +155,7 @@ contract MixinStakeStorage is
|
|||||||
/// @dev Decrements the `next` field (but not the `current` field).
|
/// @dev Decrements the `next` field (but not the `current` field).
|
||||||
/// @param balancePtr storage pointer to balance.
|
/// @param balancePtr storage pointer to balance.
|
||||||
/// @param amount to decrement by.
|
/// @param amount to decrement by.
|
||||||
function _decrementNextBalance(IStructs.StoredBalance storage balancePtr, uint256 amount)
|
function _decreaseNextBalance(IStructs.StoredBalance storage balancePtr, uint256 amount)
|
||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
// Remove stake from balance
|
// Remove stake from balance
|
||||||
|
@ -37,7 +37,6 @@ contract MixinCumulativeRewards is
|
|||||||
// Sets the default cumulative reward
|
// Sets the default cumulative reward
|
||||||
_forceSetCumulativeReward(
|
_forceSetCumulativeReward(
|
||||||
poolId,
|
poolId,
|
||||||
currentEpoch,
|
|
||||||
IStructs.Fraction({
|
IStructs.Fraction({
|
||||||
numerator: 0,
|
numerator: 0,
|
||||||
denominator: MIN_TOKEN_VALUE
|
denominator: MIN_TOKEN_VALUE
|
||||||
@ -57,89 +56,23 @@ contract MixinCumulativeRewards is
|
|||||||
return cumulativeReward.denominator != 0;
|
return cumulativeReward.denominator != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Tries to set a cumulative reward for `poolId` at `epoch`.
|
|
||||||
/// @param poolId Unique Id of pool.
|
|
||||||
/// @param epoch Epoch of cumulative reward.
|
|
||||||
/// @param value Value of cumulative reward.
|
|
||||||
function _trySetCumulativeReward(
|
|
||||||
bytes32 poolId,
|
|
||||||
uint256 epoch,
|
|
||||||
IStructs.Fraction memory value
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
{
|
|
||||||
// Do nothing if it's in the past since we don't want to
|
|
||||||
// rewrite history.
|
|
||||||
if (epoch < currentEpoch
|
|
||||||
&& _isCumulativeRewardSet(_cumulativeRewardsByPool[poolId][epoch]))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_forceSetCumulativeReward(poolId, epoch, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Sets a cumulative reward for `poolId` at `epoch`.
|
/// @dev Sets a cumulative reward for `poolId` at `epoch`.
|
||||||
/// This can be used to overwrite an existing value.
|
/// This can be used to overwrite an existing value.
|
||||||
/// @param poolId Unique Id of pool.
|
/// @param poolId Unique Id of pool.
|
||||||
/// @param epoch Epoch of cumulative reward.
|
|
||||||
/// @param value Value of cumulative reward.
|
/// @param value Value of cumulative reward.
|
||||||
function _forceSetCumulativeReward(
|
function _forceSetCumulativeReward(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
uint256 epoch,
|
|
||||||
IStructs.Fraction memory value
|
IStructs.Fraction memory value
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
_cumulativeRewardsByPool[poolId][epoch] = value;
|
uint256 currentEpoch_ = currentEpoch;
|
||||||
|
_cumulativeRewardsByPool[poolId][currentEpoch_] = value;
|
||||||
// Never set the most recent reward epoch to one in the future, because
|
|
||||||
// it may get removed if there are no more dependencies on it.
|
|
||||||
if (epoch <= currentEpoch) {
|
|
||||||
_trySetMostRecentCumulativeRewardEpoch(poolId, epoch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Tries to set the epoch of the most recent cumulative reward.
|
|
||||||
/// The value will only be set if the input epoch is greater than the
|
|
||||||
/// current most recent value.
|
|
||||||
/// @param poolId Unique Id of pool.
|
|
||||||
/// @param epoch Epoch of the most recent cumulative reward.
|
|
||||||
function _trySetMostRecentCumulativeRewardEpoch(
|
|
||||||
bytes32 poolId,
|
|
||||||
uint256 epoch
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
{
|
|
||||||
// Check if we should do any work
|
|
||||||
uint256 currentMostRecentEpoch = _cumulativeRewardsByPoolLastStored[poolId];
|
|
||||||
if (epoch == currentMostRecentEpoch) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update state to reflect the most recent cumulative reward
|
// Update state to reflect the most recent cumulative reward
|
||||||
_forceSetMostRecentCumulativeRewardEpoch(
|
uint256 currentMostRecentEpoch = _cumulativeRewardsByPoolLastStored[poolId];
|
||||||
poolId,
|
assert(currentEpoch_ >= currentMostRecentEpoch);
|
||||||
currentMostRecentEpoch,
|
_cumulativeRewardsByPoolLastStored[poolId] = currentEpoch_;
|
||||||
epoch
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Forcefully sets the epoch of the most recent cumulative reward.
|
|
||||||
/// @param poolId Unique Id of pool.
|
|
||||||
/// @param currentMostRecentEpoch Epoch of the most recent cumulative
|
|
||||||
/// reward.
|
|
||||||
/// @param newMostRecentEpoch Epoch of the new most recent cumulative
|
|
||||||
/// reward.
|
|
||||||
function _forceSetMostRecentCumulativeRewardEpoch(
|
|
||||||
bytes32 poolId,
|
|
||||||
uint256 currentMostRecentEpoch,
|
|
||||||
uint256 newMostRecentEpoch
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
{
|
|
||||||
// Sanity check that we're not trying to go back in time
|
|
||||||
assert(newMostRecentEpoch >= currentMostRecentEpoch);
|
|
||||||
_cumulativeRewardsByPoolLastStored[poolId] = newMostRecentEpoch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Computes a member's reward over a given epoch interval.
|
/// @dev Computes a member's reward over a given epoch interval.
|
||||||
|
@ -44,21 +44,15 @@ contract MixinStakingPoolRewards is
|
|||||||
{
|
{
|
||||||
address member = msg.sender;
|
address member = msg.sender;
|
||||||
|
|
||||||
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
|
|
||||||
_loadSyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]);
|
|
||||||
|
|
||||||
_withdrawAndSyncDelegatorRewards(
|
_withdrawAndSyncDelegatorRewards(
|
||||||
poolId,
|
poolId,
|
||||||
member,
|
member
|
||||||
// Initial balance
|
|
||||||
_loadUnsyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]),
|
|
||||||
finalDelegatedStakeToPoolByOwner
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update stored balance with synchronized version; this prevents
|
// Update stored balance with synchronized version; this prevents
|
||||||
// redundant withdrawals.
|
// redundant withdrawals.
|
||||||
_delegatedStakeToPoolByOwner[member][poolId] =
|
_delegatedStakeToPoolByOwner[member][poolId] =
|
||||||
finalDelegatedStakeToPoolByOwner;
|
_loadSyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Computes the reward balance in ETH of the operator of a pool.
|
/// @dev Computes the reward balance in ETH of the operator of a pool.
|
||||||
@ -108,7 +102,7 @@ contract MixinStakingPoolRewards is
|
|||||||
);
|
);
|
||||||
return _computeDelegatorReward(
|
return _computeDelegatorReward(
|
||||||
poolId,
|
poolId,
|
||||||
_loadUnsyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]),
|
member,
|
||||||
unfinalizedMembersReward,
|
unfinalizedMembersReward,
|
||||||
unfinalizedMembersStake
|
unfinalizedMembersStake
|
||||||
);
|
);
|
||||||
@ -118,34 +112,42 @@ contract MixinStakingPoolRewards is
|
|||||||
/// withdrawing rewards and adding/removing dependencies on cumulative rewards.
|
/// withdrawing rewards and adding/removing dependencies on cumulative rewards.
|
||||||
/// @param poolId Unique id of pool.
|
/// @param poolId Unique id of pool.
|
||||||
/// @param member of the pool.
|
/// @param member of the pool.
|
||||||
/// @param initialDelegatedStakeToPoolByOwner The member's delegated
|
|
||||||
/// balance at the beginning of this transaction.
|
|
||||||
/// @param finalDelegatedStakeToPoolByOwner The member's delegated balance
|
|
||||||
/// at the end of this transaction.
|
|
||||||
function _withdrawAndSyncDelegatorRewards(
|
function _withdrawAndSyncDelegatorRewards(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
address member,
|
address member
|
||||||
IStructs.StoredBalance memory initialDelegatedStakeToPoolByOwner,
|
|
||||||
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner
|
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
// Withdraw any rewards from.
|
// Ensure the pool is finalized.
|
||||||
// this must be done before we can modify the staker's portion of the
|
finalizePool(poolId);
|
||||||
// delegator pool.
|
|
||||||
_finalizePoolAndWithdrawDelegatorRewards(
|
// Compute balance owed to delegator
|
||||||
|
uint256 balance = _computeDelegatorReward(
|
||||||
poolId,
|
poolId,
|
||||||
member,
|
member,
|
||||||
initialDelegatedStakeToPoolByOwner
|
// No unfinalized values because we ensured the pool is already
|
||||||
|
// finalized.
|
||||||
|
0,
|
||||||
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add dependencies on cumulative rewards for this epoch and the next
|
// Withdraw non-0 balance
|
||||||
// epoch, if necessary.
|
if (balance != 0) {
|
||||||
_setCumulativeRewardDependenciesForDelegator(
|
// Decrease the balance of the pool
|
||||||
|
_decreasePoolRewards(poolId, balance);
|
||||||
|
|
||||||
|
// Withdraw the member's WETH balance
|
||||||
|
getWethContract().transfer(member, balance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a cumulative reward entry for this epoch.
|
||||||
|
if (!_isCumulativeRewardSet(_cumulativeRewardsByPool[poolId][currentEpoch])) {
|
||||||
|
_forceSetCumulativeReward(
|
||||||
poolId,
|
poolId,
|
||||||
finalDelegatedStakeToPoolByOwner
|
_getMostRecentCumulativeReward(poolId)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Handles a pool's reward at the current epoch.
|
/// @dev Handles a pool's reward at the current epoch.
|
||||||
/// This will split the reward between the operator and members,
|
/// This will split the reward between the operator and members,
|
||||||
@ -205,7 +207,6 @@ contract MixinStakingPoolRewards is
|
|||||||
// Store cumulative rewards for this epoch.
|
// Store cumulative rewards for this epoch.
|
||||||
_forceSetCumulativeReward(
|
_forceSetCumulativeReward(
|
||||||
poolId,
|
poolId,
|
||||||
currentEpoch,
|
|
||||||
cumulativeReward
|
cumulativeReward
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -244,50 +245,15 @@ contract MixinStakingPoolRewards is
|
|||||||
return (operatorReward, membersReward);
|
return (operatorReward, membersReward);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Transfers a delegators accumulated rewards to the delegator.
|
|
||||||
/// This is required before the member's stake in the pool can be modified.
|
|
||||||
/// @param poolId Unique id of pool.
|
|
||||||
/// @param member The member of the pool.
|
|
||||||
/// @param unsyncedStake Unsynced stake of the delegator to the pool.
|
|
||||||
function _finalizePoolAndWithdrawDelegatorRewards(
|
|
||||||
bytes32 poolId,
|
|
||||||
address member,
|
|
||||||
IStructs.StoredBalance memory unsyncedStake
|
|
||||||
)
|
|
||||||
private
|
|
||||||
{
|
|
||||||
// Ensure the pool is finalized.
|
|
||||||
finalizePool(poolId);
|
|
||||||
|
|
||||||
// Compute balance owed to delegator
|
|
||||||
uint256 balance = _computeDelegatorReward(
|
|
||||||
poolId,
|
|
||||||
unsyncedStake,
|
|
||||||
// No unfinalized values because we ensured the pool is already
|
|
||||||
// finalized.
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
if (balance == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrease the balance of the pool
|
|
||||||
_decreasePoolRewards(poolId, balance);
|
|
||||||
|
|
||||||
// Withdraw the member's WETH balance
|
|
||||||
getWethContract().transfer(member, balance);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Computes the reward balance in ETH of a specific member of a pool.
|
/// @dev Computes the reward balance in ETH of a specific member of a pool.
|
||||||
/// @param poolId Unique id of pool.
|
/// @param poolId Unique id of pool.
|
||||||
/// @param unsyncedStake Unsynced delegated stake to pool by staker
|
/// @param member of the pool.
|
||||||
/// @param unfinalizedMembersReward Unfinalized total members reward (if any).
|
/// @param unfinalizedMembersReward Unfinalized total members reward (if any).
|
||||||
/// @param unfinalizedMembersStake Unfinalized total members stake (if any).
|
/// @param unfinalizedMembersStake Unfinalized total members stake (if any).
|
||||||
/// @return reward Balance in WETH.
|
/// @return reward Balance in WETH.
|
||||||
function _computeDelegatorReward(
|
function _computeDelegatorReward(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
IStructs.StoredBalance memory unsyncedStake,
|
address member,
|
||||||
uint256 unfinalizedMembersReward,
|
uint256 unfinalizedMembersReward,
|
||||||
uint256 unfinalizedMembersStake
|
uint256 unfinalizedMembersStake
|
||||||
)
|
)
|
||||||
@ -302,6 +268,9 @@ contract MixinStakingPoolRewards is
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IStructs.StoredBalance memory unsyncedStake =
|
||||||
|
_loadUnsyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]);
|
||||||
|
|
||||||
// There can be no rewards if the last epoch when stake was synced is
|
// There can be no rewards if the last epoch when stake was synced is
|
||||||
// equal to the current epoch, because all prior rewards, including
|
// equal to the current epoch, because all prior rewards, including
|
||||||
// rewards finalized this epoch have been claimed.
|
// rewards finalized this epoch have been claimed.
|
||||||
@ -384,36 +353,6 @@ contract MixinStakingPoolRewards is
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Adds or removes cumulative reward dependencies for a delegator.
|
|
||||||
/// A delegator always depends on the cumulative reward for the current
|
|
||||||
/// and next epoch, if they would still have stake in the next epoch.
|
|
||||||
/// @param poolId Unique id of pool.
|
|
||||||
/// @param _delegatedStakeToPoolByOwner Amount of stake the member has
|
|
||||||
/// delegated to the pool.
|
|
||||||
function _setCumulativeRewardDependenciesForDelegator(
|
|
||||||
bytes32 poolId,
|
|
||||||
IStructs.StoredBalance memory _delegatedStakeToPoolByOwner
|
|
||||||
)
|
|
||||||
private
|
|
||||||
{
|
|
||||||
// Get the most recent cumulative reward, which will serve as a
|
|
||||||
// reference point when updating dependencies
|
|
||||||
IStructs.Fraction memory mostRecentCumulativeReward = _getMostRecentCumulativeReward(poolId);
|
|
||||||
|
|
||||||
// The delegator depends on the Cumulative Reward for this epoch
|
|
||||||
// only if they are currently staked or will be staked next epoch.
|
|
||||||
if (_delegatedStakeToPoolByOwner.currentEpochBalance == 0 && _delegatedStakeToPoolByOwner.nextEpochBalance == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delegator depends on the Cumulative Reward for this epoch - ensure it is set.
|
|
||||||
_trySetCumulativeReward(
|
|
||||||
poolId,
|
|
||||||
_delegatedStakeToPoolByOwner.currentEpoch,
|
|
||||||
mostRecentCumulativeReward
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Increases rewards for a pool.
|
/// @dev Increases rewards for a pool.
|
||||||
/// @param poolId Unique id of pool.
|
/// @param poolId Unique id of pool.
|
||||||
/// @param amount Amount to increment rewards by.
|
/// @param amount Amount to increment rewards by.
|
||||||
|
@ -30,11 +30,6 @@ contract TestCumulativeRewardTracking is
|
|||||||
uint256 epoch
|
uint256 epoch
|
||||||
);
|
);
|
||||||
|
|
||||||
event SetMostRecentCumulativeReward(
|
|
||||||
bytes32 poolId,
|
|
||||||
uint256 epoch
|
|
||||||
);
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
address wethAddress,
|
address wethAddress,
|
||||||
address zrxVaultAddress
|
address zrxVaultAddress
|
||||||
@ -51,31 +46,14 @@ contract TestCumulativeRewardTracking is
|
|||||||
|
|
||||||
function _forceSetCumulativeReward(
|
function _forceSetCumulativeReward(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
uint256 epoch,
|
|
||||||
IStructs.Fraction memory value
|
IStructs.Fraction memory value
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
emit SetCumulativeReward(poolId, epoch);
|
emit SetCumulativeReward(poolId, currentEpoch);
|
||||||
MixinCumulativeRewards._forceSetCumulativeReward(
|
MixinCumulativeRewards._forceSetCumulativeReward(
|
||||||
poolId,
|
poolId,
|
||||||
epoch,
|
|
||||||
value
|
value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _forceSetMostRecentCumulativeRewardEpoch(
|
|
||||||
bytes32 poolId,
|
|
||||||
uint256 currentMostRecentEpoch,
|
|
||||||
uint256 newMostRecentEpoch
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
{
|
|
||||||
emit SetMostRecentCumulativeReward(poolId, newMostRecentEpoch);
|
|
||||||
MixinCumulativeRewards._forceSetMostRecentCumulativeRewardEpoch(
|
|
||||||
poolId,
|
|
||||||
currentMostRecentEpoch,
|
|
||||||
newMostRecentEpoch
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,10 @@ contract TestDelegatorRewards is
|
|||||||
external
|
external
|
||||||
{
|
{
|
||||||
_initGenesisCumulativeRewards(poolId);
|
_initGenesisCumulativeRewards(poolId);
|
||||||
IStructs.StoredBalance memory initialStake = _delegatedStakeToPoolByOwner[delegator][poolId];
|
_withdrawAndSyncDelegatorRewards(
|
||||||
|
poolId,
|
||||||
|
delegator
|
||||||
|
);
|
||||||
IStructs.StoredBalance storage _stake = _delegatedStakeToPoolByOwner[delegator][poolId];
|
IStructs.StoredBalance storage _stake = _delegatedStakeToPoolByOwner[delegator][poolId];
|
||||||
_stake.isInitialized = true;
|
_stake.isInitialized = true;
|
||||||
_stake.currentEpochBalance += uint96(stake);
|
_stake.currentEpochBalance += uint96(stake);
|
||||||
@ -118,9 +121,7 @@ contract TestDelegatorRewards is
|
|||||||
_stake.currentEpoch = uint32(currentEpoch);
|
_stake.currentEpoch = uint32(currentEpoch);
|
||||||
_withdrawAndSyncDelegatorRewards(
|
_withdrawAndSyncDelegatorRewards(
|
||||||
poolId,
|
poolId,
|
||||||
delegator,
|
delegator
|
||||||
initialStake,
|
|
||||||
_stake
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +136,10 @@ contract TestDelegatorRewards is
|
|||||||
external
|
external
|
||||||
{
|
{
|
||||||
_initGenesisCumulativeRewards(poolId);
|
_initGenesisCumulativeRewards(poolId);
|
||||||
IStructs.StoredBalance memory initialStake = _delegatedStakeToPoolByOwner[delegator][poolId];
|
_withdrawAndSyncDelegatorRewards(
|
||||||
|
poolId,
|
||||||
|
delegator
|
||||||
|
);
|
||||||
IStructs.StoredBalance storage _stake = _delegatedStakeToPoolByOwner[delegator][poolId];
|
IStructs.StoredBalance storage _stake = _delegatedStakeToPoolByOwner[delegator][poolId];
|
||||||
if (_stake.currentEpoch < currentEpoch) {
|
if (_stake.currentEpoch < currentEpoch) {
|
||||||
_stake.currentEpochBalance = _stake.nextEpochBalance;
|
_stake.currentEpochBalance = _stake.nextEpochBalance;
|
||||||
@ -143,12 +147,6 @@ contract TestDelegatorRewards is
|
|||||||
_stake.isInitialized = true;
|
_stake.isInitialized = true;
|
||||||
_stake.nextEpochBalance += uint96(stake);
|
_stake.nextEpochBalance += uint96(stake);
|
||||||
_stake.currentEpoch = uint32(currentEpoch);
|
_stake.currentEpoch = uint32(currentEpoch);
|
||||||
_withdrawAndSyncDelegatorRewards(
|
|
||||||
poolId,
|
|
||||||
delegator,
|
|
||||||
initialStake,
|
|
||||||
_stake
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Clear stake that will occur in the next epoch
|
/// @dev Clear stake that will occur in the next epoch
|
||||||
@ -162,7 +160,10 @@ contract TestDelegatorRewards is
|
|||||||
external
|
external
|
||||||
{
|
{
|
||||||
_initGenesisCumulativeRewards(poolId);
|
_initGenesisCumulativeRewards(poolId);
|
||||||
IStructs.StoredBalance memory initialStake = _delegatedStakeToPoolByOwner[delegator][poolId];
|
_withdrawAndSyncDelegatorRewards(
|
||||||
|
poolId,
|
||||||
|
delegator
|
||||||
|
);
|
||||||
IStructs.StoredBalance storage _stake = _delegatedStakeToPoolByOwner[delegator][poolId];
|
IStructs.StoredBalance storage _stake = _delegatedStakeToPoolByOwner[delegator][poolId];
|
||||||
if (_stake.currentEpoch < currentEpoch) {
|
if (_stake.currentEpoch < currentEpoch) {
|
||||||
_stake.currentEpochBalance = _stake.nextEpochBalance;
|
_stake.currentEpochBalance = _stake.nextEpochBalance;
|
||||||
@ -170,12 +171,6 @@ contract TestDelegatorRewards is
|
|||||||
_stake.isInitialized = true;
|
_stake.isInitialized = true;
|
||||||
_stake.nextEpochBalance -= uint96(stake);
|
_stake.nextEpochBalance -= uint96(stake);
|
||||||
_stake.currentEpoch = uint32(currentEpoch);
|
_stake.currentEpoch = uint32(currentEpoch);
|
||||||
_withdrawAndSyncDelegatorRewards(
|
|
||||||
poolId,
|
|
||||||
delegator,
|
|
||||||
initialStake,
|
|
||||||
_stake
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// solhint-disable no-simple-event-func-name
|
// solhint-disable no-simple-event-func-name
|
||||||
|
@ -22,7 +22,7 @@ pragma experimental ABIEncoderV2;
|
|||||||
import "../src/Staking.sol";
|
import "../src/Staking.sol";
|
||||||
|
|
||||||
|
|
||||||
// solhint-disable no-empty-blocks
|
// solhint-disable no-empty-blocks,no-simple-event-func-name
|
||||||
/// @dev A version of the staking contract with WETH-related functions
|
/// @dev A version of the staking contract with WETH-related functions
|
||||||
/// overridden to do nothing.
|
/// overridden to do nothing.
|
||||||
contract TestStakingNoWETH is
|
contract TestStakingNoWETH is
|
||||||
|
@ -39,7 +39,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
await simulation.runTestAsync(
|
await simulation.runTestAsync(
|
||||||
[TestAction.Finalize],
|
[TestAction.Finalize],
|
||||||
[TestAction.CreatePool],
|
[TestAction.CreatePool],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 1 }, { event: 'SetMostRecentCumulativeReward', epoch: 1 }],
|
[{ event: 'SetCumulativeReward', epoch: 1 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegating in the same epoch pool is created', async () => {
|
it('delegating in the same epoch pool is created', async () => {
|
||||||
@ -53,7 +53,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Creates CR for epoch 1
|
// Creates CR for epoch 1
|
||||||
TestAction.Delegate,
|
TestAction.Delegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 0 }],
|
[],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('re-delegating in the same epoch', async () => {
|
it('re-delegating in the same epoch', async () => {
|
||||||
@ -68,7 +68,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Updates CR for epoch 0
|
// Updates CR for epoch 0
|
||||||
TestAction.Delegate,
|
TestAction.Delegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 0 }, { event: 'SetCumulativeReward', epoch: 0 }],
|
[],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegating in new epoch', async () => {
|
it('delegating in new epoch', async () => {
|
||||||
@ -86,7 +86,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Unsets the CR for epoch 0
|
// Unsets the CR for epoch 0
|
||||||
TestAction.Delegate,
|
TestAction.Delegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 1 }, { event: 'SetMostRecentCumulativeReward', epoch: 1 }],
|
[{ event: 'SetCumulativeReward', epoch: 1 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('re-delegating in a new epoch', async () => {
|
it('re-delegating in a new epoch', async () => {
|
||||||
@ -105,7 +105,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Sets MRCR to epoch 1
|
// Sets MRCR to epoch 1
|
||||||
TestAction.Delegate,
|
TestAction.Delegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 1 }, { event: 'SetMostRecentCumulativeReward', epoch: 1 }],
|
[{ event: 'SetCumulativeReward', epoch: 1 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegating in epoch 1 then again in epoch 2', async () => {
|
it('delegating in epoch 1 then again in epoch 2', async () => {
|
||||||
@ -128,7 +128,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Clears CR for epoch 1
|
// Clears CR for epoch 1
|
||||||
TestAction.Delegate,
|
TestAction.Delegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 2 }, { event: 'SetMostRecentCumulativeReward', epoch: 2 }],
|
[{ event: 'SetCumulativeReward', epoch: 2 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegate in epoch 1 then undelegate in epoch 2', async () => {
|
it('delegate in epoch 1 then undelegate in epoch 2', async () => {
|
||||||
@ -152,7 +152,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Clear CR for epoch 1
|
// Clear CR for epoch 1
|
||||||
TestAction.Undelegate,
|
TestAction.Undelegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 2 }, { event: 'SetMostRecentCumulativeReward', epoch: 2 }],
|
[{ event: 'SetCumulativeReward', epoch: 2 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegate in epoch 0 and epoch 1, then undelegate half in epoch 2', async () => {
|
it('delegate in epoch 0 and epoch 1, then undelegate half in epoch 2', async () => {
|
||||||
@ -181,7 +181,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Clears CR for epoch 1
|
// Clears CR for epoch 1
|
||||||
TestAction.Undelegate,
|
TestAction.Undelegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 2 }, { event: 'SetMostRecentCumulativeReward', epoch: 2 }],
|
[{ event: 'SetCumulativeReward', epoch: 2 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegate in epoch 1 and 2 then again in 3', async () => {
|
it('delegate in epoch 1 and 2 then again in 3', async () => {
|
||||||
@ -210,7 +210,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Clears CR for epoch 1
|
// Clears CR for epoch 1
|
||||||
TestAction.Delegate,
|
TestAction.Delegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 2 }, { event: 'SetMostRecentCumulativeReward', epoch: 2 }],
|
[{ event: 'SetCumulativeReward', epoch: 2 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegate in epoch 0, earn reward in epoch 1', async () => {
|
it('delegate in epoch 0, earn reward in epoch 1', async () => {
|
||||||
@ -233,7 +233,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Sets MRCR to epoch 2
|
// Sets MRCR to epoch 2
|
||||||
TestAction.Finalize,
|
TestAction.Finalize,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 2 }, { event: 'SetMostRecentCumulativeReward', epoch: 2 }],
|
[{ event: 'SetCumulativeReward', epoch: 2 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegate in epoch 0, epoch 2, earn reward in epoch 3, then delegate', async () => {
|
it('delegate in epoch 0, epoch 2, earn reward in epoch 3, then delegate', async () => {
|
||||||
@ -268,7 +268,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Clears CR for epoch 2
|
// Clears CR for epoch 2
|
||||||
TestAction.Delegate,
|
TestAction.Delegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 3 }],
|
[],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegate in epoch 0 and 1, earn reward in epoch 3, then undelegate half', async () => {
|
it('delegate in epoch 0 and 1, earn reward in epoch 3, then undelegate half', async () => {
|
||||||
@ -303,7 +303,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Clears CR for epoch 2
|
// Clears CR for epoch 2
|
||||||
TestAction.Undelegate,
|
TestAction.Undelegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 3 }],
|
[],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegate in epoch 1, 2, earn rewards in epoch 3, skip to epoch 4, then delegate', async () => {
|
it('delegate in epoch 1, 2, earn rewards in epoch 3, skip to epoch 4, then delegate', async () => {
|
||||||
@ -341,7 +341,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Clears CR for epoch 1
|
// Clears CR for epoch 1
|
||||||
TestAction.Delegate,
|
TestAction.Delegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 4 }, { event: 'SetMostRecentCumulativeReward', epoch: 4 }],
|
[{ event: 'SetCumulativeReward', epoch: 4 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('earn reward in epoch 1 with no stake, then delegate', async () => {
|
it('earn reward in epoch 1 with no stake, then delegate', async () => {
|
||||||
@ -362,7 +362,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Creates CR for epoch 2
|
// Creates CR for epoch 2
|
||||||
TestAction.Delegate,
|
TestAction.Delegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 1 }, { event: 'SetMostRecentCumulativeReward', epoch: 1 }],
|
[{ event: 'SetCumulativeReward', epoch: 1 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegate in epoch 1, 3, then delegate in epoch 4', async () => {
|
it('delegate in epoch 1, 3, then delegate in epoch 4', async () => {
|
||||||
@ -397,7 +397,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Creates CR for epoch 5
|
// Creates CR for epoch 5
|
||||||
TestAction.Delegate,
|
TestAction.Delegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 4 }, { event: 'SetMostRecentCumulativeReward', epoch: 4 }],
|
[{ event: 'SetCumulativeReward', epoch: 4 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('delegate in epoch 1, then epoch 3', async () => {
|
it('delegate in epoch 1, then epoch 3', async () => {
|
||||||
@ -425,7 +425,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
|
|||||||
// Clears CR for epoch 2
|
// Clears CR for epoch 2
|
||||||
TestAction.Delegate,
|
TestAction.Delegate,
|
||||||
],
|
],
|
||||||
[{ event: 'SetCumulativeReward', epoch: 3 }, { event: 'SetMostRecentCumulativeReward', epoch: 3 }],
|
[{ event: 'SetCumulativeReward', epoch: 3 }],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -36,12 +36,7 @@ export class CumulativeRewardTrackingSimulation {
|
|||||||
private static _extractTestLogs(txReceiptLogs: DecodedLogs): TestLog[] {
|
private static _extractTestLogs(txReceiptLogs: DecodedLogs): TestLog[] {
|
||||||
const logs = [];
|
const logs = [];
|
||||||
for (const log of txReceiptLogs) {
|
for (const log of txReceiptLogs) {
|
||||||
if (log.event === TestCumulativeRewardTrackingEvents.SetMostRecentCumulativeReward) {
|
if (log.event === TestCumulativeRewardTrackingEvents.SetCumulativeReward) {
|
||||||
logs.push({
|
|
||||||
event: log.event,
|
|
||||||
epoch: log.args.epoch.toNumber(),
|
|
||||||
});
|
|
||||||
} else if (log.event === TestCumulativeRewardTrackingEvents.SetCumulativeReward) {
|
|
||||||
logs.push({
|
logs.push({
|
||||||
event: log.event,
|
event: log.event,
|
||||||
epoch: log.args.epoch.toNumber(),
|
epoch: log.args.epoch.toNumber(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user