address comments

This commit is contained in:
Michael Zhu
2020-01-15 09:47:49 -08:00
parent 089ec35ceb
commit f217840998
5 changed files with 16 additions and 84 deletions

View File

@@ -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 });
}

View File

@@ -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;

View File

@@ -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.

View File

@@ -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 */

View File

@@ -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[]];