* `@0x/contracts-integrations`: Add Exchange signature validation fuzz tests. * `@0x/contracts-integrations`: Switch from actor pattern to just pure function generators. Co-authored-by: Lawrence Forman <me@merklejerk.com>
82 lines
2.6 KiB
TypeScript
82 lines
2.6 KiB
TypeScript
import {
|
|
constants as stakingConstants,
|
|
GlobalStakeByStatus,
|
|
StakeStatus,
|
|
StakingPoolById,
|
|
StoredBalance,
|
|
} from '@0x/contracts-staking';
|
|
import { BigNumber } from '@0x/utils';
|
|
|
|
import { Actor } from './actors/base';
|
|
import { AssertionResult } from './assertions/function_assertion';
|
|
import { BlockchainBalanceStore } from './balances/blockchain_balance_store';
|
|
import { DeploymentManager } from './deployment_manager';
|
|
import { logger } from './utils/logger';
|
|
|
|
// tslint:disable:max-classes-per-file
|
|
|
|
export class SimulationEnvironment {
|
|
public globalStake: GlobalStakeByStatus = {
|
|
[StakeStatus.Undelegated]: new StoredBalance(),
|
|
[StakeStatus.Delegated]: new StoredBalance(),
|
|
};
|
|
public stakingPools: StakingPoolById = {};
|
|
public currentEpoch: BigNumber = stakingConstants.INITIAL_EPOCH;
|
|
|
|
public constructor(
|
|
public readonly deployment: DeploymentManager,
|
|
public balanceStore: BlockchainBalanceStore,
|
|
public readonly actors: Actor[] = [],
|
|
) {
|
|
for (const actor of actors) {
|
|
// Set the actor's simulation environment
|
|
actor.simulationEnvironment = this;
|
|
// Register each actor in the balance store
|
|
this.balanceStore.registerTokenOwner(actor.address, actor.name);
|
|
}
|
|
}
|
|
|
|
public state(): any {
|
|
return {
|
|
globalStake: this.globalStake,
|
|
stakingPools: this.stakingPools,
|
|
balanceStore: this.balanceStore.toReadable(),
|
|
currentEpoch: this.currentEpoch,
|
|
};
|
|
}
|
|
}
|
|
|
|
export abstract class Simulation {
|
|
public readonly generator = this._assertionGenerator();
|
|
public resets = false;
|
|
|
|
constructor(public environment: SimulationEnvironment) {}
|
|
|
|
public async fuzzAsync(steps?: number): Promise<void> {
|
|
if (steps !== undefined) {
|
|
for (let i = 0; i < steps; i++) {
|
|
await this._stepAsync();
|
|
}
|
|
} else {
|
|
while (true) {
|
|
await this._stepAsync();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected abstract _assertionGenerator(): AsyncIterableIterator<AssertionResult | void>;
|
|
|
|
private async _stepAsync(): Promise<void> {
|
|
const snapshotId = this.resets ? await this.environment.deployment.web3Wrapper.takeSnapshotAsync() : undefined;
|
|
try {
|
|
await this.generator.next();
|
|
} catch (error) {
|
|
logger.logFailure(error, this.environment.state());
|
|
throw error;
|
|
}
|
|
if (snapshotId !== undefined) {
|
|
await this.environment.deployment.web3Wrapper.revertSnapshotAsync(snapshotId);
|
|
}
|
|
}
|
|
}
|