diff --git a/contracts/staking/test/actors/delegator_actor.ts b/contracts/staking/test/actors/delegator_actor.ts index a45419f3e4..3d0b30fabd 100644 --- a/contracts/staking/test/actors/delegator_actor.ts +++ b/contracts/staking/test/actors/delegator_actor.ts @@ -5,7 +5,7 @@ import { provider, txDefaults, web3Wrapper, -} from '@0x/contracts-test-utils' +} from '@0x/contracts-test-utils'; import { RevertReason } from '@0x/types'; import { BigNumber } from '@0x/utils'; import * as chai from 'chai'; @@ -19,21 +19,21 @@ import { StakerActor } from './staker_actor'; const expect = chai.expect; export class DelegatorActor extends StakerActor { - constructor(owner: string, stakingWrapper: StakingWrapper) { super(owner, stakingWrapper); } - public async depositAndDelegateAsync(poolId: string, amount: BigNumber, revertReason?: RevertReason): Promise { + public async depositAndDelegateAsync( + poolId: string, + amount: BigNumber, + revertReason?: RevertReason, + ): Promise { // query init balances const initZrxBalanceOfVault = await this._stakingWrapper.getZrxTokenBalanceOfZrxVault(); const initDelegatorBalances = await this.getBalancesAsync([poolId]); // deposit stake const txReceiptPromise = this._stakingWrapper.depositAndDelegateAsync(this._owner, poolId, amount); if (revertReason !== undefined) { - await expectTransactionFailedAsync( - txReceiptPromise, - revertReason - ); + await expectTransactionFailedAsync(txReceiptPromise, revertReason); return; } const txReceipt = await txReceiptPromise; @@ -45,23 +45,26 @@ export class DelegatorActor extends StakerActor { expectedDelegatorBalances.stakeBalanceInVault = initDelegatorBalances.stakeBalanceInVault.plus(amount); expectedDelegatorBalances.activatedStakeBalance = initDelegatorBalances.activatedStakeBalance.plus(amount); expectedDelegatorBalances.delegatedStakeBalance = initDelegatorBalances.delegatedStakeBalance.plus(amount); - expectedDelegatorBalances.stakeDelegatedToPoolByOwner[0] = initDelegatorBalances.stakeDelegatedToPoolByOwner[0].plus(amount); + expectedDelegatorBalances.stakeDelegatedToPoolByOwner[0] = initDelegatorBalances.stakeDelegatedToPoolByOwner[0].plus( + amount, + ); expectedDelegatorBalances.stakeDelegatedToPool[0] = initDelegatorBalances.stakeDelegatedToPool[0].plus(amount); await this.assertBalancesAsync(expectedDelegatorBalances, [poolId]); // check zrx balance of vault const finalZrxBalanceOfVault = await this._stakingWrapper.getZrxTokenBalanceOfZrxVault(); expect(finalZrxBalanceOfVault).to.be.bignumber.equal(initZrxBalanceOfVault.plus(amount)); } - public async activateAndDelegateStakeAsync(poolId: string, amount: BigNumber, revertReason?: RevertReason): Promise { + public async activateAndDelegateStakeAsync( + poolId: string, + amount: BigNumber, + revertReason?: RevertReason, + ): Promise { // query init balances const initDelegatorBalances = await this.getBalancesAsync([poolId]); // activate and delegate const txReceiptPromise = this._stakingWrapper.activateAndDelegateStakeAsync(this._owner, poolId, amount); if (revertReason !== undefined) { - await expectTransactionFailedAsync( - txReceiptPromise, - revertReason - ); + await expectTransactionFailedAsync(txReceiptPromise, revertReason); return; } const txReceipt = await txReceiptPromise; @@ -70,24 +73,37 @@ export class DelegatorActor extends StakerActor { // check balances let expectedDelegatorBalances = initDelegatorBalances; expectedDelegatorBalances.activatedStakeBalance = initDelegatorBalances.activatedStakeBalance.plus(amount); - expectedDelegatorBalances.withdrawableStakeBalance = expectedDelegatorBalances.withdrawableStakeBalance.minus(amount); - expectedDelegatorBalances.activatableStakeBalance = expectedDelegatorBalances.activatableStakeBalance.minus(amount); - expectedDelegatorBalances.deactivatedStakeBalance = expectedDelegatorBalances.deactivatedStakeBalance.minus(amount); + expectedDelegatorBalances.withdrawableStakeBalance = expectedDelegatorBalances.withdrawableStakeBalance.minus( + amount, + ); + expectedDelegatorBalances.activatableStakeBalance = expectedDelegatorBalances.activatableStakeBalance.minus( + amount, + ); + expectedDelegatorBalances.deactivatedStakeBalance = expectedDelegatorBalances.deactivatedStakeBalance.minus( + amount, + ); expectedDelegatorBalances.delegatedStakeBalance = initDelegatorBalances.delegatedStakeBalance.plus(amount); - expectedDelegatorBalances.stakeDelegatedToPoolByOwner[0] = initDelegatorBalances.stakeDelegatedToPoolByOwner[0].plus(amount); + expectedDelegatorBalances.stakeDelegatedToPoolByOwner[0] = initDelegatorBalances.stakeDelegatedToPoolByOwner[0].plus( + amount, + ); expectedDelegatorBalances.stakeDelegatedToPool[0] = initDelegatorBalances.stakeDelegatedToPool[0].plus(amount); await this.assertBalancesAsync(expectedDelegatorBalances, [poolId]); } - public async deactivateAndTimelockDelegatedStakeAsync(poolId: string, amount: BigNumber, revertReason?: RevertReason): Promise { + public async deactivateAndTimelockDelegatedStakeAsync( + poolId: string, + amount: BigNumber, + revertReason?: RevertReason, + ): Promise { // query init balances const initDelegatorBalances = await this.getBalancesAsync([poolId]); // deactivate and timelock - const txReceiptPromise = this._stakingWrapper.deactivateAndTimelockDelegatedStakeAsync(this._owner, poolId, amount); + const txReceiptPromise = this._stakingWrapper.deactivateAndTimelockDelegatedStakeAsync( + this._owner, + poolId, + amount, + ); if (revertReason !== undefined) { - await expectTransactionFailedAsync( - txReceiptPromise, - revertReason - ); + await expectTransactionFailedAsync(txReceiptPromise, revertReason); return; } const txReceipt = await txReceiptPromise; @@ -95,10 +111,16 @@ export class DelegatorActor extends StakerActor { // check balances let expectedDelegatorBalances = initDelegatorBalances; expectedDelegatorBalances.activatedStakeBalance = initDelegatorBalances.activatedStakeBalance.minus(amount); - expectedDelegatorBalances.timelockedStakeBalance = expectedDelegatorBalances.timelockedStakeBalance.plus(amount); - expectedDelegatorBalances.deactivatedStakeBalance = expectedDelegatorBalances.deactivatedStakeBalance.plus(amount); + expectedDelegatorBalances.timelockedStakeBalance = expectedDelegatorBalances.timelockedStakeBalance.plus( + amount, + ); + expectedDelegatorBalances.deactivatedStakeBalance = expectedDelegatorBalances.deactivatedStakeBalance.plus( + amount, + ); expectedDelegatorBalances.delegatedStakeBalance = initDelegatorBalances.delegatedStakeBalance.minus(amount); - expectedDelegatorBalances.stakeDelegatedToPoolByOwner[0] = initDelegatorBalances.stakeDelegatedToPoolByOwner[0].minus(amount); + expectedDelegatorBalances.stakeDelegatedToPoolByOwner[0] = initDelegatorBalances.stakeDelegatedToPoolByOwner[0].minus( + amount, + ); expectedDelegatorBalances.stakeDelegatedToPool[0] = initDelegatorBalances.stakeDelegatedToPool[0].minus(amount); await this.assertBalancesAsync(expectedDelegatorBalances, [poolId]); } @@ -112,7 +134,10 @@ export class DelegatorActor extends StakerActor { }; const poolIds = maybePoolIds !== undefined ? maybePoolIds : []; for (const poolId of poolIds) { - const stakeDelegatedToPoolByOwner = await this._stakingWrapper.getStakeDelegatedToPoolByOwnerAsync(poolId, this._owner); + const stakeDelegatedToPoolByOwner = await this._stakingWrapper.getStakeDelegatedToPoolByOwnerAsync( + poolId, + this._owner, + ); delegatorBalances.stakeDelegatedToPoolByOwner.push(stakeDelegatedToPoolByOwner); const stakeDelegatedToPool = await this._stakingWrapper.getStakeDelegatedToPoolAsync(poolId); delegatorBalances.stakeDelegatedToPool.push(stakeDelegatedToPool); @@ -122,11 +147,19 @@ export class DelegatorActor extends StakerActor { public async assertBalancesAsync(expectedBalances: DelegatorBalances, maybePoolIds?: string[]): Promise { await super.assertBalancesAsync(expectedBalances); const balances = await this.getBalancesAsync(maybePoolIds); - expect(balances.delegatedStakeBalance, 'delegated stake balance').to.be.bignumber.equal(expectedBalances.delegatedStakeBalance); + expect(balances.delegatedStakeBalance, 'delegated stake balance').to.be.bignumber.equal( + expectedBalances.delegatedStakeBalance, + ); const poolIds = maybePoolIds !== undefined ? maybePoolIds : []; for (let i = 0; i < poolIds.length; i++) { - expect(balances.stakeDelegatedToPoolByOwner[i], `stake delegated to pool ${poolIds[i]} by owner`).to.be.bignumber.equal(expectedBalances.stakeDelegatedToPoolByOwner[i]); - expect(balances.stakeDelegatedToPool[i], `total stake delegated to pool ${poolIds[i]}`).to.be.bignumber.equal(expectedBalances.stakeDelegatedToPool[i]); + expect( + balances.stakeDelegatedToPoolByOwner[i], + `stake delegated to pool ${poolIds[i]} by owner`, + ).to.be.bignumber.equal(expectedBalances.stakeDelegatedToPoolByOwner[i]); + expect( + balances.stakeDelegatedToPool[i], + `total stake delegated to pool ${poolIds[i]}`, + ).to.be.bignumber.equal(expectedBalances.stakeDelegatedToPool[i]); } } -} \ No newline at end of file +} diff --git a/contracts/staking/test/actors/maker_actor.ts b/contracts/staking/test/actors/maker_actor.ts index c2f278f703..f2d39afa3d 100644 --- a/contracts/staking/test/actors/maker_actor.ts +++ b/contracts/staking/test/actors/maker_actor.ts @@ -5,7 +5,7 @@ import { provider, txDefaults, web3Wrapper, -} from '@0x/contracts-test-utils' +} from '@0x/contracts-test-utils'; import { RevertReason } from '@0x/types'; import { BigNumber } from '@0x/utils'; import * as chai from 'chai'; @@ -25,7 +25,13 @@ export class MakerActor extends BaseActor { private readonly _signatureVerifierIfExists?: string; private readonly _chainIdIfExists?: number; - constructor(owner: string, stakingWrapper: StakingWrapper, ownerPrivateKey?: Buffer, signatureVerifier?: string, chainId?: number) { + constructor( + owner: string, + stakingWrapper: StakingWrapper, + ownerPrivateKey?: Buffer, + signatureVerifier?: string, + chainId?: number, + ) { super(owner, stakingWrapper); this._ownerPrivateKeyIfExists = ownerPrivateKey; this._signatureVerifierIfExists = signatureVerifier; @@ -42,8 +48,8 @@ export class MakerActor extends BaseActor { this._ownerPrivateKeyIfExists, this._signatureVerifierIfExists, this._chainIdIfExists, - signatureType + signatureType, ); return approval; } -} \ No newline at end of file +} diff --git a/contracts/staking/test/actors/pool_operator_actor.ts b/contracts/staking/test/actors/pool_operator_actor.ts index 688e6931b8..76ee65380a 100644 --- a/contracts/staking/test/actors/pool_operator_actor.ts +++ b/contracts/staking/test/actors/pool_operator_actor.ts @@ -5,7 +5,7 @@ import { provider, txDefaults, web3Wrapper, -} from '@0x/contracts-test-utils' +} from '@0x/contracts-test-utils'; import { RevertReason } from '@0x/types'; import { BigNumber } from '@0x/utils'; import * as chai from 'chai'; @@ -20,7 +20,6 @@ import { constants as stakingConstants } from '../utils/constants'; const expect = chai.expect; export class PoolOperatorActor extends BaseActor { - constructor(owner: string, stakingWrapper: StakingWrapper) { super(owner, stakingWrapper); } @@ -31,25 +30,29 @@ export class PoolOperatorActor extends BaseActor { // create pool const poolIdPromise = this._stakingWrapper.createPoolAsync(this._owner, operatorShare); if (revertReason !== undefined) { - await expectTransactionFailedAsync( - poolIdPromise, - revertReason - ); - return ""; + await expectTransactionFailedAsync(poolIdPromise, revertReason); + return ''; } const poolId = await poolIdPromise; // validate pool id expect(poolId, 'pool id').to.be.bignumber.equal(nextPoolId); return poolId; } - public async addMakerToPoolAsync(poolId: string, makerAddress: string, makerSignature: string, revertReason?: RevertReason): Promise { + public async addMakerToPoolAsync( + poolId: string, + makerAddress: string, + makerSignature: string, + revertReason?: RevertReason, + ): Promise { // add maker - const txReceiptPromise = this._stakingWrapper.addMakerToPoolAsync(poolId, makerAddress, makerSignature, this._owner); + const txReceiptPromise = this._stakingWrapper.addMakerToPoolAsync( + poolId, + makerAddress, + makerSignature, + this._owner, + ); if (revertReason !== undefined) { - await expectTransactionFailedAsync( - txReceiptPromise, - revertReason - ); + await expectTransactionFailedAsync(txReceiptPromise, revertReason); return; } const txReceipt = await txReceiptPromise; @@ -60,22 +63,23 @@ export class PoolOperatorActor extends BaseActor { const makerAddressesForPool = await this._stakingWrapper.getMakerAddressesForPool(poolId); expect(makerAddressesForPool, 'maker addresses for pool').to.include(makerAddress); } - public async removeMakerFromPoolAsync(poolId: string, makerAddress: string, revertReason?: RevertReason): Promise { + public async removeMakerFromPoolAsync( + poolId: string, + makerAddress: string, + revertReason?: RevertReason, + ): Promise { // remove maker const txReceiptPromise = this._stakingWrapper.removeMakerFromPoolAsync(poolId, makerAddress, this._owner); if (revertReason !== undefined) { - await expectTransactionFailedAsync( - txReceiptPromise, - revertReason - ); + await expectTransactionFailedAsync(txReceiptPromise, revertReason); return; } const txReceipt = await txReceiptPromise; - // check the pool id of the maker - const poolIdOfMakerAfterRemoving = await this._stakingWrapper.getMakerPoolId(makerAddress); - expect(poolIdOfMakerAfterRemoving, 'pool id of maker').to.be.equal(stakingConstants.NIL_POOL_ID); - // check the list of makers for the pool - const makerAddressesForPoolAfterRemoving = await this._stakingWrapper.getMakerAddressesForPool(poolId); - expect(makerAddressesForPoolAfterRemoving, 'maker addresses for pool').to.not.include(makerAddress); + // check the pool id of the maker + const poolIdOfMakerAfterRemoving = await this._stakingWrapper.getMakerPoolId(makerAddress); + expect(poolIdOfMakerAfterRemoving, 'pool id of maker').to.be.equal(stakingConstants.NIL_POOL_ID); + // check the list of makers for the pool + const makerAddressesForPoolAfterRemoving = await this._stakingWrapper.getMakerAddressesForPool(poolId); + expect(makerAddressesForPoolAfterRemoving, 'maker addresses for pool').to.not.include(makerAddress); } -} \ No newline at end of file +} diff --git a/contracts/staking/test/actors/staker_actor.ts b/contracts/staking/test/actors/staker_actor.ts index 09f384099b..9b167b6706 100644 --- a/contracts/staking/test/actors/staker_actor.ts +++ b/contracts/staking/test/actors/staker_actor.ts @@ -5,7 +5,7 @@ import { provider, txDefaults, web3Wrapper, -} from '@0x/contracts-test-utils' +} from '@0x/contracts-test-utils'; import { RevertReason } from '@0x/types'; import { BigNumber } from '@0x/utils'; import * as chai from 'chai'; @@ -18,7 +18,6 @@ import { BaseActor } from './base_actor'; const expect = chai.expect; export class StakerActor extends BaseActor { - constructor(owner: string, stakingWrapper: StakingWrapper) { super(owner, stakingWrapper); } @@ -33,10 +32,7 @@ export class StakerActor extends BaseActor { // deposit stake const txReceiptPromise = this._stakingWrapper.depositAndStakeAsync(this._owner, amount); if (revertReason !== undefined) { - await expectTransactionFailedAsync( - txReceiptPromise, - revertReason - ); + await expectTransactionFailedAsync(txReceiptPromise, revertReason); return; } const txReceipt = await txReceiptPromise; @@ -58,10 +54,7 @@ export class StakerActor extends BaseActor { // activate stake const txReceiptPromise = this._stakingWrapper.activateStakeAsync(this._owner, amount); if (revertReason !== undefined) { - await expectTransactionFailedAsync( - txReceiptPromise, - revertReason - ); + await expectTransactionFailedAsync(txReceiptPromise, revertReason); return; } const txReceipt = await txReceiptPromise; @@ -80,10 +73,7 @@ export class StakerActor extends BaseActor { // deactivate and timelock stake const txReceiptPromise = this._stakingWrapper.deactivateAndTimelockStakeAsync(this._owner, amount); if (revertReason !== undefined) { - await expectTransactionFailedAsync( - txReceiptPromise, - revertReason - ); + await expectTransactionFailedAsync(txReceiptPromise, revertReason); return; } const txReceipt = await txReceiptPromise; @@ -102,10 +92,7 @@ export class StakerActor extends BaseActor { // withdraw stake const txReceiptPromise = this._stakingWrapper.withdrawAsync(this._owner, amount); if (revertReason !== undefined) { - await expectTransactionFailedAsync( - txReceiptPromise, - revertReason - ); + await expectTransactionFailedAsync(txReceiptPromise, revertReason); return; } const txReceipt = await txReceiptPromise; @@ -133,19 +120,31 @@ export class StakerActor extends BaseActor { activatedStakeBalance: await this._stakingWrapper.getActivatedStakeAsync(this._owner), timelockedStakeBalance: await this._stakingWrapper.getTimelockedStakeAsync(this._owner), deactivatedStakeBalance: await this._stakingWrapper.getDeactivatedStakeAsync(this._owner), - } + }; return stakerBalances; } public async assertBalancesAsync(expectedBalances: StakerBalances): Promise { const balances = await this.getBalancesAsync(); expect(balances.zrxBalance, 'zrx balance').to.be.bignumber.equal(expectedBalances.zrxBalance); expect(balances.stakeBalance, 'stake balance').to.be.bignumber.equal(expectedBalances.stakeBalance); - expect(balances.stakeBalanceInVault, 'stake balance, recorded in vault').to.be.bignumber.equal(expectedBalances.stakeBalanceInVault); - expect(balances.withdrawableStakeBalance, 'withdrawable stake balance').to.be.bignumber.equal(expectedBalances.withdrawableStakeBalance); - expect(balances.activatableStakeBalance, 'activatable stake balance').to.be.bignumber.equal(expectedBalances.activatableStakeBalance); - expect(balances.activatedStakeBalance, 'activated stake balance').to.be.bignumber.equal(expectedBalances.activatedStakeBalance); - expect(balances.timelockedStakeBalance, 'timelocked stake balance').to.be.bignumber.equal(expectedBalances.timelockedStakeBalance); - expect(balances.deactivatedStakeBalance, 'deactivated stake balance').to.be.bignumber.equal(expectedBalances.deactivatedStakeBalance); + expect(balances.stakeBalanceInVault, 'stake balance, recorded in vault').to.be.bignumber.equal( + expectedBalances.stakeBalanceInVault, + ); + expect(balances.withdrawableStakeBalance, 'withdrawable stake balance').to.be.bignumber.equal( + expectedBalances.withdrawableStakeBalance, + ); + expect(balances.activatableStakeBalance, 'activatable stake balance').to.be.bignumber.equal( + expectedBalances.activatableStakeBalance, + ); + expect(balances.activatedStakeBalance, 'activated stake balance').to.be.bignumber.equal( + expectedBalances.activatedStakeBalance, + ); + expect(balances.timelockedStakeBalance, 'timelocked stake balance').to.be.bignumber.equal( + expectedBalances.timelockedStakeBalance, + ); + expect(balances.deactivatedStakeBalance, 'deactivated stake balance').to.be.bignumber.equal( + expectedBalances.deactivatedStakeBalance, + ); } public async forceTimelockSyncAsync(): Promise { const initBalances = await this.getBalancesAsync(); @@ -162,7 +161,9 @@ export class StakerActor extends BaseActor { let expectedBalances = initBalances; const currentTimelockPeriod = await this._stakingWrapper.getCurrentTimelockPeriodAsync(); if (currentTimelockPeriod.minus(timelockStart).isGreaterThan(1)) { - expectedBalances.activatableStakeBalance = initBalances.activatableStakeBalance.plus(initBalances.timelockedStakeBalance); + expectedBalances.activatableStakeBalance = initBalances.activatableStakeBalance.plus( + initBalances.timelockedStakeBalance, + ); expectedBalances.withdrawableStakeBalance = expectedBalances.activatableStakeBalance; expectedBalances.timelockedStakeBalance = new BigNumber(0); } diff --git a/contracts/staking/test/epoch_test.ts b/contracts/staking/test/epoch_test.ts index b9d89ccd3a..27933eb614 100644 --- a/contracts/staking/test/epoch_test.ts +++ b/contracts/staking/test/epoch_test.ts @@ -72,9 +72,13 @@ describe('Epochs', () => { describe('Epochs & Timelocks', () => { it('basic epochs & timelock periods', async () => { ///// 0/3 Validate Assumptions ///// - expect(await stakingWrapper.getEpochPeriodInSecondsAsync()).to.be.bignumber.equal(stakingConstants.EPOCH_PERIOD_IN_SECONDS); - expect(await stakingWrapper.getTimelockPeriodInEpochsAsync()).to.be.bignumber.equal(stakingConstants.TIMELOCK_PERIOD_IN_EPOCHS); - + expect(await stakingWrapper.getEpochPeriodInSecondsAsync()).to.be.bignumber.equal( + stakingConstants.EPOCH_PERIOD_IN_SECONDS, + ); + expect(await stakingWrapper.getTimelockPeriodInEpochsAsync()).to.be.bignumber.equal( + stakingConstants.TIMELOCK_PERIOD_IN_EPOCHS, + ); + ///// 1/3 Validate Initial Epoch & Timelock Period ///// { // epoch diff --git a/contracts/staking/test/exchange_test.ts b/contracts/staking/test/exchange_test.ts index aa2fcac9a7..f0d76a78a1 100644 --- a/contracts/staking/test/exchange_test.ts +++ b/contracts/staking/test/exchange_test.ts @@ -21,7 +21,6 @@ import { StakingWrapper } from './utils/staking_wrapper'; import { ERC20Wrapper, ERC20ProxyContract } from '@0x/contracts-asset-proxy'; import { StakingContract } from '../src'; - import { StakerActor } from './actors/staker_actor'; import { DelegatorActor } from './actors/delegator_actor'; @@ -77,7 +76,7 @@ describe('Exchange Integrations', () => { describe('Exchange Tracking in Staking Contract', () => { it('basic exchange tracking', async () => { // 1 try querying an invalid addresses - const invalidAddress = "0x0000000000000000000000000000000000000001"; + const invalidAddress = '0x0000000000000000000000000000000000000001'; const isInvalidAddressValid = await stakingWrapper.isValidExchangeAddressAsync(invalidAddress); expect(isInvalidAddressValid).to.be.false(); // 2 add valid address @@ -87,7 +86,7 @@ describe('Exchange Integrations', () => { // 3 try adding valid address again await expectTransactionFailedAsync( stakingWrapper.addExchangeAddressAsync(exchange), - RevertReason.ExchangeAddressAlreadyRegistered + RevertReason.ExchangeAddressAlreadyRegistered, ); // 4 remove valid address await stakingWrapper.removeExchangeAddressAsync(exchange); @@ -96,7 +95,7 @@ describe('Exchange Integrations', () => { // 5 try removing valid address again await expectTransactionFailedAsync( stakingWrapper.removeExchangeAddressAsync(exchange), - RevertReason.ExchangeAddressNotRegistered + RevertReason.ExchangeAddressNotRegistered, ); }); }); diff --git a/contracts/staking/test/math_test.ts b/contracts/staking/test/math_test.ts index 7e48ce8963..a907abee14 100644 --- a/contracts/staking/test/math_test.ts +++ b/contracts/staking/test/math_test.ts @@ -16,7 +16,6 @@ import { StakingWrapper } from './utils/staking_wrapper'; import { ERC20Wrapper, ERC20ProxyContract } from '@0x/contracts-asset-proxy'; - chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); @@ -107,7 +106,7 @@ describe('Math Libraries', () => { expect(rootAsFloatingPoint).to.be.bignumber.equal(expectedResult); }); - it('cobb douglas - approximate', async() => { + it('cobb douglas - approximate', async () => { const totalRewards = stakingWrapper.toBaseUnitAmount(57.154398); const ownerFees = stakingWrapper.toBaseUnitAmount(5.64375); const totalFees = stakingWrapper.toBaseUnitAmount(29.00679); @@ -126,14 +125,17 @@ describe('Math Libraries', () => { ownerStake, totalStake, alphaNumerator, - alphaDenominator + alphaDenominator, + ); + const ownerRewardFloatingPoint = stakingWrapper.trimFloat( + stakingWrapper.toFloatingPoint(ownerReward, 18), + 4, ); - const ownerRewardFloatingPoint = stakingWrapper.trimFloat(stakingWrapper.toFloatingPoint(ownerReward, 18), 4); // validation expect(ownerRewardFloatingPoint).to.be.bignumber.equal(expectedOwnerReward); }); - it('cobb douglas - simplified (alpha = 1/x)', async() => { + it('cobb douglas - simplified (alpha = 1/x)', async () => { // setup test parameters const totalRewards = stakingWrapper.toBaseUnitAmount(57.154398); const ownerFees = stakingWrapper.toBaseUnitAmount(5.64375); @@ -151,14 +153,17 @@ describe('Math Libraries', () => { totalFees, ownerStake, totalStake, - alphaDenominator + alphaDenominator, + ); + const ownerRewardFloatingPoint = stakingWrapper.trimFloat( + stakingWrapper.toFloatingPoint(ownerReward, 18), + 14, ); - const ownerRewardFloatingPoint = stakingWrapper.trimFloat(stakingWrapper.toFloatingPoint(ownerReward, 18), 14); // validation expect(ownerRewardFloatingPoint).to.be.bignumber.equal(expectedOwnerReward); }); - it('cobb douglas - simplified inverse (1 - alpha = 1/x)', async() => { + it('cobb douglas - simplified inverse (1 - alpha = 1/x)', async () => { const totalRewards = stakingWrapper.toBaseUnitAmount(57.154398); const ownerFees = stakingWrapper.toBaseUnitAmount(5.64375); const totalFees = stakingWrapper.toBaseUnitAmount(29.00679); @@ -175,9 +180,12 @@ describe('Math Libraries', () => { totalFees, ownerStake, totalStake, - inverseAlphaDenominator + inverseAlphaDenominator, + ); + const ownerRewardFloatingPoint = stakingWrapper.trimFloat( + stakingWrapper.toFloatingPoint(ownerReward, 18), + 12, ); - const ownerRewardFloatingPoint = stakingWrapper.trimFloat(stakingWrapper.toFloatingPoint(ownerReward, 18), 12); // validation expect(ownerRewardFloatingPoint).to.be.bignumber.equal(expectedOwnerReward); }); diff --git a/contracts/staking/test/pools_test.ts b/contracts/staking/test/pools_test.ts index dbd5b0fc48..b77c3e0912 100644 --- a/contracts/staking/test/pools_test.ts +++ b/contracts/staking/test/pools_test.ts @@ -22,7 +22,6 @@ import { StakingWrapper } from './utils/staking_wrapper'; import { ERC20Wrapper, ERC20ProxyContract } from '@0x/contracts-asset-proxy'; import { StakingContract } from '../src'; - import { StakerActor } from './actors/staker_actor'; import { DelegatorActor } from './actors/delegator_actor'; import { PoolOperatorActor } from './actors/pool_operator_actor'; @@ -75,7 +74,7 @@ describe('Staking Pool Management', () => { await blockchainLifecycle.revertAsync(); }); describe('Staking Pool Management', () => { - it('Should successfully create a pool', async() => { + it('Should successfully create a pool', async () => { // test parameters const operatorAddress = users[0]; const operatorShare = 39; @@ -84,11 +83,11 @@ describe('Staking Pool Management', () => { const poolId = await poolOperator.createPoolAsync(operatorShare); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); // check that the next pool id was incremented - const expectedNextPoolId = "0x0000000000000000000000000000000200000000000000000000000000000000"; + const expectedNextPoolId = '0x0000000000000000000000000000000200000000000000000000000000000000'; const nextPoolId = await stakingWrapper.getNextPoolIdAsync(); expect(nextPoolId).to.be.equal(expectedNextPoolId); }); - it('Should successfully add/remove a maker to a pool', async() => { + it('Should successfully add/remove a maker to a pool', async () => { // test parameters const operatorAddress = users[0]; const operatorShare = 39; @@ -104,7 +103,7 @@ describe('Staking Pool Management', () => { // remove maker from pool await poolOperator.removeMakerFromPoolAsync(poolId, makerAddress); }); - it('Should successfully add/remove multipler makers to the same pool', async() => { + it('Should successfully add/remove multipler makers to the same pool', async () => { // test parameters const operatorAddress = users[0]; const operatorShare = 39; @@ -133,7 +132,7 @@ describe('Staking Pool Management', () => { // @TODO - this fails with `RuntimeError: VM Exception while processing transaction: revert` on Ganache // await poolOperator.removeMakerFromPoolAsync(poolId, makerAddresses[2]); }); - it('Should fail to add the same maker twice', async() => { + it('Should fail to add the same maker twice', async () => { // test parameters const operatorAddress = users[0]; const operatorShare = 39; @@ -147,9 +146,14 @@ describe('Staking Pool Management', () => { const makerApproval = maker.signApprovalForStakingPool(poolId); await poolOperator.addMakerToPoolAsync(poolId, makerAddress, makerApproval.signature); // add same maker to pool again - await poolOperator.addMakerToPoolAsync(poolId, makerAddress, makerApproval.signature, RevertReason.MakerAddressAlreadyRegistered); + await poolOperator.addMakerToPoolAsync( + poolId, + makerAddress, + makerApproval.signature, + RevertReason.MakerAddressAlreadyRegistered, + ); }); - it('Should fail to remove a maker that does not exist', async() => { + it('Should fail to remove a maker that does not exist', async () => { // test parameters const operatorAddress = users[0]; const operatorShare = 39; @@ -162,22 +166,29 @@ describe('Staking Pool Management', () => { // remove non-existent maker from pool await poolOperator.removeMakerFromPoolAsync(poolId, makerAddress, RevertReason.MakerAddressNotRegistered); }); - it('Should fail to add a maker who signed with the wrong private key', async() => { + it('Should fail to add a maker who signed with the wrong private key', async () => { // test parameters const operatorAddress = users[0]; const operatorShare = 39; const poolOperator = new PoolOperatorActor(operatorAddress, stakingWrapper); const makerAddress = users[1]; - const badMakerPrivateKey = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001'); + const badMakerPrivateKey = ethUtil.toBuffer( + '0x0000000000000000000000000000000000000000000000000000000000000001', + ); const maker = new MakerActor(makerAddress, stakingWrapper, badMakerPrivateKey); // create pool const poolId = await poolOperator.createPoolAsync(operatorShare); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); // add maker to pool const makerApproval = maker.signApprovalForStakingPool(poolId); - await poolOperator.addMakerToPoolAsync(poolId, makerAddress, makerApproval.signature, RevertReason.InvalidMakerSignature); + await poolOperator.addMakerToPoolAsync( + poolId, + makerAddress, + makerApproval.signature, + RevertReason.InvalidMakerSignature, + ); }); - it('Should fail to add a maker who signed with the wrong staking contract address', async() => { + it('Should fail to add a maker who signed with the wrong staking contract address', async () => { // test parameters const operatorAddress = users[0]; const operatorShare = 39; @@ -191,9 +202,14 @@ describe('Staking Pool Management', () => { expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); // add maker to pool const makerApproval = maker.signApprovalForStakingPool(poolId); - await poolOperator.addMakerToPoolAsync(poolId, makerAddress, makerApproval.signature, RevertReason.InvalidMakerSignature); + await poolOperator.addMakerToPoolAsync( + poolId, + makerAddress, + makerApproval.signature, + RevertReason.InvalidMakerSignature, + ); }); - it('Should fail to add a maker who signed with the wrong chain id', async() => { + it('Should fail to add a maker who signed with the wrong chain id', async () => { // test parameters const operatorAddress = users[0]; const operatorShare = 39; @@ -202,50 +218,61 @@ describe('Staking Pool Management', () => { const forceMakerKeyLookup = undefined; const forceStakingContractLookup = undefined; const badChainId = 209348; - const maker = new MakerActor(makerAddress, stakingWrapper, forceMakerKeyLookup, forceStakingContractLookup, badChainId); + const maker = new MakerActor( + makerAddress, + stakingWrapper, + forceMakerKeyLookup, + forceStakingContractLookup, + badChainId, + ); // create pool const poolId = await poolOperator.createPoolAsync(operatorShare); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); // add maker to pool const makerApproval = maker.signApprovalForStakingPool(poolId); - await poolOperator.addMakerToPoolAsync(poolId, makerAddress, makerApproval.signature, RevertReason.InvalidMakerSignature); - }); - it('Should fail to add a maker when called by someone other than the pool operator', async() => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = 39; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingWrapper); - const makerAddress = users[1]; - const maker = new MakerActor(makerAddress, stakingWrapper); - const notOperatorAddress = users[2]; - // create pool - const poolId = await poolOperator.createPoolAsync(operatorShare); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - // add maker to pool - const makerApproval = maker.signApprovalForStakingPool(poolId); - await expectTransactionFailedAsync( - stakingWrapper.addMakerToPoolAsync(poolId, makerAddress, makerApproval.signature, notOperatorAddress), - RevertReason.OnlyCallableByPoolOperator + await poolOperator.addMakerToPoolAsync( + poolId, + makerAddress, + makerApproval.signature, + RevertReason.InvalidMakerSignature, ); }); - it('Should fail to remove a maker when called by someone other than the pool operator', async() => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = 39; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingWrapper); - const makerAddress = users[1]; - const maker = new MakerActor(makerAddress, stakingWrapper); - const notOperatorAddress = users[2]; - // create pool - const poolId = await poolOperator.createPoolAsync(operatorShare); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - // add maker to pool - const makerApproval = maker.signApprovalForStakingPool(poolId); - await poolOperator.addMakerToPoolAsync(poolId, makerAddress, makerApproval.signature); - // try to remove the maker address from an address other than the operator + it('Should fail to add a maker when called by someone other than the pool operator', async () => { + // test parameters + const operatorAddress = users[0]; + const operatorShare = 39; + const poolOperator = new PoolOperatorActor(operatorAddress, stakingWrapper); + const makerAddress = users[1]; + const maker = new MakerActor(makerAddress, stakingWrapper); + const notOperatorAddress = users[2]; + // create pool + const poolId = await poolOperator.createPoolAsync(operatorShare); + expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); + // add maker to pool + const makerApproval = maker.signApprovalForStakingPool(poolId); + await expectTransactionFailedAsync( + stakingWrapper.addMakerToPoolAsync(poolId, makerAddress, makerApproval.signature, notOperatorAddress), + RevertReason.OnlyCallableByPoolOperator, + ); + }); + it('Should fail to remove a maker when called by someone other than the pool operator', async () => { + // test parameters + const operatorAddress = users[0]; + const operatorShare = 39; + const poolOperator = new PoolOperatorActor(operatorAddress, stakingWrapper); + const makerAddress = users[1]; + const maker = new MakerActor(makerAddress, stakingWrapper); + const notOperatorAddress = users[2]; + // create pool + const poolId = await poolOperator.createPoolAsync(operatorShare); + expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); + // add maker to pool + const makerApproval = maker.signApprovalForStakingPool(poolId); + await poolOperator.addMakerToPoolAsync(poolId, makerAddress, makerApproval.signature); + // try to remove the maker address from an address other than the operator await expectTransactionFailedAsync( stakingWrapper.removeMakerFromPoolAsync(poolId, makerAddress, notOperatorAddress), - RevertReason.OnlyCallableByPoolOperator + RevertReason.OnlyCallableByPoolOperator, ); }); }); diff --git a/contracts/staking/test/simulations_test.ts b/contracts/staking/test/simulations_test.ts index 7525a57353..ffb47661c6 100644 --- a/contracts/staking/test/simulations_test.ts +++ b/contracts/staking/test/simulations_test.ts @@ -21,7 +21,6 @@ import { StakingWrapper } from './utils/staking_wrapper'; import { ERC20Wrapper, ERC20ProxyContract } from '@0x/contracts-asset-proxy'; import { StakingContract } from '../src'; - import { StakerActor } from './actors/staker_actor'; import { DelegatorActor } from './actors/delegator_actor'; @@ -43,11 +42,10 @@ describe('End-To-End Simulations', () => { let zrxTokenContract: DummyERC20TokenContract; let erc20ProxyContract: ERC20ProxyContract; - let stakers: string[]; + let stakers: string[]; let makers: string[]; let delegators: string[]; - // wrappers let stakingWrapper: StakingWrapper; let erc20Wrapper: ERC20Wrapper; @@ -69,7 +67,6 @@ describe('End-To-End Simulations', () => { makers = accounts.slice(4, 10); users = [...users, ...users]; // maybe this'll work? Not sure lol. - // deploy erc20 proxy erc20Wrapper = new ERC20Wrapper(provider, accounts, owner); erc20ProxyContract = await erc20Wrapper.deployProxyAsync(); @@ -89,64 +86,59 @@ describe('End-To-End Simulations', () => { describe('Simulations', () => { it('Should successfully simulate (no delegators / no shadow balances)', async () => { // @TODO - get computations more accurate - const simulationParams = { - users, - numberOfPools: 3, - poolOperatorShares: [100, 100, 100], + const simulationParams = { + users, + numberOfPools: 3, + poolOperatorShares: [100, 100, 100], stakeByPoolOperator: [ stakingWrapper.toBaseUnitAmount(42), stakingWrapper.toBaseUnitAmount(84), stakingWrapper.toBaseUnitAmount(97), ], - numberOfMakers: 6, - numberOfMakersPerPool: [1, 2, 3], - protocolFeesByMaker: [ - // pool 1 - stakingWrapper.toBaseUnitAmount(0.304958), - // pool 2 - stakingWrapper.toBaseUnitAmount(3.2), - stakingWrapper.toBaseUnitAmount(12.123258), - // pool 3 - stakingWrapper.toBaseUnitAmount(23.577), - stakingWrapper.toBaseUnitAmount(4.54522236), - stakingWrapper.toBaseUnitAmount(0) - ], - numberOfDelegators: 0, - numberOfDelegatorsPerPool: [0, 0, 0], - stakeByDelegator: [], - delegateInNextEpoch: false, // no shadow eth - withdrawByUndelegating: false, // profits are withdrawn without undelegating - expectedFeesByPool: [ - stakingWrapper.toBaseUnitAmount(0.304958), - stakingWrapper.toBaseUnitAmount(15.323258), - stakingWrapper.toBaseUnitAmount(28.12222236), - ], - expectedPayoutByPool: [ - new BigNumber('4.75677'), // 4.756772362932728793619590327361600155564384201215274334070 - new BigNumber('16.28130'), // 16.28130500394935316563988584956596823402223838026190634525 - new BigNumber('20.31028'), // 20.31028447343014834523983759032242063760612769662934308289 - ], - expectedPayoutByPoolOperator: [ - new BigNumber('4.75677'), // 4.756772362932728793619590327361600155564384201215274334070 - new BigNumber('16.28130'), // 16.28130500394935316563988584956596823402223838026190634525 - new BigNumber('20.31028'), // 20.31028447343014834523983759032242063760612769662934308289 - ], - expectedMembersPayoutByPool: [ - new BigNumber('0'), - new BigNumber('0'), - new BigNumber('0'), - ], - expectedPayoutByDelegator: [], - exchangeAddress: exchange, - - }; - const simulator = new Simulation(stakingWrapper, simulationParams); - await simulator.runAsync(); - }); + numberOfMakers: 6, + numberOfMakersPerPool: [1, 2, 3], + protocolFeesByMaker: [ + // pool 1 + stakingWrapper.toBaseUnitAmount(0.304958), + // pool 2 + stakingWrapper.toBaseUnitAmount(3.2), + stakingWrapper.toBaseUnitAmount(12.123258), + // pool 3 + stakingWrapper.toBaseUnitAmount(23.577), + stakingWrapper.toBaseUnitAmount(4.54522236), + stakingWrapper.toBaseUnitAmount(0), + ], + numberOfDelegators: 0, + numberOfDelegatorsPerPool: [0, 0, 0], + stakeByDelegator: [], + delegateInNextEpoch: false, // no shadow eth + withdrawByUndelegating: false, // profits are withdrawn without undelegating + expectedFeesByPool: [ + stakingWrapper.toBaseUnitAmount(0.304958), + stakingWrapper.toBaseUnitAmount(15.323258), + stakingWrapper.toBaseUnitAmount(28.12222236), + ], + expectedPayoutByPool: [ + new BigNumber('4.75677'), // 4.756772362932728793619590327361600155564384201215274334070 + new BigNumber('16.28130'), // 16.28130500394935316563988584956596823402223838026190634525 + new BigNumber('20.31028'), // 20.31028447343014834523983759032242063760612769662934308289 + ], + expectedPayoutByPoolOperator: [ + new BigNumber('4.75677'), // 4.756772362932728793619590327361600155564384201215274334070 + new BigNumber('16.28130'), // 16.28130500394935316563988584956596823402223838026190634525 + new BigNumber('20.31028'), // 20.31028447343014834523983759032242063760612769662934308289 + ], + expectedMembersPayoutByPool: [new BigNumber('0'), new BigNumber('0'), new BigNumber('0')], + expectedPayoutByDelegator: [], + exchangeAddress: exchange, + }; + const simulator = new Simulation(stakingWrapper, simulationParams); + await simulator.runAsync(); + }); - it('Should successfully simulate (delegators withdraw by undeleating / no shadow balances)', async () => { - // @TODO - get computations more accurate - /* + it('Should successfully simulate (delegators withdraw by undeleating / no shadow balances)', async () => { + // @TODO - get computations more accurate + /* \ // the expected payouts were computed by hand // @TODO - get computations more accurate Pool | Total Fees | Total Stake | Total Delegated Stake | Total Stake (Scaled) @@ -158,70 +150,70 @@ describe('End-To-End Simulations', () => { Cumulative Stake = 405 Total Rewards = 43.75043836 */ - const simulationParams = { - users, - numberOfPools: 3, - poolOperatorShares: [39, 59, 43], - stakeByPoolOperator: [ - stakingWrapper.toBaseUnitAmount(42), - stakingWrapper.toBaseUnitAmount(84), - stakingWrapper.toBaseUnitAmount(97), - ], - numberOfMakers: 6, - numberOfMakersPerPool: [1, 2, 3], - protocolFeesByMaker: [ - // pool 1 - stakingWrapper.toBaseUnitAmount(0.304958), - // pool 2 - stakingWrapper.toBaseUnitAmount(3.2), - stakingWrapper.toBaseUnitAmount(12.123258), - // pool 3 - stakingWrapper.toBaseUnitAmount(23.577), - stakingWrapper.toBaseUnitAmount(4.54522236), - stakingWrapper.toBaseUnitAmount(0) - ], - numberOfDelegators: 3, - numberOfDelegatorsPerPool: [0, 0, 3], - stakeByDelegator: [ - stakingWrapper.toBaseUnitAmount(17), - stakingWrapper.toBaseUnitAmount(75), - stakingWrapper.toBaseUnitAmount(90), - ], - delegateInNextEpoch: false, // delegated stake is included in payout computation + no shadow ether - withdrawByUndelegating: false, // profits are withdrawn without undelegating - expectedFeesByPool: [ - stakingWrapper.toBaseUnitAmount(0.304958), - stakingWrapper.toBaseUnitAmount(15.323258), - stakingWrapper.toBaseUnitAmount(28.12222236), - ], - expectedPayoutByPool: [ - new BigNumber('2.89303'), // 2.8930364057678784829875695710382241749912199174798475 - new BigNumber('9.90218'), // 9.9021783083174087034787071054543342142019746753770943 - new BigNumber('28.16463'), // 28.164631904035798614670299155719067954180760345463798 - ], - expectedPayoutByPoolOperator: [ - new BigNumber('1.12828'), // 0.39 * 2.89303 - new BigNumber('5.84228'), // 0.59 * 9.90218 - new BigNumber('12.11079') // 0.43 * 28.16463 - ], - expectedMembersPayoutByPool: [ - new BigNumber('1.76475'), // (1 - 0.39) * 2.89303 - new BigNumber('4.05989'), // (1 - 0.59) * 9.90218 - new BigNumber('16.05383'), // (1 - 0.43) * 28.16463 - ], - expectedPayoutByDelegator: [ - // note that the on-chain values may be slightly different due to rounding down on each entry - // there is a carry over between calls, which we account for here. the result is that delegators - // who withdraw later on will scoop up any rounding spillover from those who have already withdrawn. - new BigNumber('1.49953'), // (17 / 182) * 16.05383 - new BigNumber('6.61559'), // (75 / 182) * 16.05383 - new BigNumber('7.93871'), // (90 / 182) * 16.05383 - ], - exchangeAddress: exchange, - }; - const simulator = new Simulation(stakingWrapper, simulationParams); - await simulator.runAsync(); - }); + const simulationParams = { + users, + numberOfPools: 3, + poolOperatorShares: [39, 59, 43], + stakeByPoolOperator: [ + stakingWrapper.toBaseUnitAmount(42), + stakingWrapper.toBaseUnitAmount(84), + stakingWrapper.toBaseUnitAmount(97), + ], + numberOfMakers: 6, + numberOfMakersPerPool: [1, 2, 3], + protocolFeesByMaker: [ + // pool 1 + stakingWrapper.toBaseUnitAmount(0.304958), + // pool 2 + stakingWrapper.toBaseUnitAmount(3.2), + stakingWrapper.toBaseUnitAmount(12.123258), + // pool 3 + stakingWrapper.toBaseUnitAmount(23.577), + stakingWrapper.toBaseUnitAmount(4.54522236), + stakingWrapper.toBaseUnitAmount(0), + ], + numberOfDelegators: 3, + numberOfDelegatorsPerPool: [0, 0, 3], + stakeByDelegator: [ + stakingWrapper.toBaseUnitAmount(17), + stakingWrapper.toBaseUnitAmount(75), + stakingWrapper.toBaseUnitAmount(90), + ], + delegateInNextEpoch: false, // delegated stake is included in payout computation + no shadow ether + withdrawByUndelegating: false, // profits are withdrawn without undelegating + expectedFeesByPool: [ + stakingWrapper.toBaseUnitAmount(0.304958), + stakingWrapper.toBaseUnitAmount(15.323258), + stakingWrapper.toBaseUnitAmount(28.12222236), + ], + expectedPayoutByPool: [ + new BigNumber('2.89303'), // 2.8930364057678784829875695710382241749912199174798475 + new BigNumber('9.90218'), // 9.9021783083174087034787071054543342142019746753770943 + new BigNumber('28.16463'), // 28.164631904035798614670299155719067954180760345463798 + ], + expectedPayoutByPoolOperator: [ + new BigNumber('1.12828'), // 0.39 * 2.89303 + new BigNumber('5.84228'), // 0.59 * 9.90218 + new BigNumber('12.11079'), // 0.43 * 28.16463 + ], + expectedMembersPayoutByPool: [ + new BigNumber('1.76475'), // (1 - 0.39) * 2.89303 + new BigNumber('4.05989'), // (1 - 0.59) * 9.90218 + new BigNumber('16.05383'), // (1 - 0.43) * 28.16463 + ], + expectedPayoutByDelegator: [ + // note that the on-chain values may be slightly different due to rounding down on each entry + // there is a carry over between calls, which we account for here. the result is that delegators + // who withdraw later on will scoop up any rounding spillover from those who have already withdrawn. + new BigNumber('1.49953'), // (17 / 182) * 16.05383 + new BigNumber('6.61559'), // (75 / 182) * 16.05383 + new BigNumber('7.93871'), // (90 / 182) * 16.05383 + ], + exchangeAddress: exchange, + }; + const simulator = new Simulation(stakingWrapper, simulationParams); + await simulator.runAsync(); + }); it('Should successfully simulate (delegators withdraw by undelegating / includes shadow balances / delegators enter after reward payouts)', async () => { // @TODO - get computations more accurate @@ -260,7 +252,7 @@ describe('End-To-End Simulations', () => { // pool 3 stakingWrapper.toBaseUnitAmount(23.577), stakingWrapper.toBaseUnitAmount(4.54522236), - stakingWrapper.toBaseUnitAmount(0) + stakingWrapper.toBaseUnitAmount(0), ], numberOfDelegators: 3, numberOfDelegatorsPerPool: [0, 0, 3], @@ -269,30 +261,30 @@ describe('End-To-End Simulations', () => { stakingWrapper.toBaseUnitAmount(75), stakingWrapper.toBaseUnitAmount(90), ], - delegateInNextEpoch: true, // delegated stake is included in payout computation + forces shadow eth - withdrawByUndelegating: true, // profits are withdrawn as result of undelegating + delegateInNextEpoch: true, // delegated stake is included in payout computation + forces shadow eth + withdrawByUndelegating: true, // profits are withdrawn as result of undelegating expectedFeesByPool: [ stakingWrapper.toBaseUnitAmount(0.304958), stakingWrapper.toBaseUnitAmount(15.323258), stakingWrapper.toBaseUnitAmount(28.12222236), ], expectedPayoutByPool: [ - new BigNumber('4.75677'), // 4.756772362932728793619590327361600155564384201215274334070 - new BigNumber('16.28130'), // 16.28130500394935316563988584956596823402223838026190634525 - new BigNumber('20.31028'), // 20.31028447343014834523983759032242063760612769662934308289 + new BigNumber('4.75677'), // 4.756772362932728793619590327361600155564384201215274334070 + new BigNumber('16.28130'), // 16.28130500394935316563988584956596823402223838026190634525 + new BigNumber('20.31028'), // 20.31028447343014834523983759032242063760612769662934308289 ], expectedPayoutByPoolOperator: [ - new BigNumber('1.85514'), // 0.39 * 4.75677 - new BigNumber('9.60597'), // 0.59 * 16.28130 - new BigNumber('8.73342') // 0.43 * 20.31028 + new BigNumber('1.85514'), // 0.39 * 4.75677 + new BigNumber('9.60597'), // 0.59 * 16.28130 + new BigNumber('8.73342'), // 0.43 * 20.31028 ], expectedMembersPayoutByPool: [ - new BigNumber('2.90163'), // (1 - 0.39) * 4.75677 - new BigNumber('6.67533'), // (1 - 0.59) * 16.28130 - new BigNumber('11.57686'), // (1 - 0.43) * 20.31028 + new BigNumber('2.90163'), // (1 - 0.39) * 4.75677 + new BigNumber('6.67533'), // (1 - 0.59) * 16.28130 + new BigNumber('11.57686'), // (1 - 0.43) * 20.31028 ], expectedPayoutByDelegator: [ - new BigNumber('11.57686'), // (1 - 0.43) * 20.31028 + new BigNumber('11.57686'), // (1 - 0.43) * 20.31028 new BigNumber(0), new BigNumber(0), ], @@ -303,7 +295,7 @@ describe('End-To-End Simulations', () => { }); it('Should successfully simulate (delegators withdraw without undelegating / includes shadow balances / delegators enter after reward payouts)', async () => { - // @TODO - get computations more accurate + // @TODO - get computations more accurate /* Pool | Total Fees | Total Stake | Total Delegated Stake | Total Stake (Scaled) 0 | 0.304958 | 42 | 0 | 42 @@ -339,7 +331,7 @@ describe('End-To-End Simulations', () => { // pool 3 stakingWrapper.toBaseUnitAmount(23.577), stakingWrapper.toBaseUnitAmount(4.54522236), - stakingWrapper.toBaseUnitAmount(0) + stakingWrapper.toBaseUnitAmount(0), ], numberOfDelegators: 3, numberOfDelegatorsPerPool: [0, 0, 3], @@ -348,35 +340,34 @@ describe('End-To-End Simulations', () => { stakingWrapper.toBaseUnitAmount(75), stakingWrapper.toBaseUnitAmount(90), ], - delegateInNextEpoch: true, // delegated stake is included in payout computation + forces shadow eth - withdrawByUndelegating: false, // profits are withdrawn without undelegating + delegateInNextEpoch: true, // delegated stake is included in payout computation + forces shadow eth + withdrawByUndelegating: false, // profits are withdrawn without undelegating expectedFeesByPool: [ stakingWrapper.toBaseUnitAmount(0.304958), stakingWrapper.toBaseUnitAmount(15.323258), stakingWrapper.toBaseUnitAmount(28.12222236), ], expectedPayoutByPool: [ - new BigNumber('4.75677'), // 4.756772362932728793619590327361600155564384201215274334070 - new BigNumber('16.28130'), // 16.28130500394935316563988584956596823402223838026190634525 - new BigNumber('20.31028'), // 20.31028447343014834523983759032242063760612769662934308289 + new BigNumber('4.75677'), // 4.756772362932728793619590327361600155564384201215274334070 + new BigNumber('16.28130'), // 16.28130500394935316563988584956596823402223838026190634525 + new BigNumber('20.31028'), // 20.31028447343014834523983759032242063760612769662934308289 ], expectedPayoutByPoolOperator: [ - new BigNumber('1.85514'), // 0.39 * 4.75677 - new BigNumber('9.60597'), // 0.59 * 16.28130 - new BigNumber('8.73342') // 0.43 * 20.31028 + new BigNumber('1.85514'), // 0.39 * 4.75677 + new BigNumber('9.60597'), // 0.59 * 16.28130 + new BigNumber('8.73342'), // 0.43 * 20.31028 ], expectedMembersPayoutByPool: [ - new BigNumber('2.90163'), // (1 - 0.39) * 4.75677 - new BigNumber('6.67533'), // (1 - 0.59) * 16.28130 - new BigNumber('11.57686'), // (1 - 0.43) * 20.31028 + new BigNumber('2.90163'), // (1 - 0.39) * 4.75677 + new BigNumber('6.67533'), // (1 - 0.59) * 16.28130 + new BigNumber('11.57686'), // (1 - 0.43) * 20.31028 ], expectedPayoutByDelegator: [ - new BigNumber('11.57686'), // (1 - 0.43) * 20.31028 + new BigNumber('11.57686'), // (1 - 0.43) * 20.31028 new BigNumber(0), new BigNumber(0), ], exchangeAddress: exchange, - }; const simulator = new Simulation(stakingWrapper, simulationParams); await simulator.runAsync(); @@ -387,7 +378,7 @@ describe('End-To-End Simulations', () => { const protocolFee = new BigNumber(1); await expectTransactionFailedAsync( stakingWrapper.payProtocolFeeAsync(makerAddress, protocolFee, owner), - RevertReason.OnlyCallableByExchange + RevertReason.OnlyCallableByExchange, ); }); }); diff --git a/contracts/staking/test/stake_test.ts b/contracts/staking/test/stake_test.ts index 1fc382a3cf..7b63f25e5e 100644 --- a/contracts/staking/test/stake_test.ts +++ b/contracts/staking/test/stake_test.ts @@ -21,7 +21,6 @@ import { StakingWrapper } from './utils/staking_wrapper'; import { ERC20Wrapper, ERC20ProxyContract } from '@0x/contracts-asset-proxy'; import { StakingContract } from '../src'; - import { StakerActor } from './actors/staker_actor'; import { DelegatorActor } from './actors/delegator_actor'; diff --git a/contracts/staking/test/utils/ApprovalFactory.ts b/contracts/staking/test/utils/ApprovalFactory.ts index f542d10ec3..39e72aff1d 100644 --- a/contracts/staking/test/utils/ApprovalFactory.ts +++ b/contracts/staking/test/utils/ApprovalFactory.ts @@ -26,7 +26,7 @@ export class ApprovalFactory { poolId, makerAddress, this._verifyingContractAddress, - this._chainId + this._chainId, ); const signatureBuff = signingUtils.signMessage(approvalHashBuff, this._privateKey, signatureType); const signedApproval = { diff --git a/contracts/staking/test/utils/Simulation.ts b/contracts/staking/test/utils/Simulation.ts index 952ec7eeb1..e10d04f250 100644 --- a/contracts/staking/test/utils/Simulation.ts +++ b/contracts/staking/test/utils/Simulation.ts @@ -1,6 +1,4 @@ -import { - chaiSetup, -} from '@0x/contracts-test-utils'; +import { chaiSetup } from '@0x/contracts-test-utils'; import * as _ from 'lodash'; import * as chai from 'chai'; @@ -12,7 +10,6 @@ import { StakingWrapper } from './staking_wrapper'; import { Queue } from './queue'; import { DelegatorActor } from '../actors/delegator_actor'; - chaiSetup.configure(); const expect = chai.expect; @@ -25,7 +22,7 @@ export class Simulation { private _poolIds: string[]; private _makers: MakerActor[]; private _delegators: DelegatorActor[]; - + constructor(stakingWrapper: StakingWrapper, simulationParams: SimulationParams) { this._stakingWrapper = stakingWrapper; this._p = simulationParams; @@ -57,7 +54,7 @@ export class Simulation { } else { await this._withdrawRewardForDelegatorsByUndelegating(this._p); } - + // @TODO cleanup state and verify the staking contract is empty } @@ -73,10 +70,16 @@ export class Simulation { const initEthBalance = await this._stakingWrapper.getEthBalanceAsync(delegatorAddress); await delegator.deactivateAndTimelockDelegatedStakeAsync(poolId, amountOfStakeDelegated); const finalEthBalance = await this._stakingWrapper.getEthBalanceAsync(delegatorAddress); - const reward = finalEthBalance.minus(initEthBalance); - const rewardTrimmed = this._stakingWrapper.trimFloat(this._stakingWrapper.toFloatingPoint(reward, 18), 5); + const reward = finalEthBalance.minus(initEthBalance); + const rewardTrimmed = this._stakingWrapper.trimFloat( + this._stakingWrapper.toFloatingPoint(reward, 18), + 5, + ); const expectedReward = p.expectedPayoutByDelegator[delegatorIdx]; - expect(rewardTrimmed, `reward withdrawn from pool ${poolId} for delegator ${delegatorAddress}`).to.be.bignumber.equal(expectedReward); + expect( + rewardTrimmed, + `reward withdrawn from pool ${poolId} for delegator ${delegatorAddress}`, + ).to.be.bignumber.equal(expectedReward); delegatorIdx += 1; } poolIdx += 1; @@ -94,10 +97,16 @@ export class Simulation { const initEthBalance = await this._stakingWrapper.getEthBalanceAsync(delegatorAddress); await this._stakingWrapper.withdrawTotalRewardAsync(poolId, delegatorAddress); const finalEthBalance = await this._stakingWrapper.getEthBalanceAsync(delegatorAddress); - const reward = finalEthBalance.minus(initEthBalance); - const rewardTrimmed = this._stakingWrapper.trimFloat(this._stakingWrapper.toFloatingPoint(reward, 18), 5); + const reward = finalEthBalance.minus(initEthBalance); + const rewardTrimmed = this._stakingWrapper.trimFloat( + this._stakingWrapper.toFloatingPoint(reward, 18), + 5, + ); const expectedReward = p.expectedPayoutByDelegator[delegatorIdx]; - expect(rewardTrimmed, `reward withdrawn from pool ${poolId} for delegator ${delegatorAddress}`).to.be.bignumber.equal(expectedReward); + expect( + rewardTrimmed, + `reward withdrawn from pool ${poolId} for delegator ${delegatorAddress}`, + ).to.be.bignumber.equal(expectedReward); delegatorIdx += 1; } poolIdx += 1; @@ -198,19 +207,37 @@ export class Simulation { // check pool balance in vault const poolId = this._poolIds[i]; const rewardVaultBalance = await this._stakingWrapper.rewardVaultBalanceOfAsync(poolId); - const rewardVaultBalanceTrimmed = this._stakingWrapper.trimFloat(this._stakingWrapper.toFloatingPoint(rewardVaultBalance, 18), 5); + const rewardVaultBalanceTrimmed = this._stakingWrapper.trimFloat( + this._stakingWrapper.toFloatingPoint(rewardVaultBalance, 18), + 5, + ); const expectedRewardBalance = p.expectedPayoutByPool[i]; - expect(rewardVaultBalanceTrimmed, `expected balance in vault for pool with id ${poolId}`).to.be.bignumber.equal(expectedRewardBalance); + expect( + rewardVaultBalanceTrimmed, + `expected balance in vault for pool with id ${poolId}`, + ).to.be.bignumber.equal(expectedRewardBalance); // check operator's balance const poolOperatorVaultBalance = await this._stakingWrapper.getRewardBalanceOfOperatorAsync(poolId); - const poolOperatorVaultBalanceTrimmed = this._stakingWrapper.trimFloat(this._stakingWrapper.toFloatingPoint(poolOperatorVaultBalance, 18), 5); + const poolOperatorVaultBalanceTrimmed = this._stakingWrapper.trimFloat( + this._stakingWrapper.toFloatingPoint(poolOperatorVaultBalance, 18), + 5, + ); const expectedPoolOperatorVaultBalance = p.expectedPayoutByPoolOperator[i]; - expect(poolOperatorVaultBalanceTrimmed, `operator balance in vault for pool with id ${poolId}`).to.be.bignumber.equal(expectedPoolOperatorVaultBalance); + expect( + poolOperatorVaultBalanceTrimmed, + `operator balance in vault for pool with id ${poolId}`, + ).to.be.bignumber.equal(expectedPoolOperatorVaultBalance); // check balance of pool members const membersVaultBalance = await this._stakingWrapper.getRewardBalanceOfPoolAsync(poolId); - const membersVaultBalanceTrimmed = this._stakingWrapper.trimFloat(this._stakingWrapper.toFloatingPoint(membersVaultBalance, 18), 5); + const membersVaultBalanceTrimmed = this._stakingWrapper.trimFloat( + this._stakingWrapper.toFloatingPoint(membersVaultBalance, 18), + 5, + ); const expectedMembersVaultBalance = p.expectedMembersPayoutByPool[i]; - expect(membersVaultBalanceTrimmed, `members balance in vault for pool with id ${poolId}`).to.be.bignumber.equal(expectedMembersVaultBalance); + expect( + membersVaultBalanceTrimmed, + `members balance in vault for pool with id ${poolId}`, + ).to.be.bignumber.equal(expectedMembersVaultBalance); // @TODO compute balance of each member } } @@ -226,10 +253,12 @@ export class Simulation { const initEthBalance = await this._stakingWrapper.getEthBalanceAsync(poolOperatorAddress); await this._stakingWrapper.withdrawTotalOperatorRewardAsync(poolId, poolOperatorAddress); const finalEthBalance = await this._stakingWrapper.getEthBalanceAsync(poolOperatorAddress); - const reward = finalEthBalance.minus(initEthBalance); + const reward = finalEthBalance.minus(initEthBalance); const rewardTrimmed = this._stakingWrapper.trimFloat(this._stakingWrapper.toFloatingPoint(reward, 18), 5); const expectedReward = p.expectedPayoutByPoolOperator[i]; - expect(rewardTrimmed, `reward withdrawn from pool ${poolId} for operator`).to.be.bignumber.equal(expectedReward); + expect(rewardTrimmed, `reward withdrawn from pool ${poolId} for operator`).to.be.bignumber.equal( + expectedReward, + ); } } -} \ No newline at end of file +} diff --git a/contracts/staking/test/utils/constants.ts b/contracts/staking/test/utils/constants.ts index dba0f10f81..44030cd85f 100644 --- a/contracts/staking/test/utils/constants.ts +++ b/contracts/staking/test/utils/constants.ts @@ -1,14 +1,14 @@ import { BigNumber } from '@0x/utils'; export const constants = { - MAX_UINT_64: (new BigNumber(2)).pow(256).minus(1), - TOKEN_MULTIPLIER: (new BigNumber(10)).pow(18), - INITIAL_POOL_ID: "0x0000000000000000000000000000000100000000000000000000000000000000", - NIL_POOL_ID: "0x0000000000000000000000000000000000000000000000000000000000000000", - NIL_ADDRESS: "0x0000000000000000000000000000000000000000", - INITIAL_EPOCH: (new BigNumber(0)), + MAX_UINT_64: new BigNumber(2).pow(256).minus(1), + TOKEN_MULTIPLIER: new BigNumber(10).pow(18), + INITIAL_POOL_ID: '0x0000000000000000000000000000000100000000000000000000000000000000', + NIL_POOL_ID: '0x0000000000000000000000000000000000000000000000000000000000000000', + NIL_ADDRESS: '0x0000000000000000000000000000000000000000', + INITIAL_EPOCH: new BigNumber(0), INITIAL_TIMELOCK_PERIOD: new BigNumber(0), EPOCH_PERIOD_IN_SECONDS: new BigNumber(1000), // @TODO SET FOR DEPLOYMENT*/ TIMELOCK_PERIOD_IN_EPOCHS: new BigNumber(3), // @TODO SET FOR DEPLOYMENT CHAIN_ID: 1, -}; \ No newline at end of file +}; diff --git a/contracts/staking/test/utils/hash_utils.ts b/contracts/staking/test/utils/hash_utils.ts index 4e4faf8015..625c9a475b 100644 --- a/contracts/staking/test/utils/hash_utils.ts +++ b/contracts/staking/test/utils/hash_utils.ts @@ -7,13 +7,13 @@ export const hashUtils = { poolId: string, makerAddress: string, verifyingContractAddress: string, - chainId: number + chainId: number, ): Buffer { const typedData = eip712Utils.createStakingPoolApprovalTypedData( poolId, makerAddress, verifyingContractAddress, - chainId + chainId, ); const hashBuffer = signTypedDataUtils.generateTypedDataHash(typedData); return hashBuffer; @@ -22,7 +22,7 @@ export const hashUtils = { poolId: string, makerAddress: string, verifyingContractAddress: string, - chainId: number + chainId: number, ): string { const hashHex = `0x${hashUtils .getStakingPoolApprovalHashBuffer(poolId, makerAddress, verifyingContractAddress, chainId) diff --git a/contracts/staking/test/utils/queue.ts b/contracts/staking/test/utils/queue.ts index 5a60b92d0a..4a6d602988 100644 --- a/contracts/staking/test/utils/queue.ts +++ b/contracts/staking/test/utils/queue.ts @@ -2,7 +2,7 @@ import * as _ from 'lodash'; export class Queue { private _store: T[] = []; - constructor (store?: T[]) { + constructor(store?: T[]) { this._store = store !== undefined ? _.cloneDeep(store) : []; } public pushBack(val: T): void { diff --git a/contracts/staking/test/utils/staking_wrapper.ts b/contracts/staking/test/utils/staking_wrapper.ts index 9e42c312d2..6c2d3e339a 100644 --- a/contracts/staking/test/utils/staking_wrapper.ts +++ b/contracts/staking/test/utils/staking_wrapper.ts @@ -9,7 +9,14 @@ import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contra import { ERC20ProxyContract } from '@0x/contracts-asset-proxy'; import * as _ from 'lodash'; -import { artifacts, StakingContract, StakingProxyContract, ZrxVaultContract, RewardVaultContract, LibFeeMathTestContract } from '../../src'; +import { + artifacts, + StakingContract, + StakingProxyContract, + ZrxVaultContract, + RewardVaultContract, + LibFeeMathTestContract, +} from '../../src'; import { ApprovalFactory } from './ApprovalFactory'; import { SignedStakingPoolApproval } from './types'; import { constants } from './constants'; @@ -30,12 +37,18 @@ export class StakingWrapper { private _rewardVaultContractIfExists?: RewardVaultContract; private _LibFeeMathTestContractIfExists?: LibFeeMathTestContract; - constructor(provider: Provider, ownerAddres: string, erc20ProxyContract: ERC20ProxyContract, zrxTokenContract: DummyERC20TokenContract, accounts: string[]) { + constructor( + provider: Provider, + ownerAddres: string, + erc20ProxyContract: ERC20ProxyContract, + zrxTokenContract: DummyERC20TokenContract, + accounts: string[], + ) { this._web3Wrapper = new Web3Wrapper(provider); this._provider = provider; const decoderArtifacts = _.merge(artifacts, erc20Artifacts); this._logDecoder = new LogDecoder(this._web3Wrapper, decoderArtifacts); - this._ownerAddres= ownerAddres; + this._ownerAddres = ownerAddres; this._erc20ProxyContract = erc20ProxyContract; this._zrxTokenContract = zrxTokenContract; this._accounts = accounts; @@ -69,7 +82,7 @@ export class StakingWrapper { txDefaults, this._erc20ProxyContract.address, this._zrxTokenContract.address, - zrxAssetData + zrxAssetData, ); // deploy reward vault this._rewardVaultContractIfExists = await RewardVaultContract.deployFrom0xArtifactAsync( @@ -78,43 +91,57 @@ export class StakingWrapper { txDefaults, ); // configure erc20 proxy to accept calls from zrx vault - await this._erc20ProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync((this._zrxVaultContractIfExists as ZrxVaultContract).address); + await this._erc20ProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync( + (this._zrxVaultContractIfExists as ZrxVaultContract).address, + ); // deploy staking contract this._stakingContractIfExists = await StakingContract.deployFrom0xArtifactAsync( artifacts.Staking, this._provider, - txDefaults + txDefaults, ); // deploy staking proxy this._stakingProxyContractIfExists = await StakingProxyContract.deployFrom0xArtifactAsync( artifacts.StakingProxy, this._provider, txDefaults, - (this._stakingContractIfExists as StakingContract).address + (this._stakingContractIfExists as StakingContract).address, ); // set staking proxy contract in zrx vault - await (this._zrxVaultContractIfExists as ZrxVaultContract).setStakingContractAddrsess.awaitTransactionSuccessAsync((this._stakingProxyContractIfExists as StakingProxyContract).address); + await (this + ._zrxVaultContractIfExists as ZrxVaultContract).setStakingContractAddrsess.awaitTransactionSuccessAsync( + (this._stakingProxyContractIfExists as StakingProxyContract).address, + ); // set zrx vault in staking contract - const setZrxVaultCalldata = await (this._stakingContractIfExists as StakingContract).setZrxVault.getABIEncodedTransactionData((this._zrxVaultContractIfExists as ZrxVaultContract).address); + const setZrxVaultCalldata = await (this + ._stakingContractIfExists as StakingContract).setZrxVault.getABIEncodedTransactionData( + (this._zrxVaultContractIfExists as ZrxVaultContract).address, + ); const setZrxVaultTxData = { from: this._ownerAddres, to: (this._stakingProxyContractIfExists as StakingProxyContract).address, - data: setZrxVaultCalldata - } + data: setZrxVaultCalldata, + }; await this._web3Wrapper.awaitTransactionSuccessAsync( - await this._web3Wrapper.sendTransactionAsync(setZrxVaultTxData) + await this._web3Wrapper.sendTransactionAsync(setZrxVaultTxData), ); // set staking proxy contract in reward vault - await (this._rewardVaultContractIfExists as RewardVaultContract).setStakingContractAddrsess.awaitTransactionSuccessAsync((this._stakingProxyContractIfExists as StakingProxyContract).address); + await (this + ._rewardVaultContractIfExists as RewardVaultContract).setStakingContractAddrsess.awaitTransactionSuccessAsync( + (this._stakingProxyContractIfExists as StakingProxyContract).address, + ); // set reward vault in staking contract - const setRewardVaultCalldata = await (this._stakingContractIfExists as StakingContract).setRewardVault.getABIEncodedTransactionData((this._rewardVaultContractIfExists as RewardVaultContract).address); + const setRewardVaultCalldata = await (this + ._stakingContractIfExists as StakingContract).setRewardVault.getABIEncodedTransactionData( + (this._rewardVaultContractIfExists as RewardVaultContract).address, + ); const setRewardVaultTxData = { from: this._ownerAddres, to: (this._stakingProxyContractIfExists as StakingProxyContract).address, - data: setRewardVaultCalldata - } + data: setRewardVaultCalldata, + }; await this._web3Wrapper.awaitTransactionSuccessAsync( - await this._web3Wrapper.sendTransactionAsync(setRewardVaultTxData) + await this._web3Wrapper.sendTransactionAsync(setRewardVaultTxData), ); // deploy libmath test this._LibFeeMathTestContractIfExists = await LibFeeMathTestContract.deployFrom0xArtifactAsync( @@ -123,26 +150,33 @@ export class StakingWrapper { txDefaults, ); } - private async _executeTransactionAsync(calldata: string, from?: string, value?: BigNumber, includeLogs?: boolean): Promise { + private async _executeTransactionAsync( + calldata: string, + from?: string, + value?: BigNumber, + includeLogs?: boolean, + ): Promise { const txData = { - from: (from ? from : this._ownerAddres), + from: from ? from : this._ownerAddres, to: this.getStakingProxyContract().address, data: calldata, gas: 3000000, gasPrice: 0, - value - } + value, + }; const txHash = await this._web3Wrapper.sendTransactionAsync(txData); - const txReceipt = await (includeLogs ? this._logDecoder.getTxWithDecodedLogsAsync(txHash) : this._web3Wrapper.awaitTransactionSuccessAsync(txHash)); + const txReceipt = await (includeLogs + ? this._logDecoder.getTxWithDecodedLogsAsync(txHash) + : this._web3Wrapper.awaitTransactionSuccessAsync(txHash)); return txReceipt; } private async _callAsync(calldata: string, from?: string): Promise { const txData = { - from: (from ? from : this._ownerAddres), + from: from ? from : this._ownerAddres, to: this.getStakingProxyContract().address, data: calldata, - gas: 3000000 - } + gas: 3000000, + }; const returnValue = await this._web3Wrapper.callAsync(txData); return returnValue; } @@ -161,7 +195,11 @@ export class StakingWrapper { const txReceipt = await this._executeTransactionAsync(calldata, owner); return txReceipt; } - public async depositAndDelegateAsync(owner: string, poolId: string, amount: BigNumber): Promise { + public async depositAndDelegateAsync( + owner: string, + poolId: string, + amount: BigNumber, + ): Promise { const calldata = this.getStakingContract().depositAndDelegate.getABIEncodedTransactionData(poolId, amount); const txReceipt = await this._executeTransactionAsync(calldata, owner, new BigNumber(0), true); return txReceipt; @@ -171,18 +209,35 @@ export class StakingWrapper { const txReceipt = await this._executeTransactionAsync(calldata, owner); return txReceipt; } - public async activateAndDelegateStakeAsync(owner: string, poolId: string, amount: BigNumber): Promise { - const calldata = this.getStakingContract().activateAndDelegateStake.getABIEncodedTransactionData(poolId, amount); + public async activateAndDelegateStakeAsync( + owner: string, + poolId: string, + amount: BigNumber, + ): Promise { + const calldata = this.getStakingContract().activateAndDelegateStake.getABIEncodedTransactionData( + poolId, + amount, + ); const txReceipt = await this._executeTransactionAsync(calldata, owner); return txReceipt; } - public async deactivateAndTimelockStakeAsync(owner: string, amount: BigNumber): Promise { + public async deactivateAndTimelockStakeAsync( + owner: string, + amount: BigNumber, + ): Promise { const calldata = this.getStakingContract().deactivateAndTimelockStake.getABIEncodedTransactionData(amount); const txReceipt = await this._executeTransactionAsync(calldata, owner); return txReceipt; } - public async deactivateAndTimelockDelegatedStakeAsync(owner: string, poolId: string, amount: BigNumber): Promise { - const calldata = this.getStakingContract().deactivateAndTimelockDelegatedStake.getABIEncodedTransactionData(poolId, amount); + public async deactivateAndTimelockDelegatedStakeAsync( + owner: string, + poolId: string, + amount: BigNumber, + ): Promise { + const calldata = this.getStakingContract().deactivateAndTimelockDelegatedStake.getABIEncodedTransactionData( + poolId, + amount, + ); const txReceipt = await this._executeTransactionAsync(calldata, owner, new BigNumber(0), true); return txReceipt; } @@ -246,7 +301,10 @@ export class StakingWrapper { return value; } public async getStakeDelegatedToPoolByOwnerAsync(poolId: string, owner: string): Promise { - const calldata = this.getStakingContract().getStakeDelegatedToPoolByOwner.getABIEncodedTransactionData(owner, poolId); + const calldata = this.getStakingContract().getStakeDelegatedToPoolByOwner.getABIEncodedTransactionData( + owner, + poolId, + ); const returnData = await this._callAsync(calldata); const value = this.getStakingContract().getStakeDelegatedToPoolByOwner.getABIDecodedReturnData(returnData); return value; @@ -270,13 +328,29 @@ export class StakingWrapper { const poolId = (createPoolLog as any).args.poolId; return poolId; } - public async addMakerToPoolAsync(poolId: string, makerAddress: string, makerSignature: string, operatorAddress: string): Promise { - const calldata = this.getStakingContract().addMakerToPool.getABIEncodedTransactionData(poolId, makerAddress, makerSignature); + public async addMakerToPoolAsync( + poolId: string, + makerAddress: string, + makerSignature: string, + operatorAddress: string, + ): Promise { + const calldata = this.getStakingContract().addMakerToPool.getABIEncodedTransactionData( + poolId, + makerAddress, + makerSignature, + ); const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress); return txReceipt; } - public async removeMakerFromPoolAsync(poolId: string, makerAddress: string, operatorAddress: string): Promise { - const calldata = this.getStakingContract().removeMakerFromPool.getABIEncodedTransactionData(poolId, makerAddress); + public async removeMakerFromPoolAsync( + poolId: string, + makerAddress: string, + operatorAddress: string, + ): Promise { + const calldata = this.getStakingContract().removeMakerFromPool.getABIEncodedTransactionData( + poolId, + makerAddress, + ); const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress); return txReceipt; } @@ -291,16 +365,29 @@ export class StakingWrapper { const makerAddresses = this.getStakingContract().getMakerAddressesForPool.getABIDecodedReturnData(returndata); return makerAddresses; } - public async isValidMakerSignatureAsync(poolId: string, makerAddress: string, makerSignature: string): Promise { - const calldata = this.getStakingContract().isValidMakerSignature.getABIEncodedTransactionData(poolId, makerAddress, makerSignature); + public async isValidMakerSignatureAsync( + poolId: string, + makerAddress: string, + makerSignature: string, + ): Promise { + const calldata = this.getStakingContract().isValidMakerSignature.getABIEncodedTransactionData( + poolId, + makerAddress, + makerSignature, + ); const returndata = await this._callAsync(calldata); const isValid = this.getStakingContract().isValidMakerSignature.getABIDecodedReturnData(returndata); return isValid; } public async getStakingPoolApprovalMessageHashAsync(poolId: string, makerAddress: string): Promise { - const calldata = this.getStakingContract().getStakingPoolApprovalMessageHash.getABIEncodedTransactionData(poolId, makerAddress); + const calldata = this.getStakingContract().getStakingPoolApprovalMessageHash.getABIEncodedTransactionData( + poolId, + makerAddress, + ); const returndata = await this._callAsync(calldata); - const messageHash = this.getStakingContract().getStakingPoolApprovalMessageHash.getABIDecodedReturnData(returndata); + const messageHash = this.getStakingContract().getStakingPoolApprovalMessageHash.getABIDecodedReturnData( + returndata, + ); return messageHash; } public signApprovalForStakingPool( @@ -311,8 +398,12 @@ export class StakingWrapper { chainIdIfExists?: number, signatureType: SignatureType = SignatureType.EthSign, ): SignedStakingPoolApproval { - const makerPrivateKey = makerPrivateKeyIfExists !== undefined ? makerPrivateKeyIfExists : testUtilsConstants.TESTRPC_PRIVATE_KEYS[this._accounts.indexOf(makerAddress)]; - const verifierAddress = verifierAddressIfExists !== undefined ? verifierAddressIfExists : this.getStakingProxyContract().address; + const makerPrivateKey = + makerPrivateKeyIfExists !== undefined + ? makerPrivateKeyIfExists + : testUtilsConstants.TESTRPC_PRIVATE_KEYS[this._accounts.indexOf(makerAddress)]; + const verifierAddress = + verifierAddressIfExists !== undefined ? verifierAddressIfExists : this.getStakingProxyContract().address; const chainId = chainIdIfExists !== undefined ? chainIdIfExists : constants.CHAIN_ID; const approvalFactory = new ApprovalFactory(makerPrivateKey, verifierAddress, chainId); const signedStakingPoolApproval = approvalFactory.newSignedApproval(poolId, makerAddress, signatureType); @@ -322,7 +413,9 @@ export class StakingWrapper { public async goToNextEpochAsync(): Promise { const calldata = this.getStakingContract().finalizeFees.getABIEncodedTransactionData(); const txReceipt = await this._executeTransactionAsync(calldata, undefined, new BigNumber(0), true); - console.log(`finalization: gasUsed = ${txReceipt.gasUsed} / cumulativeGasUsed = ${txReceipt.cumulativeGasUsed}`); + console.log( + `finalization: gasUsed = ${txReceipt.gasUsed} / cumulativeGasUsed = ${txReceipt.cumulativeGasUsed}`, + ); return txReceipt; } public async skipToNextEpochAsync(): Promise { @@ -395,7 +488,11 @@ export class StakingWrapper { return value; } ///// PROTOCOL FEES ///// - public async payProtocolFeeAsync(makerAddress: string, amount: BigNumber, exchangeAddress: string): Promise { + public async payProtocolFeeAsync( + makerAddress: string, + amount: BigNumber, + exchangeAddress: string, + ): Promise { const calldata = this.getStakingContract().payProtocolFee.getABIEncodedTransactionData(makerAddress); const txReceipt = await this._executeTransactionAsync(calldata, exchangeAddress, amount); return txReceipt; @@ -461,22 +558,36 @@ export class StakingWrapper { return value; } public async getShadowBalanceInPoolByOwnerAsync(owner: string, poolId: string): Promise { - const calldata = this.getStakingContract().getShadowBalanceInPoolByOwner.getABIEncodedTransactionData(owner, poolId); + const calldata = this.getStakingContract().getShadowBalanceInPoolByOwner.getABIEncodedTransactionData( + owner, + poolId, + ); const returnData = await this._callAsync(calldata); const value = this.getStakingContract().getShadowBalanceInPoolByOwner.getABIDecodedReturnData(returnData); return value; } - public async withdrawOperatorRewardAsync(poolId: string, amount: BigNumber, operatorAddress: string): Promise { + public async withdrawOperatorRewardAsync( + poolId: string, + amount: BigNumber, + operatorAddress: string, + ): Promise { const calldata = this.getStakingContract().withdrawOperatorReward.getABIEncodedTransactionData(poolId, amount); const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress); return txReceipt; } - public async withdrawRewardAsync(poolId: string, amount: BigNumber, owner: string): Promise { + public async withdrawRewardAsync( + poolId: string, + amount: BigNumber, + owner: string, + ): Promise { const calldata = this.getStakingContract().withdrawReward.getABIEncodedTransactionData(poolId, amount); const txReceipt = await this._executeTransactionAsync(calldata, owner); return txReceipt; } - public async withdrawTotalOperatorRewardAsync(poolId: string, operatorAddress: string): Promise { + public async withdrawTotalOperatorRewardAsync( + poolId: string, + operatorAddress: string, + ): Promise { const calldata = this.getStakingContract().withdrawTotalOperatorReward.getABIEncodedTransactionData(poolId); const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress); return txReceipt; @@ -487,12 +598,18 @@ export class StakingWrapper { return txReceipt; } ///// REWARD VAULT ///// - public async rewardVaultDepositForAsync(poolId: string, amount: BigNumber, stakingContractAddress: string): Promise { + public async rewardVaultDepositForAsync( + poolId: string, + amount: BigNumber, + stakingContractAddress: string, + ): Promise { const calldata = this.getRewardVaultContract().depositFor.getABIEncodedTransactionData(poolId); const txReceipt = await this._executeTransactionAsync(calldata, stakingContractAddress, amount); return txReceipt; } - public async rewardVaultEnterCatastrophicFailureModeAsync(zeroExMultisigAddress: string): Promise { + public async rewardVaultEnterCatastrophicFailureModeAsync( + zeroExMultisigAddress: string, + ): Promise { const calldata = this.getRewardVaultContract().enterCatostrophicFailure.getABIEncodedTransactionData(); const txReceipt = await this._executeTransactionAsync(calldata, zeroExMultisigAddress); return txReceipt; @@ -509,8 +626,15 @@ export class StakingWrapper { const balance = await this.getRewardVaultContract().balanceOfPool.callAsync(poolId); return balance; } - public async rewardVaultCreatePoolAsync(poolId: string, poolOperatorShare: number, stakingContractAddress: string): Promise { - const calldata = this.getRewardVaultContract().createPool.getABIEncodedTransactionData(poolId, poolOperatorShare); + public async rewardVaultCreatePoolAsync( + poolId: string, + poolOperatorShare: number, + stakingContractAddress: string, + ): Promise { + const calldata = this.getRewardVaultContract().createPool.getABIEncodedTransactionData( + poolId, + poolOperatorShare, + ); const txReceipt = await this._executeTransactionAsync(calldata, stakingContractAddress); return txReceipt; } @@ -544,7 +668,7 @@ export class StakingWrapper { ownerStake: BigNumber, totalStake: BigNumber, alphaNumerator: BigNumber, - alphaDenominator: BigNumber + alphaDenominator: BigNumber, ) { const output = await this.getLibFeeMathTestContract().cobbDouglas.callAsync( totalRewards, @@ -553,7 +677,7 @@ export class StakingWrapper { ownerStake, totalStake, alphaNumerator, - alphaDenominator + alphaDenominator, ); return output; } @@ -563,7 +687,7 @@ export class StakingWrapper { totalFees: BigNumber, ownerStake: BigNumber, totalStake: BigNumber, - alphaDenominator: BigNumber + alphaDenominator: BigNumber, ) { const txReceipt = await this.getLibFeeMathTestContract().cobbDouglasSimplifiedInverse.awaitTransactionSuccessAsync( totalRewards, @@ -571,7 +695,7 @@ export class StakingWrapper { totalFees, ownerStake, totalStake, - alphaDenominator + alphaDenominator, ); const output = await this.getLibFeeMathTestContract().cobbDouglasSimplified.callAsync( totalRewards, @@ -579,7 +703,7 @@ export class StakingWrapper { totalFees, ownerStake, totalStake, - alphaDenominator + alphaDenominator, ); return output; } @@ -589,7 +713,7 @@ export class StakingWrapper { totalFees: BigNumber, ownerStake: BigNumber, totalStake: BigNumber, - alphaDenominator: BigNumber + alphaDenominator: BigNumber, ) { const txReceipt = await this.getLibFeeMathTestContract().cobbDouglasSimplifiedInverse.awaitTransactionSuccessAsync( totalRewards, @@ -597,7 +721,7 @@ export class StakingWrapper { totalFees, ownerStake, totalStake, - alphaDenominator + alphaDenominator, ); const output = await this.getLibFeeMathTestContract().cobbDouglasSimplifiedInverse.callAsync( @@ -606,32 +730,35 @@ export class StakingWrapper { totalFees, ownerStake, totalStake, - alphaDenominator + alphaDenominator, ); return output; } public toBaseUnitAmount(amount: BigNumber | number): BigNumber { const decimals = 18; - const amountAsBigNumber = typeof(amount) === 'number' ? new BigNumber(amount) : amount; + const amountAsBigNumber = typeof amount === 'number' ? new BigNumber(amount) : amount; const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amountAsBigNumber, decimals); return baseUnitAmount; } public toFixedPoint(amount: BigNumber | number, decimals: number): BigNumber { - const amountAsBigNumber = typeof(amount) === 'number' ? new BigNumber(amount) : amount; + const amountAsBigNumber = typeof amount === 'number' ? new BigNumber(amount) : amount; const scalar = Math.pow(10, decimals); const amountAsFixedPoint = amountAsBigNumber.times(scalar); return amountAsFixedPoint; } public toFloatingPoint(amount: BigNumber | number, decimals: number): BigNumber { - const amountAsBigNumber = typeof(amount) === 'number' ? new BigNumber(amount) : amount; + const amountAsBigNumber = typeof amount === 'number' ? new BigNumber(amount) : amount; const scalar = Math.pow(10, decimals); const amountAsFloatingPoint = amountAsBigNumber.dividedBy(scalar); return amountAsFloatingPoint; } public trimFloat(amount: BigNumber | number, decimals: number): BigNumber { - const amountAsBigNumber = typeof(amount) === 'number' ? new BigNumber(amount) : amount; + const amountAsBigNumber = typeof amount === 'number' ? new BigNumber(amount) : amount; const scalar = Math.pow(10, decimals); - const amountAsFloatingPoint = ((amountAsBigNumber.multipliedBy(scalar)).dividedToIntegerBy(1)).dividedBy(scalar); + const amountAsFloatingPoint = amountAsBigNumber + .multipliedBy(scalar) + .dividedToIntegerBy(1) + .dividedBy(scalar); return amountAsFloatingPoint; } private _validateDeployedOrThrow() { diff --git a/contracts/staking/test/utils/types.ts b/contracts/staking/test/utils/types.ts index 35100737c4..7f61041608 100644 --- a/contracts/staking/test/utils/types.ts +++ b/contracts/staking/test/utils/types.ts @@ -1,10 +1,10 @@ import { BigNumber } from '@0x/utils'; export interface StakingPoolApproval { - makerAddress: string, - poolId: string, - verifyingContractAddress: string, - chainId: number + makerAddress: string; + poolId: string; + verifyingContractAddress: string; + chainId: number; } export interface SignedStakingPoolApproval extends StakingPoolApproval { @@ -29,22 +29,22 @@ export interface DelegatorBalances extends StakerBalances { } export interface SimulationParams { - users: string[], - numberOfPools: number, - poolOperatorShares: number[], - stakeByPoolOperator: BigNumber[], - numberOfMakers: number, - numberOfMakersPerPool: number[], - protocolFeesByMaker: BigNumber[], - numberOfDelegators: number, - numberOfDelegatorsPerPool: number[], - stakeByDelegator: BigNumber[], - expectedFeesByPool: BigNumber[], - expectedPayoutByPool: BigNumber[], - expectedPayoutByPoolOperator: BigNumber[], - expectedMembersPayoutByPool: BigNumber[], - expectedPayoutByDelegator: BigNumber[], - exchangeAddress: string, - delegateInNextEpoch: Boolean, - withdrawByUndelegating: Boolean, -} \ No newline at end of file + users: string[]; + numberOfPools: number; + poolOperatorShares: number[]; + stakeByPoolOperator: BigNumber[]; + numberOfMakers: number; + numberOfMakersPerPool: number[]; + protocolFeesByMaker: BigNumber[]; + numberOfDelegators: number; + numberOfDelegatorsPerPool: number[]; + stakeByDelegator: BigNumber[]; + expectedFeesByPool: BigNumber[]; + expectedPayoutByPool: BigNumber[]; + expectedPayoutByPoolOperator: BigNumber[]; + expectedMembersPayoutByPool: BigNumber[]; + expectedPayoutByDelegator: BigNumber[]; + exchangeAddress: string; + delegateInNextEpoch: Boolean; + withdrawByUndelegating: Boolean; +} diff --git a/contracts/staking/test/vaults_test.ts b/contracts/staking/test/vaults_test.ts index 6cb9eb5e28..dc20e96793 100644 --- a/contracts/staking/test/vaults_test.ts +++ b/contracts/staking/test/vaults_test.ts @@ -21,7 +21,6 @@ import { StakingWrapper } from './utils/staking_wrapper'; import { ERC20Wrapper, ERC20ProxyContract } from '@0x/contracts-asset-proxy'; import { StakingContract } from '../src'; - import { StakerActor } from './actors/staker_actor'; import { DelegatorActor } from './actors/delegator_actor'; @@ -87,12 +86,12 @@ describe('Staking Vaults', () => { // should fail to create pool if it already exists await expectTransactionFailedAsync( stakingWrapper.rewardVaultCreatePoolAsync(poolId, operatorShare, stakingContractAddress), - RevertReason.PoolAlreadyExists + RevertReason.PoolAlreadyExists, ); // should fail to create a pool from an address other than the staking contract await expectTransactionFailedAsync( - stakingWrapper.rewardVaultCreatePoolAsync(poolId, operatorShare, notStakingContractAddress), - RevertReason.OnlyCallableByStakingContract + stakingWrapper.rewardVaultCreatePoolAsync(poolId, operatorShare, notStakingContractAddress), + RevertReason.OnlyCallableByStakingContract, ); }); }); diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts index 9cdd85b677..0bab1402a9 100644 --- a/packages/order-utils/src/constants.ts +++ b/packages/order-utils/src/constants.ts @@ -153,10 +153,7 @@ export const constants = { STAKING_DOMAIN_VERSION: '1.0.0', STAKING_POOL_APPROVAL_SCHEMA: { name: 'StakingPoolApproval', - parameters: [ - { name: 'poolId', type: 'bytes32' }, - { name: 'makerAddress', type: 'address' }, - ], + parameters: [{ name: 'poolId', type: 'bytes32' }, { name: 'makerAddress', type: 'address' }], }, ERC20_METHOD_ABI, ERC721_METHOD_ABI, diff --git a/packages/order-utils/src/eip712_utils.ts b/packages/order-utils/src/eip712_utils.ts index db3620c635..45450d3b59 100644 --- a/packages/order-utils/src/eip712_utils.ts +++ b/packages/order-utils/src/eip712_utils.ts @@ -133,13 +133,13 @@ export const eip712Utils = { poolId: string, makerAddress: string, verifyingContractAddress: string, - chainId: number + chainId: number, ): EIP712TypedData => { const domain = { name: constants.STAKING_DOMAIN_NAME, version: constants.STAKING_DOMAIN_VERSION, verifyingContractAddress, - chainId + chainId, }; const approval = { poolId,