Updated tests for epochs. More robust and helpful for staking tests.
This commit is contained in:
@@ -85,6 +85,12 @@ contract Staking is
|
||||
_withdraw(msg.sender, amount);
|
||||
}
|
||||
|
||||
function forceTimelockSync(address owner)
|
||||
external
|
||||
{
|
||||
_forceTimelockSync(owner);
|
||||
}
|
||||
|
||||
///// STAKE BALANCES /////
|
||||
|
||||
function getTotalStake(address owner)
|
||||
@@ -111,6 +117,14 @@ contract Staking is
|
||||
return _getDeactivatedStake(owner);
|
||||
}
|
||||
|
||||
function getActivatableStake(address owner)
|
||||
external
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
return _getActivatableStake(owner);
|
||||
}
|
||||
|
||||
function getWithdrawableStake(address owner)
|
||||
external
|
||||
view
|
||||
|
||||
@@ -35,7 +35,7 @@ contract MixinConstants {
|
||||
|
||||
uint64 constant public INITIAL_TIMELOCK_PERIOD = INITIAL_EPOCH;
|
||||
|
||||
uint64 constant public EPOCH_PERIOD_IN_SECONDS = 1; // @TODO SET FOR DEPLOYMENT
|
||||
uint64 constant public EPOCH_PERIOD_IN_SECONDS = 1000; // @TODO SET FOR DEPLOYMENT
|
||||
|
||||
uint64 constant public TIMELOCK_PERIOD_IN_EPOCHS = 2; // @TODO SET FOR DEPLOYMENT
|
||||
uint64 constant public TIMELOCK_PERIOD_IN_EPOCHS = 3; // @TODO SET FOR DEPLOYMENT
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ contract MixinEpoch is
|
||||
currentEpochStartTimeInSeconds = currentBlockTimestamp;
|
||||
|
||||
// increment timelock period, if needed
|
||||
if (_getCurrentTimelockPeriodEndEpoch() == nextEpoch) {
|
||||
if (_getCurrentTimelockPeriodEndEpoch() <= nextEpoch) {
|
||||
currentTimelockPeriod += 1;
|
||||
currentTimelockPeriodStartEpoch = currentEpoch;
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ contract MixinStake is
|
||||
"INSUFFICIENT_BALANCE"
|
||||
);
|
||||
activeStakeByOwner[owner] = _safeSub(activeStakeByOwner[owner], amount);
|
||||
_timelockStake(owner, amount);
|
||||
}
|
||||
|
||||
function _deactivateAndTimelockDelegatedStake(address owner, bytes32 poolId, uint256 amount)
|
||||
@@ -109,6 +110,12 @@ contract MixinStake is
|
||||
_burnStake(owner, amount);
|
||||
}
|
||||
|
||||
function _forceTimelockSync(address owner)
|
||||
internal
|
||||
{
|
||||
_syncTimelockedStake(owner);
|
||||
}
|
||||
|
||||
///// PRIVATE HELPERS /////
|
||||
|
||||
function _mintStake(address owner, uint256 amount)
|
||||
|
||||
@@ -55,22 +55,20 @@ contract MixinStakeBalances is
|
||||
return _safeSub(_getTotalStake(owner), _getActivatedStake(owner));
|
||||
}
|
||||
|
||||
/*
|
||||
function _getStakeAvailableForActivation()
|
||||
internal
|
||||
function _getActivatableStake(address owner)
|
||||
internal
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
|
||||
return _safeSub(_getDeactivatedStake(owner), _getTimelockedStake(owner));
|
||||
}
|
||||
*/
|
||||
|
||||
function _getWithdrawableStake(address owner)
|
||||
internal
|
||||
view
|
||||
returns (uint256)
|
||||
{
|
||||
return _getDeactivatedStake(owner);
|
||||
return _getActivatableStake(owner);
|
||||
}
|
||||
|
||||
function _getTimelockedStake(address owner)
|
||||
|
||||
@@ -68,11 +68,11 @@ describe('Staking Core', () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('end-to-end tests', () => {
|
||||
it('epochs & timelock periods (timelock period = 2 epochs)', async () => {
|
||||
it.only('epochs & timelock periods', async () => {
|
||||
///// 0/3 Validate Assumptions /////
|
||||
expect(await stakingWrapper.getEpochPeriodInSecondsAsync()).to.be.bignumber.equal(stakingConstants.EPOCH_PERIOD_IN_SECONDS);
|
||||
expect(await stakingWrapper.getTimelockPeriodInEpochsAsync()).to.be.bignumber.equal(stakingConstants.TIMELOCK_PERIOD_IN_EPOCHS);
|
||||
expect(stakingConstants.TIMELOCK_PERIOD_IN_EPOCHS).to.be.bignumber.equal(2);
|
||||
|
||||
///// 1/3 Validate Initial Epoch & Timelock Period /////
|
||||
{
|
||||
// epoch
|
||||
@@ -93,11 +93,8 @@ describe('Staking Core', () => {
|
||||
expect(currentTimelockPeriod).to.be.bignumber.equal(stakingConstants.INITIAL_TIMELOCK_PERIOD);
|
||||
}
|
||||
///// 3/3 Increment Epoch (Timelock Should Increment) /////
|
||||
await stakingWrapper.skipToNextEpochAsync();
|
||||
await stakingWrapper.skipToNextTimelockPeriodAsync();
|
||||
{
|
||||
// epoch
|
||||
const currentEpoch = await stakingWrapper.getCurrentEpochAsync();
|
||||
expect(currentEpoch).to.be.bignumber.equal(stakingConstants.INITIAL_EPOCH.plus(2));
|
||||
// timelock period
|
||||
const currentTimelockPeriod = await stakingWrapper.getCurrentTimelockPeriodAsync();
|
||||
expect(currentTimelockPeriod).to.be.bignumber.equal(stakingConstants.INITIAL_TIMELOCK_PERIOD.plus(1));
|
||||
@@ -106,7 +103,7 @@ describe('Staking Core', () => {
|
||||
it.skip('staking/unstaking', async () => {
|
||||
///// 1/3 SETUP TEST PARAMETERS /////
|
||||
const amountToStake = stakingWrapper.toBaseUnitAmount(10);
|
||||
const amountToUnstake = stakingWrapper.toBaseUnitAmount(5);
|
||||
const amountToUnstake = stakingWrapper.toBaseUnitAmount(4);
|
||||
const owner = stakers[0];
|
||||
// check zrx token balances before minting stake
|
||||
const zrxTokenBalanceOfVaultBeforeStaking = await stakingWrapper.getZrxTokenBalanceOfZrxVault();
|
||||
@@ -116,8 +113,7 @@ describe('Staking Core', () => {
|
||||
///// 2/3 STAKE ZRX /////
|
||||
{
|
||||
// mint stake
|
||||
const stakeMinted = await stakingWrapper.depositAndStakeAsync(owner, amountToStake);
|
||||
expect(stakeMinted).to.be.bignumber.equal(amountToStake);
|
||||
await stakingWrapper.depositAndStakeAsync(owner, amountToStake);
|
||||
// check stake balance after minting
|
||||
const stakeBalance = await stakingWrapper.getTotalStakeAsync(owner);
|
||||
expect(stakeBalance).to.be.bignumber.equal(amountToStake);
|
||||
@@ -130,23 +126,80 @@ describe('Staking Core', () => {
|
||||
const zrxTokenBalanceOfStakerAfterStaking = await stakingWrapper.getZrxTokenBalance(owner);
|
||||
expect(zrxTokenBalanceOfStakerAfterStaking).to.be.bignumber.equal(zrxTokenBalanceOfStakerBeforeStaking.minus(amountToStake));
|
||||
}
|
||||
///// 3/3 UNSTAKE ZRX /////
|
||||
///// 3/3 DEACTIVATE AND TIMELOCK STAKE /////
|
||||
{
|
||||
// unstake
|
||||
await stakingWrapper.deactivateAndTimelockStakeAsync(owner, amountToUnstake);
|
||||
// check total stake balance didn't change
|
||||
const totalStake = await stakingWrapper.getTotalStakeAsync(owner);
|
||||
expect(totalStake).to.be.bignumber.equal(amountToStake);
|
||||
// check timelocked stake is no longer activated
|
||||
const activatedStakeBalance = await stakingWrapper.getActivatedStakeAsync(owner);
|
||||
expect(activatedStakeBalance).to.be.bignumber.equal(amountToStake.minus(amountToUnstake));
|
||||
// check that timelocked stake is deactivated
|
||||
const deactivatedStakeBalance = await stakingWrapper.getDeactivatedStakeAsync(owner);
|
||||
expect(deactivatedStakeBalance).to.be.bignumber.equal(amountToUnstake);
|
||||
// check amount that is timelocked
|
||||
const timelockedStakeBalance = await stakingWrapper.getTimelockedStakeAsync(owner);
|
||||
expect(timelockedStakeBalance).to.be.bignumber.equal(amountToUnstake);
|
||||
// check that timelocked stake cannot be withdrawn
|
||||
const withdrawableStakeBalance = await stakingWrapper.getWithdrawableStakeAsync(owner);
|
||||
expect(withdrawableStakeBalance).to.be.bignumber.equal(0);
|
||||
// check that timelocked stake cannot be reactivated
|
||||
const activatableStakeBalance = await stakingWrapper.getActivatableStakeAsync(owner);
|
||||
expect(activatableStakeBalance).to.be.bignumber.equal(0);
|
||||
}
|
||||
///// 4 SKIP TO NEXT EPOCH - NOTHING SHOULD HAVE CHANGED /////
|
||||
await stakingWrapper.skipToNextEpochAsync();
|
||||
{
|
||||
// unstake
|
||||
const stakeBurned = await stakingWrapper.deactivateAndTimelockStakeAsync(owner, amountToUnstake);
|
||||
expect(stakeBurned).to.be.bignumber.equal(amountToUnstake);
|
||||
// check stake balance after burning
|
||||
const stakeBalance = await stakingWrapper.getActivatedStakeAsync(owner);
|
||||
expect(stakeBalance).to.be.bignumber.equal(amountToStake.minus(amountToUnstake));
|
||||
await stakingWrapper.deactivateAndTimelockStakeAsync(owner, amountToUnstake);
|
||||
// check total stake balance didn't change
|
||||
const totalStake = await stakingWrapper.getTotalStakeAsync(owner);
|
||||
expect(totalStake).to.be.bignumber.equal(amountToStake);
|
||||
// check timelocked stake is no longer activated
|
||||
const activatedStakeBalance = await stakingWrapper.getActivatedStakeAsync(owner);
|
||||
expect(activatedStakeBalance).to.be.bignumber.equal(amountToStake.minus(amountToUnstake));
|
||||
// check that timelocked stake is deactivated
|
||||
const deactivatedStakeBalance = await stakingWrapper.getDeactivatedStakeAsync(owner);
|
||||
expect(deactivatedStakeBalance).to.be.bignumber.equal(amountToUnstake);
|
||||
// check amount that is timelocked
|
||||
const timelockedStakeBalance = await stakingWrapper.getTimelockedStakeAsync(owner);
|
||||
expect(timelockedStakeBalance).to.be.bignumber.equal(amountToUnstake);
|
||||
// check that timelocked stake cannot be withdrawn
|
||||
const withdrawableStakeBalance = await stakingWrapper.getWithdrawableStakeAsync(owner);
|
||||
expect(withdrawableStakeBalance).to.be.bignumber.equal(0);
|
||||
// check that timelocked stake cannot be reactivated
|
||||
const activatableStakeBalance = await stakingWrapper.getActivatableStakeAsync(owner);
|
||||
expect(activatableStakeBalance).to.be.bignumber.equal(0);
|
||||
}
|
||||
|
||||
///// Stake a 0 amount to force an update //////
|
||||
|
||||
|
||||
///// 5 Reactivate Stake /////
|
||||
|
||||
///// 6 Deactivate and Timelock Stake /////
|
||||
|
||||
///// 6 Fastforward Blockchain /////
|
||||
|
||||
///// Withdraw Stake /////
|
||||
|
||||
{
|
||||
// check zrx vault balance
|
||||
/*
|
||||
const vaultBalance = await stakingWrapper.getZrxVaultBalance(owner);
|
||||
expect(vaultBalance).to.be.bignumber.equal(amountToStake.minus(amountToUnstake));
|
||||
|
||||
// check zrx token balances
|
||||
const zrxTokenBalanceOfVaultAfterStaking = await stakingWrapper.getZrxTokenBalanceOfZrxVault();
|
||||
expect(zrxTokenBalanceOfVaultAfterStaking).to.be.bignumber.equal(amountToStake.minus(amountToUnstake));
|
||||
const zrxTokenBalanceOfStakerAfterStaking = await stakingWrapper.getZrxTokenBalance(owner);
|
||||
expect(zrxTokenBalanceOfStakerAfterStaking).to.be.bignumber.equal(zrxTokenBalanceOfStakerBeforeStaking.minus(amountToStake).plus(amountToUnstake));
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
it('nth root', async () => {
|
||||
|
||||
@@ -8,6 +8,6 @@ export const constants = {
|
||||
NIL_ADDRESS: "0x0000000000000000000000000000000000000000",
|
||||
INITIAL_EPOCH: (new BigNumber(0)),
|
||||
INITIAL_TIMELOCK_PERIOD: new BigNumber(0),
|
||||
EPOCH_PERIOD_IN_SECONDS: new BigNumber(1), // @TODO SET FOR DEPLOYMENT*/
|
||||
TIMELOCK_PERIOD_IN_EPOCHS: new BigNumber(2), // @TODO SET FOR DEPLOYMENT
|
||||
EPOCH_PERIOD_IN_SECONDS: new BigNumber(1000), // @TODO SET FOR DEPLOYMENT*/
|
||||
TIMELOCK_PERIOD_IN_EPOCHS: new BigNumber(3), // @TODO SET FOR DEPLOYMENT
|
||||
};
|
||||
@@ -156,6 +156,11 @@ 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);
|
||||
const txReceipt = await this._executeTransactionAsync(calldata, this._ownerAddres);
|
||||
return txReceipt;
|
||||
}
|
||||
///// STAKE BALANCES /////
|
||||
public async getTotalStakeAsync(owner: string): Promise<string> {
|
||||
const calldata = this.getStakingContract().getTotalStake.getABIEncodedTransactionData(owner);
|
||||
@@ -172,6 +177,11 @@ export class StakingWrapper {
|
||||
const deactivatedStake = await this._callAsync(calldata);
|
||||
return deactivatedStake;
|
||||
}
|
||||
public async getActivatableStakeAsync(owner: string): Promise<string> {
|
||||
const calldata = this.getStakingContract().getActivatableStake.getABIEncodedTransactionData(owner);
|
||||
const activatableStake = await this._callAsync(calldata);
|
||||
return activatableStake;
|
||||
}
|
||||
public async getWithdrawableStakeAsync(owner: string): Promise<string> {
|
||||
const calldata = this.getStakingContract().getWithdrawableStake.getABIEncodedTransactionData(owner);
|
||||
const withdrawableStake = await this._callAsync(calldata);
|
||||
@@ -183,7 +193,7 @@ export class StakingWrapper {
|
||||
return timelockedStake;
|
||||
}
|
||||
public async getStakeDelegatedByOwnerAsync(owner: string): Promise<string> {
|
||||
const calldata = this.getStakingContract().getTimelockedStake.getABIEncodedTransactionData(owner);
|
||||
const calldata = this.getStakingContract().getStakeDelegatedByOwner.getABIEncodedTransactionData(owner);
|
||||
const stakeDelegatedByOwner = await this._callAsync(calldata);
|
||||
return stakeDelegatedByOwner;
|
||||
}
|
||||
@@ -249,6 +259,15 @@ export class StakingWrapper {
|
||||
await this._web3Wrapper.mineBlockAsync();
|
||||
return txReceipt;
|
||||
}
|
||||
public async skipToNextTimelockPeriodAsync(): Promise<void> {
|
||||
const timelockEndEpoch = await this.getCurrentTimelockPeriodEndEpochAsync();
|
||||
const currentEpoch = await this.getCurrentEpochAsync();
|
||||
const nEpochsToJump = timelockEndEpoch.minus(currentEpoch);
|
||||
const nEpochsToJumpAsNumber = nEpochsToJump.toNumber();
|
||||
for (let i = 0; i < nEpochsToJumpAsNumber; ++i) {
|
||||
await this.skipToNextEpochAsync();
|
||||
}
|
||||
}
|
||||
public async getEpochPeriodInSecondsAsync(): Promise<BigNumber> {
|
||||
const calldata = this.getStakingContract().getEpochPeriodInSeconds.getABIEncodedTransactionData();
|
||||
const returnData = await this._callAsync(calldata);
|
||||
|
||||
Reference in New Issue
Block a user