Remove reference counting for cumulative rewards

This commit is contained in:
Greg Hysen
2019-09-23 13:10:47 -07:00
parent c29a22187c
commit 5b595dd080
6 changed files with 9 additions and 228 deletions

View File

@@ -94,9 +94,6 @@ contract MixinStorage is
// mapping from Pool Id to Epoch to Reward Ratio
mapping (bytes32 => mapping (uint256 => IStructs.Fraction)) internal _cumulativeRewardsByPool;
// mapping from Pool Id to Epoch to Cumulative Rewards Reference Counter
mapping (bytes32 => mapping (uint256 => uint256)) internal _cumulativeRewardsByPoolReferenceCounter;
// mapping from Pool Id to Epoch
mapping (bytes32 => uint256) internal _cumulativeRewardsByPoolLastStored;

View File

@@ -63,30 +63,6 @@ contract MixinCumulativeRewards is
return cumulativeReward.denominator != 0;
}
/// @dev Returns true iff the cumulative reward for `poolId` at `epoch` can
/// be unset.
/// @param poolId Unique id of pool.
/// @param epoch Epoch of the cumulative reward.
function _canUnsetCumulativeReward(bytes32 poolId, uint256 epoch)
internal
view
returns (bool)
{
// Must be a value to unset
if (!_isCumulativeRewardSet(_cumulativeRewardsByPool[poolId][epoch])) {
return false;
}
// Must be no references to this CR
if (_cumulativeRewardsByPoolReferenceCounter[poolId][epoch] != 0) {
return false;
}
// Must not be the most recently *stored* CR.
if (_cumulativeRewardsByPoolLastStored[poolId] == epoch) {
return false;
}
return true;
}
/// @dev Tries to set a cumulative reward for `poolId` at `epoch`.
/// @param poolId Unique Id of pool.
/// @param epoch Epoch of cumulative reward.
@@ -129,27 +105,6 @@ contract MixinCumulativeRewards is
}
}
/// @dev Tries to unset the cumulative reward for `poolId` at `epoch`.
/// @param poolId Unique id of pool.
/// @param epoch Epoch of cumulative reward to unset.
function _tryUnsetCumulativeReward(bytes32 poolId, uint256 epoch)
internal
{
if (!_canUnsetCumulativeReward(poolId, epoch)) {
return;
}
_forceUnsetCumulativeReward(poolId, epoch);
}
/// @dev Unsets the cumulative reward for `poolId` at `epoch`.
/// @param poolId Unique id of pool.
/// @param epoch Epoch of cumulative reward to unset.
function _forceUnsetCumulativeReward(bytes32 poolId, uint256 epoch)
internal
{
delete _cumulativeRewardsByPool[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.
@@ -191,37 +146,6 @@ contract MixinCumulativeRewards is
// Sanity check that we're not trying to go back in time
assert(newMostRecentEpoch >= currentMostRecentEpoch);
_cumulativeRewardsByPoolLastStored[poolId] = newMostRecentEpoch;
// Unset the previous most recent reward, if it is no longer needed
_tryUnsetCumulativeReward(poolId, currentMostRecentEpoch);
}
/// @dev Adds a dependency on a cumulative reward for a given epoch.
/// @param poolId Unique Id of pool.
/// @param epoch Epoch to remove dependency from.
/// @param mostRecentCumulativeReward The most recent cumulative reward.
/// @param isDependent True iff there is a dependency on the cumulative
/// reward for `poolId` at `epoch`
function _addOrRemoveDependencyOnCumulativeReward(
bytes32 poolId,
uint256 epoch,
IStructs.Fraction memory mostRecentCumulativeReward,
bool isDependent
)
internal
{
if (isDependent) {
_addDependencyOnCumulativeReward(
poolId,
epoch,
mostRecentCumulativeReward
);
} else {
_removeDependencyOnCumulativeReward(
poolId,
epoch
);
}
}
/// @dev Computes a member's reward over a given epoch interval.
@@ -279,44 +203,4 @@ contract MixinCumulativeRewards is
uint256 lastStoredEpoch = _cumulativeRewardsByPoolLastStored[poolId];
return _cumulativeRewardsByPool[poolId][lastStoredEpoch];
}
/// @dev Adds a dependency on a cumulative reward for a given epoch.
/// @param poolId Unique Id of pool.
/// @param epoch Epoch to remove dependency from.
/// @param mostRecentCumulativeReward The most recent cumulative reward.
function _addDependencyOnCumulativeReward(
bytes32 poolId,
uint256 epoch,
IStructs.Fraction memory mostRecentCumulativeReward
)
private
{
// Add dependency by increasing the reference counter
_cumulativeRewardsByPoolReferenceCounter[poolId][epoch] =
_cumulativeRewardsByPoolReferenceCounter[poolId][epoch].safeAdd(1);
// Set CR to most recent reward (if it is not already set)
_trySetCumulativeReward(
poolId,
epoch,
mostRecentCumulativeReward
);
}
/// @dev Removes a dependency on a cumulative reward for a given epoch.
/// @param poolId Unique Id of pool.
/// @param epoch Epoch to remove dependency from.
function _removeDependencyOnCumulativeReward(
bytes32 poolId,
uint256 epoch
)
private
{
// Remove dependency by decreasing reference counter
_cumulativeRewardsByPoolReferenceCounter[poolId][epoch] =
_cumulativeRewardsByPoolReferenceCounter[poolId][epoch].safeSub(1);
// Clear cumulative reward from state, if it is no longer needed
_tryUnsetCumulativeReward(poolId, epoch);
}
}

View File

@@ -152,16 +152,7 @@ contract MixinStakingPoolRewards is
// epoch, if necessary.
_setCumulativeRewardDependenciesForDelegator(
poolId,
finalDelegatedStakeToPoolByOwner,
true
);
// Remove dependencies on previous cumulative rewards, if they are no
// longer needed.
_setCumulativeRewardDependenciesForDelegator(
poolId,
initialDelegatedStakeToPoolByOwner,
false
finalDelegatedStakeToPoolByOwner
);
}
@@ -387,20 +378,12 @@ contract MixinStakingPoolRewards is
/// @param poolId Unique id of pool.
/// @param _delegatedStakeToPoolByOwner Amount of stake the member has
/// delegated to the pool.
/// @param isDependent is true iff adding a dependency. False, otherwise.
function _setCumulativeRewardDependenciesForDelegator(
bytes32 poolId,
IStructs.StoredBalance memory _delegatedStakeToPoolByOwner,
bool isDependent
IStructs.StoredBalance memory _delegatedStakeToPoolByOwner
)
private
{
// If this delegator is not yet initialized then there's no dependency
// to unset.
if (!isDependent && !_delegatedStakeToPoolByOwner.isInitialized) {
return;
}
// Get the most recent cumulative reward, which will serve as a
// reference point when updating dependencies
IStructs.Fraction memory mostRecentCumulativeReward = _getMostRecentCumulativeReward(poolId);
@@ -409,21 +392,19 @@ contract MixinStakingPoolRewards is
if (_delegatedStakeToPoolByOwner.currentEpochBalance != 0
|| _delegatedStakeToPoolByOwner.nextEpochBalance != 0)
{
_addOrRemoveDependencyOnCumulativeReward(
_trySetCumulativeReward(
poolId,
_delegatedStakeToPoolByOwner.currentEpoch,
mostRecentCumulativeReward,
isDependent
mostRecentCumulativeReward
);
}
// Record dependency on the next epoch
if (_delegatedStakeToPoolByOwner.nextEpochBalance != 0) {
_addOrRemoveDependencyOnCumulativeReward(
_trySetCumulativeReward(
poolId,
uint256(_delegatedStakeToPoolByOwner.currentEpoch).safeAdd(1),
mostRecentCumulativeReward,
isDependent
mostRecentCumulativeReward
);
}
}

View File

@@ -30,11 +30,6 @@ contract TestCumulativeRewardTracking is
uint256 epoch
);
event UnsetCumulativeReward(
bytes32 poolId,
uint256 epoch
);
event SetMostRecentCumulativeReward(
bytes32 poolId,
uint256 epoch
@@ -59,13 +54,6 @@ contract TestCumulativeRewardTracking is
);
}
function _forceUnsetCumulativeReward(bytes32 poolId, uint256 epoch)
internal
{
emit UnsetCumulativeReward(poolId, epoch);
MixinCumulativeRewards._forceUnsetCumulativeReward(poolId, epoch);
}
function _forceSetMostRecentCumulativeRewardEpoch(
bytes32 poolId,
uint256 currentMostRecentEpoch,

View File

@@ -78,22 +78,6 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
],
);
});
it('delegating then undelegating in the same epoch', async () => {
await simulation.runTestAsync(
[
// Creates CR for epoch 0
TestAction.CreatePool,
// Updates CR for epoch 0
// Creates CR for epoch 1
TestAction.Delegate,
],
[
// Unsets the CR for epoch 1
TestAction.Undelegate,
],
[{ event: 'UnsetCumulativeReward', epoch: 1 }],
);
});
it('delegating in new epoch', async () => {
// since there was no delegation in epoch 0 there is no longer a dependency on the CR for epoch 0
await simulation.runTestAsync(
@@ -113,7 +97,6 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
[
{ event: 'SetCumulativeReward', epoch: 1 },
{ event: 'SetMostRecentCumulativeReward', epoch: 1 },
{ event: 'UnsetCumulativeReward', epoch: 0 },
{ event: 'SetCumulativeReward', epoch: 2 },
],
);
@@ -140,32 +123,9 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
{ event: 'SetCumulativeReward', epoch: 1 },
{ event: 'SetMostRecentCumulativeReward', epoch: 1 },
{ event: 'SetCumulativeReward', epoch: 2 },
{ event: 'UnsetCumulativeReward', epoch: 0 },
],
);
});
it('delegate then undelegate to remove all dependencies', async () => {
await simulation.runTestAsync(
[
// Creates CR for epoch 0
TestAction.CreatePool,
// Moves to epoch 1
TestAction.Finalize,
// Creates CR for epoch 1
// Sets MRCR to epoch 1
// Clears CR for epoch 0
// Creates CR for epoch 2
TestAction.Delegate,
],
[
// Clears CR from epoch 2
// Does NOT clear CR from epoch 1 because it is the current
// epoch.
TestAction.Undelegate,
],
[{ event: 'UnsetCumulativeReward', epoch: 2 }],
);
});
it('delegating in epoch 1 then again in epoch 2', async () => {
await simulation.runTestAsync(
[
@@ -192,7 +152,6 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
{ event: 'SetCumulativeReward', epoch: 2 },
{ event: 'SetMostRecentCumulativeReward', epoch: 2 },
{ event: 'SetCumulativeReward', epoch: 3 },
{ event: 'UnsetCumulativeReward', epoch: 1 },
],
);
});
@@ -217,11 +176,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
// Clear CR for epoch 1
TestAction.Undelegate,
],
[
{ event: 'SetCumulativeReward', epoch: 2 },
{ event: 'SetMostRecentCumulativeReward', epoch: 2 },
{ event: 'UnsetCumulativeReward', epoch: 1 },
],
[{ event: 'SetCumulativeReward', epoch: 2 }, { event: 'SetMostRecentCumulativeReward', epoch: 2 }],
);
});
it('delegate in epoch 0 and epoch 1, then undelegate half in epoch 2', async () => {
@@ -254,7 +209,6 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
{ event: 'SetCumulativeReward', epoch: 2 },
{ event: 'SetMostRecentCumulativeReward', epoch: 2 },
{ event: 'SetCumulativeReward', epoch: 3 },
{ event: 'UnsetCumulativeReward', epoch: 1 },
],
);
});
@@ -288,7 +242,6 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
{ event: 'SetCumulativeReward', epoch: 2 },
{ event: 'SetMostRecentCumulativeReward', epoch: 2 },
{ event: 'SetCumulativeReward', epoch: 3 },
{ event: 'UnsetCumulativeReward', epoch: 1 },
],
);
});
@@ -347,12 +300,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
// Clears CR for epoch 2
TestAction.Delegate,
],
[
{ event: 'SetCumulativeReward', epoch: 3 },
{ event: 'SetCumulativeReward', epoch: 4 },
{ event: 'UnsetCumulativeReward', epoch: 1 },
{ event: 'UnsetCumulativeReward', epoch: 2 },
],
[{ event: 'SetCumulativeReward', epoch: 3 }, { event: 'SetCumulativeReward', epoch: 4 }],
);
});
it('delegate in epoch 0 and 1, earn reward in epoch 3, then undelegate half', async () => {
@@ -387,12 +335,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
// Clears CR for epoch 2
TestAction.Undelegate,
],
[
{ event: 'SetCumulativeReward', epoch: 3 },
{ event: 'SetCumulativeReward', epoch: 4 },
{ event: 'UnsetCumulativeReward', epoch: 1 },
{ event: 'UnsetCumulativeReward', epoch: 2 },
],
[{ event: 'SetCumulativeReward', epoch: 3 }, { event: 'SetCumulativeReward', epoch: 4 }],
);
});
it('delegate in epoch 1, 2, earn rewards in epoch 3, skip to epoch 4, then delegate', async () => {
@@ -433,10 +376,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
[
{ event: 'SetCumulativeReward', epoch: 4 },
{ event: 'SetMostRecentCumulativeReward', epoch: 4 },
{ event: 'UnsetCumulativeReward', epoch: 3 },
{ event: 'SetCumulativeReward', epoch: 5 },
{ event: 'UnsetCumulativeReward', epoch: 1 },
{ event: 'UnsetCumulativeReward', epoch: 2 },
],
);
});
@@ -461,7 +401,6 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
[
{ event: 'SetCumulativeReward', epoch: 1 },
{ event: 'SetMostRecentCumulativeReward', epoch: 1 },
{ event: 'UnsetCumulativeReward', epoch: 0 },
{ event: 'SetCumulativeReward', epoch: 2 },
],
);
@@ -502,7 +441,6 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
{ event: 'SetCumulativeReward', epoch: 4 },
{ event: 'SetMostRecentCumulativeReward', epoch: 4 },
{ event: 'SetCumulativeReward', epoch: 5 },
{ event: 'UnsetCumulativeReward', epoch: 3 },
],
);
});
@@ -535,8 +473,6 @@ blockchainTests.resets('Cumulative Reward Tracking', env => {
{ event: 'SetCumulativeReward', epoch: 3 },
{ event: 'SetMostRecentCumulativeReward', epoch: 3 },
{ event: 'SetCumulativeReward', epoch: 4 },
{ event: 'UnsetCumulativeReward', epoch: 1 },
{ event: 'UnsetCumulativeReward', epoch: 2 },
],
);
});

View File

@@ -46,11 +46,6 @@ export class CumulativeRewardTrackingSimulation {
event: log.event,
epoch: log.args.epoch.toNumber(),
});
} else if (log.event === TestCumulativeRewardTrackingEvents.UnsetCumulativeReward) {
logs.push({
event: log.event,
epoch: log.args.epoch.toNumber(),
});
}
}
return logs;