address comments and tests

This commit is contained in:
Michael Zhu
2019-11-22 14:13:49 -08:00
parent 51f5e60224
commit 2542b1b44d
10 changed files with 200 additions and 110 deletions

View File

@@ -21,17 +21,21 @@ import { Taker } from '../framework/actors/taker';
import { actorAddressesByName } from '../framework/actors/utils';
import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store';
import { DeploymentManager } from '../framework/deployment_manager';
import { TestEth2DaiContract, TestUniswapExchangeContract } from '../wrappers';
import { deployForwarderAsync } from './deploy_forwarder';
import { ForwarderTestFactory } from './forwarder_test_factory';
blockchainTests.resets('Forwarder <> ERC20Bridge integration tests', env => {
blockchainTests.resets.only('Forwarder <> ERC20Bridge integration tests', env => {
let deployment: DeploymentManager;
let forwarder: ForwarderContract;
let assetDataEncoder: IAssetDataContract;
let balanceStore: BlockchainBalanceStore;
let testFactory: ForwarderTestFactory;
let forwarder: ForwarderContract;
let assetDataEncoder: IAssetDataContract;
let eth2Dai: TestEth2DaiContract;
let uniswapExchange: TestUniswapExchangeContract;
let erc721Token: DummyERC721TokenContract;
let nftId: BigNumber;
let makerTokenAssetData: string;
@@ -58,10 +62,12 @@ blockchainTests.resets('Forwarder <> ERC20Bridge integration tests', env => {
[erc721Token] = deployment.tokens.erc721;
forwarder = await deployForwarderAsync(deployment, env);
const [eth2DaiBridge] = await deployEth2DaiBridgeAsync(deployment, env);
const [uniswapBridge, [uniswapMakerTokenExchange]] = await deployUniswapBridgeAsync(deployment, env, [
makerToken.address,
]);
const eth2DaiContracts = await deployEth2DaiBridgeAsync(deployment, env);
const [eth2DaiBridge] = eth2DaiContracts;
[, eth2Dai] = eth2DaiContracts;
const uniswapContracts = await deployUniswapBridgeAsync(deployment, env, [makerToken.address]);
const [uniswapBridge] = uniswapContracts;
[, [uniswapExchange]] = uniswapContracts;
makerTokenAssetData = assetDataEncoder.ERC20Token(makerToken.address).getABIEncodedTransactionData();
makerFeeTokenAssetData = assetDataEncoder.ERC20Token(makerFeeToken.address).getABIEncodedTransactionData();
@@ -129,7 +135,7 @@ blockchainTests.resets('Forwarder <> ERC20Bridge integration tests', env => {
[nftId] = await maker.configureERC721TokenAsync(erc721Token);
// We need to top up the TestUniswapExchange with some ETH so that it can perform tokenToEthSwapInput
await uniswapMakerTokenExchange.topUpEth().awaitTransactionSuccessAsync({
await uniswapExchange.topUpEth().awaitTransactionSuccessAsync({
from: forwarderFeeRecipient.address,
value: constants.ONE_ETHER.times(10),
});
@@ -160,6 +166,11 @@ blockchainTests.resets('Forwarder <> ERC20Bridge integration tests', env => {
it('should partially fill a single Eth2DaiBridge order without a taker fee', async () => {
await testFactory.marketSellTestAsync([eth2DaiBridgeOrder], 0.34);
});
it('should correctly handle excess maker asset acquired from Eth2Dai', async () => {
const bridgeExcessBuyAmount = new BigNumber(1);
await eth2Dai.setExcessBuyAmount(bridgeExcessBuyAmount).awaitTransactionSuccessAsync();
await testFactory.marketSellTestAsync([eth2DaiBridgeOrder], 0.34, { bridgeExcessBuyAmount });
});
it('should fill a single Eth2DaiBridge order with a WETH taker fee', async () => {
const order = {
...eth2DaiBridgeOrder,
@@ -196,6 +207,11 @@ blockchainTests.resets('Forwarder <> ERC20Bridge integration tests', env => {
it('should partially fill a single UniswapBridge order without a taker fee', async () => {
await testFactory.marketSellTestAsync([uniswapBridgeOrder], 0.34);
});
it('should correctly handle excess maker asset acquired from Uniswap', async () => {
const bridgeExcessBuyAmount = new BigNumber(1);
await uniswapExchange.setExcessBuyAmount(bridgeExcessBuyAmount).awaitTransactionSuccessAsync();
await testFactory.marketSellTestAsync([uniswapBridgeOrder], 0.34, { bridgeExcessBuyAmount });
});
it('should fill a single UniswapBridge order with a WETH taker fee', async () => {
const order = {
...uniswapBridgeOrder,
@@ -249,6 +265,11 @@ blockchainTests.resets('Forwarder <> ERC20Bridge integration tests', env => {
it('should return excess ETH', async () => {
await testFactory.marketBuyTestAsync([eth2DaiBridgeOrder], 1, { ethValueAdjustment: 1 });
});
it('should correctly handle excess maker asset acquired from Eth2Dai', async () => {
const bridgeExcessBuyAmount = new BigNumber(1);
await eth2Dai.setExcessBuyAmount(bridgeExcessBuyAmount).awaitTransactionSuccessAsync();
await testFactory.marketBuyTestAsync([eth2DaiBridgeOrder], 0.34, { bridgeExcessBuyAmount });
});
it('should fill a single Eth2DaiBridge order with a WETH taker fee', async () => {
const order = {
...eth2DaiBridgeOrder,
@@ -295,6 +316,11 @@ blockchainTests.resets('Forwarder <> ERC20Bridge integration tests', env => {
it('should partially fill a single UniswapBridge order without a taker fee', async () => {
await testFactory.marketBuyTestAsync([uniswapBridgeOrder], 0.34);
});
it('should correctly handle excess maker asset acquired from Uniswap', async () => {
const bridgeExcessBuyAmount = new BigNumber(1);
await uniswapExchange.setExcessBuyAmount(bridgeExcessBuyAmount).awaitTransactionSuccessAsync();
await testFactory.marketBuyTestAsync([uniswapBridgeOrder], 0.34, { bridgeExcessBuyAmount });
});
it('should fill a single UniswapBridge order with a WETH taker fee', async () => {
const order = {
...uniswapBridgeOrder,

View File

@@ -29,28 +29,32 @@ interface ForwarderFillState {
interface MarketSellOptions {
forwarderFeePercentage: Numberish;
revertError: RevertError;
bridgeExcessBuyAmount: BigNumber;
}
interface MarketBuyOptions extends MarketSellOptions {
ethValueAdjustment: number; // Used to provided insufficient/excess ETH
}
function isPercentageFee(takerFeeAssetData: string, makerAssetData: string): boolean {
const makerAssetProxyId = hexSlice(makerAssetData, 0, 4);
const takerFeeAssetProxyId = hexSlice(takerFeeAssetData, 0, 4);
if (makerAssetProxyId === AssetProxyId.ERC20Bridge && takerFeeAssetProxyId === AssetProxyId.ERC20) {
function areUnderlyingAssetsEqual(assetData1: string, assetData2: string): boolean {
const assetProxyId1 = hexSlice(assetData1, 0, 4);
const assetProxyId2 = hexSlice(assetData2, 0, 4);
if (
(assetProxyId1 === AssetProxyId.ERC20 || assetProxyId1 === AssetProxyId.ERC20Bridge) &&
(assetProxyId2 === AssetProxyId.ERC20 || assetProxyId2 === AssetProxyId.ERC20Bridge)
) {
const assetDataDecoder = new IAssetDataContract(constants.NULL_ADDRESS, provider);
const [makerTokenAddress] = assetDataDecoder.getABIDecodedTransactionData<string>(
'ERC20Bridge',
makerAssetData,
);
const takerFeeTokenAddress = assetDataDecoder.getABIDecodedTransactionData<string>(
'ERC20Token',
takerFeeAssetData,
);
return makerTokenAddress === takerFeeTokenAddress;
const tokenAddress1 =
assetProxyId1 === AssetProxyId.ERC20
? assetDataDecoder.getABIDecodedTransactionData<string>('ERC20Token', assetData1)
: assetDataDecoder.getABIDecodedTransactionData<[string]>('ERC20Bridge', assetData1)[0];
const tokenAddress2 =
assetProxyId2 === AssetProxyId.ERC20
? assetDataDecoder.getABIDecodedTransactionData<string>('ERC20Token', assetData2)
: assetDataDecoder.getABIDecodedTransactionData<[string]>('ERC20Bridge', assetData2)[0];
return tokenAddress2 === tokenAddress1;
} else {
return makerAssetData === takerFeeAssetData;
return false;
}
}
@@ -92,7 +96,7 @@ export class ForwarderTestFactory {
const tx = this._forwarder
.marketBuyOrdersWithEth(
orders,
makerAssetAcquiredAmount,
makerAssetAcquiredAmount.minus(options.bridgeExcessBuyAmount || 0),
orders.map(signedOrder => signedOrder.signature),
feePercentage,
this._forwarderFeeRecipient.address,
@@ -208,6 +212,7 @@ export class ForwarderTestFactory {
order,
ordersInfoBefore[i].orderTakerAssetFilledAmount,
Math.min(remainingOrdersToFill, 1),
options.bridgeExcessBuyAmount || constants.ZERO_AMOUNT,
);
remainingOrdersToFill = Math.max(remainingOrdersToFill - 1, 0);
@@ -232,6 +237,7 @@ export class ForwarderTestFactory {
order: SignedOrder,
takerAssetFilled: BigNumber,
fillFraction: number,
bridgeExcessBuyAmount: BigNumber,
): Promise<ForwarderFillState> {
let { makerAssetAmount, takerAssetAmount, makerFee, takerFee } = order;
makerAssetAmount = makerAssetAmount.times(fillFraction).integerValue(BigNumber.ROUND_CEIL);
@@ -251,9 +257,10 @@ export class ForwarderTestFactory {
const takerFeeFilled = takerAssetFilled.times(order.takerFee).dividedToIntegerBy(order.takerAssetAmount);
takerFee = BigNumber.max(takerFee.minus(takerFeeFilled), 0);
makerAssetAmount = makerAssetAmount.plus(bridgeExcessBuyAmount);
let wethSpentAmount = takerAssetAmount.plus(DeploymentManager.protocolFee);
let makerAssetAcquiredAmount = makerAssetAmount;
if (isPercentageFee(order.takerFeeAssetData, order.makerAssetData)) {
if (areUnderlyingAssetsEqual(order.takerFeeAssetData, order.makerAssetData)) {
makerAssetAcquiredAmount = makerAssetAcquiredAmount.minus(takerFee);
} else if (order.takerFeeAssetData === order.takerAssetData) {
wethSpentAmount = wethSpentAmount.plus(takerFee);