decouple state (SimulationEnvironment) and Simulation

This commit is contained in:
Michael Zhu
2019-11-05 11:08:58 -08:00
parent 3c7a0bcd85
commit 44f268a7ee
5 changed files with 36 additions and 29 deletions

View File

@@ -5,7 +5,7 @@ import { SignatureType, SignedZeroExTransaction, ZeroExTransaction } from '@0x/t
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import { Simulation } from '../simulation/simulation';
import { SimulationEnvironment } from '../simulation/simulation';
import { DeploymentManager } from '../deployment_manager';
import { AssertionResult } from '../../src/function_assertions';
@@ -14,7 +14,7 @@ export type Constructor<T = {}> = new (...args: any[]) => T;
export interface ActorConfig {
name?: string;
deployment: DeploymentManager;
simulation?: Simulation;
simulationEnvironment?: SimulationEnvironment;
[mixinProperty: string]: any;
}
@@ -24,7 +24,7 @@ export class Actor {
public readonly name: string;
public readonly privateKey: Buffer;
public readonly deployment: DeploymentManager;
public readonly simulation?: Simulation;
public readonly simulationEnvironment?: SimulationEnvironment;
public simulationActions: {
[action: string]: (...args: any[]) => Promise<IteratorResult<AssertionResult | void>>;
} = {};
@@ -36,7 +36,7 @@ export class Actor {
this.name = config.name || this.address;
this.deployment = config.deployment;
this.privateKey = constants.TESTRPC_PRIVATE_KEYS[config.deployment.accounts.indexOf(this.address)];
this.simulation = config.simulation;
this.simulationEnvironment = config.simulationEnvironment;
this._transactionFactory = new TransactionFactory(
this.privateKey,
config.deployment.exchange.address,

View File

@@ -44,7 +44,7 @@ export function PoolOperatorMixin<TBase extends Constructor>(Base: TBase): TBase
this.actor = (this as any) as Actor;
// Register this mixin's assertion generators
if (this.actor.simulation !== undefined) {
if (this.actor.simulationEnvironment !== undefined) {
this.actor.simulationActions = {
...this.actor.simulationActions,
validCreateStakingPool: this._validCreateStakingPool().next,

View File

@@ -1,9 +1,9 @@
import { BlockchainBalanceStore } from '@0x/contracts-exchange';
import { StakeInfo, StakeStatus } from '@0x/contracts-staking';
import { getRandomInteger } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { validStakeAssertion, validUnstakeAssertion } from '../function-assertions';
import { Simulation } from '../simulation/simulation';
import { AssertionResult } from '../utils/function_assertions';
import { Actor, Constructor } from './base';
@@ -31,11 +31,12 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
this.actor = (this as any) as Actor;
// Register this mixin's assertion generators
if (this.actor.simulation !== undefined) {
if (this.actor.simulationEnvironment !== undefined) {
const { balanceStore } = this.actor.simulationEnvironment;
this.actor.simulationActions = {
...this.actor.simulationActions,
validStake: this._validStake(this.actor.simulation).next,
validUnstake: this._validUnstake(this.actor.simulation).next,
validStake: this._validStake(balanceStore).next,
validUnstake: this._validUnstake(balanceStore).next,
};
}
}
@@ -59,25 +60,25 @@ export function StakerMixin<TBase extends Constructor>(Base: TBase): TBase & Con
}
}
private async *_validStake(simulation: Simulation): AsyncIterableIterator<AssertionResult> {
private async *_validStake(balanceStore: BlockchainBalanceStore): AsyncIterableIterator<AssertionResult> {
const { zrx } = this.actor.deployment.tokens;
const assertion = validStakeAssertion(this.actor.deployment, simulation.balanceStore);
const assertion = validStakeAssertion(this.actor.deployment, balanceStore);
while (true) {
await simulation.balanceStore.updateErc20BalancesAsync();
const zrxBalance = simulation.balanceStore.balances.erc20[this.actor.address][zrx.address];
await balanceStore.updateErc20BalancesAsync();
const zrxBalance = balanceStore.balances.erc20[this.actor.address][zrx.address];
const amount = getRandomInteger(0, zrxBalance);
console.log(`stake(${amount})`);
yield assertion.executeAsync(amount, { from: this.actor.address });
}
}
private async *_validUnstake(simulation: Simulation): AsyncIterableIterator<AssertionResult> {
private async *_validUnstake(balanceStore: BlockchainBalanceStore): AsyncIterableIterator<AssertionResult> {
const { stakingWrapper } = this.actor.deployment.staking;
const assertion = validUnstakeAssertion(this.actor.deployment, simulation.balanceStore);
const assertion = validUnstakeAssertion(this.actor.deployment, balanceStore);
while (true) {
await simulation.balanceStore.updateErc20BalancesAsync();
await balanceStore.updateErc20BalancesAsync();
const undelegatedStake = await stakingWrapper.getOwnerStakeByStatus.callAsync(
this.actor.address,
StakeStatus.Undelegated,

View File

@@ -6,19 +6,24 @@ import { PoolOperator, Staker } from '../actors';
import { DeploymentManager } from '../utils/deployment_manager';
import { AssertionResult } from '../utils/function_assertions';
import { Simulation } from './simulation';
import { Simulation, SimulationEnvironment } from './simulation';
class PoolManagementSimulation extends Simulation {
constructor(balanceStore: BlockchainBalanceStore, deployment: DeploymentManager) {
super(balanceStore, deployment);
constructor(environment: SimulationEnvironment) {
super(environment);
}
protected async *_assertionGenerator(): AsyncIterableIterator<AssertionResult> {
const staker = new Staker({ name: 'Staker', deployment: this._deployment, simulation: this });
await staker.configureERC20TokenAsync(this._deployment.tokens.zrx);
this.balanceStore.registerTokenOwner(staker.address, staker.name);
const { deployment, balanceStore } = this.environment;
const staker = new Staker({ name: 'Staker', deployment, simulationEnvironment: this.environment });
await staker.configureERC20TokenAsync(deployment.tokens.zrx);
balanceStore.registerTokenOwner(staker.address, staker.name);
const operator = new PoolOperator({ name: 'Operator', deployment: this._deployment, simulation: this });
const operator = new PoolOperator({
name: 'Operator',
deployment,
simulationEnvironment: this.environment,
});
const actions = [
staker.simulationActions.validStake,
@@ -49,7 +54,7 @@ blockchainTests.only('Pool management fuzz test', env => {
{ erc20: { ZRX: deployment.tokens.zrx } },
);
const sim = new PoolManagementSimulation(balanceStore, deployment);
const sim = new PoolManagementSimulation({ balanceStore, deployment });
return sim.fuzzAsync();
});
});

View File

@@ -4,14 +4,15 @@ import * as _ from 'lodash';
import { DeploymentManager } from '../utils/deployment_manager';
import { AssertionResult } from '../utils/function_assertions';
export interface SimulationEnvironment {
balanceStore: BlockchainBalanceStore;
deployment: DeploymentManager;
}
export abstract class Simulation {
public poolIds = [];
private readonly _generator = this._assertionGenerator();
protected constructor(
public readonly balanceStore: BlockchainBalanceStore,
protected readonly _deployment: DeploymentManager,
) {}
protected constructor(public readonly environment: SimulationEnvironment) {}
public async stepAsync(): Promise<void> {
await this._generator.next();