add createStakingPool and decreaseStakingPoolOperatorShare

This commit is contained in:
Michael Zhu
2019-11-04 17:38:28 -08:00
parent 8e2e9e9331
commit 3c7a0bcd85
8 changed files with 112 additions and 5 deletions

View File

@@ -26,7 +26,7 @@ export class Actor {
public readonly deployment: DeploymentManager;
public readonly simulation?: Simulation;
public simulationActions: {
[action: string]: (...args: any[]) => Promise<IteratorResult<AssertionResult>>;
[action: string]: (...args: any[]) => Promise<IteratorResult<AssertionResult | void>>;
} = {};
protected readonly _transactionFactory: TransactionFactory;

View File

@@ -1,4 +1,13 @@
import { constants } from '@0x/contracts-staking';
import { getRandomInteger } from '@0x/contracts-test-utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import {
validCreateStakingPoolAssertion,
validDecreaseStakingPoolOperatorShareAssertion,
} from '../function-assertions';
import { AssertionResult } from '../utils/function_assertions';
import { Actor, Constructor } from './base';
@@ -33,6 +42,15 @@ export function PoolOperatorMixin<TBase extends Constructor>(Base: TBase): TBase
// tslint:disable-next-line:no-inferred-empty-object-type
super(...args);
this.actor = (this as any) as Actor;
// Register this mixin's assertion generators
if (this.actor.simulation !== undefined) {
this.actor.simulationActions = {
...this.actor.simulationActions,
validCreateStakingPool: this._validCreateStakingPool().next,
validDecreaseStakingPoolOperatorShare: this._validDecreaseStakingPoolOperatorShare().next,
};
}
}
/**
@@ -70,6 +88,27 @@ export function PoolOperatorMixin<TBase extends Constructor>(Base: TBase): TBase
{ from: this.actor.address },
);
}
private async *_validCreateStakingPool(): AsyncIterableIterator<AssertionResult> {
const assertion = validCreateStakingPoolAssertion(this.actor.deployment, this);
while (true) {
const operatorShare = getRandomInteger(0, constants.PPM);
yield assertion.executeAsync(operatorShare, false, { from: this.actor.address });
}
}
private async *_validDecreaseStakingPoolOperatorShare(): AsyncIterableIterator<AssertionResult | void> {
const assertion = validDecreaseStakingPoolOperatorShareAssertion(this.actor.deployment, this);
while (true) {
const poolId = _.sample(Object.keys(this.operatorShares));
if (poolId === undefined) {
yield undefined;
} else {
const operatorShare = getRandomInteger(0, this.operatorShares[poolId]);
yield assertion.executeAsync(poolId, operatorShare, { from: this.actor.address });
}
}
}
};
}

View File

@@ -3,8 +3,8 @@ import { getRandomInteger } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { validStakeAssertion, validUnstakeAssertion } from '../function-assertions';
import { AssertionResult } from '../utils/function_assertions';
import { Simulation } from '../simulation/simulation';
import { AssertionResult } from '../utils/function_assertions';
import { Actor, Constructor } from './base';

View File

@@ -0,0 +1,36 @@
import { expect } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { DeploymentManager } from '../utils/deployment_manager';
import { FunctionAssertion, FunctionResult } from '../utils/function_assertions';
export function validCreateStakingPoolAssertion(
deployment: DeploymentManager,
context?: any,
): FunctionAssertion<string> {
const { stakingWrapper } = deployment.staking;
return new FunctionAssertion(stakingWrapper.createStakingPool, {
before: async () => {
const lastPoolId = await stakingWrapper.lastPoolId.callAsync();
return `0x${new BigNumber(lastPoolId)
.plus(1)
.toString(16)
.padStart(64, '0')}`;
},
after: async (
expectedPoolId: string,
result: FunctionResult,
operatorShare: number,
addOperatorAsMaker: boolean,
) => {
const log = result.receipt!.logs[0];
const actualPoolId = (log as any).args.poolId;
expect(actualPoolId).to.equal(expectedPoolId);
console.log(`createStakingPool(${operatorShare}, ${addOperatorAsMaker}) => ${actualPoolId}`);
if (context !== undefined) {
context.operatorShares[actualPoolId] = operatorShare;
}
},
});
}

View File

@@ -0,0 +1,22 @@
import { expect } from '@0x/contracts-test-utils';
import { DeploymentManager } from '../utils/deployment_manager';
import { FunctionAssertion, FunctionResult } from '../utils/function_assertions';
export function validDecreaseStakingPoolOperatorShareAssertion(
deployment: DeploymentManager,
context?: any,
): FunctionAssertion<{}> {
const { stakingWrapper } = deployment.staking;
return new FunctionAssertion(stakingWrapper.decreaseStakingPoolOperatorShare, {
after: async (_beforeInfo, _result: FunctionResult, poolId: string, expectedOperatorShare: number) => {
const { operatorShare } = await stakingWrapper.getStakingPool.callAsync(poolId);
expect(operatorShare).to.bignumber.equal(expectedOperatorShare);
console.log(`decreaseStakingPoolOperatorShare(${poolId}, ${expectedOperatorShare})`);
if (context !== undefined) {
context.operatorShares[poolId] = operatorShare;
}
},
});
}

View File

@@ -1,2 +1,4 @@
export * from './stake';
export * from './unstake';
export * from './createStakingPool';
export * from './decreaseStakingPoolOperatorShare';

View File

@@ -2,7 +2,7 @@ import { BlockchainBalanceStore } from '@0x/contracts-exchange';
import { blockchainTests } from '@0x/contracts-test-utils';
import * as _ from 'lodash';
import { Staker } from '../actors';
import { PoolOperator, Staker } from '../actors';
import { DeploymentManager } from '../utils/deployment_manager';
import { AssertionResult } from '../utils/function_assertions';
@@ -18,7 +18,14 @@ class PoolManagementSimulation extends Simulation {
await staker.configureERC20TokenAsync(this._deployment.tokens.zrx);
this.balanceStore.registerTokenOwner(staker.address, staker.name);
const actions = [staker.simulationActions.validStake, staker.simulationActions.validUnstake];
const operator = new PoolOperator({ name: 'Operator', deployment: this._deployment, simulation: this });
const actions = [
staker.simulationActions.validStake,
staker.simulationActions.validUnstake,
operator.simulationActions.validCreateStakingPool,
operator.simulationActions.validDecreaseStakingPoolOperatorShare,
];
while (true) {
const action = _.sample(actions);
await action!();
@@ -26,7 +33,7 @@ class PoolManagementSimulation extends Simulation {
}
}
blockchainTests.skip('Pool management fuzz test', env => {
blockchainTests.only('Pool management fuzz test', env => {
it('fuzz', async () => {
const deployment = await DeploymentManager.deployAsync(env, {
numErc20TokensToDeploy: 0,

View File

@@ -5,6 +5,7 @@ import { DeploymentManager } from '../utils/deployment_manager';
import { AssertionResult } from '../utils/function_assertions';
export abstract class Simulation {
public poolIds = [];
private readonly _generator = this._assertionGenerator();
protected constructor(