CamelCase for timelocks
This commit is contained in:
@@ -24,7 +24,7 @@ import "./stake/MixinZrxVault.sol";
|
||||
import "./staking_pools/MixinStakingPoolRewardVault.sol";
|
||||
import "./sys/MixinScheduler.sol";
|
||||
import "./stake/MixinStakeBalances.sol";
|
||||
import "./stake/MixinTimelockedStake.sol";
|
||||
import "./stake/MixinTimeLockedStake.sol";
|
||||
import "./stake/MixinStake.sol";
|
||||
import "./stake/MixinDelegatedStake.sol";
|
||||
import "./staking_pools/MixinStakingPool.sol";
|
||||
@@ -44,7 +44,7 @@ contract Staking is
|
||||
MixinStakingPoolRewardVault,
|
||||
MixinZrxVault,
|
||||
MixinStakingPool,
|
||||
MixinTimelockedStake,
|
||||
MixinTimeLockedStake,
|
||||
MixinStakeBalances,
|
||||
MixinStake,
|
||||
MixinStakingPoolRewards,
|
||||
|
@@ -50,7 +50,7 @@ contract MixinExchangeFees is
|
||||
MixinScheduler,
|
||||
MixinStakingPoolRewardVault,
|
||||
MixinStakingPool,
|
||||
MixinTimelockedStake,
|
||||
MixinTimeLockedStake,
|
||||
MixinStakeBalances
|
||||
{
|
||||
|
||||
|
@@ -42,8 +42,8 @@ contract MixinStorage is
|
||||
// mapping from Owner to Amount of Instactive Stake
|
||||
mapping (address => uint256) internal activatedStakeByOwner;
|
||||
|
||||
// mapping from Owner to Amount Timelocked
|
||||
mapping (address => IStructs.Timelock) internal timelockedStakeByOwner;
|
||||
// mapping from Owner to Amount TimeLocked
|
||||
mapping (address => IStructs.TimeLock) internal timeLockedStakeByOwner;
|
||||
|
||||
// mapping from Owner to Amount Delegated
|
||||
mapping (address => uint256) internal delegatedStakeByOwner;
|
||||
@@ -77,10 +77,10 @@ contract MixinStorage is
|
||||
uint64 internal currentEpochStartTimeInSeconds;
|
||||
|
||||
// current withdrawal period
|
||||
uint64 internal currentTimelockPeriod = INITIAL_TIMELOCK_PERIOD;
|
||||
uint64 internal currentTimeLockPeriod = INITIAL_TIMELOCK_PERIOD;
|
||||
|
||||
// current epoch start time
|
||||
uint64 internal currentTimelockPeriodStartEpoch = INITIAL_EPOCH;
|
||||
uint64 internal currentTimeLockPeriodStartEpoch = INITIAL_EPOCH;
|
||||
|
||||
// fees collected this epoch
|
||||
mapping (bytes32 => uint256) internal protocolFeesThisEpochByPool;
|
||||
|
@@ -41,12 +41,12 @@ interface IStakingEvents {
|
||||
uint64 earliestEndTimeInSeconds
|
||||
);
|
||||
|
||||
/// @dev Emitted by MixinScheduler when the timelock period is changed.
|
||||
/// @param timelockPeriod The timelock period we changed to.
|
||||
/// @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.
|
||||
/// @param endEpoch The epoch this period ends.
|
||||
event TimelockPeriodChanged(
|
||||
uint64 timelockPeriod,
|
||||
event TimeLockPeriodChanged(
|
||||
uint64 timeLockPeriod,
|
||||
uint64 startEpoch,
|
||||
uint64 endEpoch
|
||||
);
|
||||
|
@@ -58,13 +58,13 @@ interface IStructs {
|
||||
uint256 weightedStake;
|
||||
}
|
||||
|
||||
/// @dev Tracks timelocked stake (see MixinTimelockedStake).
|
||||
/// @param lockedAt The Timelock Period that stake was most recently locked at.
|
||||
/// @param total Amount of stake that is timelocked.
|
||||
/// @param pending Stake pending to be un-timelocked next Timelock Period.
|
||||
struct Timelock {
|
||||
/// @dev Tracks timeLocked stake (see MixinTimeLockedStake).
|
||||
/// @param lockedAt The TimeLock Period that stake was most recently locked at.
|
||||
/// @param total Amount of stake that is timeLocked.
|
||||
/// @param pending Stake pending to be un-TimeLocked next TimeLock Period.
|
||||
struct TimeLock {
|
||||
uint64 lockedAt;
|
||||
uint96 total;
|
||||
uint96 pending;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -23,9 +23,9 @@ pragma solidity ^0.5.5;
|
||||
|
||||
/// @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.
|
||||
/// 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
|
||||
|
@@ -26,7 +26,7 @@ import "./MixinZrxVault.sol";
|
||||
import "../staking_pools/MixinStakingPoolRewardVault.sol";
|
||||
import "../sys/MixinScheduler.sol";
|
||||
import "./MixinStakeBalances.sol";
|
||||
import "./MixinTimelockedStake.sol";
|
||||
import "./MixinTimeLockedStake.sol";
|
||||
import "./MixinStake.sol";
|
||||
import "../staking_pools/MixinStakingPoolRewards.sol";
|
||||
|
||||
@@ -48,7 +48,7 @@ contract MixinDelegatedStake is
|
||||
MixinStakingPoolRewardVault,
|
||||
MixinZrxVault,
|
||||
MixinStakingPool,
|
||||
MixinTimelockedStake,
|
||||
MixinTimeLockedStake,
|
||||
MixinStakeBalances,
|
||||
MixinStake,
|
||||
MixinStakingPoolRewards
|
||||
@@ -85,14 +85,14 @@ contract MixinDelegatedStake is
|
||||
_delegateStake(owner, poolId, amount);
|
||||
}
|
||||
|
||||
/// @dev Deactivate & Timelock stake that is currently in the Activated & Delegated state.
|
||||
/// @dev Deactivate & TimeLock stake that is currently in the Activated & Delegated state.
|
||||
/// Note that the sender must be payable, as they may receive rewards in ETH from their staking pool.
|
||||
/// @param poolId Unique Id of staking pool that the Stake is currently delegated to.
|
||||
/// @param amount of Stake to deactivate and timelock.
|
||||
function deactivateAndTimelockDelegatedStake(bytes32 poolId, uint256 amount)
|
||||
/// @param amount of Stake to deactivate and timeLock.
|
||||
function deactivateAndTimeLockDelegatedStake(bytes32 poolId, uint256 amount)
|
||||
public
|
||||
{
|
||||
deactivateAndTimelockStake(amount);
|
||||
deactivateAndTimeLockStake(amount);
|
||||
address payable owner = msg.sender;
|
||||
_undelegateStake(owner, poolId, amount);
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ import "./MixinZrxVault.sol";
|
||||
import "../staking_pools/MixinStakingPoolRewardVault.sol";
|
||||
import "../sys/MixinScheduler.sol";
|
||||
import "./MixinStakeBalances.sol";
|
||||
import "./MixinTimelockedStake.sol";
|
||||
import "./MixinTimeLockedStake.sol";
|
||||
|
||||
|
||||
/// @dev This mixin contains logic for managing ZRX tokens and Stake.
|
||||
@@ -35,7 +35,7 @@ import "./MixinTimelockedStake.sol";
|
||||
/// Stake can exist in one of many states:
|
||||
/// 1. Activated
|
||||
/// 2. Activated & Delegated
|
||||
/// 3. Deactivated & Timelocked
|
||||
/// 3. Deactivated & TimeLocked
|
||||
/// 4. Deactivated & Withdrawable
|
||||
///
|
||||
/// -- State Definitions --
|
||||
@@ -49,9 +49,9 @@ import "./MixinTimelockedStake.sol";
|
||||
/// For example, if delegated to a staking pool then it carries weight when computing fee-based rewards for
|
||||
/// the staking pool; however, in this case, delegated stake carries less weight that regular stake (see MixinStakingPool).
|
||||
///
|
||||
/// Deactivated & Timelocked Stake
|
||||
/// Deactivated & TimeLocked Stake
|
||||
/// Stake in this state cannot be used as a utility within the 0x ecosystem.
|
||||
/// Stake is timelocked when it moves out of activated states (Activated / Activated & Delagated).
|
||||
/// Stake is timeLocked when it moves out of activated states (Activated / Activated & Delagated).
|
||||
/// By limiting the portability of stake, we mitigate undesirable behavior such as switching staking pools
|
||||
/// in the middle of an epoch.
|
||||
///
|
||||
@@ -61,11 +61,11 @@ import "./MixinTimelockedStake.sol";
|
||||
/// ----------------------------
|
||||
///
|
||||
/// -- Valid State Transtions --
|
||||
/// Activated -> Deactivated & Timelocked
|
||||
/// Activated -> Deactivated & TimeLocked
|
||||
///
|
||||
/// Activated & Delegated -> Deactivated & Timelocked
|
||||
/// Activated & Delegated -> Deactivated & TimeLocked
|
||||
///
|
||||
/// Deactivated & Timelocked -> Deactivated & Withdrawable
|
||||
/// Deactivated & TimeLocked -> Deactivated & Withdrawable
|
||||
///
|
||||
/// Deactivated & Withdrawable -> Activated
|
||||
/// Deactivated & Withdrawable -> Activated & Delegated
|
||||
@@ -74,7 +74,7 @@ import "./MixinTimelockedStake.sol";
|
||||
///
|
||||
/// Freshly minted stake is in the "Deactvated & Withdrawable" State, so it can
|
||||
/// either be activated, delegated or withdrawn.
|
||||
/// See MixinDelegatedStake and MixinTimelockedStake for more on respective state transitions.
|
||||
/// See MixinDelegatedStake and MixinTimeLockedStake for more on respective state transitions.
|
||||
contract MixinStake is
|
||||
IStakingEvents,
|
||||
MixinDeploymentConstants,
|
||||
@@ -84,7 +84,7 @@ contract MixinStake is
|
||||
MixinScheduler,
|
||||
MixinStakingPoolRewardVault,
|
||||
MixinZrxVault,
|
||||
MixinTimelockedStake,
|
||||
MixinTimeLockedStake,
|
||||
MixinStakeBalances
|
||||
{
|
||||
|
||||
@@ -116,7 +116,7 @@ contract MixinStake is
|
||||
external
|
||||
{
|
||||
address owner = msg.sender;
|
||||
_syncTimelockedStake(owner);
|
||||
_syncTimeLockedStake(owner);
|
||||
require(
|
||||
amount <= getDeactivatedStake(owner),
|
||||
"INSUFFICIENT_BALANCE"
|
||||
@@ -130,7 +130,7 @@ contract MixinStake is
|
||||
public
|
||||
{
|
||||
address owner = msg.sender;
|
||||
_syncTimelockedStake(owner);
|
||||
_syncTimeLockedStake(owner);
|
||||
require(
|
||||
amount <= getActivatableStake(owner),
|
||||
"INSUFFICIENT_BALANCE"
|
||||
@@ -139,20 +139,20 @@ contract MixinStake is
|
||||
totalActivatedStake = totalActivatedStake._add(amount);
|
||||
}
|
||||
|
||||
/// @dev Deactivate & Timelock stake that is currently in the Activated state.
|
||||
/// @param amount of Stake to deactivate and timelock.
|
||||
function deactivateAndTimelockStake(uint256 amount)
|
||||
/// @dev Deactivate & TimeLock stake that is currently in the Activated state.
|
||||
/// @param amount of Stake to deactivate and timeLock.
|
||||
function deactivateAndTimeLockStake(uint256 amount)
|
||||
public
|
||||
{
|
||||
address owner = msg.sender;
|
||||
_syncTimelockedStake(owner);
|
||||
_syncTimeLockedStake(owner);
|
||||
require(
|
||||
amount <= getActivatedStake(owner),
|
||||
"INSUFFICIENT_BALANCE"
|
||||
);
|
||||
activatedStakeByOwner[owner] = activatedStakeByOwner[owner]._sub(amount);
|
||||
totalActivatedStake = totalActivatedStake._sub(amount);
|
||||
_timelockStake(owner, amount);
|
||||
_timeLockStake(owner, amount);
|
||||
}
|
||||
|
||||
/// @dev Mints Stake in the Deactivated & Withdrawable state.
|
||||
|
@@ -24,7 +24,7 @@ import "../interfaces/IStructs.sol";
|
||||
import "../immutable/MixinConstants.sol";
|
||||
import "../immutable/MixinStorage.sol";
|
||||
import "../sys/MixinScheduler.sol";
|
||||
import "./MixinTimelockedStake.sol";
|
||||
import "./MixinTimeLockedStake.sol";
|
||||
|
||||
|
||||
/// @dev This mixin contains logic for querying stake balances.
|
||||
@@ -35,7 +35,7 @@ contract MixinStakeBalances is
|
||||
MixinConstants,
|
||||
MixinStorage,
|
||||
MixinScheduler,
|
||||
MixinTimelockedStake
|
||||
MixinTimeLockedStake
|
||||
{
|
||||
|
||||
using LibSafeMath for uint256;
|
||||
@@ -76,7 +76,7 @@ contract MixinStakeBalances is
|
||||
}
|
||||
|
||||
/// @dev Returns the deactivated stake for a given owner.
|
||||
/// This stake is in the "Deactivated & Timelocked" OR "Deactivated & Withdrawable" states.
|
||||
/// This stake is in the "Deactivated & TimeLocked" OR "Deactivated & Withdrawable" states.
|
||||
/// @param owner to query.
|
||||
/// @return Deactivated stake for owner.
|
||||
function getDeactivatedStake(address owner)
|
||||
@@ -108,7 +108,7 @@ contract MixinStakeBalances is
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
return getDeactivatedStake(owner)._sub(getTimelockedStake(owner));
|
||||
return getDeactivatedStake(owner)._sub(getTimeLockedStake(owner));
|
||||
}
|
||||
|
||||
/// @dev Returns the stake that can be withdrawn for a given owner.
|
||||
@@ -160,30 +160,30 @@ contract MixinStakeBalances is
|
||||
return delegatedStakeByPoolId[poolId];
|
||||
}
|
||||
|
||||
/// @dev Returns the timelocked stake for a given owner.
|
||||
/// This stake is in the "Deactivated & Timelocked" state.
|
||||
/// @dev Returns the timeLocked stake for a given owner.
|
||||
/// This stake is in the "Deactivated & TimeLocked" state.
|
||||
/// @param owner to query.
|
||||
/// @return Timelocked stake for owner.
|
||||
function getTimelockedStake(address owner)
|
||||
/// @return TimeLocked stake for owner.
|
||||
function getTimeLockedStake(address owner)
|
||||
public
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
(IStructs.Timelock memory timelock,) = _getSynchronizedTimelock(owner);
|
||||
return timelock.total;
|
||||
(IStructs.TimeLock memory timeLock,) = _getSynchronizedTimeLock(owner);
|
||||
return timeLock.total;
|
||||
}
|
||||
|
||||
/// @dev Returns the starting Timelock Period of timelocked state for a given owner.
|
||||
/// This stake is in the "Deactivated & Timelocked" state.
|
||||
/// See MixinScheduling and MixinTimelock.
|
||||
/// @dev Returns the starting TimeLock Period of timeLocked state for a given owner.
|
||||
/// This stake is in the "Deactivated & TimeLocked" state.
|
||||
/// See MixinScheduling and MixinTimeLock.
|
||||
/// @param owner to query.
|
||||
/// @return Start of timelock for owner's timelocked stake.
|
||||
function getTimelockStart(address owner)
|
||||
/// @return Start of timeLock for owner's timeLocked stake.
|
||||
function getTimeLockStart(address owner)
|
||||
public
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
(IStructs.Timelock memory timelock,) = _getSynchronizedTimelock(owner);
|
||||
return timelock.lockedAt;
|
||||
(IStructs.TimeLock memory timeLock,) = _getSynchronizedTimeLock(owner);
|
||||
return timeLock.lockedAt;
|
||||
}
|
||||
}
|
||||
|
@@ -26,42 +26,42 @@ import "../interfaces/IStakingEvents.sol";
|
||||
import "../sys/MixinScheduler.sol";
|
||||
|
||||
|
||||
/// @dev This mixin contains logic for timelocking stake.
|
||||
/// @dev This mixin contains logic for timeLocking stake.
|
||||
/// **** Read MixinStake before continuing ****
|
||||
/// When stake moves from an Activated state it must first go to
|
||||
/// the Deactivated & Timelocked state. The stake will be timelocked
|
||||
/// for a period of time, called a Timelock Period, which is measured in epochs.
|
||||
/// the Deactivated & TimeLocked state. The stake will be timeLocked
|
||||
/// for a period of time, called a TimeLock Period, which is measured in epochs.
|
||||
/// (see MixinScheduler).
|
||||
/// Stake remains timelocked for at least one full Timelock Period; so,
|
||||
/// if your stake is locked sometime during Timelock Period #1 then it will
|
||||
/// be un-timelocked at Timelock Period #3.
|
||||
/// Note that no action is required by the user to un-timelock their stake, and
|
||||
/// when stake is un-timelocked it is moved to the state Deactivated & Withdrawable.
|
||||
/// Stake remains timeLocked for at least one full TimeLock Period; so,
|
||||
/// if your stake is locked sometime during TimeLock Period #1 then it will
|
||||
/// be un-TimeLocked at TimeLock Period #3.
|
||||
/// Note that no action is required by the user to un-TimeLock their stake, and
|
||||
/// when stake is un-TimeLocked it is moved to the state Deactivated & Withdrawable.
|
||||
/// (see MixinStake).
|
||||
///
|
||||
/// -- The Timelocking Data Structure --
|
||||
/// Three fields are used to represent a timelock:
|
||||
/// 1. Total timelocked stake (called `total`)
|
||||
/// 2. Timelocked stake pending removal of timelock, on next Timelock Period (called `pending`)
|
||||
/// 3. The most recent Timelock Period in which stake was timelocked. (called `lockedAt`)
|
||||
/// -- The TimeLocking Data Structure --
|
||||
/// Three fields are used to represent a timeLock:
|
||||
/// 1. Total timeLocked stake (called `total`)
|
||||
/// 2. TimeLocked stake pending removal of timeLock, on next TimeLock Period (called `pending`)
|
||||
/// 3. The most recent TimeLock Period in which stake was timeLocked. (called `lockedAt`)
|
||||
///
|
||||
/// Each user has exactly one instance of this timelock struct, which manages all of
|
||||
/// their timelocked stake. This data structure is defined in `IStructs.Timelock`.
|
||||
/// Each user has exactly one instance of this timeLock struct, which manages all of
|
||||
/// their timeLocked stake. This data structure is defined in `IStructs.TimeLock`.
|
||||
/// This data structure was designed to fit into one word of storage, as a gas optimization.
|
||||
/// Its fields are updated only when a user interacts with their stake.
|
||||
/// ------------------------------------
|
||||
///
|
||||
/// -- Timelocking Example --
|
||||
/// In the example below, the user executes a series of actions on their stake (`Action`) during `Timelock Period` N.
|
||||
/// The fields of the user's timelocked struct (`lockedAt`, `total`, `pending`) are illustrated exactly as
|
||||
/// -- TimeLocking Example --
|
||||
/// In the example below, the user executes a series of actions on their stake (`Action`) during `TimeLock Period` N.
|
||||
/// The fields of the user's timeLocked struct (`lockedAt`, `total`, `pending`) are illustrated exactly as
|
||||
/// they would be represented in storage.
|
||||
/// The field `un-timelocked` is the amount of un-timelocked stake, as represented *in storage*; however, because
|
||||
/// The field `un-TimeLocked` is the amount of un-TimeLocked stake, as represented *in storage*; however, because
|
||||
/// state is only updated when the user interacts with their stake, this field may lag.
|
||||
/// The field `un-timelocked (virtual)` is the true amount of un-timelocked stake, as represented in the system;
|
||||
/// The field `un-TimeLocked (virtual)` is the true amount of un-TimeLocked stake, as represented in the system;
|
||||
/// the value in this field represents stake that has moved from the state
|
||||
/// "Deactivated & Timelocke" to "Deactivated & Withdrawable" (see MixinStake).
|
||||
/// "Deactivated & TimeLocke" to "Deactivated & Withdrawable" (see MixinStake).
|
||||
///
|
||||
/// | Action | Timelock Period | lockedAt | total | pending | un-timelocked | un-timelocked (virtual) |
|
||||
/// | Action | TimeLock Period | lockedAt | total | pending | un-TimeLocked | un-TimeLocked (virtual) |
|
||||
/// | | 0 | 0 | 0 | 0 | 0 | 0 |
|
||||
/// | lock(5) | 1 | 1 | 5 | 0 | 0 | 0 |
|
||||
/// | | 2 | 1 | 5 | 0 | 0 | 0 |
|
||||
@@ -76,7 +76,7 @@ import "../sys/MixinScheduler.sol";
|
||||
/// | | 7 | 6 | 20 | 0 | 0 | 0 |
|
||||
/// | | 8 | 6 | 20 | 0 | 0 | 20 |
|
||||
/// -------------------------------------------------------------------------------------------------------------
|
||||
contract MixinTimelockedStake is
|
||||
contract MixinTimeLockedStake is
|
||||
IStakingEvents,
|
||||
MixinDeploymentConstants,
|
||||
MixinConstants,
|
||||
@@ -86,63 +86,63 @@ contract MixinTimelockedStake is
|
||||
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
/// @dev Forces the timelock data structure to sync to state.
|
||||
/// @dev Forces the timeLock data structure to sync to state.
|
||||
/// This is not necessary but may optimize some subsequent calls.
|
||||
/// @param owner of Stake.
|
||||
function forceTimelockSync(address owner)
|
||||
function forceTimeLockSync(address owner)
|
||||
external
|
||||
{
|
||||
_syncTimelockedStake(owner);
|
||||
_syncTimeLockedStake(owner);
|
||||
}
|
||||
|
||||
/// @dev Timelocks Stake
|
||||
/// This moves state into the Deactivated & Timelocked state.
|
||||
/// @dev TimeLocks Stake
|
||||
/// This moves state into the Deactivated & TimeLocked state.
|
||||
/// @param owner of Stake.
|
||||
/// @param amount of Stake to timelock.
|
||||
function _timelockStake(address owner, uint256 amount)
|
||||
/// @param amount of Stake to timeLock.
|
||||
function _timeLockStake(address owner, uint256 amount)
|
||||
internal
|
||||
{
|
||||
(IStructs.Timelock memory ownerTimelock,) = _getSynchronizedTimelock(owner);
|
||||
(IStructs.TimeLock memory ownerTimeLock,) = _getSynchronizedTimeLock(owner);
|
||||
uint96 downcastAmount = amount._downcastToUint96();
|
||||
ownerTimelock.total += downcastAmount;
|
||||
timelockedStakeByOwner[owner] = ownerTimelock;
|
||||
ownerTimeLock.total += downcastAmount;
|
||||
timeLockedStakeByOwner[owner] = ownerTimeLock;
|
||||
}
|
||||
|
||||
/// @dev Updates storage to reflect the most up-to-date timelock data structure for a given owner.
|
||||
/// @dev Updates storage to reflect the most up-to-date timeLock data structure for a given owner.
|
||||
/// @param owner of Stake.
|
||||
function _syncTimelockedStake(address owner)
|
||||
function _syncTimeLockedStake(address owner)
|
||||
internal
|
||||
{
|
||||
(IStructs.Timelock memory ownerTimelock, bool isOutOfSync) = _getSynchronizedTimelock(owner);
|
||||
(IStructs.TimeLock memory ownerTimeLock, bool isOutOfSync) = _getSynchronizedTimeLock(owner);
|
||||
if (!isOutOfSync) {
|
||||
return;
|
||||
}
|
||||
timelockedStakeByOwner[owner] = ownerTimelock;
|
||||
timeLockedStakeByOwner[owner] = ownerTimeLock;
|
||||
}
|
||||
|
||||
/// @dev Returns the most up-to-date timelock data structure for a given owner.
|
||||
/// @dev Returns the most up-to-date timeLock data structure for a given owner.
|
||||
/// @param owner of Stake.
|
||||
function _getSynchronizedTimelock(address owner)
|
||||
function _getSynchronizedTimeLock(address owner)
|
||||
internal
|
||||
view
|
||||
returns (
|
||||
IStructs.Timelock memory ownerTimelock,
|
||||
IStructs.TimeLock memory ownerTimeLock,
|
||||
bool isOutOfSync
|
||||
)
|
||||
{
|
||||
uint64 currentTimelockPeriod = getCurrentTimelockPeriod();
|
||||
ownerTimelock = timelockedStakeByOwner[owner];
|
||||
uint64 currentTimeLockPeriod = getCurrentTimeLockPeriod();
|
||||
ownerTimeLock = timeLockedStakeByOwner[owner];
|
||||
isOutOfSync = false;
|
||||
if (currentTimelockPeriod == ownerTimelock.lockedAt._add(1)) {
|
||||
if (currentTimeLockPeriod == ownerTimeLock.lockedAt._add(1)) {
|
||||
// shift n periods
|
||||
ownerTimelock.pending = ownerTimelock.total;
|
||||
ownerTimeLock.pending = ownerTimeLock.total;
|
||||
isOutOfSync = true;
|
||||
} else if (currentTimelockPeriod > ownerTimelock.lockedAt) {
|
||||
// Timelock has expired - zero out
|
||||
ownerTimelock.lockedAt = 0;
|
||||
ownerTimelock.total = 0;
|
||||
ownerTimelock.pending = 0;
|
||||
} else if (currentTimeLockPeriod > ownerTimeLock.lockedAt) {
|
||||
// TimeLock has expired - zero out
|
||||
ownerTimeLock.lockedAt = 0;
|
||||
ownerTimeLock.total = 0;
|
||||
ownerTimeLock.pending = 0;
|
||||
}
|
||||
return (ownerTimelock, isOutOfSync);
|
||||
return (ownerTimeLock, isOutOfSync);
|
||||
}
|
||||
}
|
||||
|
@@ -67,7 +67,7 @@ contract MixinStakingPoolRewards is
|
||||
MixinScheduler,
|
||||
MixinStakingPoolRewardVault,
|
||||
MixinStakingPool,
|
||||
MixinTimelockedStake,
|
||||
MixinTimeLockedStake,
|
||||
MixinStakeBalances
|
||||
{
|
||||
|
||||
|
@@ -31,7 +31,7 @@ import "../interfaces/IStakingEvents.sol";
|
||||
/// Epochs have a fixed minimum time period that is configured when this contract is deployed.
|
||||
/// The current epoch only changes by calling this contract, which can be invoked by anyone.
|
||||
/// Epochs serve as the basis for all other time intervals, which provides a more stable
|
||||
/// and consistent scheduling metric than time. Timelocks, for example, are measured in epochs.
|
||||
/// and consistent scheduling metric than time. TimeLocks, for example, are measured in epochs.
|
||||
contract MixinScheduler is
|
||||
IStakingEvents,
|
||||
MixinDeploymentConstants,
|
||||
@@ -86,20 +86,20 @@ contract MixinScheduler is
|
||||
return getCurrentEpochStartTimeInSeconds()._add(getEpochDurationInSeconds());
|
||||
}
|
||||
|
||||
/// @dev Returns the current timelock period.
|
||||
/// @return Timelock period.
|
||||
function getCurrentTimelockPeriod()
|
||||
/// @dev Returns the current timeLock period.
|
||||
/// @return TimeLock period.
|
||||
function getCurrentTimeLockPeriod()
|
||||
public
|
||||
view
|
||||
returns (uint64)
|
||||
{
|
||||
return currentTimelockPeriod;
|
||||
return currentTimeLockPeriod;
|
||||
}
|
||||
|
||||
/// @dev Returns the length of a timelock period, measured in epochs.
|
||||
/// Timelock period = [startEpoch..endEpoch)
|
||||
/// @return Timelock period end.
|
||||
function getTimelockDurationInEpochs()
|
||||
/// @dev Returns the length of a timeLock period, measured in epochs.
|
||||
/// TimeLock period = [startEpoch..endEpoch)
|
||||
/// @return TimeLock period end.
|
||||
function getTimeLockDurationInEpochs()
|
||||
public
|
||||
pure
|
||||
returns (uint64)
|
||||
@@ -107,30 +107,30 @@ contract MixinScheduler is
|
||||
return TIMELOCK_DURATION_IN_EPOCHS;
|
||||
}
|
||||
|
||||
/// @dev Returns the epoch that the current timelock period started at.
|
||||
/// Timelock period = [startEpoch..endEpoch)
|
||||
/// @return Timelock period start.
|
||||
function getCurrentTimelockPeriodStartEpoch()
|
||||
/// @dev Returns the epoch that the current timeLock period started at.
|
||||
/// TimeLock period = [startEpoch..endEpoch)
|
||||
/// @return TimeLock period start.
|
||||
function getCurrentTimeLockPeriodStartEpoch()
|
||||
public
|
||||
view
|
||||
returns (uint64)
|
||||
{
|
||||
return currentTimelockPeriodStartEpoch;
|
||||
return currentTimeLockPeriodStartEpoch;
|
||||
}
|
||||
|
||||
/// @dev Returns the epoch that the current timelock period will end.
|
||||
/// Timelock period = [startEpoch..endEpoch)
|
||||
/// @return Timelock period.
|
||||
function getCurrentTimelockPeriodEndEpoch()
|
||||
/// @dev Returns the epoch that the current timeLock period will end.
|
||||
/// TimeLock period = [startEpoch..endEpoch)
|
||||
/// @return TimeLock period.
|
||||
function getCurrentTimeLockPeriodEndEpoch()
|
||||
public
|
||||
view
|
||||
returns (uint64)
|
||||
{
|
||||
return getCurrentTimelockPeriodStartEpoch()._add(getTimelockDurationInEpochs());
|
||||
return getCurrentTimeLockPeriodStartEpoch()._add(getTimeLockDurationInEpochs());
|
||||
}
|
||||
|
||||
/// @dev Moves to the next epoch, given the current epoch period has ended.
|
||||
/// Time intervals that are measured in epochs (like timelocks) are also incremented, given
|
||||
/// Time intervals that are measured in epochs (like timeLocks) are also incremented, given
|
||||
/// their periods have ended.
|
||||
function _goToNextEpoch()
|
||||
internal
|
||||
@@ -158,16 +158,16 @@ contract MixinScheduler is
|
||||
earliestEndTimeInSeconds
|
||||
);
|
||||
|
||||
// increment timelock period, if needed
|
||||
if (getCurrentTimelockPeriodEndEpoch() <= nextEpoch) {
|
||||
currentTimelockPeriod = currentTimelockPeriod._add(1);
|
||||
currentTimelockPeriodStartEpoch = currentEpoch;
|
||||
uint64 endEpoch = currentEpoch._add(getTimelockDurationInEpochs());
|
||||
// increment timeLock period, if needed
|
||||
if (getCurrentTimeLockPeriodEndEpoch() <= nextEpoch) {
|
||||
currentTimeLockPeriod = currentTimeLockPeriod._add(1);
|
||||
currentTimeLockPeriodStartEpoch = currentEpoch;
|
||||
uint64 endEpoch = currentEpoch._add(getTimeLockDurationInEpochs());
|
||||
|
||||
// notify
|
||||
emit TimelockPeriodChanged(
|
||||
currentTimelockPeriod,
|
||||
currentTimelockPeriodStartEpoch,
|
||||
emit TimeLockPeriodChanged(
|
||||
currentTimeLockPeriod,
|
||||
currentTimeLockPeriodStartEpoch,
|
||||
endEpoch
|
||||
);
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@
|
||||
"compile:truffle": "truffle compile"
|
||||
},
|
||||
"config": {
|
||||
"abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingPoolRewardVault|IStakingProxy|IStructs|IVaultCore|IWallet|IZrxVault|LibEIP712Hash|LibFeeMath|LibFeeMathTest|LibRewardMath|LibSafeMath|LibSafeMath64|LibSafeMath96|LibSignatureValidator|MixinConstants|MixinDelegatedStake|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinOwnable|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakingPool|MixinStakingPoolRewardVault|MixinStakingPoolRewards|MixinStorage|MixinTimelockedStake|MixinVaultCore|MixinZrxVault|Staking|StakingPoolRewardVault|StakingProxy|ZrxVault).json",
|
||||
"abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingPoolRewardVault|IStakingProxy|IStructs|IVaultCore|IWallet|IZrxVault|LibEIP712Hash|LibFeeMath|LibFeeMathTest|LibRewardMath|LibSafeMath|LibSafeMath64|LibSafeMath96|LibSignatureValidator|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": {
|
||||
|
@@ -34,7 +34,7 @@ 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 MixinStorage from '../generated-artifacts/MixinStorage.json';
|
||||
import * as MixinTimelockedStake from '../generated-artifacts/MixinTimelockedStake.json';
|
||||
import * as MixinTimeLockedStake from '../generated-artifacts/MixinTimeLockedStake.json';
|
||||
import * as MixinVaultCore from '../generated-artifacts/MixinVaultCore.json';
|
||||
import * as MixinZrxVault from '../generated-artifacts/MixinZrxVault.json';
|
||||
import * as Staking from '../generated-artifacts/Staking.json';
|
||||
@@ -67,7 +67,7 @@ export const artifacts = {
|
||||
MixinDelegatedStake: MixinDelegatedStake as ContractArtifact,
|
||||
MixinStake: MixinStake as ContractArtifact,
|
||||
MixinStakeBalances: MixinStakeBalances as ContractArtifact,
|
||||
MixinTimelockedStake: MixinTimelockedStake as ContractArtifact,
|
||||
MixinTimeLockedStake: MixinTimeLockedStake as ContractArtifact,
|
||||
MixinZrxVault: MixinZrxVault as ContractArtifact,
|
||||
MixinStakingPool: MixinStakingPool as ContractArtifact,
|
||||
MixinStakingPoolRewardVault: MixinStakingPoolRewardVault as ContractArtifact,
|
||||
|
@@ -32,7 +32,7 @@ export * from '../generated-wrappers/mixin_staking_pool';
|
||||
export * from '../generated-wrappers/mixin_staking_pool_reward_vault';
|
||||
export * from '../generated-wrappers/mixin_staking_pool_rewards';
|
||||
export * from '../generated-wrappers/mixin_storage';
|
||||
export * from '../generated-wrappers/mixin_timelocked_stake';
|
||||
export * from '../generated-wrappers/mixin_time_locked_stake';
|
||||
export * from '../generated-wrappers/mixin_vault_core';
|
||||
export * from '../generated-wrappers/mixin_zrx_vault';
|
||||
export * from '../generated-wrappers/staking';
|
||||
|
@@ -86,15 +86,15 @@ export class DelegatorActor extends StakerActor {
|
||||
expectedDelegatorBalances.stakeDelegatedToPool[0] = initDelegatorBalances.stakeDelegatedToPool[0].plus(amount);
|
||||
await this.assertBalancesAsync(expectedDelegatorBalances, [poolId]);
|
||||
}
|
||||
public async deactivateAndTimelockDelegatedStakeAsync(
|
||||
public async deactivateAndTimeLockDelegatedStakeAsync(
|
||||
poolId: string,
|
||||
amount: BigNumber,
|
||||
revertReason?: RevertReason,
|
||||
): Promise<void> {
|
||||
// query init balances
|
||||
const initDelegatorBalances = await this.getBalancesAsync([poolId]);
|
||||
// deactivate and timelock
|
||||
const txReceiptPromise = this._stakingWrapper.deactivateAndTimelockDelegatedStakeAsync(
|
||||
// deactivate and timeLock
|
||||
const txReceiptPromise = this._stakingWrapper.deactivateAndTimeLockDelegatedStakeAsync(
|
||||
this._owner,
|
||||
poolId,
|
||||
amount,
|
||||
@@ -108,7 +108,7 @@ export class DelegatorActor extends StakerActor {
|
||||
// check balances
|
||||
const expectedDelegatorBalances = initDelegatorBalances;
|
||||
expectedDelegatorBalances.activatedStakeBalance = initDelegatorBalances.activatedStakeBalance.minus(amount);
|
||||
expectedDelegatorBalances.timelockedStakeBalance = expectedDelegatorBalances.timelockedStakeBalance.plus(
|
||||
expectedDelegatorBalances.timeLockedStakeBalance = expectedDelegatorBalances.timeLockedStakeBalance.plus(
|
||||
amount,
|
||||
);
|
||||
expectedDelegatorBalances.deactivatedStakeBalance = expectedDelegatorBalances.deactivatedStakeBalance.plus(
|
||||
|
@@ -61,11 +61,11 @@ export class StakerActor extends BaseActor {
|
||||
expectedStakerBalances.deactivatedStakeBalance = initStakerBalances.deactivatedStakeBalance.minus(amount);
|
||||
await this.assertBalancesAsync(expectedStakerBalances);
|
||||
}
|
||||
public async deactivateAndTimelockStakeAsync(amount: BigNumber, revertReason?: RevertReason): Promise<void> {
|
||||
public async deactivateAndTimeLockStakeAsync(amount: BigNumber, revertReason?: RevertReason): Promise<void> {
|
||||
// query init balances
|
||||
const initStakerBalances = await this.getBalancesAsync();
|
||||
// deactivate and timelock stake
|
||||
const txReceiptPromise = this._stakingWrapper.deactivateAndTimelockStakeAsync(this._owner, amount);
|
||||
// deactivate and timeLock stake
|
||||
const txReceiptPromise = this._stakingWrapper.deactivateAndTimeLockStakeAsync(this._owner, amount);
|
||||
if (revertReason !== undefined) {
|
||||
await expectTransactionFailedAsync(txReceiptPromise, revertReason);
|
||||
return;
|
||||
@@ -75,7 +75,7 @@ export class StakerActor extends BaseActor {
|
||||
// check balances
|
||||
const expectedStakerBalances = initStakerBalances;
|
||||
expectedStakerBalances.activatedStakeBalance = initStakerBalances.activatedStakeBalance.minus(amount);
|
||||
expectedStakerBalances.timelockedStakeBalance = initStakerBalances.timelockedStakeBalance.plus(amount);
|
||||
expectedStakerBalances.timeLockedStakeBalance = initStakerBalances.timeLockedStakeBalance.plus(amount);
|
||||
expectedStakerBalances.deactivatedStakeBalance = initStakerBalances.deactivatedStakeBalance.plus(amount);
|
||||
await this.assertBalancesAsync(expectedStakerBalances);
|
||||
}
|
||||
@@ -115,7 +115,7 @@ export class StakerActor extends BaseActor {
|
||||
withdrawableStakeBalance: await this._stakingWrapper.getWithdrawableStakeAsync(this._owner),
|
||||
activatableStakeBalance: await this._stakingWrapper.getActivatableStakeAsync(this._owner),
|
||||
activatedStakeBalance: await this._stakingWrapper.getActivatedStakeAsync(this._owner),
|
||||
timelockedStakeBalance: await this._stakingWrapper.getTimelockedStakeAsync(this._owner),
|
||||
timeLockedStakeBalance: await this._stakingWrapper.getTimeLockedStakeAsync(this._owner),
|
||||
deactivatedStakeBalance: await this._stakingWrapper.getDeactivatedStakeAsync(this._owner),
|
||||
};
|
||||
return stakerBalances;
|
||||
@@ -136,33 +136,33 @@ export class StakerActor extends BaseActor {
|
||||
expect(balances.activatedStakeBalance, 'activated stake balance').to.be.bignumber.equal(
|
||||
expectedBalances.activatedStakeBalance,
|
||||
);
|
||||
expect(balances.timelockedStakeBalance, 'timelocked stake balance').to.be.bignumber.equal(
|
||||
expectedBalances.timelockedStakeBalance,
|
||||
expect(balances.timeLockedStakeBalance, 'timeLocked stake balance').to.be.bignumber.equal(
|
||||
expectedBalances.timeLockedStakeBalance,
|
||||
);
|
||||
expect(balances.deactivatedStakeBalance, 'deactivated stake balance').to.be.bignumber.equal(
|
||||
expectedBalances.deactivatedStakeBalance,
|
||||
);
|
||||
}
|
||||
public async forceTimelockSyncAsync(): Promise<void> {
|
||||
public async forceTimeLockSyncAsync(): Promise<void> {
|
||||
const initBalances = await this.getBalancesAsync();
|
||||
await this._stakingWrapper.forceTimelockSyncAsync(this._owner);
|
||||
await this._stakingWrapper.forceTimeLockSyncAsync(this._owner);
|
||||
await this.assertBalancesAsync(initBalances);
|
||||
}
|
||||
public async skipToNextTimelockPeriodAsync(): Promise<void> {
|
||||
public async skipToNextTimeLockPeriodAsync(): Promise<void> {
|
||||
// query some initial values
|
||||
const initBalances = await this.getBalancesAsync();
|
||||
const timelockStart = await this._stakingWrapper.getTimelockStartAsync(this._owner);
|
||||
const timeLockStart = await this._stakingWrapper.getTimeLockStartAsync(this._owner);
|
||||
// skip to next period
|
||||
await this._stakingWrapper.skipToNextTimelockPeriodAsync();
|
||||
await this._stakingWrapper.skipToNextTimeLockPeriodAsync();
|
||||
// validate new balances
|
||||
const expectedBalances = initBalances;
|
||||
const currentTimelockPeriod = await this._stakingWrapper.getCurrentTimelockPeriodAsync();
|
||||
if (currentTimelockPeriod.minus(timelockStart).isGreaterThan(1)) {
|
||||
const currentTimeLockPeriod = await this._stakingWrapper.getCurrentTimeLockPeriodAsync();
|
||||
if (currentTimeLockPeriod.minus(timeLockStart).isGreaterThan(1)) {
|
||||
expectedBalances.activatableStakeBalance = initBalances.activatableStakeBalance.plus(
|
||||
initBalances.timelockedStakeBalance,
|
||||
initBalances.timeLockedStakeBalance,
|
||||
);
|
||||
expectedBalances.withdrawableStakeBalance = expectedBalances.activatableStakeBalance;
|
||||
expectedBalances.timelockedStakeBalance = new BigNumber(0);
|
||||
expectedBalances.timeLockedStakeBalance = new BigNumber(0);
|
||||
}
|
||||
await this.assertBalancesAsync(expectedBalances);
|
||||
}
|
||||
|
@@ -51,41 +51,41 @@ describe('Epochs', () => {
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('Epochs & Timelocks', () => {
|
||||
it('basic epochs & timelock periods', async () => {
|
||||
describe('Epochs & TimeLocks', () => {
|
||||
it('basic epochs & timeLock periods', async () => {
|
||||
///// 0/3 Validate Assumptions /////
|
||||
expect(await stakingWrapper.getEpochDurationInSecondsAsync()).to.be.bignumber.equal(
|
||||
stakingConstants.EPOCH_DURATION_IN_SECONDS,
|
||||
);
|
||||
expect(await stakingWrapper.getTimelockDurationInEpochsAsync()).to.be.bignumber.equal(
|
||||
expect(await stakingWrapper.getTimeLockDurationInEpochsAsync()).to.be.bignumber.equal(
|
||||
stakingConstants.TIMELOCK_DURATION_IN_EPOCHS,
|
||||
);
|
||||
|
||||
///// 1/3 Validate Initial Epoch & Timelock Period /////
|
||||
///// 1/3 Validate Initial Epoch & TimeLock Period /////
|
||||
{
|
||||
// epoch
|
||||
const currentEpoch = await stakingWrapper.getCurrentEpochAsync();
|
||||
expect(currentEpoch).to.be.bignumber.equal(stakingConstants.INITIAL_EPOCH);
|
||||
// timelock period
|
||||
const currentTimelockPeriod = await stakingWrapper.getCurrentTimelockPeriodAsync();
|
||||
expect(currentTimelockPeriod).to.be.bignumber.equal(stakingConstants.INITIAL_TIMELOCK_PERIOD);
|
||||
// timeLock period
|
||||
const currentTimeLockPeriod = await stakingWrapper.getCurrentTimeLockPeriodAsync();
|
||||
expect(currentTimeLockPeriod).to.be.bignumber.equal(stakingConstants.INITIAL_TIMELOCK_PERIOD);
|
||||
}
|
||||
///// 2/3 Increment Epoch (Timelock Should Not Increment) /////
|
||||
///// 2/3 Increment Epoch (TimeLock Should Not Increment) /////
|
||||
await stakingWrapper.skipToNextEpochAsync();
|
||||
{
|
||||
// epoch
|
||||
const currentEpoch = await stakingWrapper.getCurrentEpochAsync();
|
||||
expect(currentEpoch).to.be.bignumber.equal(stakingConstants.INITIAL_EPOCH.plus(1));
|
||||
// timelock period
|
||||
const currentTimelockPeriod = await stakingWrapper.getCurrentTimelockPeriodAsync();
|
||||
expect(currentTimelockPeriod).to.be.bignumber.equal(stakingConstants.INITIAL_TIMELOCK_PERIOD);
|
||||
// timeLock period
|
||||
const currentTimeLockPeriod = await stakingWrapper.getCurrentTimeLockPeriodAsync();
|
||||
expect(currentTimeLockPeriod).to.be.bignumber.equal(stakingConstants.INITIAL_TIMELOCK_PERIOD);
|
||||
}
|
||||
///// 3/3 Increment Epoch (Timelock Should Increment) /////
|
||||
await stakingWrapper.skipToNextTimelockPeriodAsync();
|
||||
///// 3/3 Increment Epoch (TimeLock Should Increment) /////
|
||||
await stakingWrapper.skipToNextTimeLockPeriodAsync();
|
||||
{
|
||||
// timelock period
|
||||
const currentTimelockPeriod = await stakingWrapper.getCurrentTimelockPeriodAsync();
|
||||
expect(currentTimelockPeriod).to.be.bignumber.equal(stakingConstants.INITIAL_TIMELOCK_PERIOD.plus(1));
|
||||
// timeLock period
|
||||
const currentTimeLockPeriod = await stakingWrapper.getCurrentTimeLockPeriodAsync();
|
||||
expect(currentTimeLockPeriod).to.be.bignumber.equal(stakingConstants.INITIAL_TIMELOCK_PERIOD.plus(1));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@@ -63,16 +63,16 @@ describe('Staking & Delegating', () => {
|
||||
// run test - this actor will validate its own state
|
||||
const staker = new StakerActor(stakers[0], stakingWrapper);
|
||||
await staker.depositZrxAndMintActivatedStakeAsync(amountToStake);
|
||||
await staker.deactivateAndTimelockStakeAsync(amountToDeactivate);
|
||||
// note - we cannot re-activate this timelocked stake until at least one full timelock period has passed.
|
||||
await staker.deactivateAndTimeLockStakeAsync(amountToDeactivate);
|
||||
// note - we cannot re-activate this timeLocked stake until at least one full timeLock period has passed.
|
||||
// attempting to do so should revert.
|
||||
await staker.activateStakeAsync(amountToReactivate, RevertReason.InsufficientBalance);
|
||||
await staker.skipToNextTimelockPeriodAsync();
|
||||
await staker.skipToNextTimeLockPeriodAsync();
|
||||
await staker.activateStakeAsync(amountToReactivate, RevertReason.InsufficientBalance);
|
||||
await staker.skipToNextTimelockPeriodAsync();
|
||||
await staker.skipToNextTimeLockPeriodAsync();
|
||||
// this forces the internal state to update; it is not necessary to activate stake, but
|
||||
// allows us to check that state is updated correctly after a timelock period rolls over.
|
||||
await staker.forceTimelockSyncAsync();
|
||||
// allows us to check that state is updated correctly after a timeLock period rolls over.
|
||||
await staker.forceTimeLockSyncAsync();
|
||||
// now we can activate stake
|
||||
await staker.activateStakeAsync(amountToReactivate);
|
||||
await staker.burnDeactivatedStakeAndWithdrawZrxAsync(amountToWithdraw);
|
||||
@@ -92,16 +92,16 @@ describe('Staking & Delegating', () => {
|
||||
// run test
|
||||
const delegator = new DelegatorActor(stakers[0], stakingWrapper);
|
||||
await delegator.depositZrxAndDelegateToStakingPoolAsync(poolId, amountToDelegate);
|
||||
await delegator.deactivateAndTimelockDelegatedStakeAsync(poolId, amountToDeactivate);
|
||||
// note - we cannot re-activate this timelocked stake until at least one full timelock period has passed.
|
||||
await delegator.deactivateAndTimeLockDelegatedStakeAsync(poolId, amountToDeactivate);
|
||||
// note - we cannot re-activate this timeLocked stake until at least one full timeLock period has passed.
|
||||
// attempting to do so should revert.
|
||||
await delegator.activateStakeAsync(amountToReactivate, RevertReason.InsufficientBalance);
|
||||
await delegator.skipToNextTimelockPeriodAsync();
|
||||
await delegator.skipToNextTimeLockPeriodAsync();
|
||||
await delegator.activateStakeAsync(amountToReactivate, RevertReason.InsufficientBalance);
|
||||
await delegator.skipToNextTimelockPeriodAsync();
|
||||
await delegator.skipToNextTimeLockPeriodAsync();
|
||||
// this forces the internal state to update; it is not necessary to activate stake, but
|
||||
// allows us to check that state is updated correctly after a timelock period rolls over.
|
||||
await delegator.forceTimelockSyncAsync();
|
||||
// allows us to check that state is updated correctly after a timeLock period rolls over.
|
||||
await delegator.forceTimeLockSyncAsync();
|
||||
// now we can activate stake
|
||||
await delegator.activateAndDelegateStakeAsync(poolId, amountToReactivate);
|
||||
await delegator.burnDeactivatedStakeAndWithdrawZrxAsync(amountToWithdraw);
|
||||
|
@@ -72,7 +72,7 @@ export class Simulation {
|
||||
const delegatorAddress = delegator.getOwner();
|
||||
const amountOfStakeDelegated = p.stakeByDelegator[delegatorIdx];
|
||||
const initEthBalance = await this._stakingWrapper.getEthBalanceAsync(delegatorAddress);
|
||||
await delegator.deactivateAndTimelockDelegatedStakeAsync(poolId, amountOfStakeDelegated);
|
||||
await delegator.deactivateAndTimeLockDelegatedStakeAsync(poolId, amountOfStakeDelegated);
|
||||
const finalEthBalance = await this._stakingWrapper.getEthBalanceAsync(delegatorAddress);
|
||||
const reward = finalEthBalance.minus(initEthBalance);
|
||||
const rewardTrimmed = StakingWrapper.trimFloat(StakingWrapper.toFloatingPoint(reward, 18), 5);
|
||||
|
@@ -228,20 +228,20 @@ export class StakingWrapper {
|
||||
const txReceipt = await this._executeTransactionAsync(calldata, owner);
|
||||
return txReceipt;
|
||||
}
|
||||
public async deactivateAndTimelockStakeAsync(
|
||||
public async deactivateAndTimeLockStakeAsync(
|
||||
owner: string,
|
||||
amount: BigNumber,
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const calldata = this.getStakingContract().deactivateAndTimelockStake.getABIEncodedTransactionData(amount);
|
||||
const calldata = this.getStakingContract().deactivateAndTimeLockStake.getABIEncodedTransactionData(amount);
|
||||
const txReceipt = await this._executeTransactionAsync(calldata, owner);
|
||||
return txReceipt;
|
||||
}
|
||||
public async deactivateAndTimelockDelegatedStakeAsync(
|
||||
public async deactivateAndTimeLockDelegatedStakeAsync(
|
||||
owner: string,
|
||||
poolId: string,
|
||||
amount: BigNumber,
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const calldata = this.getStakingContract().deactivateAndTimelockDelegatedStake.getABIEncodedTransactionData(
|
||||
const calldata = this.getStakingContract().deactivateAndTimeLockDelegatedStake.getABIEncodedTransactionData(
|
||||
poolId,
|
||||
amount,
|
||||
);
|
||||
@@ -258,8 +258,8 @@ export class StakingWrapper {
|
||||
const txReceipt = await this._executeTransactionAsync(calldata, owner);
|
||||
return txReceipt;
|
||||
}
|
||||
public async forceTimelockSyncAsync(owner: string): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const calldata = this.getStakingContract().forceTimelockSync.getABIEncodedTransactionData(owner);
|
||||
public async forceTimeLockSyncAsync(owner: string): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
const calldata = this.getStakingContract().forceTimeLockSync.getABIEncodedTransactionData(owner);
|
||||
const txReceipt = await this._executeTransactionAsync(calldata, this._ownerAddress);
|
||||
return txReceipt;
|
||||
}
|
||||
@@ -294,16 +294,16 @@ export class StakingWrapper {
|
||||
const value = this.getStakingContract().getWithdrawableStake.getABIDecodedReturnData(returnData);
|
||||
return value;
|
||||
}
|
||||
public async getTimelockedStakeAsync(owner: string): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getTimelockedStake.getABIEncodedTransactionData(owner);
|
||||
public async getTimeLockedStakeAsync(owner: string): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getTimeLockedStake.getABIEncodedTransactionData(owner);
|
||||
const returnData = await this._callAsync(calldata);
|
||||
const value = this.getStakingContract().getTimelockedStake.getABIDecodedReturnData(returnData);
|
||||
const value = this.getStakingContract().getTimeLockedStake.getABIDecodedReturnData(returnData);
|
||||
return value;
|
||||
}
|
||||
public async getTimelockStartAsync(owner: string): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getTimelockStart.getABIEncodedTransactionData(owner);
|
||||
public async getTimeLockStartAsync(owner: string): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getTimeLockStart.getABIEncodedTransactionData(owner);
|
||||
const returnData = await this._callAsync(calldata);
|
||||
const value = this.getStakingContract().getTimelockStart.getABIDecodedReturnData(returnData);
|
||||
const value = this.getStakingContract().getTimeLockStart.getABIDecodedReturnData(returnData);
|
||||
return value;
|
||||
}
|
||||
public async getStakeDelegatedByOwnerAsync(owner: string): Promise<BigNumber> {
|
||||
@@ -440,10 +440,10 @@ export class StakingWrapper {
|
||||
await this._web3Wrapper.mineBlockAsync();
|
||||
return txReceipt;
|
||||
}
|
||||
public async skipToNextTimelockPeriodAsync(): Promise<void> {
|
||||
const timelockEndEpoch = await this.getCurrentTimelockPeriodEndEpochAsync();
|
||||
public async skipToNextTimeLockPeriodAsync(): Promise<void> {
|
||||
const timeLockEndEpoch = await this.getCurrentTimeLockPeriodEndEpochAsync();
|
||||
const currentEpoch = await this.getCurrentEpochAsync();
|
||||
const nEpochsToJump = timelockEndEpoch.minus(currentEpoch);
|
||||
const nEpochsToJump = timeLockEndEpoch.minus(currentEpoch);
|
||||
const nEpochsToJumpAsNumber = nEpochsToJump.toNumber();
|
||||
for (let i = 0; i < nEpochsToJumpAsNumber; ++i) {
|
||||
await this.skipToNextEpochAsync();
|
||||
@@ -455,10 +455,10 @@ export class StakingWrapper {
|
||||
const value = this.getStakingContract().getEpochDurationInSeconds.getABIDecodedReturnData(returnData);
|
||||
return value;
|
||||
}
|
||||
public async getTimelockDurationInEpochsAsync(): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getTimelockDurationInEpochs.getABIEncodedTransactionData();
|
||||
public async getTimeLockDurationInEpochsAsync(): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getTimeLockDurationInEpochs.getABIEncodedTransactionData();
|
||||
const returnData = await this._callAsync(calldata);
|
||||
const value = this.getStakingContract().getTimelockDurationInEpochs.getABIDecodedReturnData(returnData);
|
||||
const value = this.getStakingContract().getTimeLockDurationInEpochs.getABIDecodedReturnData(returnData);
|
||||
return value;
|
||||
}
|
||||
public async getCurrentEpochStartTimeInSecondsAsync(): Promise<BigNumber> {
|
||||
@@ -467,10 +467,10 @@ export class StakingWrapper {
|
||||
const value = this.getStakingContract().getCurrentEpochStartTimeInSeconds.getABIDecodedReturnData(returnData);
|
||||
return value;
|
||||
}
|
||||
public async getCurrentTimelockPeriodStartEpochAsync(): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getCurrentTimelockPeriodStartEpoch.getABIEncodedTransactionData();
|
||||
public async getCurrentTimeLockPeriodStartEpochAsync(): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getCurrentTimeLockPeriodStartEpoch.getABIEncodedTransactionData();
|
||||
const returnData = await this._callAsync(calldata);
|
||||
const value = this.getStakingContract().getCurrentTimelockPeriodStartEpoch.getABIDecodedReturnData(returnData);
|
||||
const value = this.getStakingContract().getCurrentTimeLockPeriodStartEpoch.getABIDecodedReturnData(returnData);
|
||||
return value;
|
||||
}
|
||||
public async getCurrentEpochEarliestEndTimeInSecondsAsync(): Promise<BigNumber> {
|
||||
@@ -481,10 +481,10 @@ export class StakingWrapper {
|
||||
);
|
||||
return value;
|
||||
}
|
||||
public async getCurrentTimelockPeriodEndEpochAsync(): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getCurrentTimelockPeriodEndEpoch.getABIEncodedTransactionData();
|
||||
public async getCurrentTimeLockPeriodEndEpochAsync(): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getCurrentTimeLockPeriodEndEpoch.getABIEncodedTransactionData();
|
||||
const returnData = await this._callAsync(calldata);
|
||||
const value = this.getStakingContract().getCurrentTimelockPeriodEndEpoch.getABIDecodedReturnData(returnData);
|
||||
const value = this.getStakingContract().getCurrentTimeLockPeriodEndEpoch.getABIDecodedReturnData(returnData);
|
||||
return value;
|
||||
}
|
||||
public async getCurrentEpochAsync(): Promise<BigNumber> {
|
||||
@@ -493,10 +493,10 @@ export class StakingWrapper {
|
||||
const value = this.getStakingContract().getCurrentEpoch.getABIDecodedReturnData(returnData);
|
||||
return value;
|
||||
}
|
||||
public async getCurrentTimelockPeriodAsync(): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getCurrentTimelockPeriod.getABIEncodedTransactionData();
|
||||
public async getCurrentTimeLockPeriodAsync(): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getCurrentTimeLockPeriod.getABIEncodedTransactionData();
|
||||
const returnData = await this._callAsync(calldata);
|
||||
const value = this.getStakingContract().getCurrentTimelockPeriod.getABIDecodedReturnData(returnData);
|
||||
const value = this.getStakingContract().getCurrentTimeLockPeriod.getABIDecodedReturnData(returnData);
|
||||
return value;
|
||||
}
|
||||
///// PROTOCOL FEES /////
|
||||
|
@@ -19,7 +19,7 @@ export interface StakerBalances {
|
||||
activatableStakeBalance: BigNumber;
|
||||
activatedStakeBalance: BigNumber;
|
||||
deactivatedStakeBalance: BigNumber;
|
||||
timelockedStakeBalance: BigNumber;
|
||||
timeLockedStakeBalance: BigNumber;
|
||||
}
|
||||
|
||||
export interface DelegatorBalances extends StakerBalances {
|
||||
|
@@ -32,7 +32,7 @@
|
||||
"generated-artifacts/MixinStakingPoolRewardVault.json",
|
||||
"generated-artifacts/MixinStakingPoolRewards.json",
|
||||
"generated-artifacts/MixinStorage.json",
|
||||
"generated-artifacts/MixinTimelockedStake.json",
|
||||
"generated-artifacts/MixinTimeLockedStake.json",
|
||||
"generated-artifacts/MixinVaultCore.json",
|
||||
"generated-artifacts/MixinZrxVault.json",
|
||||
"generated-artifacts/Staking.json",
|
||||
|
Reference in New Issue
Block a user