aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contract-wrappers
diff options
context:
space:
mode:
Diffstat (limited to 'packages/contract-wrappers')
-rw-r--r--packages/contract-wrappers/CHANGELOG.json6
-rw-r--r--packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts27
-rw-r--r--packages/contract-wrappers/src/utils/calldata_optimization_utils.ts44
-rw-r--r--packages/contract-wrappers/src/utils/constants.ts1
-rw-r--r--packages/contract-wrappers/test/calldata_optimization_utils_test.ts60
5 files changed, 129 insertions, 9 deletions
diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json
index 8fa31052c..02e1acf91 100644
--- a/packages/contract-wrappers/CHANGELOG.json
+++ b/packages/contract-wrappers/CHANGELOG.json
@@ -1,10 +1,14 @@
[
{
- "version": "1.1.0-rc.2",
+ "version": "1.0.1-rc.3",
"changes": [
{
"note": "Add ForwarderWrapper",
"pr": 934
+ },
+ {
+ "note": "Optimize orders in ForwarderWrapper",
+ "pr": 936
}
]
},
diff --git a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts
index 90cfbe2af..13ef0fe01 100644
--- a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts
+++ b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts
@@ -10,6 +10,7 @@ import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema';
import { txOptsSchema } from '../schemas/tx_opts_schema';
import { TransactionOpts } from '../types';
import { assert } from '../utils/assert';
+import { calldataOptimizationUtils } from '../utils/calldata_optimization_utils';
import { constants } from '../utils/constants';
import { ContractWrapper } from './contract_wrapper';
@@ -75,14 +76,19 @@ export class ForwarderWrapper extends ContractWrapper {
this.getZRXTokenAddress(),
this.getEtherTokenAddress(),
);
+ // lowercase input addresses
const normalizedTakerAddress = takerAddress.toLowerCase();
const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase();
+ // optimize orders
+ const optimizedMarketOrders = calldataOptimizationUtils.optimizeForwarderOrders(signedOrders);
+ const optimizedFeeOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(signedFeeOrders);
+ // send transaction
const forwarderContractInstance = await this._getForwarderContractAsync();
const txHash = await forwarderContractInstance.marketSellOrdersWithEth.sendTransactionAsync(
- signedOrders,
- _.map(signedOrders, order => order.signature),
- signedFeeOrders,
- _.map(signedFeeOrders, order => order.signature),
+ optimizedMarketOrders,
+ _.map(optimizedMarketOrders, order => order.signature),
+ optimizedFeeOrders,
+ _.map(optimizedFeeOrders, order => order.signature),
feePercentage,
feeRecipientAddress,
{
@@ -138,15 +144,20 @@ export class ForwarderWrapper extends ContractWrapper {
this.getZRXTokenAddress(),
this.getEtherTokenAddress(),
);
+ // lowercase input addresses
const normalizedTakerAddress = takerAddress.toLowerCase();
const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase();
+ // optimize orders
+ const optimizedMarketOrders = calldataOptimizationUtils.optimizeForwarderOrders(signedOrders);
+ const optimizedFeeOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(signedFeeOrders);
+ // send transaction
const forwarderContractInstance = await this._getForwarderContractAsync();
const txHash = await forwarderContractInstance.marketBuyOrdersWithEth.sendTransactionAsync(
- signedOrders,
+ optimizedMarketOrders,
makerAssetFillAmount,
- _.map(signedOrders, order => order.signature),
- signedFeeOrders,
- _.map(signedFeeOrders, order => order.signature),
+ _.map(optimizedMarketOrders, order => order.signature),
+ optimizedFeeOrders,
+ _.map(optimizedFeeOrders, order => order.signature),
feePercentage,
feeRecipientAddress,
{
diff --git a/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts b/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts
new file mode 100644
index 000000000..3172cf531
--- /dev/null
+++ b/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts
@@ -0,0 +1,44 @@
+import { SignedOrder } from '@0xproject/types';
+import * as _ from 'lodash';
+
+import { constants } from './constants';
+
+export const calldataOptimizationUtils = {
+ /**
+ * Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and
+ * all makerAssetData are '0x' except for that of the first order, which retains its original value
+ * @param orders An array of SignedOrder objects
+ * @returns optimized orders
+ */
+ optimizeForwarderOrders(orders: SignedOrder[]): SignedOrder[] {
+ const optimizedOrders = _.map(orders, (order, index) =>
+ transformOrder(order, {
+ makerAssetData: index === 0 ? order.makerAssetData : constants.NULL_BYTES,
+ takerAssetData: constants.NULL_BYTES,
+ }),
+ );
+ return optimizedOrders;
+ },
+ /**
+ * Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and
+ * all makerAssetData are '0x'
+ * @param orders An array of SignedOrder objects
+ * @returns optimized orders
+ */
+ optimizeForwarderFeeOrders(orders: SignedOrder[]): SignedOrder[] {
+ const optimizedOrders = _.map(orders, (order, index) =>
+ transformOrder(order, {
+ makerAssetData: constants.NULL_BYTES,
+ takerAssetData: constants.NULL_BYTES,
+ }),
+ );
+ return optimizedOrders;
+ },
+};
+
+const transformOrder = (order: SignedOrder, partialOrder: Partial<SignedOrder>) => {
+ return {
+ ...order,
+ ...partialOrder,
+ };
+};
diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts
index d436efefc..2df11538c 100644
--- a/packages/contract-wrappers/src/utils/constants.ts
+++ b/packages/contract-wrappers/src/utils/constants.ts
@@ -2,6 +2,7 @@ import { BigNumber } from '@0xproject/utils';
export const constants = {
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
+ NULL_BYTES: '0x',
TESTRPC_NETWORK_ID: 50,
INVALID_JUMP_PATTERN: 'invalid JUMP at',
REVERT: 'revert',
diff --git a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts
new file mode 100644
index 000000000..a4cea772f
--- /dev/null
+++ b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts
@@ -0,0 +1,60 @@
+import { orderFactory } from '@0xproject/order-utils';
+import * as chai from 'chai';
+import * as _ from 'lodash';
+import 'mocha';
+
+import { assert } from '../src/utils/assert';
+import { calldataOptimizationUtils } from '../src/utils/calldata_optimization_utils';
+import { constants } from '../src/utils/constants';
+
+import { chaiSetup } from './utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+// utility for generating a set of order objects with mostly NULL values
+// except for a specified makerAssetData and takerAssetData
+const FAKE_ORDERS_COUNT = 5;
+const generateFakeOrders = (makerAssetData: string, takerAssetData: string) =>
+ _.map(_.range(FAKE_ORDERS_COUNT), index => {
+ const order = orderFactory.createOrder(
+ constants.NULL_ADDRESS,
+ constants.ZERO_AMOUNT,
+ makerAssetData,
+ constants.ZERO_AMOUNT,
+ takerAssetData,
+ constants.NULL_ADDRESS,
+ );
+ return {
+ ...order,
+ signature: 'dummy signature',
+ };
+ });
+
+describe('calldataOptimizationUtils', () => {
+ const fakeMakerAssetData = 'fakeMakerAssetData';
+ const fakeTakerAssetData = 'fakeTakerAssetData';
+ const orders = generateFakeOrders(fakeMakerAssetData, fakeTakerAssetData);
+ describe('#optimizeForwarderOrders', () => {
+ it('should make makerAssetData `0x` unless first order', () => {
+ const optimizedOrders = calldataOptimizationUtils.optimizeForwarderOrders(orders);
+ expect(optimizedOrders[0].makerAssetData).to.equal(fakeMakerAssetData);
+ const ordersWithoutHead = _.slice(optimizedOrders, 1);
+ _.forEach(ordersWithoutHead, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES));
+ });
+ it('should make all takerAssetData `0x`', () => {
+ const optimizedOrders = calldataOptimizationUtils.optimizeForwarderOrders(orders);
+ _.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES));
+ });
+ });
+ describe('#optimizeForwarderFeeOrders', () => {
+ it('should make all makerAssetData `0x`', () => {
+ const optimizedOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(orders);
+ _.forEach(optimizedOrders, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES));
+ });
+ it('should make all takerAssetData `0x`', () => {
+ const optimizedOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(orders);
+ _.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES));
+ });
+ });
+});