diff --git a/contracts/integrations/test/fuzz_tests/pool_management_test.ts b/contracts/integrations/test/fuzz_tests/pool_management_test.ts index e8b415b1c1..e55c68cef0 100644 --- a/contracts/integrations/test/fuzz_tests/pool_management_test.ts +++ b/contracts/integrations/test/fuzz_tests/pool_management_test.ts @@ -2,6 +2,7 @@ import { blockchainTests } from '@0x/contracts-test-utils'; import { Actor } from '../framework/actors/base'; import { PoolOperator } from '../framework/actors/pool_operator'; +import { filterActorsByRole } from '../framework/actors/utils'; import { AssertionResult } from '../framework/assertions/function_assertion'; import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store'; import { DeploymentManager } from '../framework/deployment_manager'; @@ -10,16 +11,12 @@ import { Pseudorandom } from '../framework/utils/pseudorandom'; export class PoolManagementSimulation extends Simulation { protected async *_assertionGenerator(): AsyncIterableIterator { - const { deployment } = this.environment; - const operator = new PoolOperator({ - name: 'Operator', - deployment, - simulationEnvironment: this.environment, - }); + const { actors } = this.environment; + const operators = filterActorsByRole(actors, PoolOperator); const actions = [ - operator.simulationActions.validCreateStakingPool, - operator.simulationActions.validDecreaseStakingPoolOperatorShare, + ...operators.map(operator => operator.simulationActions.validCreateStakingPool), + ...operators.map(operator => operator.simulationActions.validDecreaseStakingPoolOperatorShare), ]; while (true) { const action = Pseudorandom.sample(actions); @@ -46,8 +43,11 @@ blockchainTests('Pool management fuzz test', env => { }); const balanceStore = new BlockchainBalanceStore({}, {}); - const simulationEnv = new SimulationEnvironment(deployment, balanceStore); - const simulation = new PoolManagementSimulation(simulationEnv); + const simulationEnvironment = new SimulationEnvironment(deployment, balanceStore); + new PoolOperator({ deployment, simulationEnvironment, name: 'Operator 1' }); + new PoolOperator({ deployment, simulationEnvironment, name: 'Operator 2' }); + + const simulation = new PoolManagementSimulation(simulationEnvironment); return simulation.fuzzAsync(); }); }); diff --git a/contracts/integrations/test/fuzz_tests/pool_membership_test.ts b/contracts/integrations/test/fuzz_tests/pool_membership_test.ts index bdf25b9600..5ff6b3bc40 100644 --- a/contracts/integrations/test/fuzz_tests/pool_membership_test.ts +++ b/contracts/integrations/test/fuzz_tests/pool_membership_test.ts @@ -3,6 +3,7 @@ import { blockchainTests } from '@0x/contracts-test-utils'; import { Actor } from '../framework/actors/base'; import { MakerTaker } from '../framework/actors/hybrids'; import { Maker } from '../framework/actors/maker'; +import { PoolOperator } from '../framework/actors/pool_operator'; import { Taker } from '../framework/actors/taker'; import { filterActorsByRole } from '../framework/actors/utils'; import { AssertionResult } from '../framework/assertions/function_assertion'; @@ -13,7 +14,7 @@ import { Pseudorandom } from '../framework/utils/pseudorandom'; import { PoolManagementSimulation } from './pool_management_test'; -class PoolMembershipSimulation extends Simulation { +export class PoolMembershipSimulation extends Simulation { protected async *_assertionGenerator(): AsyncIterableIterator { const { actors } = this.environment; const makers = filterActorsByRole(actors, Maker); @@ -42,7 +43,7 @@ blockchainTests('pool membership fuzz test', env => { }); after(async () => { - Actor.count = 0; + Actor.reset(); }); it('fuzz', async () => { @@ -67,12 +68,14 @@ blockchainTests('pool membership fuzz test', env => { new Taker({ deployment, simulationEnvironment, name: 'Taker 1' }), new Taker({ deployment, simulationEnvironment, name: 'Taker 2' }), new MakerTaker({ deployment, simulationEnvironment, name: 'Maker/Taker' }), + new PoolOperator({ deployment, simulationEnvironment, name: 'Operator 1' }), + new PoolOperator({ deployment, simulationEnvironment, name: 'Operator 2' }), ]; + const takers = filterActorsByRole(actors, Taker); for (const taker of takers) { await taker.configureERC20TokenAsync(deployment.tokens.weth, deployment.staking.stakingProxy.address); } - for (const actor of actors) { balanceStore.registerTokenOwner(actor.address, actor.name); } diff --git a/contracts/integrations/test/fuzz_tests/stake_management_test.ts b/contracts/integrations/test/fuzz_tests/stake_management_test.ts index a6f67bdc34..2d00efecdc 100644 --- a/contracts/integrations/test/fuzz_tests/stake_management_test.ts +++ b/contracts/integrations/test/fuzz_tests/stake_management_test.ts @@ -1,7 +1,10 @@ import { blockchainTests } from '@0x/contracts-test-utils'; import { Actor } from '../framework/actors/base'; +import { StakerOperator } from '../framework/actors/hybrids'; +import { PoolOperator } from '../framework/actors/pool_operator'; import { Staker } from '../framework/actors/staker'; +import { filterActorsByRole } from '../framework/actors/utils'; import { AssertionResult } from '../framework/assertions/function_assertion'; import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store'; import { DeploymentManager } from '../framework/deployment_manager'; @@ -12,17 +15,15 @@ import { PoolManagementSimulation } from './pool_management_test'; export class StakeManagementSimulation extends Simulation { protected async *_assertionGenerator(): AsyncIterableIterator { - const { deployment, balanceStore } = this.environment; + const { actors } = this.environment; + const stakers = filterActorsByRole(actors, Staker); + const poolManagement = new PoolManagementSimulation(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 actions = [ - staker.simulationActions.validStake, - staker.simulationActions.validUnstake, - staker.simulationActions.validMoveStake, + ...stakers.map(staker => staker.simulationActions.validStake), + ...stakers.map(staker => staker.simulationActions.validUnstake), + ...stakers.map(staker => staker.simulationActions.validMoveStake), poolManagement.generator, ]; while (true) { @@ -57,8 +58,23 @@ blockchainTests('Stake management fuzz test', env => { { erc20: { ZRX: deployment.tokens.zrx } }, ); - const simulationEnv = new SimulationEnvironment(deployment, balanceStore); - const simulation = new StakeManagementSimulation(simulationEnv); + const simulationEnvironment = new SimulationEnvironment(deployment, balanceStore); + const actors = [ + new Staker({ name: 'Staker 1', deployment, simulationEnvironment }), + new Staker({ name: 'Staker 2', deployment, simulationEnvironment }), + new StakerOperator({ name: 'Staker/Operator', deployment, simulationEnvironment }), + new PoolOperator({ deployment, simulationEnvironment, name: 'Operator' }), + ]; + + const stakers = filterActorsByRole(actors, Staker); + for (const staker of stakers) { + await staker.configureERC20TokenAsync(deployment.tokens.zrx); + } + for (const actor of actors) { + balanceStore.registerTokenOwner(actor.address, actor.name); + } + + const simulation = new StakeManagementSimulation(simulationEnvironment); return simulation.fuzzAsync(); }); }); diff --git a/contracts/integrations/test/fuzz_tests/staking_rewards_test.ts b/contracts/integrations/test/fuzz_tests/staking_rewards_test.ts new file mode 100644 index 0000000000..4d7ddbbce2 --- /dev/null +++ b/contracts/integrations/test/fuzz_tests/staking_rewards_test.ts @@ -0,0 +1,109 @@ +import { blockchainTests } from '@0x/contracts-test-utils'; + +import { Actor } from '../framework/actors/base'; +import { + MakerTaker, + OperatorStakerMaker, + StakerKeeper, + StakerMaker, + StakerOperator, +} from '../framework/actors/hybrids'; +import { Keeper } from '../framework/actors/keeper'; +import { Maker } from '../framework/actors/maker'; +import { PoolOperator } from '../framework/actors/pool_operator'; +import { Staker } from '../framework/actors/staker'; +import { Taker } from '../framework/actors/taker'; +import { filterActorsByRole } from '../framework/actors/utils'; +import { AssertionResult } from '../framework/assertions/function_assertion'; +import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store'; +import { DeploymentManager } from '../framework/deployment_manager'; +import { Simulation, SimulationEnvironment } from '../framework/simulation'; +import { Pseudorandom } from '../framework/utils/pseudorandom'; + +import { PoolManagementSimulation } from './pool_management_test'; +import { PoolMembershipSimulation } from './pool_membership_test'; +import { StakeManagementSimulation } from './stake_management_test'; + +export class StakingRewardsSimulation extends Simulation { + protected async *_assertionGenerator(): AsyncIterableIterator { + const { actors } = this.environment; + const stakers = filterActorsByRole(actors, Staker); + const keepers = filterActorsByRole(actors, Keeper); + + const poolManagement = new PoolManagementSimulation(this.environment); + const poolMembership = new PoolMembershipSimulation(this.environment); + const stakeManagement = new StakeManagementSimulation(this.environment); + + const actions = [ + ...stakers.map(staker => staker.simulationActions.validWithdrawDelegatorRewards), + ...keepers.map(keeper => keeper.simulationActions.validFinalizePool), + ...keepers.map(keeper => keeper.simulationActions.validEndEpoch), + poolManagement.generator, + poolMembership.generator, + stakeManagement.generator, + ]; + while (true) { + const action = Pseudorandom.sample(actions); + yield (await action!.next()).value; // tslint:disable-line:no-non-null-assertion + } + } +} + +blockchainTests('Staking rewards fuzz test', env => { + before(function(): void { + if (process.env.FUZZ_TEST !== 'staking_rewards') { + this.skip(); + } + }); + + after(async () => { + Actor.reset(); + }); + + it('fuzz', async () => { + const deployment = await DeploymentManager.deployAsync(env, { + numErc20TokensToDeploy: 4, + numErc721TokensToDeploy: 0, + numErc1155TokensToDeploy: 0, + }); + const balanceStore = new BlockchainBalanceStore( + { + StakingProxy: deployment.staking.stakingProxy.address, + ZRXVault: deployment.staking.zrxVault.address, + }, + { erc20: { ZRX: deployment.tokens.zrx } }, + ); + const simulationEnvironment = new SimulationEnvironment(deployment, balanceStore); + + const actors = [ + new Maker({ deployment, simulationEnvironment, name: 'Maker 1' }), + new Maker({ deployment, simulationEnvironment, name: 'Maker 2' }), + new Taker({ deployment, simulationEnvironment, name: 'Taker 1' }), + new Taker({ deployment, simulationEnvironment, name: 'Taker 2' }), + new MakerTaker({ deployment, simulationEnvironment, name: 'Maker/Taker' }), + new Staker({ deployment, simulationEnvironment, name: 'Staker 1' }), + new Staker({ deployment, simulationEnvironment, name: 'Staker 2' }), + new Keeper({ deployment, simulationEnvironment, name: 'Keeper' }), + new StakerKeeper({ deployment, simulationEnvironment, name: 'Staker/Keeper' }), + new StakerMaker({ deployment, simulationEnvironment, name: 'Staker/Maker' }), + new PoolOperator({ deployment, simulationEnvironment, name: 'Pool Operator' }), + new StakerOperator({ deployment, simulationEnvironment, name: 'Staker/Operator' }), + new OperatorStakerMaker({ deployment, simulationEnvironment, name: 'Operator/Staker/Maker' }), + ]; + + const takers = filterActorsByRole(actors, Taker); + for (const taker of takers) { + await taker.configureERC20TokenAsync(deployment.tokens.weth, deployment.staking.stakingProxy.address); + } + const stakers = filterActorsByRole(actors, Staker); + for (const staker of stakers) { + await staker.configureERC20TokenAsync(deployment.tokens.zrx); + } + for (const actor of actors) { + balanceStore.registerTokenOwner(actor.address, actor.name); + } + + const simulation = new StakingRewardsSimulation(simulationEnvironment); + return simulation.fuzzAsync(); + }); +});