Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
export async function scenarioAsync(): Promise {
await runMigrationsOnceIfRequiredAsync();
let txHash;
PrintUtils.printScenario('Create Staking Pool');
// account information, balances, general contract logs
const web3Wrapper = new Web3Wrapper(providerEngine);
const [maker, otherMaker] = await web3Wrapper.getAvailableAddressesAsync();
const contractWrappers = new ContractWrappers(providerEngine, { chainId: NETWORK_CONFIGS.chainId });
const zrxTokenAddress = contractWrappers.contractAddresses.zrxToken;
const printUtils = new PrintUtils(web3Wrapper, contractWrappers, { maker }, { ZRX: zrxTokenAddress });
// Staking Proxy is a delegate contract. We initialize a Staking Contract (ABI) pointing to the delegate proxy
// at stakingProxyContractAddress
const stakingContract = new StakingContract(contractWrappers.contractAddresses.stakingProxy, providerEngine, {
from: maker,
});
// A small share is kept for the operator, note 1,000,000 represents all rebates
// going to the operator
const operatorSharePpm = new BigNumber(900000); // 90 %
const stakingPoolReceipt = await stakingContract
.createStakingPool(operatorSharePpm, true)
.awaitTransactionSuccessAsync({
from: maker,
});
// A small share is kept for the operator, note 1,000,000 represents all rebates
// going to the operator
const operatorSharePpm = new BigNumber(900000); // 90 %
const stakingPoolReceipt = await stakingContract
.createStakingPool(operatorSharePpm, true)
.awaitTransactionSuccessAsync({
from: maker,
});
const createStakingPoolLog = stakingPoolReceipt.logs[0];
const poolId = (createStakingPoolLog as any).args.poolId;
await printUtils.awaitTransactionMinedSpinnerAsync(`Create Pool ${poolId}`, stakingPoolReceipt.transactionHash);
// Approve the ZRX token for Staking using the ERC20Proxy
const zrxTokenContract = new ERC20TokenContract(zrxTokenAddress, providerEngine, { from: maker });
await zrxTokenContract
.approve(contractWrappers.contractAddresses.erc20Proxy, UNLIMITED_ALLOWANCE_IN_BASE_UNITS)
.sendTransactionAsync();
// Stake 1000 ZRX
const stakeAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(100), DECIMALS);
// Transfer the ZRX to the Staking Contract
txHash = await stakingContract.stake(stakeAmount).sendTransactionAsync({ from: maker });
await printUtils.awaitTransactionMinedSpinnerAsync('Stake ZRX', txHash);
// Move the staked ZRX to delegate the Staking Pool
txHash = await stakingContract
.moveStake(
{ status: StakeStatus.Undelegated, poolId: NIL_POOL_ID },
{ status: StakeStatus.Delegated, poolId },
stakeAmount,
)
private async _fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues): Promise {
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const fromBlock = tradeHistoryStorage.getFillsLatestBlock(this._userAddressIfExists, this.networkId);
const blockRange: BlockRange = {
fromBlock,
toBlock: 'latest' as BlockParam,
};
const decodedLogs = await this._contractWrappers.exchange.getLogsAsync(
ExchangeEvents.Fill,
blockRange,
indexFilterValues,
);
for (const decodedLog of decodedLogs) {
if (!this._doesLogEventInvolveUser(decodedLog)) {
continue; // We aren't interested in the fill event
}
this._updateLatestFillsBlockIfNeeded(decodedLog.blockNumber);
const fill = await this._convertDecodedLogToFillAsync(decodedLog);
tradeHistoryStorage.addFillToUser(this._userAddressIfExists, this.networkId, fill);
}
}
private async _convertDecodedLogToFillAsync(decodedLog: LogWithDecodedArgs): Promise {
break;
}
case WETH9Events.Withdrawal: {
// Invalidate cache
const args = decodedLog.args as WETH9WithdrawalEventArgs;
const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address);
this._deleteLazyStoreBalance(tokenAssetData, args._owner);
// Revalidate orders
const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker(
args._owner,
tokenAssetData,
);
await this._emitRevalidateOrdersAsync(orderHashes, transactionHash);
break;
}
case ExchangeEvents.Fill: {
// Invalidate cache
const args = decodedLog.args as ExchangeFillEventArgs;
this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(args.orderHash);
// Revalidate orders
const orderHash = args.orderHash;
const isOrderWatched = this._orderByOrderHash[orderHash] !== undefined;
if (isOrderWatched) {
await this._emitRevalidateOrdersAsync([orderHash], transactionHash);
}
break;
}
case ExchangeEvents.Cancel: {
// Invalidate cache
const args = decodedLog.args as ExchangeCancelEventArgs;
this._orderFilledCancelledLazyStore.deleteIsCancelled(args.orderHash);
// Revalidate orders
private async _startListeningForExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues): Promise {
utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.');
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
// Fetch historical logs
await this._fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues);
// Start a subscription for new logs
this._contractWrappers.exchange.subscribe(
ExchangeEvents.Fill,
indexFilterValues,
async (err: Error, decodedLogEvent: DecodedLogEvent) => {
if (err) {
// Note: it's not entirely clear from the documentation which
// errors will be thrown by `watch`. For now, let's log the error
// to rollbar and stop watching when one occurs
errorReporter.report(err); // fire and forget
return;
} else {
const decodedLog = decodedLogEvent.log;
if (!this._doesLogEventInvolveUser(decodedLog)) {
return; // We aren't interested in the fill event
}
this._updateLatestFillsBlockIfNeeded(decodedLog.blockNumber);
const fill = await this._convertDecodedLogToFillAsync(decodedLog);
if (decodedLogEvent.isRemoved) {
await this._emitRevalidateOrdersAsync(orderHashes, transactionHash);
break;
}
case ExchangeEvents.Fill: {
// Invalidate cache
const args = decodedLog.args as ExchangeFillEventArgs;
this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(args.orderHash);
// Revalidate orders
const orderHash = args.orderHash;
const isOrderWatched = this._orderByOrderHash[orderHash] !== undefined;
if (isOrderWatched) {
await this._emitRevalidateOrdersAsync([orderHash], transactionHash);
}
break;
}
case ExchangeEvents.Cancel: {
// Invalidate cache
const args = decodedLog.args as ExchangeCancelEventArgs;
this._orderFilledCancelledLazyStore.deleteIsCancelled(args.orderHash);
// Revalidate orders
const orderHash = args.orderHash;
const isOrderWatched = this._orderByOrderHash[orderHash] !== undefined;
if (isOrderWatched) {
await this._emitRevalidateOrdersAsync([orderHash], transactionHash);
}
break;
}
case ExchangeEvents.CancelUpTo: {
// TODO(logvinov): Do it smarter and actually look at the salt and order epoch
// Invalidate cache
const args = decodedLog.args as ExchangeCancelUpToEventArgs;
this._orderFilledCancelledLazyStore.deleteAllIsCancelled();
(accOrders, order, index) => {
// get corresponding on-chain state for the order
const { orderInfo, traderInfo } = ordersAndTradersInfo[index];
// if the order IS NOT fillable, do not add anything to the accumulations and continue iterating
if (orderInfo.orderStatus !== OrderStatus.Fillable) {
return accOrders;
}
// if the order IS fillable, add the order and calculate the remaining fillable amount
const transferrableAssetAmount = BigNumber.min(traderInfo.makerAllowance, traderInfo.makerBalance);
const transferrableFeeAssetAmount = BigNumber.min(traderInfo.makerZrxAllowance, traderInfo.makerZrxBalance);
const remainingTakerAssetAmount = order.takerAssetAmount.minus(orderInfo.orderTakerAssetFilledAmount);
const remainingMakerAssetAmount = orderCalculationUtils.getMakerFillAmount(
order,
remainingTakerAssetAmount,
);
const remainingFillableCalculator = new RemainingFillableCalculator(
order.makerFee,
order.makerAssetAmount,
isMakerAssetZrxToken,
transferrableAssetAmount,
transferrableFeeAssetAmount,
(accOrders, order, index) => {
// get corresponding on-chain state for the order
const { orderInfo, traderInfo } = ordersAndTradersInfo[index];
// if the order IS NOT fillable, do not add anything to the accumulations and continue iterating
if (orderInfo.orderStatus !== OrderStatus.Fillable) {
return accOrders;
}
// if the order IS fillable, add the order and calculate the remaining fillable amount
const transferrableAssetAmount = BigNumber.min(traderInfo.makerAllowance, traderInfo.makerBalance);
const transferrableFeeAssetAmount = BigNumber.min(traderInfo.makerZrxAllowance, traderInfo.makerZrxBalance);
const remainingTakerAssetAmount = order.takerAssetAmount.minus(orderInfo.orderTakerAssetFilledAmount);
const remainingMakerAssetAmount = orderCalculationUtils.getMakerFillAmount(
order,
remainingTakerAssetAmount,
);
const remainingFillableCalculator = new RemainingFillableCalculator(
order.makerFee,
order.makerAssetAmount,
isMakerAssetZrxToken,
transferrableAssetAmount,
transferrableFeeAssetAmount,
(accOrders, order, index) => {
// get corresponding on-chain state for the order
const { orderInfo, traderInfo } = ordersAndTradersInfo[index];
// if the order IS NOT fillable, do not add anything to the accumulations and continue iterating
if (orderInfo.orderStatus !== OrderStatus.Fillable) {
return accOrders;
}
// if the order IS fillable, add the order and calculate the remaining fillable amount
const transferrableAssetAmount = BigNumber.min(traderInfo.makerAllowance, traderInfo.makerBalance);
const transferrableFeeAssetAmount = BigNumber.min(traderInfo.makerZrxAllowance, traderInfo.makerZrxBalance);
const remainingTakerAssetAmount = order.takerAssetAmount.minus(orderInfo.orderTakerAssetFilledAmount);
const remainingMakerAssetAmount = orderCalculationUtils.getMakerFillAmount(
order,
remainingTakerAssetAmount,
);
const remainingFillableCalculator = new RemainingFillableCalculator(
order.makerFee,
order.makerAssetAmount,
isMakerAssetZrxToken,
transferrableAssetAmount,
transferrableFeeAssetAmount,
}
break;
}
case ExchangeEvents.Cancel: {
// Invalidate cache
const args = decodedLog.args as ExchangeCancelEventArgs;
this._orderFilledCancelledLazyStore.deleteIsCancelled(args.orderHash);
// Revalidate orders
const orderHash = args.orderHash;
const isOrderWatched = this._orderByOrderHash[orderHash] !== undefined;
if (isOrderWatched) {
await this._emitRevalidateOrdersAsync([orderHash], transactionHash);
}
break;
}
case ExchangeEvents.CancelUpTo: {
// TODO(logvinov): Do it smarter and actually look at the salt and order epoch
// Invalidate cache
const args = decodedLog.args as ExchangeCancelUpToEventArgs;
this._orderFilledCancelledLazyStore.deleteAllIsCancelled();
// Revalidate orders
const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByMaker(args.makerAddress);
await this._emitRevalidateOrdersAsync(orderHashes, transactionHash);
break;
}
default:
throw errorUtils.spawnSwitchErr('decodedLog.event', decodedLog.event);
}
}
private async _emitRevalidateOrdersAsync(orderHashes: string[], transactionHash?: string): Promise {