forwarder test factory first pass (supports orders with no fees and percentage fees)
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
import { ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy';
|
||||
import { chaiSetup, constants, ERC20BalancesByOwner, web3Wrapper } from '@0x/contracts-test-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
|
||||
import { ForwarderWrapper } from './forwarder_wrapper';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
// TODO: move these somewhere?
|
||||
const enum OrderFee {
|
||||
NoFee,
|
||||
Percentage,
|
||||
Weth,
|
||||
}
|
||||
|
||||
interface ForwarderFillState {
|
||||
takerAssetFillAmount: BigNumber;
|
||||
makerAssetFillAmount: BigNumber;
|
||||
wethFees: BigNumber;
|
||||
percentageFees: BigNumber;
|
||||
maxOversoldWeth: BigNumber;
|
||||
maxOverboughtMakerAsset: BigNumber;
|
||||
}
|
||||
|
||||
function getFeeType(order: SignedOrder): OrderFee {
|
||||
if (order.takerFee.eq(new BigNumber(0))) {
|
||||
return OrderFee.NoFee;
|
||||
} else if (order.takerFeeAssetData === order.makerAssetData) {
|
||||
return OrderFee.Percentage;
|
||||
} else {
|
||||
return OrderFee.Weth;
|
||||
}
|
||||
}
|
||||
|
||||
export class ForwarderTestFactory {
|
||||
private readonly _forwarderWrapper: ForwarderWrapper;
|
||||
private readonly _erc20Wrapper: ERC20Wrapper;
|
||||
private readonly _forwarderAddress: string;
|
||||
private readonly _makerAddress: string;
|
||||
private readonly _takerAddress: string;
|
||||
private readonly _orderFeeRecipientAddress: string;
|
||||
private readonly _forwarderFeeRecipientAddress: string;
|
||||
private readonly _gasPrice: BigNumber;
|
||||
private readonly _wethAddress: string;
|
||||
|
||||
constructor(
|
||||
forwarderWrapper: ForwarderWrapper,
|
||||
erc20Wrapper: ERC20Wrapper,
|
||||
forwarderAddress: string,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
orderFeeRecipientAddress: string,
|
||||
forwarderFeeRecipientAddress: string,
|
||||
gasPrice: BigNumber,
|
||||
wethAddress: string,
|
||||
) {
|
||||
this._forwarderWrapper = forwarderWrapper;
|
||||
this._erc20Wrapper = erc20Wrapper;
|
||||
this._forwarderAddress = forwarderAddress;
|
||||
this._makerAddress = makerAddress;
|
||||
this._takerAddress = takerAddress;
|
||||
this._orderFeeRecipientAddress = orderFeeRecipientAddress;
|
||||
this._forwarderFeeRecipientAddress = forwarderFeeRecipientAddress;
|
||||
this._gasPrice = gasPrice;
|
||||
this._wethAddress = wethAddress;
|
||||
}
|
||||
|
||||
// TODO: different assets (ERC721), rounding, forwarder fees
|
||||
public async generateTestAsync(
|
||||
orders: SignedOrder[],
|
||||
makerAssetAddress: string,
|
||||
takerEthBalanceBefore: BigNumber,
|
||||
erc20Balances: ERC20BalancesByOwner,
|
||||
): Promise<void> {
|
||||
// Simulates filling all but the last order, which will be partially filled
|
||||
const expectedResults = orders
|
||||
.reduce(
|
||||
(prev: ForwarderFillState, order: SignedOrder, currentIndex: number) => {
|
||||
const current = { ...prev };
|
||||
const { makerAssetAmount, takerAssetAmount, takerFee } = currentIndex === (orders.length - 1) ?
|
||||
{
|
||||
makerAssetAmount: order.makerAssetAmount.dividedToIntegerBy(2),
|
||||
takerAssetAmount: order.takerAssetAmount.dividedToIntegerBy(2),
|
||||
takerFee: order.takerFee.dividedToIntegerBy(2),
|
||||
} : order;
|
||||
|
||||
current.takerAssetFillAmount = current.takerAssetFillAmount.plus(
|
||||
takerAssetAmount,
|
||||
);
|
||||
current.makerAssetFillAmount = current.makerAssetFillAmount.plus(
|
||||
makerAssetAmount,
|
||||
);
|
||||
|
||||
switch (getFeeType(order)) {
|
||||
case OrderFee.Percentage:
|
||||
current.percentageFees = current.percentageFees.plus(takerFee);
|
||||
break;
|
||||
case OrderFee.Weth:
|
||||
current.wethFees = current.wethFees.plus(takerFee);
|
||||
current.maxOversoldWeth = current.maxOversoldWeth.plus(new BigNumber(1));
|
||||
current.maxOverboughtMakerAsset = current.maxOversoldWeth
|
||||
.times(makerAssetAmount)
|
||||
.dividedToIntegerBy(takerAssetAmount);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return current;
|
||||
},
|
||||
{
|
||||
takerAssetFillAmount: new BigNumber(0),
|
||||
makerAssetFillAmount: new BigNumber(0),
|
||||
wethFees: new BigNumber(0),
|
||||
percentageFees: new BigNumber(0),
|
||||
maxOversoldWeth: new BigNumber(0),
|
||||
maxOverboughtMakerAsset: new BigNumber(0),
|
||||
},
|
||||
);
|
||||
|
||||
const ethValue = expectedResults.takerAssetFillAmount.plus(expectedResults.wethFees);
|
||||
const tx = await this._forwarderWrapper.marketSellOrdersWithEthAsync(orders, {
|
||||
value: ethValue,
|
||||
from: this._takerAddress,
|
||||
});
|
||||
const totalEthSpent = ethValue.plus(this._gasPrice.times(tx.gasUsed));
|
||||
|
||||
const takerEthBalanceAfter = await web3Wrapper.getBalanceInWeiAsync(this._takerAddress);
|
||||
const forwarderEthBalance = await web3Wrapper.getBalanceInWeiAsync(this._forwarderAddress);
|
||||
const newBalances = await this._erc20Wrapper.getBalancesAsync();
|
||||
|
||||
expect(takerEthBalanceAfter).to.be.bignumber.equal(takerEthBalanceBefore.minus(totalEthSpent));
|
||||
|
||||
expect(newBalances[this._makerAddress][makerAssetAddress]).to.be.bignumber.equal(
|
||||
erc20Balances[this._makerAddress][makerAssetAddress].minus(expectedResults.makerAssetFillAmount),
|
||||
);
|
||||
expect(newBalances[this._takerAddress][makerAssetAddress]).to.be.bignumber.equal(
|
||||
erc20Balances[this._takerAddress][makerAssetAddress].plus(expectedResults.makerAssetFillAmount).minus(expectedResults.percentageFees),
|
||||
);
|
||||
expect(newBalances[this._orderFeeRecipientAddress][makerAssetAddress]).to.be.bignumber.equal(
|
||||
erc20Balances[this._orderFeeRecipientAddress][makerAssetAddress].plus(expectedResults.percentageFees),
|
||||
);
|
||||
|
||||
expect(newBalances[this._makerAddress][this._wethAddress]).to.be.bignumber.equal(
|
||||
erc20Balances[this._makerAddress][this._wethAddress].plus(expectedResults.takerAssetFillAmount).minus(expectedResults.wethFees),
|
||||
);
|
||||
expect(newBalances[this._orderFeeRecipientAddress][this._wethAddress]).to.be.bignumber.equal(
|
||||
erc20Balances[this._orderFeeRecipientAddress][this._wethAddress].plus(expectedResults.wethFees),
|
||||
);
|
||||
|
||||
expect(newBalances[this._forwarderAddress][this._wethAddress]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(newBalances[this._forwarderAddress][makerAssetAddress]).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(forwarderEthBalance).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
}
|
||||
}
|
@@ -1 +1,2 @@
|
||||
export * from './forwarder_wrapper';
|
||||
export * from './forwarder_test_factory';
|
||||
|
Reference in New Issue
Block a user