ran prettier

This commit is contained in:
Greg Hysen 2019-06-28 18:48:00 -07:00
parent 9eb676fb46
commit cd14d1ef0f
13 changed files with 152 additions and 122 deletions

View File

@ -3,20 +3,21 @@
This package implements the stake-based liquidity incentives defined by [ZEIP-31](https://github.com/0xProject/ZEIPs/issues/31). This package implements the stake-based liquidity incentives defined by [ZEIP-31](https://github.com/0xProject/ZEIPs/issues/31).
Functionality: Functionality:
1. Stake your ZRX tokens to unlock their utility within the 0x ecosystem.
- Earn rebates on market making on the 0x protocol
- Participate in governance over the 0x protocol
2. Create staking pools to leverage the weight of other stakers.
- Increase your market making rebates.
- Increase your voting power.
3. Delegate your Zrx to staking pools to
- Earn a portion of the pool's market making rebates.
- Support a pool's mission sharing your voting power.
1. Stake your ZRX tokens to unlock their utility within the 0x ecosystem.
- Earn rebates on market making on the 0x protocol
- Participate in governance over the 0x protocol
2. Create staking pools to leverage the weight of other stakers.
- Increase your market making rebates.
- Increase your voting power.
3. Delegate your Zrx to staking pools to
- Earn a portion of the pool's market making rebates.
- Support a pool's mission sharing your voting power.
## Architecture ## Architecture
This system is composed of four deployed contracts: This system is composed of four deployed contracts:
1. Staking Contract, which is an upgradeable/stateless contract that implements staking logic. 1. Staking Contract, which is an upgradeable/stateless contract that implements staking logic.
2. Staking Contract Proxy, which stores staking state and delegates to the Staking Contract. 2. Staking Contract Proxy, which stores staking state and delegates to the Staking Contract.
3. Zrx Vault, which securely holds staked Zrx Tokens. 3. Zrx Vault, which securely holds staked Zrx Tokens.
@ -27,19 +28,21 @@ These contracts connect to each other and the broader 0x ecosystem like this:
![](images/architecture.png) ![](images/architecture.png)
## Architecture (Catastrophic Failure Mode) ## Architecture (Catastrophic Failure Mode)
If a vulnerability is discovered in the staking contract.
1. The 0x Exchange contract stops charging protocol fees
2. The staking contract is set to read-only mode (clients may still query balances)
3. Vaults are detached from the staking contract
4. Users may withdraw their assets directly from vaults
5. If state is corrupted, the staking storage is detached from the logic contract and a new storage contract is deployed
Steps 1-3 are triggered immediately upon discovering a potential failure. Steps 4-5 are triggered if the internal staking state has been corrupted; in this worst-case scenario, the staking contract must be re-deployed — users withdraw their funds from the vaults and re-stake under a new staking contract. If a vulnerability is discovered in the staking contract.
1. The 0x Exchange contract stops charging protocol fees
2. The staking contract is set to read-only mode (clients may still query balances)
3. Vaults are detached from the staking contract
4. Users may withdraw their assets directly from vaults
5. If state is corrupted, the staking storage is detached from the logic contract and a new storage contract is deployed
Steps 1-3 are triggered immediately upon discovering a potential failure. Steps 4-5 are triggered if the internal staking state has been corrupted; in this worst-case scenario, the staking contract must be re-deployed — users withdraw their funds from the vaults and re-stake under a new staking contract.
![](images/architecture_failure_mode.png) ![](images/architecture_failure_mode.png)
## Contracts Directory Structure ## Contracts Directory Structure
The contracts can be found in `contracts/src`. The contracts can be found in `contracts/src`.
``` ```
@ -59,7 +62,6 @@ The contracts can be found in `contracts/src`.
These contracts use an actor/simulation pattern. A simulation runs with a specified set of actors, initial state and expected output. Actors have a specific role and validate each call they make to the staking system; for example, there is a Staking Actor who stakes/unstakes their Zrx tokens and validates balances/events. Similarly, there could exist an actor who tries to steal funds. These contracts use an actor/simulation pattern. A simulation runs with a specified set of actors, initial state and expected output. Actors have a specific role and validate each call they make to the staking system; for example, there is a Staking Actor who stakes/unstakes their Zrx tokens and validates balances/events. Similarly, there could exist an actor who tries to steal funds.
## Installation ## Installation
**Install** **Install**

View File

@ -1,6 +1,4 @@
import { import { expectTransactionFailedAsync } from '@0x/contracts-test-utils';
expectTransactionFailedAsync,
} from '@0x/contracts-test-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -26,7 +24,11 @@ export class DelegatorActor extends StakerActor {
const initZrxBalanceOfVault = await this._stakingWrapper.getZrxTokenBalanceOfZrxVaultAsync(); const initZrxBalanceOfVault = await this._stakingWrapper.getZrxTokenBalanceOfZrxVaultAsync();
const initDelegatorBalances = await this.getBalancesAsync([poolId]); const initDelegatorBalances = await this.getBalancesAsync([poolId]);
// deposit stake // deposit stake
const txReceiptPromise = this._stakingWrapper.depositZrxAndDelegateToStakingPoolAsync(this._owner, poolId, amount); const txReceiptPromise = this._stakingWrapper.depositZrxAndDelegateToStakingPoolAsync(
this._owner,
poolId,
amount,
);
if (revertReason !== undefined) { if (revertReason !== undefined) {
await expectTransactionFailedAsync(txReceiptPromise, revertReason); await expectTransactionFailedAsync(txReceiptPromise, revertReason);
return; return;

View File

@ -1,6 +1,4 @@
import { import { expectTransactionFailedAsync } from '@0x/contracts-test-utils';
expectTransactionFailedAsync,
} from '@0x/contracts-test-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import * as chai from 'chai'; import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -62,7 +60,11 @@ export class PoolOperatorActor extends BaseActor {
revertReason?: RevertReason, revertReason?: RevertReason,
): Promise<void> { ): Promise<void> {
// remove maker // remove maker
const txReceiptPromise = this._stakingWrapper.removeMakerFromStakingPoolAsync(poolId, makerAddress, this._owner); const txReceiptPromise = this._stakingWrapper.removeMakerFromStakingPoolAsync(
poolId,
makerAddress,
this._owner,
);
if (revertReason !== undefined) { if (revertReason !== undefined) {
await expectTransactionFailedAsync(txReceiptPromise, revertReason); await expectTransactionFailedAsync(txReceiptPromise, revertReason);
return; return;

View File

@ -1,6 +1,4 @@
import { import { expectTransactionFailedAsync } from '@0x/contracts-test-utils';
expectTransactionFailedAsync,
} from '@0x/contracts-test-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -81,7 +79,10 @@ export class StakerActor extends BaseActor {
expectedStakerBalances.deactivatedStakeBalance = initStakerBalances.deactivatedStakeBalance.plus(amount); expectedStakerBalances.deactivatedStakeBalance = initStakerBalances.deactivatedStakeBalance.plus(amount);
await this.assertBalancesAsync(expectedStakerBalances); await this.assertBalancesAsync(expectedStakerBalances);
} }
public async burnDeactivatedStakeAndWithdrawZrxAsync(amount: BigNumber, revertReason?: RevertReason): Promise<void> { public async burnDeactivatedStakeAndWithdrawZrxAsync(
amount: BigNumber,
revertReason?: RevertReason,
): Promise<void> {
// query init balances // query init balances
const initZrxBalanceOfVault = await this._stakingWrapper.getZrxTokenBalanceOfZrxVaultAsync(); const initZrxBalanceOfVault = await this._stakingWrapper.getZrxTokenBalanceOfZrxVaultAsync();
const initStakerBalances = await this.getBalancesAsync(); const initStakerBalances = await this.getBalancesAsync();

View File

@ -1,10 +1,6 @@
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy'; import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { import { chaiSetup, provider, web3Wrapper } from '@0x/contracts-test-utils';
chaiSetup,
provider,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';

View File

@ -1,11 +1,6 @@
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy'; import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { import { chaiSetup, expectTransactionFailedAsync, provider, web3Wrapper } from '@0x/contracts-test-utils';
chaiSetup,
expectTransactionFailedAsync,
provider,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';

View File

@ -1,10 +1,6 @@
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy'; import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { import { chaiSetup, provider, web3Wrapper } from '@0x/contracts-test-utils';
chaiSetup,
provider,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';

View File

@ -1,11 +1,6 @@
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy'; import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { import { chaiSetup, expectTransactionFailedAsync, provider, web3Wrapper } from '@0x/contracts-test-utils';
chaiSetup,
expectTransactionFailedAsync,
provider,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
@ -151,7 +146,11 @@ describe('Staking Pool Management', () => {
const poolId = await poolOperator.createStakingPoolAsync(operatorShare); const poolId = await poolOperator.createStakingPoolAsync(operatorShare);
expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID);
// remove non-existent maker from pool // remove non-existent maker from pool
await poolOperator.removeMakerFromStakingPoolAsync(poolId, makerAddress, RevertReason.MakerAddressNotRegistered); await poolOperator.removeMakerFromStakingPoolAsync(
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 // test parameters
@ -238,7 +237,12 @@ describe('Staking Pool Management', () => {
// add maker to pool // add maker to pool
const makerApproval = maker.signApprovalForStakingPool(poolId); const makerApproval = maker.signApprovalForStakingPool(poolId);
await expectTransactionFailedAsync( await expectTransactionFailedAsync(
stakingWrapper.addMakerToStakingPoolAsync(poolId, makerAddress, makerApproval.signature, notOperatorAddress), stakingWrapper.addMakerToStakingPoolAsync(
poolId,
makerAddress,
makerApproval.signature,
notOperatorAddress,
),
RevertReason.OnlyCallableByPoolOperator, RevertReason.OnlyCallableByPoolOperator,
); );
}); });

View File

@ -1,11 +1,6 @@
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy'; import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { import { chaiSetup, expectTransactionFailedAsync, provider, web3Wrapper } from '@0x/contracts-test-utils';
chaiSetup,
expectTransactionFailedAsync,
provider,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';

View File

@ -1,10 +1,6 @@
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy'; import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { import { chaiSetup, provider, web3Wrapper } from '@0x/contracts-test-utils';
chaiSetup,
provider,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';

View File

@ -59,7 +59,9 @@ export class Simulation {
// @TODO cleanup state and verify the staking contract is empty // @TODO cleanup state and verify the staking contract is empty
} }
private async _withdrawRewardForStakingPoolMemberForDelegatorsByUndelegatingAsync(p: SimulationParams): Promise<void> { private async _withdrawRewardForStakingPoolMemberForDelegatorsByUndelegatingAsync(
p: SimulationParams,
): Promise<void> {
let delegatorIdx = 0; let delegatorIdx = 0;
let poolIdx = 0; let poolIdx = 0;
for (const numberOfDelegatorsInPool of p.numberOfDelegatorsPerPool) { for (const numberOfDelegatorsInPool of p.numberOfDelegatorsPerPool) {
@ -73,10 +75,7 @@ export class Simulation {
await delegator.deactivateAndTimelockDelegatedStakeAsync(poolId, amountOfStakeDelegated); await delegator.deactivateAndTimelockDelegatedStakeAsync(poolId, amountOfStakeDelegated);
const finalEthBalance = await this._stakingWrapper.getEthBalanceAsync(delegatorAddress); const finalEthBalance = await this._stakingWrapper.getEthBalanceAsync(delegatorAddress);
const reward = finalEthBalance.minus(initEthBalance); const reward = finalEthBalance.minus(initEthBalance);
const rewardTrimmed = StakingWrapper.trimFloat( const rewardTrimmed = StakingWrapper.trimFloat(StakingWrapper.toFloatingPoint(reward, 18), 5);
StakingWrapper.toFloatingPoint(reward, 18),
5,
);
const expectedReward = p.expectedPayoutByDelegator[delegatorIdx]; const expectedReward = p.expectedPayoutByDelegator[delegatorIdx];
expect( expect(
rewardTrimmed, rewardTrimmed,
@ -101,10 +100,7 @@ export class Simulation {
await this._stakingWrapper.withdrawTotalRewardForStakingPoolMemberAsync(poolId, delegatorAddress); await this._stakingWrapper.withdrawTotalRewardForStakingPoolMemberAsync(poolId, delegatorAddress);
const finalEthBalance = await this._stakingWrapper.getEthBalanceAsync(delegatorAddress); const finalEthBalance = await this._stakingWrapper.getEthBalanceAsync(delegatorAddress);
const reward = finalEthBalance.minus(initEthBalance); const reward = finalEthBalance.minus(initEthBalance);
const rewardTrimmed = StakingWrapper.trimFloat( const rewardTrimmed = StakingWrapper.trimFloat(StakingWrapper.toFloatingPoint(reward, 18), 5);
StakingWrapper.toFloatingPoint(reward, 18),
5,
);
const expectedReward = p.expectedPayoutByDelegator[delegatorIdx]; const expectedReward = p.expectedPayoutByDelegator[delegatorIdx];
expect( expect(
rewardTrimmed, rewardTrimmed,
@ -228,7 +224,9 @@ export class Simulation {
`expected balance in vault for pool with id ${poolId}`, `expected balance in vault for pool with id ${poolId}`,
).to.be.bignumber.equal(expectedRewardBalance); ).to.be.bignumber.equal(expectedRewardBalance);
// check operator's balance // check operator's balance
const poolOperatorVaultBalance = await this._stakingWrapper.getRewardBalanceOfStakingPoolOperatorAsync(poolId); const poolOperatorVaultBalance = await this._stakingWrapper.getRewardBalanceOfStakingPoolOperatorAsync(
poolId,
);
const poolOperatorVaultBalanceTrimmed = StakingWrapper.trimFloat( const poolOperatorVaultBalanceTrimmed = StakingWrapper.trimFloat(
StakingWrapper.toFloatingPoint(poolOperatorVaultBalance, 18), StakingWrapper.toFloatingPoint(poolOperatorVaultBalance, 18),
5, 5,

View File

@ -117,7 +117,7 @@ export class StakingWrapper {
); );
// configure erc20 proxy to accept calls from zrx vault // configure erc20 proxy to accept calls from zrx vault
await this._erc20ProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync( await this._erc20ProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync(
(this._zrxVaultContractIfExists).address, this._zrxVaultContractIfExists.address,
); );
// deploy staking contract // deploy staking contract
this._stakingContractIfExists = await StakingContract.deployFrom0xArtifactAsync( this._stakingContractIfExists = await StakingContract.deployFrom0xArtifactAsync(
@ -130,39 +130,35 @@ export class StakingWrapper {
artifacts.StakingProxy, artifacts.StakingProxy,
this._provider, this._provider,
txDefaults, txDefaults,
(this._stakingContractIfExists).address, this._stakingContractIfExists.address,
); );
// set staking proxy contract in zrx vault // set staking proxy contract in zrx vault
await (this await this._zrxVaultContractIfExists.setStakingContract.awaitTransactionSuccessAsync(
._zrxVaultContractIfExists).setStakingContract.awaitTransactionSuccessAsync( this._stakingProxyContractIfExists.address,
(this._stakingProxyContractIfExists).address,
); );
// set zrx vault in staking contract // set zrx vault in staking contract
const setZrxVaultCalldata = (this const setZrxVaultCalldata = this._stakingContractIfExists.setZrxVault.getABIEncodedTransactionData(
._stakingContractIfExists).setZrxVault.getABIEncodedTransactionData( this._zrxVaultContractIfExists.address,
(this._zrxVaultContractIfExists).address,
); );
const setZrxVaultTxData = { const setZrxVaultTxData = {
from: this._ownerAddress, from: this._ownerAddress,
to: (this._stakingProxyContractIfExists).address, to: this._stakingProxyContractIfExists.address,
data: setZrxVaultCalldata, data: setZrxVaultCalldata,
}; };
await this._web3Wrapper.awaitTransactionSuccessAsync( await this._web3Wrapper.awaitTransactionSuccessAsync(
await this._web3Wrapper.sendTransactionAsync(setZrxVaultTxData), await this._web3Wrapper.sendTransactionAsync(setZrxVaultTxData),
); );
// set staking proxy contract in reward vault // set staking proxy contract in reward vault
await (this await this._rewardVaultContractIfExists.setStakingContract.awaitTransactionSuccessAsync(
._rewardVaultContractIfExists).setStakingContract.awaitTransactionSuccessAsync( this._stakingProxyContractIfExists.address,
(this._stakingProxyContractIfExists).address,
); );
// set reward vault in staking contract // set reward vault in staking contract
const setStakingPoolRewardVaultCalldata = (this const setStakingPoolRewardVaultCalldata = this._stakingContractIfExists.setStakingPoolRewardVault.getABIEncodedTransactionData(
._stakingContractIfExists).setStakingPoolRewardVault.getABIEncodedTransactionData( this._rewardVaultContractIfExists.address,
(this._rewardVaultContractIfExists).address,
); );
const setStakingPoolRewardVaultTxData = { const setStakingPoolRewardVaultTxData = {
from: this._ownerAddress, from: this._ownerAddress,
to: (this._stakingProxyContractIfExists).address, to: this._stakingProxyContractIfExists.address,
data: setStakingPoolRewardVaultCalldata, data: setStakingPoolRewardVaultCalldata,
}; };
await this._web3Wrapper.awaitTransactionSuccessAsync( await this._web3Wrapper.awaitTransactionSuccessAsync(
@ -180,12 +176,20 @@ export class StakingWrapper {
return balance; return balance;
} }
///// STAKE ///// ///// STAKE /////
public async depositZrxAndMintDeactivatedStakeAsync(owner: string, amount: BigNumber): Promise<TransactionReceiptWithDecodedLogs> { public async depositZrxAndMintDeactivatedStakeAsync(
const calldata = this.getStakingContract().depositZrxAndMintDeactivatedStake.getABIEncodedTransactionData(amount); owner: string,
amount: BigNumber,
): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().depositZrxAndMintDeactivatedStake.getABIEncodedTransactionData(
amount,
);
const txReceipt = await this._executeTransactionAsync(calldata, owner); const txReceipt = await this._executeTransactionAsync(calldata, owner);
return txReceipt; return txReceipt;
} }
public async depositZrxAndMintActivatedStakeAsync(owner: string, amount: BigNumber): Promise<TransactionReceiptWithDecodedLogs> { public async depositZrxAndMintActivatedStakeAsync(
owner: string,
amount: BigNumber,
): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().depositZrxAndMintActivatedStake.getABIEncodedTransactionData(amount); const calldata = this.getStakingContract().depositZrxAndMintActivatedStake.getABIEncodedTransactionData(amount);
const txReceipt = await this._executeTransactionAsync(calldata, owner); const txReceipt = await this._executeTransactionAsync(calldata, owner);
return txReceipt; return txReceipt;
@ -195,7 +199,10 @@ export class StakingWrapper {
poolId: string, poolId: string,
amount: BigNumber, amount: BigNumber,
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().depositZrxAndDelegateToStakingPool.getABIEncodedTransactionData(poolId, amount); const calldata = this.getStakingContract().depositZrxAndDelegateToStakingPool.getABIEncodedTransactionData(
poolId,
amount,
);
const txReceipt = await this._executeTransactionAsync(calldata, owner, new BigNumber(0), true); const txReceipt = await this._executeTransactionAsync(calldata, owner, new BigNumber(0), true);
return txReceipt; return txReceipt;
} }
@ -236,8 +243,13 @@ export class StakingWrapper {
const txReceipt = await this._executeTransactionAsync(calldata, owner, new BigNumber(0), true); const txReceipt = await this._executeTransactionAsync(calldata, owner, new BigNumber(0), true);
return txReceipt; return txReceipt;
} }
public async burnDeactivatedStakeAndWithdrawZrxAsync(owner: string, amount: BigNumber): Promise<TransactionReceiptWithDecodedLogs> { public async burnDeactivatedStakeAndWithdrawZrxAsync(
const calldata = this.getStakingContract().burnDeactivatedStakeAndWithdrawZrx.getABIEncodedTransactionData(amount); owner: string,
amount: BigNumber,
): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().burnDeactivatedStakeAndWithdrawZrx.getABIEncodedTransactionData(
amount,
);
const txReceipt = await this._executeTransactionAsync(calldata, owner); const txReceipt = await this._executeTransactionAsync(calldata, owner);
return txReceipt; return txReceipt;
} }
@ -408,9 +420,7 @@ export class StakingWrapper {
public async goToNextEpochAsync(): Promise<TransactionReceiptWithDecodedLogs> { public async goToNextEpochAsync(): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().finalizeFees.getABIEncodedTransactionData(); const calldata = this.getStakingContract().finalizeFees.getABIEncodedTransactionData();
const txReceipt = await this._executeTransactionAsync(calldata, undefined, new BigNumber(0), true); const txReceipt = await this._executeTransactionAsync(calldata, undefined, new BigNumber(0), true);
logUtils.log( logUtils.log(`Finalization costed ${txReceipt.gasUsed} gas`);
`Finalization costed ${txReceipt.gasUsed} gas`,
);
return txReceipt; return txReceipt;
} }
public async skipToNextEpochAsync(): Promise<TransactionReceiptWithDecodedLogs> { public async skipToNextEpochAsync(): Promise<TransactionReceiptWithDecodedLogs> {
@ -461,7 +471,9 @@ export class StakingWrapper {
public async getCurrentEpochEarliestEndTimeInSecondsAsync(): Promise<BigNumber> { public async getCurrentEpochEarliestEndTimeInSecondsAsync(): Promise<BigNumber> {
const calldata = this.getStakingContract().getCurrentEpochEarliestEndTimeInSeconds.getABIEncodedTransactionData(); const calldata = this.getStakingContract().getCurrentEpochEarliestEndTimeInSeconds.getABIEncodedTransactionData();
const returnData = await this._callAsync(calldata); const returnData = await this._callAsync(calldata);
const value = this.getStakingContract().getCurrentEpochEarliestEndTimeInSeconds.getABIDecodedReturnData(returnData); const value = this.getStakingContract().getCurrentEpochEarliestEndTimeInSeconds.getABIDecodedReturnData(
returnData,
);
return value; return value;
} }
public async getCurrentTimelockPeriodEndEpochAsync(): Promise<BigNumber> { public async getCurrentTimelockPeriodEndEpochAsync(): Promise<BigNumber> {
@ -511,13 +523,19 @@ export class StakingWrapper {
const isValid = this.getStakingContract().isValidExchangeAddress.getABIDecodedReturnData(returnData); const isValid = this.getStakingContract().isValidExchangeAddress.getABIDecodedReturnData(returnData);
return isValid; return isValid;
} }
public async addExchangeAddressAsync(exchangeAddress: string, ownerAddressIfExists?: string): Promise<TransactionReceiptWithDecodedLogs> { public async addExchangeAddressAsync(
exchangeAddress: string,
ownerAddressIfExists?: string,
): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().addExchangeAddress.getABIEncodedTransactionData(exchangeAddress); const calldata = this.getStakingContract().addExchangeAddress.getABIEncodedTransactionData(exchangeAddress);
const ownerAddress = ownerAddressIfExists !== undefined ? ownerAddressIfExists : this._ownerAddress; const ownerAddress = ownerAddressIfExists !== undefined ? ownerAddressIfExists : this._ownerAddress;
const txReceipt = await this._executeTransactionAsync(calldata, ownerAddress); const txReceipt = await this._executeTransactionAsync(calldata, ownerAddress);
return txReceipt; return txReceipt;
} }
public async removeExchangeAddressAsync(exchangeAddress: string, ownerAddressIfExists?: string): Promise<TransactionReceiptWithDecodedLogs> { public async removeExchangeAddressAsync(
exchangeAddress: string,
ownerAddressIfExists?: string,
): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().removeExchangeAddress.getABIEncodedTransactionData(exchangeAddress); const calldata = this.getStakingContract().removeExchangeAddress.getABIEncodedTransactionData(exchangeAddress);
const ownerAddress = ownerAddressIfExists !== undefined ? ownerAddressIfExists : this._ownerAddress; const ownerAddress = ownerAddressIfExists !== undefined ? ownerAddressIfExists : this._ownerAddress;
const txReceipt = await this._executeTransactionAsync(calldata, ownerAddress); const txReceipt = await this._executeTransactionAsync(calldata, ownerAddress);
@ -525,31 +543,48 @@ export class StakingWrapper {
} }
///// REWARDS ///// ///// REWARDS /////
public async getTotalRewardBalanceOfStakingPoolAsync(poolId: string): Promise<BigNumber> { public async getTotalRewardBalanceOfStakingPoolAsync(poolId: string): Promise<BigNumber> {
const calldata = this.getStakingContract().getTotalRewardBalanceOfStakingPool.getABIEncodedTransactionData(poolId); const calldata = this.getStakingContract().getTotalRewardBalanceOfStakingPool.getABIEncodedTransactionData(
poolId,
);
const returnData = await this._callAsync(calldata); const returnData = await this._callAsync(calldata);
const value = this.getStakingContract().getTotalRewardBalanceOfStakingPool.getABIDecodedReturnData(returnData); const value = this.getStakingContract().getTotalRewardBalanceOfStakingPool.getABIDecodedReturnData(returnData);
return value; return value;
} }
public async getRewardBalanceOfStakingPoolOperatorAsync(poolId: string): Promise<BigNumber> { public async getRewardBalanceOfStakingPoolOperatorAsync(poolId: string): Promise<BigNumber> {
const calldata = this.getStakingContract().getRewardBalanceOfStakingPoolOperator.getABIEncodedTransactionData(poolId); const calldata = this.getStakingContract().getRewardBalanceOfStakingPoolOperator.getABIEncodedTransactionData(
poolId,
);
const returnData = await this._callAsync(calldata); const returnData = await this._callAsync(calldata);
const value = this.getStakingContract().getRewardBalanceOfStakingPoolOperator.getABIDecodedReturnData(returnData); const value = this.getStakingContract().getRewardBalanceOfStakingPoolOperator.getABIDecodedReturnData(
returnData,
);
return value; return value;
} }
public async getRewardBalanceOfStakingPoolMembersAsync(poolId: string): Promise<BigNumber> { public async getRewardBalanceOfStakingPoolMembersAsync(poolId: string): Promise<BigNumber> {
const calldata = this.getStakingContract().getRewardBalanceOfStakingPoolMembers.getABIEncodedTransactionData(poolId); const calldata = this.getStakingContract().getRewardBalanceOfStakingPoolMembers.getABIEncodedTransactionData(
poolId,
);
const returnData = await this._callAsync(calldata); const returnData = await this._callAsync(calldata);
const value = this.getStakingContract().getRewardBalanceOfStakingPoolMembers.getABIDecodedReturnData(returnData); const value = this.getStakingContract().getRewardBalanceOfStakingPoolMembers.getABIDecodedReturnData(
returnData,
);
return value; return value;
} }
public async computeRewardBalanceOfStakingPoolMemberAsync(poolId: string, owner: string): Promise<BigNumber> { public async computeRewardBalanceOfStakingPoolMemberAsync(poolId: string, owner: string): Promise<BigNumber> {
const calldata = this.getStakingContract().computeRewardBalanceOfStakingPoolMember.getABIEncodedTransactionData(poolId, owner); const calldata = this.getStakingContract().computeRewardBalanceOfStakingPoolMember.getABIEncodedTransactionData(
poolId,
owner,
);
const returnData = await this._callAsync(calldata); const returnData = await this._callAsync(calldata);
const value = this.getStakingContract().computeRewardBalanceOfStakingPoolMember.getABIDecodedReturnData(returnData); const value = this.getStakingContract().computeRewardBalanceOfStakingPoolMember.getABIDecodedReturnData(
returnData,
);
return value; return value;
} }
public async getTotalShadowBalanceOfStakingPoolAsync(poolId: string): Promise<BigNumber> { public async getTotalShadowBalanceOfStakingPoolAsync(poolId: string): Promise<BigNumber> {
const calldata = this.getStakingContract().getTotalShadowBalanceOfStakingPool.getABIEncodedTransactionData(poolId); const calldata = this.getStakingContract().getTotalShadowBalanceOfStakingPool.getABIEncodedTransactionData(
poolId,
);
const returnData = await this._callAsync(calldata); const returnData = await this._callAsync(calldata);
const value = this.getStakingContract().getTotalShadowBalanceOfStakingPool.getABIDecodedReturnData(returnData); const value = this.getStakingContract().getTotalShadowBalanceOfStakingPool.getABIDecodedReturnData(returnData);
return value; return value;
@ -568,7 +603,10 @@ export class StakingWrapper {
amount: BigNumber, amount: BigNumber,
operatorAddress: string, operatorAddress: string,
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().withdrawRewardForStakingPoolOperator.getABIEncodedTransactionData(poolId, amount); const calldata = this.getStakingContract().withdrawRewardForStakingPoolOperator.getABIEncodedTransactionData(
poolId,
amount,
);
const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress); const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress);
return txReceipt; return txReceipt;
} }
@ -577,7 +615,10 @@ export class StakingWrapper {
amount: BigNumber, amount: BigNumber,
owner: string, owner: string,
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().withdrawRewardForStakingPoolMember.getABIEncodedTransactionData(poolId, amount); const calldata = this.getStakingContract().withdrawRewardForStakingPoolMember.getABIEncodedTransactionData(
poolId,
amount,
);
const txReceipt = await this._executeTransactionAsync(calldata, owner); const txReceipt = await this._executeTransactionAsync(calldata, owner);
return txReceipt; return txReceipt;
} }
@ -585,12 +626,19 @@ export class StakingWrapper {
poolId: string, poolId: string,
operatorAddress: string, operatorAddress: string,
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().withdrawTotalRewardForStakingPoolOperator.getABIEncodedTransactionData(poolId); const calldata = this.getStakingContract().withdrawTotalRewardForStakingPoolOperator.getABIEncodedTransactionData(
poolId,
);
const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress); const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress);
return txReceipt; return txReceipt;
} }
public async withdrawTotalRewardForStakingPoolMemberAsync(poolId: string, owner: string): Promise<TransactionReceiptWithDecodedLogs> { public async withdrawTotalRewardForStakingPoolMemberAsync(
const calldata = this.getStakingContract().withdrawTotalRewardForStakingPoolMember.getABIEncodedTransactionData(poolId); poolId: string,
owner: string,
): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().withdrawTotalRewardForStakingPoolMember.getABIEncodedTransactionData(
poolId,
);
const txReceipt = await this._executeTransactionAsync(calldata, owner); const txReceipt = await this._executeTransactionAsync(calldata, owner);
return txReceipt; return txReceipt;
} }

View File

@ -1,11 +1,6 @@
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy'; import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { import { chaiSetup, expectTransactionFailedAsync, provider, web3Wrapper } from '@0x/contracts-test-utils';
chaiSetup,
expectTransactionFailedAsync,
provider,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';