address comments
This commit is contained in:
@@ -92,7 +92,7 @@ export function PoolOperatorMixin<TBase extends Constructor>(Base: TBase): TBase
|
||||
const operatorShare = Pseudorandom.integer(
|
||||
0,
|
||||
stakingConstants.PPM,
|
||||
Distributions.Kumaraswamy(0.2, 0.2),
|
||||
Distributions.Kumaraswamy(),
|
||||
).toNumber();
|
||||
yield assertion.executeAsync([operatorShare, false], { from: this.actor.address });
|
||||
}
|
||||
@@ -104,7 +104,7 @@ export function PoolOperatorMixin<TBase extends Constructor>(Base: TBase): TBase
|
||||
const operatorShare = Pseudorandom.integer(
|
||||
(stakingConstants.PPM as number) + 1,
|
||||
constants.MAX_UINT32,
|
||||
Distributions.Kumaraswamy(0.2, 0.2),
|
||||
Distributions.Kumaraswamy(),
|
||||
).toNumber();
|
||||
yield assertion.executeAsync([operatorShare, false], { from: this.actor.address });
|
||||
}
|
||||
@@ -121,7 +121,7 @@ export function PoolOperatorMixin<TBase extends Constructor>(Base: TBase): TBase
|
||||
const operatorShare = Pseudorandom.integer(
|
||||
0,
|
||||
stakingPools[poolId].operatorShare,
|
||||
Distributions.Kumaraswamy(0.2, 0.2),
|
||||
Distributions.Kumaraswamy(),
|
||||
).toNumber();
|
||||
yield assertion.executeAsync([poolId, operatorShare], { from: this.actor.address });
|
||||
}
|
||||
@@ -139,7 +139,7 @@ export function PoolOperatorMixin<TBase extends Constructor>(Base: TBase): TBase
|
||||
const operatorShare = Pseudorandom.integer(
|
||||
(stakingPools[poolId].operatorShare as number) + 1,
|
||||
constants.MAX_UINT32,
|
||||
Distributions.Kumaraswamy(0.2, 0.2),
|
||||
Distributions.Kumaraswamy(),
|
||||
).toNumber();
|
||||
yield assertion.executeAsync([poolId, operatorShare], { from: this.actor.address });
|
||||
}
|
||||
|
@@ -6,11 +6,7 @@ import * as _ from 'lodash';
|
||||
|
||||
import { AssertionResult } from '../assertions/function_assertion';
|
||||
import { assetProxyTransferFailedAssertion } from '../assertions/generic_assertions';
|
||||
import {
|
||||
moveStakeInvalidAmountAssertion,
|
||||
moveStakeNonexistentPoolAssertion,
|
||||
validMoveStakeAssertion,
|
||||
} from '../assertions/moveStake';
|
||||
import { moveStakeNonexistentPoolAssertion, validMoveStakeAssertion } from '../assertions/moveStake';
|
||||
import { validStakeAssertion } from '../assertions/stake';
|
||||
import { invalidUnstakeAssertion, validUnstakeAssertion } from '../assertions/unstake';
|
||||
import {
|
||||
@@ -59,7 +55,6 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
invalidUnstake: this._invalidUnstake(),
|
||||
validMoveStake: this._validMoveStake(),
|
||||
moveStakeNonexistentPool: this._moveStakeNonexistentPool(),
|
||||
moveStakeInvalidAmount: this._moveStakeInvalidAmount(),
|
||||
validWithdrawDelegatorRewards: this._validWithdrawDelegatorRewards(),
|
||||
invalidWithdrawDelegatorRewards: this._invalidWithdrawDelegatorRewards(),
|
||||
};
|
||||
@@ -106,7 +101,7 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
while (true) {
|
||||
await balanceStore.updateErc20BalancesAsync();
|
||||
const zrxBalance = balanceStore.balances.erc20[this.actor.address][zrx.address];
|
||||
const amount = Pseudorandom.integer(zrxBalance, constants.MAX_UINT256);
|
||||
const amount = Pseudorandom.integer(zrxBalance.plus(1), constants.MAX_UINT256);
|
||||
yield assertion.executeAsync([amount], { from: this.actor.address });
|
||||
}
|
||||
}
|
||||
@@ -144,7 +139,7 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
undelegatedStake.nextEpochBalance,
|
||||
);
|
||||
const assertion = invalidUnstakeAssertion(deployment, withdrawableStake);
|
||||
const amount = Pseudorandom.integer(withdrawableStake, constants.MAX_UINT256);
|
||||
const amount = Pseudorandom.integer(withdrawableStake.plus(1), constants.MAX_UINT256);
|
||||
yield assertion.executeAsync([amount], { from: this.actor.address });
|
||||
}
|
||||
}
|
||||
@@ -200,41 +195,14 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
}
|
||||
}
|
||||
|
||||
private async *_moveStakeInvalidAmount(): AsyncIterableIterator<AssertionResult | void> {
|
||||
while (true) {
|
||||
const [from, to] = this._validMoveParams();
|
||||
if (from.status === StakeStatus.Undelegated && to.status === StakeStatus.Undelegated) {
|
||||
yield;
|
||||
} else {
|
||||
// The next epoch balance of the `from` stake is the amount that can be moved
|
||||
const moveableStake =
|
||||
from.status === StakeStatus.Undelegated
|
||||
? this.stake[StakeStatus.Undelegated].nextEpochBalance
|
||||
: this.stake[StakeStatus.Delegated][from.poolId].nextEpochBalance;
|
||||
const amount = Pseudorandom.integer(moveableStake.plus(1), constants.MAX_UINT256);
|
||||
const assertion = moveStakeInvalidAmountAssertion(this.actor.deployment);
|
||||
yield assertion.executeAsync([from, to, amount], { from: this.actor.address });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async *_moveStakeNonexistentPool(): AsyncIterableIterator<AssertionResult> {
|
||||
const { stakingWrapper } = this.actor.deployment.staking;
|
||||
// Randomly chooses a poolId that hasn't been used yet
|
||||
const unusedPoolId = (lastPoolId: string) =>
|
||||
`0x${Pseudorandom.integer(new BigNumber(lastPoolId).plus(1), constants.MAX_UINT256)
|
||||
.plus(1)
|
||||
.toString(16)
|
||||
.padStart(64, '0')}`;
|
||||
|
||||
while (true) {
|
||||
const [from, to, amount] = this._validMoveParams();
|
||||
const lastPoolId = await stakingWrapper.lastPoolId().callAsync();
|
||||
|
||||
// If there is 0 moveable stake for the sampled `to` pool, we need to mutate the `to`
|
||||
// info, otherwise `moveStake` will just noop
|
||||
// If there is 0 moveable stake for the sampled `to` pool, we need to mutate the
|
||||
// `from` info, otherwise `moveStake` will just noop
|
||||
if (amount.isZero()) {
|
||||
from.poolId = unusedPoolId(lastPoolId);
|
||||
from.poolId = Pseudorandom.hex();
|
||||
// Status must be delegated and amount must be nonzero to trigger _assertStakingPoolExists
|
||||
from.status = StakeStatus.Delegated;
|
||||
const randomAmount = Pseudorandom.integer(1, constants.MAX_UINT256);
|
||||
@@ -245,7 +213,7 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
|
||||
const infoToMutate = Pseudorandom.sample([[from], [to], [from, to]]);
|
||||
let nonExistentPoolId;
|
||||
for (const info of infoToMutate!) {
|
||||
info.poolId = unusedPoolId(lastPoolId);
|
||||
info.poolId = Pseudorandom.hex();
|
||||
nonExistentPoolId = nonExistentPoolId || info.poolId;
|
||||
// Status must be delegated and amount must be nonzero to trigger _assertStakingPoolExists
|
||||
info.status = StakeStatus.Delegated;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { StakingRevertErrors, StoredBalance } from '@0x/contracts-staking';
|
||||
import { expect } from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { BigNumber, hexUtils } from '@0x/utils';
|
||||
import { TxData } from 'ethereum-types';
|
||||
|
||||
import { DeploymentManager } from '../deployment_manager';
|
||||
@@ -26,10 +26,7 @@ export function validCreateStakingPoolAssertion(
|
||||
before: async () => {
|
||||
const lastPoolId = await stakingWrapper.lastPoolId().callAsync();
|
||||
// Effectively the last poolId + 1, but as a bytestring
|
||||
return `0x${new BigNumber(lastPoolId)
|
||||
.plus(1)
|
||||
.toString(16)
|
||||
.padStart(64, '0')}`;
|
||||
return hexUtils.leftPad(new BigNumber(lastPoolId).plus(1));
|
||||
},
|
||||
after: async (
|
||||
expectedPoolId: string,
|
||||
@@ -73,10 +70,7 @@ export function invalidCreateStakingPoolAssertion(
|
||||
before: async () => {
|
||||
const lastPoolId = await stakingWrapper.lastPoolId().callAsync();
|
||||
// Effectively the last poolId + 1, but as a bytestring
|
||||
return `0x${new BigNumber(lastPoolId)
|
||||
.plus(1)
|
||||
.toString(16)
|
||||
.padStart(64, '0')}`;
|
||||
return hexUtils.leftPad(new BigNumber(lastPoolId).plus(1));
|
||||
},
|
||||
after: async (expectedPoolId: string, result: FunctionResult, args: [number, boolean]) => {
|
||||
// Ensure that the tx reverted.
|
||||
|
@@ -9,7 +9,6 @@ import {
|
||||
StoredBalance,
|
||||
} from '@0x/contracts-staking';
|
||||
import { expect } from '@0x/contracts-test-utils';
|
||||
import { SafeMathRevertErrors } from '@0x/contracts-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { TxData } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
@@ -221,31 +220,4 @@ export function moveStakeNonexistentPoolAssertion(
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a FunctionAssertion for `moveStake` which assumes the input amount exceeds the moveable
|
||||
* amount of stake. Checks that the transaction reverts.
|
||||
*/
|
||||
export function moveStakeInvalidAmountAssertion(
|
||||
deployment: DeploymentManager,
|
||||
): FunctionAssertion<[StakeInfo, StakeInfo, BigNumber], void, void> {
|
||||
return new FunctionAssertion<[StakeInfo, StakeInfo, BigNumber], void, void>(
|
||||
deployment.staking.stakingWrapper,
|
||||
'moveStake',
|
||||
{
|
||||
after: async (_beforeInfo: void, result: FunctionResult) => {
|
||||
// Ensure that the tx reverted.
|
||||
expect(result.success).to.be.false();
|
||||
|
||||
// This isn't ideal but unfortunately there are several different revert errors that
|
||||
// can be triggered by trying to move more stake than possible.
|
||||
expect(
|
||||
result.data instanceof SafeMathRevertErrors.Uint256BinOpError ||
|
||||
result.data instanceof SafeMathRevertErrors.Uint256DowncastError ||
|
||||
result.data instanceof StakingRevertErrors.InsufficientBalanceError,
|
||||
).to.be.true();
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
/* tslint:enable:no-unnecessary-type-assertion */
|
||||
|
@@ -30,12 +30,10 @@ export class StakeManagementSimulation extends Simulation {
|
||||
...stakers.map(staker => [staker.simulationActions.validStake, 0.28 / stakers.length]),
|
||||
// 2% chance of executing invalidUnstake for a random staker
|
||||
...stakers.map(staker => [staker.simulationActions.validUnstake, 0.02 / stakers.length]),
|
||||
// 26% chance of executing validMoveStake for a random staker
|
||||
...stakers.map(staker => [staker.simulationActions.validMoveStake, 0.26 / stakers.length]),
|
||||
// 28% chance of executing validMoveStake for a random staker
|
||||
...stakers.map(staker => [staker.simulationActions.validMoveStake, 0.28 / stakers.length]),
|
||||
// 2% chance of executing moveStakeNonexistentPool for a random staker
|
||||
...stakers.map(staker => [staker.simulationActions.moveStakeNonexistentPool, 0.02 / stakers.length]),
|
||||
// 2% chance of executing moveStakeInvalidAmount for a random staker
|
||||
...stakers.map(staker => [staker.simulationActions.moveStakeInvalidAmount, 0.02 / stakers.length]),
|
||||
// 20% chance of executing an assertion generated from the pool management simulation
|
||||
[poolManagement.generator, 0.2],
|
||||
]) as [Array<AsyncIterableIterator<AssertionResult | void>>, number[]];
|
||||
|
Reference in New Issue
Block a user