Add tests with multiple fee recipients

This commit is contained in:
Amir Bandeali
2019-11-30 18:44:31 -08:00
parent 79ea0bf9f4
commit 5be0632e01
4 changed files with 70 additions and 23 deletions

View File

@@ -20,7 +20,7 @@ import { TestEth2DaiContract, TestUniswapExchangeContract } from '../wrappers';
import { deployForwarderAsync } from './deploy_forwarder';
import { ForwarderTestFactory } from './forwarder_test_factory';
blockchainTests.resets.only('Forwarder <> ERC20Bridge integration tests', env => {
blockchainTests.resets('Forwarder <> ERC20Bridge integration tests', env => {
let deployment: DeploymentManager;
let balanceStore: BlockchainBalanceStore;
let testFactory: ForwarderTestFactory;
@@ -146,7 +146,7 @@ blockchainTests.resets.only('Forwarder <> ERC20Bridge integration tests', env =>
const tokenIds = { erc721: { [erc721Token.address]: [nftId] } };
balanceStore = new BlockchainBalanceStore(tokenOwners, tokenContracts, tokenIds);
testFactory = new ForwarderTestFactory(forwarder, deployment, balanceStore, taker, forwarderFeeRecipient);
testFactory = new ForwarderTestFactory(forwarder, deployment, balanceStore, taker, [forwarderFeeRecipient]);
});
after(async () => {

View File

@@ -7,9 +7,10 @@ import {
constants,
expect,
getLatestBlockTimestampAsync,
randomAddress,
toBaseUnitAmount,
} from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
import { Actor } from '../framework/actors/base';
import { FeeRecipient } from '../framework/actors/fee_recipient';
@@ -23,7 +24,7 @@ import { DeploymentManager } from '../framework/deployment_manager';
import { deployForwarderAsync } from './deploy_forwarder';
import { ForwarderTestFactory } from './forwarder_test_factory';
blockchainTests.only('Forwarder integration tests', env => {
blockchainTests('Forwarder integration tests', env => {
let deployment: DeploymentManager;
let forwarder: ForwarderContract;
let balanceStore: BlockchainBalanceStore;
@@ -101,7 +102,7 @@ blockchainTests.only('Forwarder integration tests', env => {
const tokenIds = { erc721: { [erc721Token.address]: [nftId] } };
balanceStore = new BlockchainBalanceStore(tokenOwners, tokenContracts, tokenIds);
testFactory = new ForwarderTestFactory(forwarder, deployment, balanceStore, taker, forwarderFeeRecipient);
testFactory = new ForwarderTestFactory(forwarder, deployment, balanceStore, taker, [forwarderFeeRecipient]);
});
after(async () => {
@@ -179,12 +180,9 @@ blockchainTests.only('Forwarder integration tests', env => {
await balanceStore.updateBalancesAsync();
// Execute test case
const tx = await forwarder
.marketSellOrdersWithEth(
[order],
[order.signature],
constants.ZERO_AMOUNT,
.marketSellOrdersWithEth([order], [order.signature], constants.ZERO_AMOUNT, [
forwarderFeeRecipient.address,
)
])
.awaitTransactionSuccessAsync({
value: order.takerAssetAmount.plus(DeploymentManager.protocolFee),
from: taker.address,
@@ -223,12 +221,9 @@ blockchainTests.only('Forwarder integration tests', env => {
const ethValue = order.takerAssetAmount.plus(DeploymentManager.protocolFee).plus(2);
const takerEthBalanceBefore = await env.web3Wrapper.getBalanceInWeiAsync(taker.address);
const tx = await forwarder
.marketSellOrdersWithEth(
[order],
[order.signature],
constants.ZERO_AMOUNT,
.marketSellOrdersWithEth([order], [order.signature], constants.ZERO_AMOUNT, [
forwarderFeeRecipient.address,
)
])
.awaitTransactionSuccessAsync({
value: ethValue,
from: taker.address,
@@ -314,6 +309,44 @@ blockchainTests.only('Forwarder integration tests', env => {
forwarderFeeAmount: toBaseUnitAmount(0.2),
});
});
it('should fill the order and send fees to different feeRecipient addresses', async () => {
const order = await maker.signOrderAsync({
makerAssetAmount: toBaseUnitAmount(157),
takerAssetAmount: toBaseUnitAmount(36),
});
await testFactory.marketSellTestAsync([order], 0.67, {
forwarderFeeAmount: toBaseUnitAmount(0.2),
forwarderFeeRecipientAddresses: [randomAddress(), randomAddress()],
});
});
it('should fill the order and send fees to multiple instances of the same feeRecipient address', async () => {
const order = await maker.signOrderAsync({
makerAssetAmount: toBaseUnitAmount(157),
takerAssetAmount: toBaseUnitAmount(36),
});
const feeRecipient = randomAddress();
await testFactory.marketSellTestAsync([order], 0.67, {
forwarderFeeAmount: toBaseUnitAmount(0.2),
forwarderFeeRecipientAddresses: [feeRecipient, feeRecipient],
});
});
it('should fail if a fee is specified with no feeRecipient', async () => {
const order = await maker.signOrderAsync({
makerAssetAmount: toBaseUnitAmount(157),
takerAssetAmount: toBaseUnitAmount(36),
});
const forwarderFeeAmount = toBaseUnitAmount(0.2);
const revertError = new SafeMathRevertErrors.Uint256BinOpError(
SafeMathRevertErrors.BinOpErrorCodes.DivisionByZero,
forwarderFeeAmount,
constants.ZERO_AMOUNT,
);
await testFactory.marketSellTestAsync([order], 0.67, {
forwarderFeeAmount,
forwarderFeeRecipientAddresses: [],
revertError,
});
});
});
blockchainTests.resets('marketBuyOrdersWithEth without extra fees', () => {
it('should buy the exact amount of makerAsset in a single order', async () => {
@@ -490,7 +523,7 @@ blockchainTests.only('Forwarder integration tests', env => {
desiredMakerAssetFillAmount,
[order.signature],
constants.ZERO_AMOUNT,
forwarderFeeRecipient.address,
[forwarderFeeRecipient.address],
)
.awaitTransactionSuccessAsync({
value: ethValue,
@@ -537,7 +570,7 @@ blockchainTests.only('Forwarder integration tests', env => {
desiredMakerAssetFillAmount,
[order.signature],
constants.ZERO_AMOUNT,
forwarderFeeRecipient.address,
[forwarderFeeRecipient.address],
)
.awaitTransactionSuccessAsync({
value: takerAssetFillAmount.plus(DeploymentManager.protocolFee),

View File

@@ -1,6 +1,6 @@
import { IAssetDataContract } from '@0x/contracts-asset-proxy';
import { ForwarderContract } from '@0x/contracts-exchange-forwarder';
import { constants, expect, getPercentageOfValue, hexSlice, OrderStatus, provider } from '@0x/contracts-test-utils';
import { constants, expect, hexSlice, OrderStatus, provider } from '@0x/contracts-test-utils';
import { AssetProxyId, OrderInfo, SignedOrder } from '@0x/types';
import { BigNumber, hexUtils, RevertError } from '@0x/utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@@ -20,6 +20,7 @@ interface ForwarderFillState {
interface MarketSellOptions {
forwarderFeeAmount: BigNumber;
forwarderFeeRecipientAddresses: string[];
revertError: RevertError;
bridgeExcessBuyAmount: BigNumber;
}
@@ -56,7 +57,7 @@ export class ForwarderTestFactory {
private readonly _deployment: DeploymentManager,
private readonly _balanceStore: BlockchainBalanceStore,
private readonly _taker: Taker,
private readonly _forwarderFeeRecipient: FeeRecipient,
private readonly _forwarderFeeRecipients: FeeRecipient[],
) {}
public async marketBuyTestAsync(
@@ -66,6 +67,9 @@ export class ForwarderTestFactory {
): Promise<void> {
const ethValueAdjustment = options.ethValueAdjustment || 0;
const forwarderFeeAmount = options.forwarderFeeAmount || constants.ZERO_AMOUNT;
const forwarderFeeRecipientAddresses =
options.forwarderFeeRecipientAddresses ||
this._forwarderFeeRecipients.map(feeRecipient => feeRecipient.address);
const orderInfoBefore = await Promise.all(
orders.map(order => this._deployment.exchange.getOrderInfo(order).callAsync()),
@@ -88,7 +92,7 @@ export class ForwarderTestFactory {
makerAssetAcquiredAmount.minus(options.bridgeExcessBuyAmount || 0),
orders.map(signedOrder => signedOrder.signature),
forwarderFeeAmount,
this._forwarderFeeRecipient.address,
forwarderFeeRecipientAddresses,
)
.awaitTransactionSuccessAsync({
value: wethSpentAmount.plus(forwarderFeeAmount).plus(ethValueAdjustment),
@@ -125,13 +129,16 @@ export class ForwarderTestFactory {
);
const forwarderFeeAmount = options.forwarderFeeAmount || constants.ZERO_AMOUNT;
const forwarderFeeRecipientAddresses =
options.forwarderFeeRecipientAddresses ||
this._forwarderFeeRecipients.map(feeRecipient => feeRecipient.address);
const tx = this._forwarder
.marketSellOrdersWithEth(
orders,
orders.map(signedOrder => signedOrder.signature),
forwarderFeeAmount,
this._forwarderFeeRecipient.address,
forwarderFeeRecipientAddresses,
)
.awaitTransactionSuccessAsync({
value: wethSpentAmount.plus(forwarderFeeAmount),
@@ -210,9 +217,15 @@ export class ForwarderTestFactory {
}
const ethSpentOnForwarderFee = options.forwarderFeeAmount || constants.ZERO_AMOUNT;
const forwarderFeeRecipientAddresses =
options.forwarderFeeRecipientAddresses ||
this._forwarderFeeRecipients.map(feeRecipient => feeRecipient.address);
const ethFeePerFeeRecipient = ethSpentOnForwarderFee.dividedToIntegerBy(forwarderFeeRecipientAddresses.length);
// In reality the Forwarder is a middleman in this transaction and the ETH gets wrapped and unwrapped.
balances.sendEth(this._taker.address, this._forwarderFeeRecipient.address, ethSpentOnForwarderFee);
forwarderFeeRecipientAddresses.forEach(feeRecipientAddress =>
// In reality the Forwarder is a middleman in this transaction and the ETH gets wrapped and unwrapped.
balances.sendEth(this._taker.address, feeRecipientAddress, ethFeePerFeeRecipient),
);
return { ...currentTotal, balances };
}

View File

@@ -67,6 +67,7 @@ export class LocalBalanceStore extends BalanceStore {
* @param amount Amount of ETH to transfer.
*/
public sendEth(fromAddress: string, toAddress: string, amount: Numberish): void {
this.balances.eth[toAddress] = this.balances.eth[toAddress] || constants.ZERO_AMOUNT;
this.balances.eth[fromAddress] = this.balances.eth[fromAddress].minus(amount);
this.balances.eth[toAddress] = this.balances.eth[toAddress].plus(amount);
}