Fix the rounding of makerFillAmount and correctly validate partial fees

This commit is contained in:
Leonid Logvinov
2017-10-23 10:47:03 +03:00
parent 9d0ccdfdcc
commit fbe34663da

View File

@@ -27,13 +27,22 @@ export class OrderValidationUtils {
if (!_.isUndefined(expectedFillTakerTokenAmount)) { if (!_.isUndefined(expectedFillTakerTokenAmount)) {
fillTakerTokenAmount = expectedFillTakerTokenAmount; fillTakerTokenAmount = expectedFillTakerTokenAmount;
} }
const fillMakerTokenAmount = this.getFillMakerTokenAmount(signedOrder, fillTakerTokenAmount); const fillMakerTokenAmount = this.getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerTokenAmount,
);
await exchangeTradeEmulator.transferFromAsync( await exchangeTradeEmulator.transferFromAsync(
signedOrder.makerTokenAddress, signedOrder.maker, signedOrder.taker, fillMakerTokenAmount, signedOrder.makerTokenAddress, signedOrder.maker, signedOrder.taker, fillMakerTokenAmount,
TradeSide.Maker, TransferType.Trade, TradeSide.Maker, TransferType.Trade,
); );
const makerFeeAmount = this.getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerFee,
);
await exchangeTradeEmulator.transferFromAsync( await exchangeTradeEmulator.transferFromAsync(
zrxTokenAddress, signedOrder.maker, signedOrder.feeRecipient, signedOrder.makerFee, zrxTokenAddress, signedOrder.maker, signedOrder.feeRecipient, makerFeeAmount,
TradeSide.Maker, TransferType.Fee, TradeSide.Maker, TransferType.Fee,
); );
} }
@@ -100,7 +109,11 @@ export class OrderValidationUtils {
public async validateFillOrderBalancesAllowancesThrowIfInvalidAsync( public async validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder, exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder,
fillTakerTokenAmount: BigNumber.BigNumber, senderAddress: string, zrxTokenAddress: string): Promise<void> { fillTakerTokenAmount: BigNumber.BigNumber, senderAddress: string, zrxTokenAddress: string): Promise<void> {
const fillMakerTokenAmount = this.getFillMakerTokenAmount(signedOrder, fillTakerTokenAmount); const fillMakerTokenAmount = this.getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerTokenAmount,
);
await exchangeTradeEmulator.transferFromAsync( await exchangeTradeEmulator.transferFromAsync(
signedOrder.makerTokenAddress, signedOrder.maker, senderAddress, fillMakerTokenAmount, signedOrder.makerTokenAddress, signedOrder.maker, senderAddress, fillMakerTokenAmount,
TradeSide.Maker, TransferType.Trade, TradeSide.Maker, TransferType.Trade,
@@ -109,12 +122,22 @@ export class OrderValidationUtils {
signedOrder.takerTokenAddress, senderAddress, signedOrder.maker, fillTakerTokenAmount, signedOrder.takerTokenAddress, senderAddress, signedOrder.maker, fillTakerTokenAmount,
TradeSide.Taker, TransferType.Trade, TradeSide.Taker, TransferType.Trade,
); );
await exchangeTradeEmulator.transferFromAsync( const makerFeeAmount = this.getPartialAmount(
zrxTokenAddress, signedOrder.maker, signedOrder.feeRecipient, signedOrder.makerFee, TradeSide.Maker, fillTakerTokenAmount,
TransferType.Fee, signedOrder.takerTokenAmount,
signedOrder.makerFee,
); );
await exchangeTradeEmulator.transferFromAsync( await exchangeTradeEmulator.transferFromAsync(
zrxTokenAddress, senderAddress, signedOrder.feeRecipient, signedOrder.takerFee, TradeSide.Taker, zrxTokenAddress, signedOrder.maker, signedOrder.feeRecipient, makerFeeAmount, TradeSide.Maker,
TransferType.Fee,
);
const takerFeeAmount = this.getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.takerFee,
);
await exchangeTradeEmulator.transferFromAsync(
zrxTokenAddress, senderAddress, signedOrder.feeRecipient, takerFeeAmount, TradeSide.Taker,
TransferType.Fee, TransferType.Fee,
); );
} }
@@ -131,10 +154,12 @@ export class OrderValidationUtils {
throw new Error(ExchangeContractErrs.OrderFillExpired); throw new Error(ExchangeContractErrs.OrderFillExpired);
} }
} }
private getFillMakerTokenAmount(signedOrder: Order, private getPartialAmount(numerator: BigNumber.BigNumber, denominator: BigNumber.BigNumber,
fillTakerTokenAmount: BigNumber.BigNumber): BigNumber.BigNumber { target: BigNumber.BigNumber): BigNumber.BigNumber {
const exchangeRate = signedOrder.takerTokenAmount.div(signedOrder.makerTokenAmount); const fillMakerTokenAmount = numerator
const fillMakerTokenAmount = fillTakerTokenAmount.div(exchangeRate); .mul(target)
.div(denominator)
.round(0);
return fillMakerTokenAmount; return fillMakerTokenAmount;
} }
} }