diff --git a/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol b/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol index 055874580a..9400c659d2 100644 --- a/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol +++ b/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol @@ -41,11 +41,20 @@ contract ERC20BridgeSampler is uint256 constant internal UNISWAP_SAMPLE_CALL_GAS = 150e3; uint256 constant internal ETH2DAI_SAMPLE_CALL_GAS = 250e3; - function queryMultipleOrdersAndSampleBuys( + /// @dev Query batches of native orders and sample sell quotes on multiple DEXes at once. + /// @param orders Batches of Native orders to query. + /// @param orderSignatures Batches of Signatures for each respective order in `orders`. + /// @param sources Address of each DEX. Passing in an unsupported DEX will throw. + /// @param takerTokenAmounts Batches of Taker token sell amount for each sample. + /// @return ordersAndSamples How much taker asset can be filled + /// by each order in `orders`. Maker amounts bought for each source at + /// each taker token amount. First indexed by source index, then sample + /// index. + function queryBatchOrdersAndSampleSells( LibOrder.Order[][] memory orders, bytes[][] memory orderSignatures, address[] memory sources, - uint256[] memory makerTokenAmounts + uint256[][] memory takerTokenAmounts ) public view @@ -54,23 +63,30 @@ contract ERC20BridgeSampler is ) { ordersAndSamples = new OrdersAndSample[](orders.length); - uint256[] memory amounts = new uint256[](1); for (uint256 i = 0; i != orders.length; i++) { - amounts[0] = makerTokenAmounts[i]; ( - uint256[] memory orderFillableTakerAssetAmounts, - uint256[][] memory makerTokenAmountsBySource - ) = queryOrdersAndSampleBuys(orders[i], orderSignatures[i], sources, amounts); - ordersAndSamples[i].orderFillableTakerAssetAmounts = orderFillableTakerAssetAmounts; - ordersAndSamples[i].makerTokenAmountsBySource = makerTokenAmountsBySource; + uint256[] memory orderFillableAssetAmounts, + uint256[][] memory tokenAmountsBySource + ) = queryOrdersAndSampleSells(orders[i], orderSignatures[i], sources, takerTokenAmounts[i]); + ordersAndSamples[i].orderFillableAssetAmounts = orderFillableAssetAmounts; + ordersAndSamples[i].tokenAmountsBySource = tokenAmountsBySource; } } - function queryMultipleOrdersAndSampleSells( + /// @dev Query batches of native orders and sample buy quotes on multiple DEXes at once. + /// @param orders Batches of Native orders to query. + /// @param orderSignatures Batches of Signatures for each respective order in `orders`. + /// @param sources Address of each DEX. Passing in an unsupported DEX will throw. + /// @param makerTokenAmounts Batches of Maker token sell amount for each sample. + /// @return ordersAndSamples How much taker asset can be filled + /// by each order in `orders`. Taker amounts sold for each source at + /// each maker token amount. First indexed by source index, then sample + /// index. + function queryBatchOrdersAndSampleBuys( LibOrder.Order[][] memory orders, bytes[][] memory orderSignatures, address[] memory sources, - uint256[] memory makerTokenAmounts + uint256[][] memory makerTokenAmounts ) public view @@ -79,18 +95,17 @@ contract ERC20BridgeSampler is ) { ordersAndSamples = new OrdersAndSample[](orders.length); - uint256[] memory amounts = new uint256[](1); for (uint256 i = 0; i != orders.length; i++) { - amounts[0] = makerTokenAmounts[i]; ( - uint256[] memory orderFillableTakerAssetAmounts, - uint256[][] memory makerTokenAmountsBySource - ) = queryOrdersAndSampleSells(orders[i], orderSignatures[i], sources, amounts); - ordersAndSamples[i].orderFillableTakerAssetAmounts = orderFillableTakerAssetAmounts; - ordersAndSamples[i].makerTokenAmountsBySource = makerTokenAmountsBySource; + uint256[] memory orderFillableAssetAmounts, + uint256[][] memory tokenAmountsBySource + ) = queryOrdersAndSampleBuys(orders[i], orderSignatures[i], sources, makerTokenAmounts[i]); + ordersAndSamples[i].orderFillableAssetAmounts = orderFillableAssetAmounts; + ordersAndSamples[i].tokenAmountsBySource = tokenAmountsBySource; } } + /// @dev Query native orders and sample sell quotes on multiple DEXes at once. /// @param orders Native orders to query. /// @param orderSignatures Signatures for each respective order in `orders`. diff --git a/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol b/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol index 4836dd57fe..42661de16d 100644 --- a/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol +++ b/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol @@ -24,15 +24,24 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; interface IERC20BridgeSampler { struct OrdersAndSample { - uint256[] orderFillableTakerAssetAmounts; - uint256[][] makerTokenAmountsBySource; + uint256[] orderFillableAssetAmounts; + uint256[][] tokenAmountsBySource; } - function queryMultipleOrdersAndSampleBuys( + /// @dev Query batches of native orders and sample sell quotes on multiple DEXes at once. + /// @param orders Batches of Native orders to query. + /// @param orderSignatures Batches of Signatures for each respective order in `orders`. + /// @param sources Address of each DEX. Passing in an unsupported DEX will throw. + /// @param takerTokenAmounts Batches of Taker token sell amount for each sample. + /// @return ordersAndSamples How much taker asset can be filled + /// by each order in `orders`. Maker amounts bought for each source at + /// each taker token amount. First indexed by source index, then sample + /// index. + function queryBatchOrdersAndSampleSells( LibOrder.Order[][] calldata orders, bytes[][] calldata orderSignatures, address[] calldata sources, - uint256[] calldata makerTokenAmounts + uint256[][] calldata takerTokenAmounts ) external view @@ -40,11 +49,20 @@ interface IERC20BridgeSampler { OrdersAndSample[] memory ordersAndSamples ); - function queryMultipleOrdersAndSampleSells( + /// @dev Query batches of native orders and sample buy quotes on multiple DEXes at once. + /// @param orders Batches of Native orders to query. + /// @param orderSignatures Batches of Signatures for each respective order in `orders`. + /// @param sources Address of each DEX. Passing in an unsupported DEX will throw. + /// @param makerTokenAmounts Batches of Maker token sell amount for each sample. + /// @return ordersAndSamples How much taker asset can be filled + /// by each order in `orders`. Taker amounts sold for each source at + /// each maker token amount. First indexed by source index, then sample + /// index + function queryBatchOrdersAndSampleBuys( LibOrder.Order[][] calldata orders, bytes[][] calldata orderSignatures, address[] calldata sources, - uint256[] calldata makerTokenAmounts + uint256[][] calldata makerTokenAmounts ) external view diff --git a/packages/asset-swapper/src/utils/market_operation_utils/index.ts b/packages/asset-swapper/src/utils/market_operation_utils/index.ts index 4b0de6e66d..2f64cc1ecd 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/index.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/index.ts @@ -173,7 +173,7 @@ export class MarketOperationUtils { const batchSampleResults = await this._dexSampler.getBatchFillableAmountsAndSampleMarketBuyAsync( batchNativeOrders, - makerAmounts, + makerAmounts.map(makerAmount => DexOrderSampler.getSampleAmounts(makerAmount, _opts.numSamples)), difference(BUY_SOURCES, _opts.excludedSources), ); return batchSampleResults.map(([fillableAmounts, dexQuotes], i) => diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts index e7af37dfca..3a2e81628f 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts @@ -52,12 +52,12 @@ export class DexOrderSampler { public async getBatchFillableAmountsAndSampleMarketBuyAsync( nativeOrders: SignedOrder[][], - sampleAmounts: BigNumber[], + sampleAmounts: BigNumber[][], sources: ERC20BridgeSource[], ): Promise> { const signatures = nativeOrders.map(o => o.map(i => i.signature)); const fillableAmountsAndSamples = await this._samplerContract - .queryMultipleOrdersAndSampleBuys( + .queryBatchOrdersAndSampleBuys( nativeOrders, signatures, sources.map(s => SOURCE_TO_ADDRESS[s]), @@ -66,16 +66,16 @@ export class DexOrderSampler { .callAsync(); const batchFillableAmountsAndQuotes: Array<[BigNumber[], DexSample[][]]> = []; fillableAmountsAndSamples.forEach((sampleResult, i) => { - const { makerTokenAmountsBySource, orderFillableTakerAssetAmounts } = sampleResult; - const quotes = makerTokenAmountsBySource.map((rawDexSamples, sourceIdx) => { + const { tokenAmountsBySource, orderFillableAssetAmounts } = sampleResult; + const quotes = tokenAmountsBySource.map((rawDexSamples, sourceIdx) => { const source = sources[sourceIdx]; - return rawDexSamples.map(sample => ({ + return rawDexSamples.map((sample, sampleIdx) => ({ source, - input: sampleAmounts[i], + input: sampleAmounts[i][sampleIdx], output: sample, })); }); - batchFillableAmountsAndQuotes.push([orderFillableTakerAssetAmounts, quotes]); + batchFillableAmountsAndQuotes.push([orderFillableAssetAmounts, quotes]); }); return batchFillableAmountsAndQuotes; } diff --git a/packages/contract-addresses/addresses.json b/packages/contract-addresses/addresses.json index 8501bb095d..80a2d78591 100644 --- a/packages/contract-addresses/addresses.json +++ b/packages/contract-addresses/addresses.json @@ -22,7 +22,7 @@ "devUtils": "0x5f53f2aa72cb3a9371bf3c58e8fb3a313478b2f4", "erc20BridgeProxy": "0x8ed95d1746bf1e4dab58d8ed4724f1ef95b20db0", "uniswapBridge": "0x533344cfdf2a3e911e2cf4c6f5ed08e791f5355f", - "erc20BridgeSampler": "0xdf291ac755a47ef44e18fecc71f1c13a07d8b303", + "erc20BridgeSampler": "0xba30e1e50075c9f7b66fceadb772c538d0a12497", "kyberBridge": "0xf342f3a80fdc9b48713d58fe97e17f5cc764ee62", "eth2DaiBridge": "0xe97ea901d034ba2e018155264f77c417ce7717f9", "chaiBridge": "0x77c31eba23043b9a72d13470f3a3a311344d7438", diff --git a/packages/contract-artifacts/artifacts/IERC20BridgeSampler.json b/packages/contract-artifacts/artifacts/IERC20BridgeSampler.json index ac3b2e7fd8..11259f12af 100644 --- a/packages/contract-artifacts/artifacts/IERC20BridgeSampler.json +++ b/packages/contract-artifacts/artifacts/IERC20BridgeSampler.json @@ -97,22 +97,14 @@ }, { "internalType": "bytes[][]", "name": "orderSignatures", "type": "bytes[][]" }, { "internalType": "address[]", "name": "sources", "type": "address[]" }, - { "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" } + { "internalType": "uint256[][]", "name": "makerTokenAmounts", "type": "uint256[][]" } ], - "name": "queryMultipleOrdersAndSampleBuys", + "name": "queryBatchOrdersAndSampleBuys", "outputs": [ { "components": [ - { - "internalType": "uint256[]", - "name": "orderFillableTakerAssetAmounts", - "type": "uint256[]" - }, - { - "internalType": "uint256[][]", - "name": "makerTokenAmountsBySource", - "type": "uint256[][]" - } + { "internalType": "uint256[]", "name": "orderFillableAssetAmounts", "type": "uint256[]" }, + { "internalType": "uint256[][]", "name": "tokenAmountsBySource", "type": "uint256[][]" } ], "internalType": "struct IERC20BridgeSampler.OrdersAndSample[]", "name": "ordersAndSamples", @@ -149,22 +141,14 @@ }, { "internalType": "bytes[][]", "name": "orderSignatures", "type": "bytes[][]" }, { "internalType": "address[]", "name": "sources", "type": "address[]" }, - { "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" } + { "internalType": "uint256[][]", "name": "takerTokenAmounts", "type": "uint256[][]" } ], - "name": "queryMultipleOrdersAndSampleSells", + "name": "queryBatchOrdersAndSampleSells", "outputs": [ { "components": [ - { - "internalType": "uint256[]", - "name": "orderFillableTakerAssetAmounts", - "type": "uint256[]" - }, - { - "internalType": "uint256[][]", - "name": "makerTokenAmountsBySource", - "type": "uint256[][]" - } + { "internalType": "uint256[]", "name": "orderFillableAssetAmounts", "type": "uint256[]" }, + { "internalType": "uint256[][]", "name": "tokenAmountsBySource", "type": "uint256[][]" } ], "internalType": "struct IERC20BridgeSampler.OrdersAndSample[]", "name": "ordersAndSamples", diff --git a/packages/contract-wrappers/src/generated-wrappers/i_erc20_bridge_sampler.ts b/packages/contract-wrappers/src/generated-wrappers/i_erc20_bridge_sampler.ts index 4b52879154..0fa4beb3a4 100644 --- a/packages/contract-wrappers/src/generated-wrappers/i_erc20_bridge_sampler.ts +++ b/packages/contract-wrappers/src/generated-wrappers/i_erc20_bridge_sampler.ts @@ -356,21 +356,21 @@ export class IERC20BridgeSamplerContract extends BaseContract { }, { name: 'makerTokenAmounts', - type: 'uint256[]', + type: 'uint256[][]', }, ], - name: 'queryMultipleOrdersAndSampleBuys', + name: 'queryBatchOrdersAndSampleBuys', outputs: [ { name: 'ordersAndSamples', type: 'tuple[]', components: [ { - name: 'orderFillableTakerAssetAmounts', + name: 'orderFillableAssetAmounts', type: 'uint256[]', }, { - name: 'makerTokenAmountsBySource', + name: 'tokenAmountsBySource', type: 'uint256[][]', }, ], @@ -454,22 +454,22 @@ export class IERC20BridgeSamplerContract extends BaseContract { type: 'address[]', }, { - name: 'makerTokenAmounts', - type: 'uint256[]', + name: 'takerTokenAmounts', + type: 'uint256[][]', }, ], - name: 'queryMultipleOrdersAndSampleSells', + name: 'queryBatchOrdersAndSampleSells', outputs: [ { name: 'ordersAndSamples', type: 'tuple[]', components: [ { - name: 'orderFillableTakerAssetAmounts', + name: 'orderFillableAssetAmounts', type: 'uint256[]', }, { - name: 'makerTokenAmountsBySource', + name: 'tokenAmountsBySource', type: 'uint256[][]', }, ], @@ -852,7 +852,7 @@ export class IERC20BridgeSamplerContract extends BaseContract { }, }; } - public queryMultipleOrdersAndSampleBuys( + public queryBatchOrdersAndSampleBuys( orders: Array<{ makerAddress: string; takerAddress: string; @@ -871,25 +871,21 @@ export class IERC20BridgeSamplerContract extends BaseContract { }>[], orderSignatures: string[][], sources: string[], - makerTokenAmounts: BigNumber[], - ): ContractFunctionObj< - Array<{ orderFillableTakerAssetAmounts: BigNumber[]; makerTokenAmountsBySource: BigNumber[][] }> - > { + makerTokenAmounts: BigNumber[][], + ): ContractFunctionObj> { const self = (this as any) as IERC20BridgeSamplerContract; assert.isArray('orders', orders); assert.isArray('orderSignatures', orderSignatures); assert.isArray('sources', sources); assert.isArray('makerTokenAmounts', makerTokenAmounts); const functionSignature = - 'queryMultipleOrdersAndSampleBuys((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[][],bytes[][],address[],uint256[])'; + 'queryBatchOrdersAndSampleBuys((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[][],bytes[][],address[],uint256[][])'; return { async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, - ): Promise< - Array<{ orderFillableTakerAssetAmounts: BigNumber[]; makerTokenAmountsBySource: BigNumber[][] }> - > { + ): Promise> { BaseContract._assertCallParams(callData, defaultBlock); const rawCallResult = await self._performCallAsync( { ...callData, data: this.getABIEncodedTransactionData() }, @@ -897,7 +893,7 @@ export class IERC20BridgeSamplerContract extends BaseContract { ); const abiEncoder = self._lookupAbiEncoder(functionSignature); return abiEncoder.strictDecodeReturnValue< - Array<{ orderFillableTakerAssetAmounts: BigNumber[]; makerTokenAmountsBySource: BigNumber[][] }> + Array<{ orderFillableAssetAmounts: BigNumber[]; tokenAmountsBySource: BigNumber[][] }> >(rawCallResult); }, getABIEncodedTransactionData(): string { @@ -910,7 +906,7 @@ export class IERC20BridgeSamplerContract extends BaseContract { }, }; } - public queryMultipleOrdersAndSampleSells( + public queryBatchOrdersAndSampleSells( orders: Array<{ makerAddress: string; takerAddress: string; @@ -929,25 +925,21 @@ export class IERC20BridgeSamplerContract extends BaseContract { }>[], orderSignatures: string[][], sources: string[], - makerTokenAmounts: BigNumber[], - ): ContractFunctionObj< - Array<{ orderFillableTakerAssetAmounts: BigNumber[]; makerTokenAmountsBySource: BigNumber[][] }> - > { + takerTokenAmounts: BigNumber[][], + ): ContractFunctionObj> { const self = (this as any) as IERC20BridgeSamplerContract; assert.isArray('orders', orders); assert.isArray('orderSignatures', orderSignatures); assert.isArray('sources', sources); - assert.isArray('makerTokenAmounts', makerTokenAmounts); + assert.isArray('takerTokenAmounts', takerTokenAmounts); const functionSignature = - 'queryMultipleOrdersAndSampleSells((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[][],bytes[][],address[],uint256[])'; + 'queryBatchOrdersAndSampleSells((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[][],bytes[][],address[],uint256[][])'; return { async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, - ): Promise< - Array<{ orderFillableTakerAssetAmounts: BigNumber[]; makerTokenAmountsBySource: BigNumber[][] }> - > { + ): Promise> { BaseContract._assertCallParams(callData, defaultBlock); const rawCallResult = await self._performCallAsync( { ...callData, data: this.getABIEncodedTransactionData() }, @@ -955,7 +947,7 @@ export class IERC20BridgeSamplerContract extends BaseContract { ); const abiEncoder = self._lookupAbiEncoder(functionSignature); return abiEncoder.strictDecodeReturnValue< - Array<{ orderFillableTakerAssetAmounts: BigNumber[]; makerTokenAmountsBySource: BigNumber[][] }> + Array<{ orderFillableAssetAmounts: BigNumber[]; tokenAmountsBySource: BigNumber[][] }> >(rawCallResult); }, getABIEncodedTransactionData(): string { @@ -963,7 +955,7 @@ export class IERC20BridgeSamplerContract extends BaseContract { orders, orderSignatures, sources, - makerTokenAmounts, + takerTokenAmounts, ]); }, };