771 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			771 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { ERC20ProxyContract } from '@0x/contracts-asset-proxy';
 | |
| import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
 | |
| import { constants as testUtilsConstants, LogDecoder, txDefaults } from '@0x/contracts-test-utils';
 | |
| import { assetDataUtils } from '@0x/order-utils';
 | |
| import { SignatureType } from '@0x/types';
 | |
| import { BigNumber, logUtils } from '@0x/utils';
 | |
| import { Web3Wrapper } from '@0x/web3-wrapper';
 | |
| import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
 | |
| import * as _ from 'lodash';
 | |
| 
 | |
| import {
 | |
|     artifacts,
 | |
|     LibFeeMathTestContract,
 | |
|     StakingPoolRewardVaultContract,
 | |
|     StakingContract,
 | |
|     StakingProxyContract,
 | |
|     ZrxVaultContract,
 | |
| } from '../../src';
 | |
| 
 | |
| import { ApprovalFactory } from './approval_factory';
 | |
| import { constants } from './constants';
 | |
| import { SignedStakingPoolApproval } from './types';
 | |
| 
 | |
| export class StakingWrapper {
 | |
|     private readonly _web3Wrapper: Web3Wrapper;
 | |
|     private readonly _provider: Provider;
 | |
|     private readonly _logDecoder: LogDecoder;
 | |
|     private readonly _ownerAddress: string;
 | |
|     private readonly _erc20ProxyContract: ERC20ProxyContract;
 | |
|     private readonly _zrxTokenContract: DummyERC20TokenContract;
 | |
|     private readonly _accounts: string[];
 | |
|     private _stakingContractIfExists?: StakingContract;
 | |
|     private _stakingProxyContractIfExists?: StakingProxyContract;
 | |
|     private _zrxVaultContractIfExists?: ZrxVaultContract;
 | |
|     private _rewardVaultContractIfExists?: StakingPoolRewardVaultContract;
 | |
|     private _LibFeeMathTestContractIfExists?: LibFeeMathTestContract;
 | |
|     public static toBaseUnitAmount(amount: BigNumber | number): BigNumber {
 | |
|         const decimals = 18;
 | |
|         const amountAsBigNumber = typeof amount === 'number' ? new BigNumber(amount) : amount;
 | |
|         const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amountAsBigNumber, decimals);
 | |
|         return baseUnitAmount;
 | |
|     }
 | |
|     public static toFixedPoint(amount: BigNumber | number, decimals: number): BigNumber {
 | |
|         const amountAsBigNumber = typeof amount === 'number' ? new BigNumber(amount) : amount;
 | |
|         const scalar = Math.pow(10, decimals);
 | |
|         const amountAsFixedPoint = amountAsBigNumber.times(scalar);
 | |
|         return amountAsFixedPoint;
 | |
|     }
 | |
|     public static toFloatingPoint(amount: BigNumber | number, decimals: number): BigNumber {
 | |
|         const amountAsBigNumber = typeof amount === 'number' ? new BigNumber(amount) : amount;
 | |
|         const scalar = Math.pow(10, decimals);
 | |
|         const amountAsFloatingPoint = amountAsBigNumber.dividedBy(scalar);
 | |
|         return amountAsFloatingPoint;
 | |
|     }
 | |
|     public static trimFloat(amount: BigNumber | number, decimals: number): BigNumber {
 | |
|         const amountAsBigNumber = typeof amount === 'number' ? new BigNumber(amount) : amount;
 | |
|         const scalar = Math.pow(10, decimals);
 | |
|         const amountAsFloatingPoint = amountAsBigNumber
 | |
|             .multipliedBy(scalar)
 | |
|             .dividedToIntegerBy(1)
 | |
|             .dividedBy(scalar);
 | |
|         return amountAsFloatingPoint;
 | |
|     }
 | |
| 
 | |
|     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._ownerAddress = ownerAddres;
 | |
|         this._erc20ProxyContract = erc20ProxyContract;
 | |
|         this._zrxTokenContract = zrxTokenContract;
 | |
|         this._accounts = accounts;
 | |
|     }
 | |
|     public getStakingContract(): StakingContract {
 | |
|         this._validateDeployedOrThrow();
 | |
|         return this._stakingContractIfExists as StakingContract;
 | |
|     }
 | |
|     public getStakingProxyContract(): StakingProxyContract {
 | |
|         this._validateDeployedOrThrow();
 | |
|         return this._stakingProxyContractIfExists as StakingProxyContract;
 | |
|     }
 | |
|     public getZrxVaultContract(): ZrxVaultContract {
 | |
|         this._validateDeployedOrThrow();
 | |
|         return this._zrxVaultContractIfExists as ZrxVaultContract;
 | |
|     }
 | |
|     public getStakingPoolRewardVaultContract(): StakingPoolRewardVaultContract {
 | |
|         this._validateDeployedOrThrow();
 | |
|         return this._rewardVaultContractIfExists as StakingPoolRewardVaultContract;
 | |
|     }
 | |
|     public getLibFeeMathTestContract(): LibFeeMathTestContract {
 | |
|         this._validateDeployedOrThrow();
 | |
|         return this._LibFeeMathTestContractIfExists as LibFeeMathTestContract;
 | |
|     }
 | |
|     public async deployAndConfigureContractsAsync(): Promise<void> {
 | |
|         // deploy zrx vault
 | |
|         const zrxAssetData = assetDataUtils.encodeERC20AssetData(this._zrxTokenContract.address);
 | |
|         this._zrxVaultContractIfExists = await ZrxVaultContract.deployFrom0xArtifactAsync(
 | |
|             artifacts.ZrxVault,
 | |
|             this._provider,
 | |
|             txDefaults,
 | |
|             this._erc20ProxyContract.address,
 | |
|             this._zrxTokenContract.address,
 | |
|             zrxAssetData,
 | |
|         );
 | |
|         // deploy reward vault
 | |
|         this._rewardVaultContractIfExists = await StakingPoolRewardVaultContract.deployFrom0xArtifactAsync(
 | |
|             artifacts.StakingPoolRewardVault,
 | |
|             this._provider,
 | |
|             txDefaults,
 | |
|         );
 | |
|         // configure erc20 proxy to accept calls from zrx vault
 | |
|         await this._erc20ProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync(
 | |
|             (this._zrxVaultContractIfExists).address,
 | |
|         );
 | |
|         // deploy staking contract
 | |
|         this._stakingContractIfExists = await StakingContract.deployFrom0xArtifactAsync(
 | |
|             artifacts.Staking,
 | |
|             this._provider,
 | |
|             txDefaults,
 | |
|         );
 | |
|         // deploy staking proxy
 | |
|         this._stakingProxyContractIfExists = await StakingProxyContract.deployFrom0xArtifactAsync(
 | |
|             artifacts.StakingProxy,
 | |
|             this._provider,
 | |
|             txDefaults,
 | |
|             (this._stakingContractIfExists).address,
 | |
|         );
 | |
|         // set staking proxy contract in zrx vault
 | |
|         await (this
 | |
|             ._zrxVaultContractIfExists).setStakingContractAddrsess.awaitTransactionSuccessAsync(
 | |
|             (this._stakingProxyContractIfExists).address,
 | |
|         );
 | |
|         // set zrx vault in staking contract
 | |
|         const setZrxVaultCalldata = (this
 | |
|             ._stakingContractIfExists).setZrxVault.getABIEncodedTransactionData(
 | |
|             (this._zrxVaultContractIfExists).address,
 | |
|         );
 | |
|         const setZrxVaultTxData = {
 | |
|             from: this._ownerAddress,
 | |
|             to: (this._stakingProxyContractIfExists).address,
 | |
|             data: setZrxVaultCalldata,
 | |
|         };
 | |
|         await this._web3Wrapper.awaitTransactionSuccessAsync(
 | |
|             await this._web3Wrapper.sendTransactionAsync(setZrxVaultTxData),
 | |
|         );
 | |
|         // set staking proxy contract in reward vault
 | |
|         await (this
 | |
|             ._rewardVaultContractIfExists).setStakingContractAddrsess.awaitTransactionSuccessAsync(
 | |
|             (this._stakingProxyContractIfExists).address,
 | |
|         );
 | |
|         // set reward vault in staking contract
 | |
|         const setStakingPoolRewardVaultCalldata = (this
 | |
|             ._stakingContractIfExists).setStakingPoolRewardVault.getABIEncodedTransactionData(
 | |
|             (this._rewardVaultContractIfExists).address,
 | |
|         );
 | |
|         const setStakingPoolRewardVaultTxData = {
 | |
|             from: this._ownerAddress,
 | |
|             to: (this._stakingProxyContractIfExists).address,
 | |
|             data: setStakingPoolRewardVaultCalldata,
 | |
|         };
 | |
|         await this._web3Wrapper.awaitTransactionSuccessAsync(
 | |
|             await this._web3Wrapper.sendTransactionAsync(setStakingPoolRewardVaultTxData),
 | |
|         );
 | |
|         // deploy libmath test
 | |
|         this._LibFeeMathTestContractIfExists = await LibFeeMathTestContract.deployFrom0xArtifactAsync(
 | |
|             artifacts.LibFeeMathTest,
 | |
|             this._provider,
 | |
|             txDefaults,
 | |
|         );
 | |
|     }
 | |
|     public async getEthBalanceAsync(owner: string): Promise<BigNumber> {
 | |
|         const balance = this._web3Wrapper.getBalanceInWeiAsync(owner);
 | |
|         return balance;
 | |
|     }
 | |
|     ///// STAKE /////
 | |
|     public async depositAsync(owner: string, amount: BigNumber): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().deposit.getABIEncodedTransactionData(amount);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, owner);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async depositAndStakeAsync(owner: string, amount: BigNumber): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().depositAndStake.getABIEncodedTransactionData(amount);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, owner);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async depositAndDelegateAsync(
 | |
|         owner: string,
 | |
|         poolId: string,
 | |
|         amount: BigNumber,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().depositAndDelegate.getABIEncodedTransactionData(poolId, amount);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, owner, new BigNumber(0), true);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async activateStakeAsync(owner: string, amount: BigNumber): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().activateStake.getABIEncodedTransactionData(amount);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, owner);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async activateAndDelegateStakeAsync(
 | |
|         owner: string,
 | |
|         poolId: string,
 | |
|         amount: BigNumber,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         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<TransactionReceiptWithDecodedLogs> {
 | |
|         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<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().deactivateAndTimelockDelegatedStake.getABIEncodedTransactionData(
 | |
|             poolId,
 | |
|             amount,
 | |
|         );
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, owner, new BigNumber(0), true);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async withdrawAsync(owner: string, amount: BigNumber): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().withdraw.getABIEncodedTransactionData(amount);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, owner);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async forceTimelockSyncAsync(owner: string): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().forceTimelockSync.getABIEncodedTransactionData(owner);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, this._ownerAddress);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     ///// STAKE BALANCES /////
 | |
|     public async getTotalStakeAsync(owner: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getTotalStake.getABIEncodedTransactionData(owner);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getTotalStake.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getActivatedStakeAsync(owner: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getActivatedStake.getABIEncodedTransactionData(owner);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getActivatedStake.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getDeactivatedStakeAsync(owner: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getDeactivatedStake.getABIEncodedTransactionData(owner);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getDeactivatedStake.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getActivatableStakeAsync(owner: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getActivatableStake.getABIEncodedTransactionData(owner);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getActivatableStake.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getWithdrawableStakeAsync(owner: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getWithdrawableStake.getABIEncodedTransactionData(owner);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getWithdrawableStake.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getTimelockedStakeAsync(owner: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getTimelockedStake.getABIEncodedTransactionData(owner);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getTimelockedStake.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getTimelockStartAsync(owner: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getTimelockStart.getABIEncodedTransactionData(owner);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getTimelockStart.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getStakeDelegatedByOwnerAsync(owner: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getStakeDelegatedByOwner.getABIEncodedTransactionData(owner);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getStakeDelegatedByOwner.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getStakeDelegatedToPoolByOwnerAsync(poolId: string, owner: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getStakeDelegatedToPoolByOwner.getABIEncodedTransactionData(
 | |
|             owner,
 | |
|             poolId,
 | |
|         );
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getStakeDelegatedToPoolByOwner.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getStakeDelegatedToPoolAsync(poolId: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getStakeDelegatedToPool.getABIEncodedTransactionData(poolId);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getStakeDelegatedToPool.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     ///// POOLS /////
 | |
|     public async getNextStakingPoolIdAsync(): Promise<string> {
 | |
|         const calldata = this.getStakingContract().getNextStakingPoolId.getABIEncodedTransactionData();
 | |
|         const nextPoolId = await this._callAsync(calldata);
 | |
|         return nextPoolId;
 | |
|     }
 | |
|     public async createStakingPoolAsync(operatorAddress: string, operatorShare: number): Promise<string> {
 | |
|         const calldata = this.getStakingContract().createStakingPool.getABIEncodedTransactionData(operatorShare);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress);
 | |
|         const createStakingPoolLog = this._logDecoder.decodeLogOrThrow(txReceipt.logs[0]);
 | |
|         const poolId = (createStakingPoolLog as any).args.poolId;
 | |
|         return poolId;
 | |
|     }
 | |
|     public async addMakerToStakingPoolAsync(
 | |
|         poolId: string,
 | |
|         makerAddress: string,
 | |
|         makerSignature: string,
 | |
|         operatorAddress: string,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().addMakerToStakingPool.getABIEncodedTransactionData(
 | |
|             poolId,
 | |
|             makerAddress,
 | |
|             makerSignature,
 | |
|         );
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async removeMakerFromStakingPoolAsync(
 | |
|         poolId: string,
 | |
|         makerAddress: string,
 | |
|         operatorAddress: string,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().removeMakerFromStakingPool.getABIEncodedTransactionData(
 | |
|             poolId,
 | |
|             makerAddress,
 | |
|         );
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async getStakingPoolIdOfMakerAsync(makerAddress: string): Promise<string> {
 | |
|         const calldata = this.getStakingContract().getStakingPoolIdOfMaker.getABIEncodedTransactionData(makerAddress);
 | |
|         const poolId = await this._callAsync(calldata);
 | |
|         return poolId;
 | |
|     }
 | |
|     public async getMakersForStakingPoolAsync(poolId: string): Promise<string[]> {
 | |
|         const calldata = this.getStakingContract().getMakersForStakingPool.getABIEncodedTransactionData(poolId);
 | |
|         const returndata = await this._callAsync(calldata);
 | |
|         const makerAddresses = this.getStakingContract().getMakersForStakingPool.getABIDecodedReturnData(returndata);
 | |
|         return makerAddresses;
 | |
|     }
 | |
|     public async isValidMakerSignatureAsync(
 | |
|         poolId: string,
 | |
|         makerAddress: string,
 | |
|         makerSignature: string,
 | |
|     ): Promise<boolean> {
 | |
|         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<string> {
 | |
|         const calldata = this.getStakingContract().getStakingPoolApprovalMessageHash.getABIEncodedTransactionData(
 | |
|             poolId,
 | |
|             makerAddress,
 | |
|         );
 | |
|         const returndata = await this._callAsync(calldata);
 | |
|         const messageHash = this.getStakingContract().getStakingPoolApprovalMessageHash.getABIDecodedReturnData(
 | |
|             returndata,
 | |
|         );
 | |
|         return messageHash;
 | |
|     }
 | |
|     public signApprovalForStakingPool(
 | |
|         poolId: string,
 | |
|         makerAddress: string,
 | |
|         makerPrivateKeyIfExists?: Buffer,
 | |
|         verifierAddressIfExists?: string,
 | |
|         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 chainId = chainIdIfExists !== undefined ? chainIdIfExists : constants.CHAIN_ID;
 | |
|         const approvalFactory = new ApprovalFactory(makerPrivateKey, verifierAddress, chainId);
 | |
|         const signedStakingPoolApproval = approvalFactory.newSignedApproval(poolId, makerAddress, signatureType);
 | |
|         return signedStakingPoolApproval;
 | |
|     }
 | |
|     ///// EPOCHS /////
 | |
|     public async goToNextEpochAsync(): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().finalizeFees.getABIEncodedTransactionData();
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, undefined, new BigNumber(0), true);
 | |
|         logUtils.log(
 | |
|             `Finalization costed ${txReceipt.gasUsed} gas`,
 | |
|         );
 | |
|         console.log(JSON.stringify(txReceipt.logs, null, 4));
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async skipToNextEpochAsync(): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         // increase timestamp of next block
 | |
|         const epochPeriodInSeconds = await this.getEpochPeriodInSecondsAsync();
 | |
|         await this._web3Wrapper.increaseTimeAsync(epochPeriodInSeconds.toNumber());
 | |
|         // mine next block
 | |
|         await this._web3Wrapper.mineBlockAsync();
 | |
|         // increment epoch in contracts
 | |
|         const txReceipt = await this.goToNextEpochAsync();
 | |
|         // mine next block
 | |
|         await this._web3Wrapper.mineBlockAsync();
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async skipToNextTimelockPeriodAsync(): Promise<void> {
 | |
|         const timelockEndEpoch = await this.getCurrentTimelockPeriodEndEpochAsync();
 | |
|         const currentEpoch = await this.getCurrentEpochAsync();
 | |
|         const nEpochsToJump = timelockEndEpoch.minus(currentEpoch);
 | |
|         const nEpochsToJumpAsNumber = nEpochsToJump.toNumber();
 | |
|         for (let i = 0; i < nEpochsToJumpAsNumber; ++i) {
 | |
|             await this.skipToNextEpochAsync();
 | |
|         }
 | |
|     }
 | |
|     public async getEpochPeriodInSecondsAsync(): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getEpochPeriodInSeconds.getABIEncodedTransactionData();
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getEpochPeriodInSeconds.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getTimelockPeriodInEpochsAsync(): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getTimelockPeriodInEpochs.getABIEncodedTransactionData();
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getTimelockPeriodInEpochs.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getCurrentEpochStartTimeInSecondsAsync(): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getCurrentEpochStartTimeInSeconds.getABIEncodedTransactionData();
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getCurrentEpochStartTimeInSeconds.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getCurrentTimelockPeriodStartEpochAsync(): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getCurrentTimelockPeriodStartEpoch.getABIEncodedTransactionData();
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getCurrentTimelockPeriodStartEpoch.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getCurrentEpochEarliestEndTimeInSecondsAsync(): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getCurrentEpochEarliestEndTimeInSeconds.getABIEncodedTransactionData();
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getCurrentEpochEarliestEndTimeInSeconds.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getCurrentTimelockPeriodEndEpochAsync(): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getCurrentTimelockPeriodEndEpoch.getABIEncodedTransactionData();
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getCurrentTimelockPeriodEndEpoch.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getCurrentEpochAsync(): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getCurrentEpoch.getABIEncodedTransactionData();
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getCurrentEpoch.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getCurrentTimelockPeriodAsync(): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getCurrentTimelockPeriod.getABIEncodedTransactionData();
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getCurrentTimelockPeriod.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     ///// PROTOCOL FEES /////
 | |
|     public async payProtocolFeeAsync(
 | |
|         makerAddress: string,
 | |
|         amount: BigNumber,
 | |
|         exchangeAddress: string,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().payProtocolFee.getABIEncodedTransactionData(makerAddress);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, exchangeAddress, amount);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async getProtocolFeesThisEpochByPoolAsync(poolId: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getProtocolFeesThisEpochByPool.getABIEncodedTransactionData(poolId);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getProtocolFeesThisEpochByPool.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getTotalProtocolFeesThisEpochAsync(): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getTotalProtocolFeesThisEpoch.getABIEncodedTransactionData();
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getTotalProtocolFeesThisEpoch.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     ///// EXCHANGES /////
 | |
|     public async isValidExchangeAddressAsync(exchangeAddress: string): Promise<boolean> {
 | |
|         const calldata = this.getStakingContract().isValidExchangeAddress.getABIEncodedTransactionData(exchangeAddress);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const isValid = this.getStakingContract().isValidExchangeAddress.getABIDecodedReturnData(returnData);
 | |
|         return isValid;
 | |
|     }
 | |
|     public async addExchangeAddressAsync(exchangeAddress: string, ownerAddressIfExists?: string): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().addExchangeAddress.getABIEncodedTransactionData(exchangeAddress);
 | |
|         const ownerAddress = ownerAddressIfExists !== undefined ? ownerAddressIfExists : this._ownerAddress;
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, ownerAddress);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async removeExchangeAddressAsync(exchangeAddress: string, ownerAddressIfExists?: string): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().removeExchangeAddress.getABIEncodedTransactionData(exchangeAddress);
 | |
|         const ownerAddress = ownerAddressIfExists !== undefined ? ownerAddressIfExists : this._ownerAddress;
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, ownerAddress);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     ///// REWARDS /////
 | |
|     public async getTotalRewardBalanceOfStakingPoolAsync(poolId: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getTotalRewardBalanceOfStakingPool.getABIEncodedTransactionData(poolId);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getTotalRewardBalanceOfStakingPool.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getRewardBalanceOfStakingPoolOperatorAsync(poolId: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getRewardBalanceOfStakingPoolOperator.getABIEncodedTransactionData(poolId);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getRewardBalanceOfStakingPoolOperator.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getRewardBalanceOfStakingPoolMembersAsync(poolId: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getRewardBalanceOfStakingPoolMembers.getABIEncodedTransactionData(poolId);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getRewardBalanceOfStakingPoolMembers.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async computeRewardBalanceOfStakingPoolMemberAsync(poolId: string, owner: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().computeRewardBalanceOfStakingPoolMember.getABIEncodedTransactionData(poolId, owner);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().computeRewardBalanceOfStakingPoolMember.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getTotalShadowBalanceOfStakingPoolAsync(poolId: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getTotalShadowBalanceOfStakingPool.getABIEncodedTransactionData(poolId);
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getTotalShadowBalanceOfStakingPool.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async getShadowBalanceOfStakingPoolMemberAsync(owner: string, poolId: string): Promise<BigNumber> {
 | |
|         const calldata = this.getStakingContract().getShadowBalanceOfStakingPoolMember.getABIEncodedTransactionData(
 | |
|             owner,
 | |
|             poolId,
 | |
|         );
 | |
|         const returnData = await this._callAsync(calldata);
 | |
|         const value = this.getStakingContract().getShadowBalanceOfStakingPoolMember.getABIDecodedReturnData(returnData);
 | |
|         return value;
 | |
|     }
 | |
|     public async withdrawRewardForStakingPoolOperatorAsync(
 | |
|         poolId: string,
 | |
|         amount: BigNumber,
 | |
|         operatorAddress: string,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().withdrawRewardForStakingPoolOperator.getABIEncodedTransactionData(poolId, amount);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async withdrawRewardForStakingPoolMemberAsync(
 | |
|         poolId: string,
 | |
|         amount: BigNumber,
 | |
|         owner: string,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().withdrawRewardForStakingPoolMember.getABIEncodedTransactionData(poolId, amount);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, owner);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async withdrawTotalRewardForStakingPoolOperatorAsync(
 | |
|         poolId: string,
 | |
|         operatorAddress: string,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().withdrawTotalRewardForStakingPoolOperator.getABIEncodedTransactionData(poolId);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, operatorAddress);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async withdrawTotalRewardForStakingPoolMemberAsync(poolId: string, owner: string): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingContract().withdrawTotalRewardForStakingPoolMember.getABIEncodedTransactionData(poolId);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, owner);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     ///// REWARD VAULT /////
 | |
|     public async rewardVaultDepositForAsync(
 | |
|         poolId: string,
 | |
|         amount: BigNumber,
 | |
|         stakingContractAddress: string,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingPoolRewardVaultContract().depositFor.getABIEncodedTransactionData(poolId);
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, stakingContractAddress, amount);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async rewardVaultEnterCatastrophicFailureModeAsync(
 | |
|         zeroExMultisigAddress: string,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingPoolRewardVaultContract().enterCatostrophicFailure.getABIEncodedTransactionData();
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, zeroExMultisigAddress);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     public async rewardVaultBalanceOfAsync(poolId: string): Promise<BigNumber> {
 | |
|         const balance = await this.getStakingPoolRewardVaultContract().balanceOf.callAsync(poolId);
 | |
|         return balance;
 | |
|     }
 | |
|     public async rewardVaultBalanceOfOperatorAsync(poolId: string): Promise<BigNumber> {
 | |
|         const balance = await this.getStakingPoolRewardVaultContract().balanceOfOperator.callAsync(poolId);
 | |
|         return balance;
 | |
|     }
 | |
|     public async rewardVaultBalanceOfMembersAsync(poolId: string): Promise<BigNumber> {
 | |
|         const balance = await this.getStakingPoolRewardVaultContract().balanceOfMembers.callAsync(poolId);
 | |
|         return balance;
 | |
|     }
 | |
|     public async rewardVaultRegisterPoolAsync(
 | |
|         poolId: string,
 | |
|         poolOperatorShare: number,
 | |
|         stakingContractAddress: string,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const calldata = this.getStakingPoolRewardVaultContract().registerStakingPool.getABIEncodedTransactionData(
 | |
|             poolId,
 | |
|             poolOperatorShare,
 | |
|         );
 | |
|         const txReceipt = await this._executeTransactionAsync(calldata, stakingContractAddress);
 | |
|         return txReceipt;
 | |
|     }
 | |
|     ///// ZRX VAULT /////
 | |
|     public async getZrxVaultBalanceAsync(holder: string): Promise<BigNumber> {
 | |
|         const balance = await this.getZrxVaultContract().balanceOf.callAsync(holder);
 | |
|         return balance;
 | |
|     }
 | |
|     public async getZrxTokenBalanceAsync(holder: string): Promise<BigNumber> {
 | |
|         const balance = await this._zrxTokenContract.balanceOf.callAsync(holder);
 | |
|         return balance;
 | |
|     }
 | |
|     public async getZrxTokenBalanceOfZrxVaultAsync(): Promise<BigNumber> {
 | |
|         const balance = await this._zrxTokenContract.balanceOf.callAsync(this.getZrxVaultContract().address);
 | |
|         return balance;
 | |
|     }
 | |
|     ///// MATH /////
 | |
|     public async nthRootAsync(value: BigNumber, n: BigNumber): Promise<BigNumber> {
 | |
|         // const txReceipt = await this.getLibFeeMathTestContract().nthRoot.await(value, n);
 | |
|         const output = await this.getLibFeeMathTestContract().nthRoot.callAsync(value, n);
 | |
|         return output;
 | |
|     }
 | |
|     public async nthRootFixedPointAsync(value: BigNumber, n: BigNumber): Promise<BigNumber> {
 | |
|         const output = await this.getLibFeeMathTestContract().nthRootFixedPoint.callAsync(value, n);
 | |
|         return output;
 | |
|     }
 | |
|     public async cobbDouglasAsync(
 | |
|         totalRewards: BigNumber,
 | |
|         ownerFees: BigNumber,
 | |
|         totalFees: BigNumber,
 | |
|         ownerStake: BigNumber,
 | |
|         totalStake: BigNumber,
 | |
|         alphaNumerator: BigNumber,
 | |
|         alphaDenominator: BigNumber,
 | |
|     ): Promise<BigNumber> {
 | |
|         const output = await this.getLibFeeMathTestContract().cobbDouglas.callAsync(
 | |
|             totalRewards,
 | |
|             ownerFees,
 | |
|             totalFees,
 | |
|             ownerStake,
 | |
|             totalStake,
 | |
|             alphaNumerator,
 | |
|             alphaDenominator,
 | |
|         );
 | |
|         return output;
 | |
|     }
 | |
|     public async cobbDouglasSimplifiedAsync(
 | |
|         totalRewards: BigNumber,
 | |
|         ownerFees: BigNumber,
 | |
|         totalFees: BigNumber,
 | |
|         ownerStake: BigNumber,
 | |
|         totalStake: BigNumber,
 | |
|         alphaDenominator: BigNumber,
 | |
|     ): Promise<BigNumber> {
 | |
|         await this.getLibFeeMathTestContract().cobbDouglasSimplifiedInverse.awaitTransactionSuccessAsync(
 | |
|             totalRewards,
 | |
|             ownerFees,
 | |
|             totalFees,
 | |
|             ownerStake,
 | |
|             totalStake,
 | |
|             alphaDenominator,
 | |
|         );
 | |
|         const output = await this.getLibFeeMathTestContract().cobbDouglasSimplified.callAsync(
 | |
|             totalRewards,
 | |
|             ownerFees,
 | |
|             totalFees,
 | |
|             ownerStake,
 | |
|             totalStake,
 | |
|             alphaDenominator,
 | |
|         );
 | |
|         return output;
 | |
|     }
 | |
|     public async cobbDouglasSimplifiedInverseAsync(
 | |
|         totalRewards: BigNumber,
 | |
|         ownerFees: BigNumber,
 | |
|         totalFees: BigNumber,
 | |
|         ownerStake: BigNumber,
 | |
|         totalStake: BigNumber,
 | |
|         alphaDenominator: BigNumber,
 | |
|     ): Promise<BigNumber> {
 | |
|         await this.getLibFeeMathTestContract().cobbDouglasSimplifiedInverse.awaitTransactionSuccessAsync(
 | |
|             totalRewards,
 | |
|             ownerFees,
 | |
|             totalFees,
 | |
|             ownerStake,
 | |
|             totalStake,
 | |
|             alphaDenominator,
 | |
|         );
 | |
|         const output = await this.getLibFeeMathTestContract().cobbDouglasSimplifiedInverse.callAsync(
 | |
|             totalRewards,
 | |
|             ownerFees,
 | |
|             totalFees,
 | |
|             ownerStake,
 | |
|             totalStake,
 | |
|             alphaDenominator,
 | |
|         );
 | |
|         return output;
 | |
|     }
 | |
|     private async _executeTransactionAsync(
 | |
|         calldata: string,
 | |
|         from?: string,
 | |
|         value?: BigNumber,
 | |
|         includeLogs?: boolean,
 | |
|     ): Promise<TransactionReceiptWithDecodedLogs> {
 | |
|         const txData = {
 | |
|             from: from ? from : this._ownerAddress,
 | |
|             to: this.getStakingProxyContract().address,
 | |
|             data: calldata,
 | |
|             gas: 3000000,
 | |
|             gasPrice: 0,
 | |
|             value,
 | |
|         };
 | |
|         const txHash = await this._web3Wrapper.sendTransactionAsync(txData);
 | |
|         const txReceipt = await (includeLogs
 | |
|             ? this._logDecoder.getTxWithDecodedLogsAsync(txHash)
 | |
|             : this._web3Wrapper.awaitTransactionSuccessAsync(txHash));
 | |
|         return txReceipt;
 | |
|     }
 | |
|     private async _callAsync(calldata: string, from?: string): Promise<any> {
 | |
|         const txData = {
 | |
|             from: from ? from : this._ownerAddress,
 | |
|             to: this.getStakingProxyContract().address,
 | |
|             data: calldata,
 | |
|             gas: 3000000,
 | |
|         };
 | |
|         const returnValue = await this._web3Wrapper.callAsync(txData);
 | |
|         return returnValue;
 | |
|     }
 | |
|     private _validateDeployedOrThrow(): void {
 | |
|         if (this._stakingContractIfExists === undefined) {
 | |
|             throw new Error('Staking contracts are not deployed. Call `deployStakingContracts`');
 | |
|         }
 | |
|     }
 | |
| }
 | |
| // tslint:disable-line:max-file-line-count
 |