fix: Update to use KNP getExpectedRateAfterFee (#2629)

* Update to use KNP getExpectedRateAfterFee

* hack: use overrides instead of forking in ganache

* fix: added some tests using overrides

* override sampler

* Overrides in bridge_sampler_mainnet_test

* use getContracts to fake out tests

* chore: supply devUtils address

* feat: specify the call override by default

* CHANGELOGs

* export SamplerOverrides

* fix package.json

* fix: after rebase
This commit is contained in:
Jacob Evans 2020-07-15 14:05:57 +10:00 committed by GitHub
parent ff9c9241d8
commit 762e0aec2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 610 additions and 234 deletions

View File

@ -84,7 +84,7 @@
"@0x/contracts-erc20": "^3.2.0", "@0x/contracts-erc20": "^3.2.0",
"@0x/contracts-erc721": "^3.1.6", "@0x/contracts-erc721": "^3.1.6",
"@0x/contracts-exchange-libs": "^4.3.6", "@0x/contracts-exchange-libs": "^4.3.6",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/types": "^3.1.3", "@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0", "@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0", "@0x/utils": "^5.5.0",

View File

@ -85,7 +85,7 @@
}, },
"dependencies": { "dependencies": {
"@0x/base-contract": "^6.2.2", "@0x/base-contract": "^6.2.2",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/typescript-typings": "^5.1.0", "@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0", "@0x/utils": "^5.5.0",
"ethereum-types": "^3.1.1" "ethereum-types": "^3.1.1"

View File

@ -60,7 +60,7 @@
"@0x/contracts-gen": "^2.0.9", "@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.3", "@0x/contracts-test-utils": "^5.3.3",
"@0x/dev-utils": "^3.2.2", "@0x/dev-utils": "^3.2.2",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0", "@0x/sol-compiler": "^4.1.0",
"@0x/ts-doc-gen": "^0.0.22", "@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0", "@0x/tslint-config": "^4.0.0",

View File

@ -1,4 +1,17 @@
[ [
{
"version": "1.7.0",
"changes": [
{
"note": "Pass in `DevUtils` address to required functions",
"pr": 2629
},
{
"note": "Use new Kyber Katalyst functions",
"pr": 2629
}
]
},
{ {
"version": "1.6.0", "version": "1.6.0",
"changes": [ "changes": [

View File

@ -30,6 +30,8 @@ import "./IERC20BridgeSampler.sol";
import "./IEth2Dai.sol"; import "./IEth2Dai.sol";
import "./IKyberNetwork.sol"; import "./IKyberNetwork.sol";
import "./IKyberNetworkProxy.sol"; import "./IKyberNetworkProxy.sol";
import "./IKyberStorage.sol";
import "./IKyberHintHandler.sol";
import "./IUniswapExchangeQuotes.sol"; import "./IUniswapExchangeQuotes.sol";
import "./ICurve.sol"; import "./ICurve.sol";
import "./ILiquidityProvider.sol"; import "./ILiquidityProvider.sol";
@ -58,16 +60,12 @@ contract ERC20BridgeSampler is
/// @dev Default gas limit for liquidity provider calls. /// @dev Default gas limit for liquidity provider calls.
uint256 constant internal DEFAULT_CALL_GAS = 400e3; // 400k uint256 constant internal DEFAULT_CALL_GAS = 400e3; // 400k
/// @dev The Kyber Uniswap Reserve address /// @dev The Kyber Uniswap Reserve address
address constant internal KYBER_UNIWAP_RESERVE = 0x31E085Afd48a1d6e51Cc193153d625e8f0514C7F; address constant internal KYBER_UNISWAP_RESERVE = 0x31E085Afd48a1d6e51Cc193153d625e8f0514C7F;
/// @dev The Kyber Uniswap V2 Reserve address
address constant internal KYBER_UNISWAPV2_RESERVE = 0x10908C875D865C66f271F5d3949848971c9595C9;
/// @dev The Kyber Eth2Dai Reserve address /// @dev The Kyber Eth2Dai Reserve address
address constant internal KYBER_ETH2DAI_RESERVE = 0x1E158c0e93c30d24e918Ef83d1e0bE23595C3c0f; address constant internal KYBER_ETH2DAI_RESERVE = 0x1E158c0e93c30d24e918Ef83d1e0bE23595C3c0f;
address private _devUtilsAddress;
constructor(address devUtilsAddress) public {
_devUtilsAddress = devUtilsAddress;
}
/// @dev Call multiple public functions on this contract in a single transaction. /// @dev Call multiple public functions on this contract in a single transaction.
/// @param callDatas ABI-encoded call data for each function call. /// @param callDatas ABI-encoded call data for each function call.
/// @return callResults ABI-encoded results data for each call. /// @return callResults ABI-encoded results data for each call.
@ -91,18 +89,19 @@ contract ERC20BridgeSampler is
/// maker/taker asset amounts (returning 0). /// maker/taker asset amounts (returning 0).
/// @param orders Native orders to query. /// @param orders Native orders to query.
/// @param orderSignatures Signatures for each respective order in `orders`. /// @param orderSignatures Signatures for each respective order in `orders`.
/// @param devUtilsAddress Address to the DevUtils contract.
/// @return orderFillableTakerAssetAmounts How much taker asset can be filled /// @return orderFillableTakerAssetAmounts How much taker asset can be filled
/// by each order in `orders`. /// by each order in `orders`.
function getOrderFillableTakerAssetAmounts( function getOrderFillableTakerAssetAmounts(
LibOrder.Order[] memory orders, LibOrder.Order[] memory orders,
bytes[] memory orderSignatures bytes[] memory orderSignatures,
address devUtilsAddress
) )
public public
view view
returns (uint256[] memory orderFillableTakerAssetAmounts) returns (uint256[] memory orderFillableTakerAssetAmounts)
{ {
orderFillableTakerAssetAmounts = new uint256[](orders.length); orderFillableTakerAssetAmounts = new uint256[](orders.length);
address devUtilsAddress = _devUtilsAddress;
for (uint256 i = 0; i != orders.length; i++) { for (uint256 i = 0; i != orders.length; i++) {
// Ignore orders with no signature or empty maker/taker amounts. // Ignore orders with no signature or empty maker/taker amounts.
if (orderSignatures[i].length == 0 || if (orderSignatures[i].length == 0 ||
@ -149,11 +148,13 @@ contract ERC20BridgeSampler is
/// Effectively ignores orders that have empty signatures or /// Effectively ignores orders that have empty signatures or
/// @param orders Native orders to query. /// @param orders Native orders to query.
/// @param orderSignatures Signatures for each respective order in `orders`. /// @param orderSignatures Signatures for each respective order in `orders`.
/// @param devUtilsAddress Address to the DevUtils contract.
/// @return orderFillableMakerAssetAmounts How much maker asset can be filled /// @return orderFillableMakerAssetAmounts How much maker asset can be filled
/// by each order in `orders`. /// by each order in `orders`.
function getOrderFillableMakerAssetAmounts( function getOrderFillableMakerAssetAmounts(
LibOrder.Order[] memory orders, LibOrder.Order[] memory orders,
bytes[] memory orderSignatures bytes[] memory orderSignatures,
address devUtilsAddress
) )
public public
view view
@ -161,7 +162,8 @@ contract ERC20BridgeSampler is
{ {
orderFillableMakerAssetAmounts = getOrderFillableTakerAssetAmounts( orderFillableMakerAssetAmounts = getOrderFillableTakerAssetAmounts(
orders, orders,
orderSignatures orderSignatures,
devUtilsAddress
); );
// `orderFillableMakerAssetAmounts` now holds taker asset amounts, so // `orderFillableMakerAssetAmounts` now holds taker asset amounts, so
// convert them to maker asset amounts. // convert them to maker asset amounts.
@ -196,26 +198,15 @@ contract ERC20BridgeSampler is
makerTokenAmounts = new uint256[](numSamples); makerTokenAmounts = new uint256[](numSamples);
address wethAddress = _getWethAddress(); address wethAddress = _getWethAddress();
uint256 value; uint256 value;
address reserve;
for (uint256 i = 0; i < numSamples; i++) { for (uint256 i = 0; i < numSamples; i++) {
if (takerToken == wethAddress || makerToken == wethAddress) { if (takerToken == wethAddress || makerToken == wethAddress) {
// Direct ETH based trade // Direct ETH based trade
(value, reserve) = _sampleSellFromKyberNetwork(takerToken, makerToken, takerTokenAmounts[i]); value = _sampleSellFromKyberNetwork(takerToken, makerToken, takerTokenAmounts[i]);
// If this fills on an on-chain reserve we remove it as that can introduce collisions
if (reserve == KYBER_UNIWAP_RESERVE || reserve == KYBER_ETH2DAI_RESERVE) {
value = 0;
}
} else { } else {
// Hop to ETH // Hop to ETH
(value, reserve) = _sampleSellFromKyberNetwork(takerToken, wethAddress, takerTokenAmounts[i]); value = _sampleSellFromKyberNetwork(takerToken, wethAddress, takerTokenAmounts[i]);
if (value != 0) { if (value != 0) {
address otherReserve; value = _sampleSellFromKyberNetwork(wethAddress, makerToken, value);
(value, otherReserve) = _sampleSellFromKyberNetwork(wethAddress, makerToken, value);
// If this fills on Eth2Dai it is ok as we queried a different market
// If this fills on Uniswap on both legs then this is a hard collision
if (reserve == KYBER_UNIWAP_RESERVE && reserve == otherReserve) {
value = 0;
}
} }
} }
makerTokenAmounts[i] = value; makerTokenAmounts[i] = value;
@ -960,6 +951,25 @@ contract ERC20BridgeSampler is
} }
} }
function _appendToList(bytes32[] memory list, bytes32 item) private view returns (bytes32[] memory appendedList)
{
appendedList = new bytes32[](list.length + 1);
for (uint256 i = 0; i < list.length; i++) {
appendedList[i] = list[i];
}
appendedList[appendedList.length - 1] = item;
}
function _getKyberAddresses()
private
view
returns (IKyberHintHandler kyberHint, IKyberStorage kyberStorage)
{
(, , kyberHint, kyberStorage, ,) = IKyberNetwork(
IKyberNetworkProxy(_getKyberNetworkProxyAddress()).kyberNetwork()).getContracts();
return (IKyberHintHandler(kyberHint), IKyberStorage(kyberStorage));
}
function _sampleSellFromKyberNetwork( function _sampleSellFromKyberNetwork(
address takerToken, address takerToken,
address makerToken, address makerToken,
@ -967,43 +977,67 @@ contract ERC20BridgeSampler is
) )
private private
view view
returns (uint256 makerTokenAmount, address reserve) returns (uint256 makerTokenAmount)
{ {
address _takerToken = takerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : takerToken; (IKyberHintHandler kyberHint, IKyberStorage kyberStorage) = _getKyberAddresses();
address _makerToken = makerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : makerToken; // Ban reserves which can clash with our internal aggregation
uint256 takerTokenDecimals = _getTokenDecimals(takerToken); bytes32[] memory reserveIds = kyberStorage.getReserveIdsPerTokenSrc(
uint256 makerTokenDecimals = _getTokenDecimals(makerToken); takerToken == _getWethAddress() ? makerToken : takerToken
(bool didSucceed, bytes memory resultData) = _getKyberNetworkProxyAddress().staticcall.gas(DEFAULT_CALL_GAS)( );
abi.encodeWithSelector( bytes32[] memory bannedReserveIds = new bytes32[](0);
IKyberNetworkProxy(0).kyberNetworkContract.selector // Poor mans resize and append
)); for (uint256 i = 0; i < reserveIds.length; i++) {
if (!didSucceed) { if (
return (0, address(0)); reserveIds[i] == kyberStorage.getReserveId(KYBER_UNISWAP_RESERVE) ||
reserveIds[i] == kyberStorage.getReserveId(KYBER_UNISWAPV2_RESERVE) ||
reserveIds[i] == kyberStorage.getReserveId(KYBER_ETH2DAI_RESERVE)
) {
bannedReserveIds = _appendToList(bannedReserveIds, reserveIds[i]);
}
} }
address kyberNetworkContract = abi.decode(resultData, (address)); // Sampler either detects X->ETH/ETH->X
(didSucceed, resultData) = // or subsamples as X->ETH-Y. So token->token here is not possible
kyberNetworkContract.staticcall.gas(KYBER_CALL_GAS)( bytes memory hint;
if (takerToken == _getWethAddress()) {
// ETH -> X
hint = kyberHint.buildEthToTokenHint(
makerToken,
IKyberHintHandler.TradeType.MaskOut,
bannedReserveIds,
new uint256[](0));
} else {
// X->ETH
hint = kyberHint.buildEthToTokenHint(
takerToken,
IKyberHintHandler.TradeType.MaskOut,
bannedReserveIds,
new uint256[](0));
}
(bool didSucceed, bytes memory resultData) =
_getKyberNetworkProxyAddress().staticcall.gas(KYBER_CALL_GAS)(
abi.encodeWithSelector( abi.encodeWithSelector(
IKyberNetwork(0).searchBestRate.selector, IKyberNetworkProxy(0).getExpectedRateAfterFee.selector,
_takerToken, takerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : takerToken,
_makerToken, makerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : makerToken,
takerTokenAmount, takerTokenAmount,
false // usePermissionless 0, // fee
hint
)); ));
uint256 rate = 0; uint256 rate = 0;
address reserve;
if (didSucceed) { if (didSucceed) {
(reserve, rate) = abi.decode(resultData, (address, uint256)); (rate) = abi.decode(resultData, (uint256));
} else { } else {
return (0, address(0)); return 0;
} }
uint256 makerTokenDecimals = _getTokenDecimals(makerToken);
uint256 takerTokenDecimals = _getTokenDecimals(takerToken);
makerTokenAmount = makerTokenAmount =
rate * rate *
takerTokenAmount * takerTokenAmount *
10 ** makerTokenDecimals / 10 ** makerTokenDecimals /
10 ** takerTokenDecimals / 10 ** takerTokenDecimals /
10 ** 18; 10 ** 18;
return makerTokenAmount;
return (makerTokenAmount, reserve);
} }
} }

View File

@ -40,11 +40,13 @@ interface IERC20BridgeSampler {
/// @dev Queries the fillable taker asset amounts of native orders. /// @dev Queries the fillable taker asset amounts of native orders.
/// @param orders Native orders to query. /// @param orders Native orders to query.
/// @param orderSignatures Signatures for each respective order in `orders`. /// @param orderSignatures Signatures for each respective order in `orders`.
/// @param devUtilsAddress Address to the DevUtils contract.
/// @return orderFillableTakerAssetAmounts How much taker asset can be filled /// @return orderFillableTakerAssetAmounts How much taker asset can be filled
/// by each order in `orders`. /// by each order in `orders`.
function getOrderFillableTakerAssetAmounts( function getOrderFillableTakerAssetAmounts(
LibOrder.Order[] calldata orders, LibOrder.Order[] calldata orders,
bytes[] calldata orderSignatures bytes[] calldata orderSignatures,
address devUtilsAddress
) )
external external
view view
@ -53,11 +55,13 @@ interface IERC20BridgeSampler {
/// @dev Queries the fillable maker asset amounts of native orders. /// @dev Queries the fillable maker asset amounts of native orders.
/// @param orders Native orders to query. /// @param orders Native orders to query.
/// @param orderSignatures Signatures for each respective order in `orders`. /// @param orderSignatures Signatures for each respective order in `orders`.
/// @param devUtilsAddress Address to the DevUtils contract.
/// @return orderFillableMakerAssetAmounts How much maker asset can be filled /// @return orderFillableMakerAssetAmounts How much maker asset can be filled
/// by each order in `orders`. /// by each order in `orders`.
function getOrderFillableMakerAssetAmounts( function getOrderFillableMakerAssetAmounts(
LibOrder.Order[] calldata orders, LibOrder.Order[] calldata orders,
bytes[] calldata orderSignatures bytes[] calldata orderSignatures,
address devUtilsAddress
) )
external external
view view

View File

@ -0,0 +1,52 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;
interface IKyberHintHandler {
function kyberStorage() external returns (address);
enum TradeType {BestOfAll, MaskIn, MaskOut, Split}
function buildTokenToEthHint(
address tokenSrc,
TradeType tokenToEthType,
bytes32[] calldata tokenToEthReserveIds,
uint256[] calldata tokenToEthSplits
) external view returns (bytes memory hint);
function buildEthToTokenHint(
address tokenDest,
TradeType ethToTokenType,
bytes32[] calldata ethToTokenReserveIds,
uint256[] calldata ethToTokenSplits
) external view returns (bytes memory hint);
function buildTokenToTokenHint(
address tokenSrc,
TradeType tokenToEthType,
bytes32[] calldata tokenToEthReserveIds,
uint256[] calldata tokenToEthSplits,
address tokenDest,
TradeType ethToTokenType,
bytes32[] calldata ethToTokenReserveIds,
uint256[] calldata ethToTokenSplits
) external view returns (bytes memory hint);
}

View File

@ -1,6 +1,6 @@
/* /*
Copyright 2019 ZeroEx Intl. Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -18,16 +18,20 @@
pragma solidity ^0.5.9; pragma solidity ^0.5.9;
import "./IKyberStorage.sol";
import "./IKyberHintHandler.sol";
interface IKyberNetwork { interface IKyberNetwork {
function searchBestRate( function getContracts()
address fromToken,
address toToken,
uint256 fromAmount,
bool usePermissionless
)
external external
view view
returns (address reserve, uint256 expectedRate); returns (
address kyberFeeHandlerAddress,
address kyberDaoAddress,
IKyberHintHandler kyberMatchingEngineAddress,
IKyberStorage kyberStorageAddress,
address gasHelperAddress,
address[] memory kyberProxyAddresses);
} }

View File

@ -1,6 +1,6 @@
/* /*
Copyright 2019 ZeroEx Intl. Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -21,14 +21,14 @@ pragma solidity ^0.5.9;
interface IKyberNetworkProxy { interface IKyberNetworkProxy {
function kyberNetworkContract() external view returns (address); function kyberNetwork() external view returns (address);
function kyberHintHandler() external view returns (address);
function getExpectedRate( function getExpectedRateAfterFee(
address fromToken, address src,
address toToken, address dest,
uint256 fromAmount uint256 srcQty,
) uint256 platformFeeBps,
external bytes calldata hint
view ) external view returns (uint256 expectedRate);
returns (uint256 expectedRate, uint256 slippageRate);
} }

View File

@ -0,0 +1,37 @@
/*
Copyright 2020 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;
interface IKyberStorage {
function getReserveId(
address reserve
)
external
view
returns (bytes32 reserveId);
function getReserveIdsPerTokenSrc(
address token
)
external
view
returns (bytes32[] memory reserveIds);
}

View File

@ -244,15 +244,17 @@ contract TestERC20BridgeSamplerUniswapV2Router01 is
} }
// solhint-disable space-after-comma
contract TestERC20BridgeSamplerKyberNetwork is contract TestERC20BridgeSamplerKyberNetwork is
IKyberNetwork,
DeploymentConstants, DeploymentConstants,
FailTrigger FailTrigger
{ {
bytes32 constant private SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7; bytes32 constant private SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7;
address constant public ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address constant public ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
function kyberNetworkContract() enum TradeType {BestOfAll, MaskIn, MaskOut, Split}
function kyberNetwork()
external external
view view
returns (address) returns (address)
@ -260,19 +262,91 @@ contract TestERC20BridgeSamplerKyberNetwork is
return address(this); return address(this);
} }
// IKyberNetwork not exposed via IKyberNetworkProxy // IKyberNetwork
function searchBestRate( function getContracts()
address fromToken, external
address toToken, view
uint256 fromAmount, returns (
bool // usePermissionless address kyberFeeHandlerAddress,
address kyberDaoAddress,
address kyberMatchingEngineAddress,
address kyberStorageAddress,
address gasHelperAddress,
address[] memory kyberProxyAddresses
)
{
return (kyberFeeHandlerAddress,
kyberDaoAddress,
address(this),
address(this),
gasHelperAddress,
kyberProxyAddresses
);
}
// IKyberStorage
function getReserveIdsPerTokenSrc(
address /* token */
) )
external external
view view
returns (address reserve, uint256 expectedRate) returns (bytes32[] memory reserveIds)
{ {
(expectedRate, ) = this.getExpectedRate(fromToken, toToken, fromAmount); return reserveIds;
return (address(this), expectedRate); }
function getReserveId(
address /* reserve */
)
external
view
returns (bytes32 reserveId)
{
return reserveId;
}
// IKyberHintHandler
function buildTokenToEthHint(
address /* tokenSrc */,
TradeType /* tokenToEthType */,
bytes32[] calldata /* tokenToEthReserveIds */,
uint256[] calldata /* tokenToEthSplits */
) external view returns (bytes memory hint)
{
return hint;
}
function buildEthToTokenHint(
address /* tokenDest */,
TradeType /* ethToTokenType */,
bytes32[] calldata /* ethToTokenReserveIds */,
uint256[] calldata /* ethToTokenSplits */
) external view returns (bytes memory hint)
{
return hint;
}
// Deterministic `IKyberNetworkProxy.getExpectedRateAfterFee()`.
function getExpectedRateAfterFee(
address fromToken,
address toToken,
uint256 /* srcQty */,
uint256 /* fee */,
bytes calldata /* hint */
)
external
view
returns
(uint256 expectedRate)
{
_revertIfShouldFail();
fromToken = fromToken == ETH_ADDRESS ? _getWethAddress() : fromToken;
toToken = toToken == ETH_ADDRESS ? _getWethAddress() : toToken;
expectedRate = LibDeterministicQuotes.getDeterministicRate(
SALT,
fromToken,
toToken
);
} }
// Deterministic `IKyberNetworkProxy.getExpectedRate()`. // Deterministic `IKyberNetworkProxy.getExpectedRate()`.
@ -294,6 +368,14 @@ contract TestERC20BridgeSamplerKyberNetwork is
toToken toToken
); );
} }
function _getKyberNetworkProxyAddress()
internal
view
returns (address)
{
return address(this);
}
} }
@ -381,7 +463,7 @@ contract TestERC20BridgeSampler is
uint8 private constant MAX_ORDER_STATUS = uint8(LibOrder.OrderStatus.CANCELLED) + 1; uint8 private constant MAX_ORDER_STATUS = uint8(LibOrder.OrderStatus.CANCELLED) + 1;
constructor() public ERC20BridgeSampler(address(this)) { constructor() public ERC20BridgeSampler() {
uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory(); uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory();
uniswapV2Router = new TestERC20BridgeSamplerUniswapV2Router01(); uniswapV2Router = new TestERC20BridgeSamplerUniswapV2Router01();
eth2Dai = new TestERC20BridgeSamplerEth2Dai(); eth2Dai = new TestERC20BridgeSamplerEth2Dai();

View File

@ -38,7 +38,7 @@
"config": { "config": {
"publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler,ILiquidityProvider,ILiquidityProviderRegistry,DummyLiquidityProviderRegistry,DummyLiquidityProvider", "publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler,ILiquidityProvider,ILiquidityProviderRegistry,DummyLiquidityProviderRegistry,DummyLiquidityProvider",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|IKyberNetworkProxy|ILiquidityProvider|ILiquidityProviderRegistry|IMultiBridge|IUniswapExchangeQuotes|IUniswapV2Router01|TestERC20BridgeSampler).json" "abis": "./test/generated-artifacts/@(DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberHintHandler|IKyberNetwork|IKyberNetworkProxy|IKyberStorage|ILiquidityProvider|ILiquidityProviderRegistry|IMultiBridge|IUniswapExchangeQuotes|IUniswapV2Router01|TestERC20BridgeSampler).json"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -12,8 +12,10 @@ import * as ICurve from '../test/generated-artifacts/ICurve.json';
import * as IDevUtils from '../test/generated-artifacts/IDevUtils.json'; import * as IDevUtils from '../test/generated-artifacts/IDevUtils.json';
import * as IERC20BridgeSampler from '../test/generated-artifacts/IERC20BridgeSampler.json'; import * as IERC20BridgeSampler from '../test/generated-artifacts/IERC20BridgeSampler.json';
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json'; import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
import * as IKyberHintHandler from '../test/generated-artifacts/IKyberHintHandler.json';
import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json'; import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json';
import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json'; import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json';
import * as IKyberStorage from '../test/generated-artifacts/IKyberStorage.json';
import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvider.json'; import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvider.json';
import * as ILiquidityProviderRegistry from '../test/generated-artifacts/ILiquidityProviderRegistry.json'; import * as ILiquidityProviderRegistry from '../test/generated-artifacts/ILiquidityProviderRegistry.json';
import * as IMultiBridge from '../test/generated-artifacts/IMultiBridge.json'; import * as IMultiBridge from '../test/generated-artifacts/IMultiBridge.json';
@ -28,8 +30,10 @@ export const artifacts = {
IDevUtils: IDevUtils as ContractArtifact, IDevUtils: IDevUtils as ContractArtifact,
IERC20BridgeSampler: IERC20BridgeSampler as ContractArtifact, IERC20BridgeSampler: IERC20BridgeSampler as ContractArtifact,
IEth2Dai: IEth2Dai as ContractArtifact, IEth2Dai: IEth2Dai as ContractArtifact,
IKyberHintHandler: IKyberHintHandler as ContractArtifact,
IKyberNetwork: IKyberNetwork as ContractArtifact, IKyberNetwork: IKyberNetwork as ContractArtifact,
IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact, IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
IKyberStorage: IKyberStorage as ContractArtifact,
ILiquidityProvider: ILiquidityProvider as ContractArtifact, ILiquidityProvider: ILiquidityProvider as ContractArtifact,
ILiquidityProviderRegistry: ILiquidityProviderRegistry as ContractArtifact, ILiquidityProviderRegistry: ILiquidityProviderRegistry as ContractArtifact,
IMultiBridge: IMultiBridge as ContractArtifact, IMultiBridge: IMultiBridge as ContractArtifact,

View File

@ -33,6 +33,7 @@ blockchainTests('erc20-bridge-sampler', env => {
const INVALID_TOKEN_PAIR_ERROR = 'ERC20BridgeSampler/INVALID_TOKEN_PAIR'; const INVALID_TOKEN_PAIR_ERROR = 'ERC20BridgeSampler/INVALID_TOKEN_PAIR';
const MAKER_TOKEN = randomAddress(); const MAKER_TOKEN = randomAddress();
const TAKER_TOKEN = randomAddress(); const TAKER_TOKEN = randomAddress();
let devUtilsAddress: string;
const FAKE_BUY_OPTS = { const FAKE_BUY_OPTS = {
targetSlippageBps: new BigNumber(5), targetSlippageBps: new BigNumber(5),
maxIterations: new BigNumber(5), maxIterations: new BigNumber(5),
@ -45,6 +46,8 @@ blockchainTests('erc20-bridge-sampler', env => {
env.txDefaults, env.txDefaults,
{}, {},
); );
// TestERC20BridgeSampler stubs DevUtils
devUtilsAddress = testContract.address;
}); });
function getPackedHash(...args: string[]): string { function getPackedHash(...args: string[]): string {
@ -272,12 +275,14 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN); const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN);
const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const expected = orders.map(getDeterministicFillableTakerAssetAmount); const expected = orders.map(getDeterministicFillableTakerAssetAmount);
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync(); const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq(expected); expect(actual).to.deep.eq(expected);
}); });
it('returns empty for no orders', async () => { it('returns empty for no orders', async () => {
const actual = await testContract.getOrderFillableTakerAssetAmounts([], []).callAsync(); const actual = await testContract.getOrderFillableTakerAssetAmounts([], [], devUtilsAddress).callAsync();
expect(actual).to.deep.eq([]); expect(actual).to.deep.eq([]);
}); });
@ -285,7 +290,9 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].makerAssetAmount = constants.ZERO_AMOUNT; orders[0].makerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync(); const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
}); });
@ -293,14 +300,18 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].takerAssetAmount = constants.ZERO_AMOUNT; orders[0].takerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync(); const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
}); });
it('returns zero for an order with an empty signature', async () => { it('returns zero for an order with an empty signature', async () => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
const signatures: string[] = _.times(orders.length, () => constants.NULL_BYTES); const signatures: string[] = _.times(orders.length, () => constants.NULL_BYTES);
const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync(); const actual = await testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
}); });
}); });
@ -310,12 +321,14 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN); const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN);
const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const expected = orders.map(getDeterministicFillableMakerAssetAmount); const expected = orders.map(getDeterministicFillableMakerAssetAmount);
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync(); const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq(expected); expect(actual).to.deep.eq(expected);
}); });
it('returns empty for no orders', async () => { it('returns empty for no orders', async () => {
const actual = await testContract.getOrderFillableMakerAssetAmounts([], []).callAsync(); const actual = await testContract.getOrderFillableMakerAssetAmounts([], [], devUtilsAddress).callAsync();
expect(actual).to.deep.eq([]); expect(actual).to.deep.eq([]);
}); });
@ -323,7 +336,9 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].makerAssetAmount = constants.ZERO_AMOUNT; orders[0].makerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync(); const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
}); });
@ -331,14 +346,18 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].takerAssetAmount = constants.ZERO_AMOUNT; orders[0].takerAssetAmount = constants.ZERO_AMOUNT;
const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync(); const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
}); });
it('returns zero for an order with an empty signature', async () => { it('returns zero for an order with an empty signature', async () => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
const signatures: string[] = _.times(orders.length, () => constants.NULL_BYTES); const signatures: string[] = _.times(orders.length, () => constants.NULL_BYTES);
const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync(); const actual = await testContract
.getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress)
.callAsync();
expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); expect(actual).to.deep.eq([constants.ZERO_AMOUNT]);
}); });
}); });
@ -1029,7 +1048,9 @@ blockchainTests('erc20-bridge-sampler', env => {
const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const expected = orders.map(getDeterministicFillableTakerAssetAmount); const expected = orders.map(getDeterministicFillableTakerAssetAmount);
const calls = [ const calls = [
testContract.getOrderFillableTakerAssetAmounts(orders, signatures).getABIEncodedTransactionData(), testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
]; ];
const r = await testContract.batchCall(calls).callAsync(); const r = await testContract.batchCall(calls).callAsync();
expect(r).to.be.length(1); expect(r).to.be.length(1);
@ -1046,8 +1067,12 @@ blockchainTests('erc20-bridge-sampler', env => {
orders[1].map(getDeterministicFillableMakerAssetAmount), orders[1].map(getDeterministicFillableMakerAssetAmount),
]; ];
const calls = [ const calls = [
testContract.getOrderFillableTakerAssetAmounts(orders[0], signatures).getABIEncodedTransactionData(), testContract
testContract.getOrderFillableMakerAssetAmounts(orders[1], signatures).getABIEncodedTransactionData(), .getOrderFillableTakerAssetAmounts(orders[0], signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
testContract
.getOrderFillableMakerAssetAmounts(orders[1], signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
]; ];
const r = await testContract.batchCall(calls).callAsync(); const r = await testContract.batchCall(calls).callAsync();
expect(r).to.be.length(2); expect(r).to.be.length(2);
@ -1069,7 +1094,7 @@ blockchainTests('erc20-bridge-sampler', env => {
testContract testContract
.batchCall([ .batchCall([
testContract testContract
.getOrderFillableTakerAssetAmounts(orders, signatures) .getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
]) ])
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),

View File

@ -10,8 +10,10 @@ export * from '../test/generated-wrappers/i_curve';
export * from '../test/generated-wrappers/i_dev_utils'; export * from '../test/generated-wrappers/i_dev_utils';
export * from '../test/generated-wrappers/i_erc20_bridge_sampler'; export * from '../test/generated-wrappers/i_erc20_bridge_sampler';
export * from '../test/generated-wrappers/i_eth2_dai'; export * from '../test/generated-wrappers/i_eth2_dai';
export * from '../test/generated-wrappers/i_kyber_hint_handler';
export * from '../test/generated-wrappers/i_kyber_network'; export * from '../test/generated-wrappers/i_kyber_network';
export * from '../test/generated-wrappers/i_kyber_network_proxy'; export * from '../test/generated-wrappers/i_kyber_network_proxy';
export * from '../test/generated-wrappers/i_kyber_storage';
export * from '../test/generated-wrappers/i_liquidity_provider'; export * from '../test/generated-wrappers/i_liquidity_provider';
export * from '../test/generated-wrappers/i_liquidity_provider_registry'; export * from '../test/generated-wrappers/i_liquidity_provider_registry';
export * from '../test/generated-wrappers/i_multi_bridge'; export * from '../test/generated-wrappers/i_multi_bridge';

View File

@ -16,8 +16,10 @@
"test/generated-artifacts/IDevUtils.json", "test/generated-artifacts/IDevUtils.json",
"test/generated-artifacts/IERC20BridgeSampler.json", "test/generated-artifacts/IERC20BridgeSampler.json",
"test/generated-artifacts/IEth2Dai.json", "test/generated-artifacts/IEth2Dai.json",
"test/generated-artifacts/IKyberHintHandler.json",
"test/generated-artifacts/IKyberNetwork.json", "test/generated-artifacts/IKyberNetwork.json",
"test/generated-artifacts/IKyberNetworkProxy.json", "test/generated-artifacts/IKyberNetworkProxy.json",
"test/generated-artifacts/IKyberStorage.json",
"test/generated-artifacts/ILiquidityProvider.json", "test/generated-artifacts/ILiquidityProvider.json",
"test/generated-artifacts/ILiquidityProviderRegistry.json", "test/generated-artifacts/ILiquidityProviderRegistry.json",
"test/generated-artifacts/IMultiBridge.json", "test/generated-artifacts/IMultiBridge.json",

View File

@ -64,7 +64,7 @@
"@0x/contracts-test-utils": "^5.3.3", "@0x/contracts-test-utils": "^5.3.3",
"@0x/contracts-utils": "^4.5.0", "@0x/contracts-utils": "^4.5.0",
"@0x/dev-utils": "^3.2.2", "@0x/dev-utils": "^3.2.2",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0", "@0x/sol-compiler": "^4.1.0",
"@0x/ts-doc-gen": "^0.0.22", "@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0", "@0x/tslint-config": "^4.0.0",

View File

@ -83,7 +83,7 @@
"@0x/base-contract": "^6.2.2", "@0x/base-contract": "^6.2.2",
"@0x/contracts-test-utils": "^5.3.3", "@0x/contracts-test-utils": "^5.3.3",
"@0x/contracts-utils": "^4.5.0", "@0x/contracts-utils": "^4.5.0",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/types": "^3.1.3", "@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0", "@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0", "@0x/utils": "^5.5.0",

View File

@ -93,7 +93,7 @@
"@0x/contracts-erc1155": "^2.1.6", "@0x/contracts-erc1155": "^2.1.6",
"@0x/contracts-erc20": "^3.2.0", "@0x/contracts-erc20": "^3.2.0",
"@0x/contracts-erc721": "^3.1.6", "@0x/contracts-erc721": "^3.1.6",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/utils": "^5.5.0", "@0x/utils": "^5.5.0",
"lodash": "^4.17.11" "lodash": "^4.17.11"
}, },

View File

@ -62,7 +62,7 @@
"@0x/contracts-test-utils": "^5.3.3", "@0x/contracts-test-utils": "^5.3.3",
"@0x/contracts-utils": "^4.5.0", "@0x/contracts-utils": "^4.5.0",
"@0x/dev-utils": "^3.2.2", "@0x/dev-utils": "^3.2.2",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0", "@0x/sol-compiler": "^4.1.0",
"@0x/ts-doc-gen": "^0.0.22", "@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0", "@0x/tslint-config": "^4.0.0",

View File

@ -66,7 +66,7 @@
"@0x/coordinator-server": "^1.0.5", "@0x/coordinator-server": "^1.0.5",
"@0x/dev-utils": "^3.2.2", "@0x/dev-utils": "^3.2.2",
"@0x/migrations": "^6.3.0", "@0x/migrations": "^6.3.0",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0", "@0x/sol-compiler": "^4.1.0",
"@0x/tslint-config": "^4.0.0", "@0x/tslint-config": "^4.0.0",
"@0x/web3-wrapper": "^7.1.0", "@0x/web3-wrapper": "^7.1.0",

View File

@ -1,6 +1,7 @@
import { artifacts, ERC20BridgeSamplerContract } from '@0x/contracts-erc20-bridge-sampler'; import { artifacts, ERC20BridgeSamplerContract } from '@0x/contracts-erc20-bridge-sampler';
import { blockchainTests, constants, describe, expect, toBaseUnitAmount } from '@0x/contracts-test-utils'; import { blockchainTests, describe, expect, toBaseUnitAmount, Web3ProviderEngine } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils'; import { RPCSubprovider } from '@0x/dev-utils/node_modules/@0x/subproviders';
import { BigNumber, providerUtils } from '@0x/utils';
export const VB = '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b'; export const VB = '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b';
blockchainTests.configure({ blockchainTests.configure({
@ -11,14 +12,21 @@ blockchainTests.configure({
blockchainTests.fork.resets('Mainnet Sampler Tests', env => { blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
let testContract: ERC20BridgeSamplerContract; let testContract: ERC20BridgeSamplerContract;
const fakeSamplerAddress = '0x1111111111111111111111111111111111111111';
const overrides = {
[fakeSamplerAddress]: {
code: artifacts.ERC20BridgeSampler.compilerOutput.evm.deployedBytecode.object,
},
};
before(async () => { before(async () => {
testContract = await ERC20BridgeSamplerContract.deployFrom0xArtifactAsync( const provider = new Web3ProviderEngine();
artifacts.ERC20BridgeSampler, // tslint:disable-next-line:no-non-null-assertion
env.provider, provider.addProvider(new RPCSubprovider(process.env.FORK_RPC_URL!));
{ ...env.txDefaults, from: VB }, providerUtils.startProviderEngine(provider);
{}, testContract = new ERC20BridgeSamplerContract(fakeSamplerAddress, provider, {
constants.NULL_ADDRESS, ...env.txDefaults,
); from: VB,
});
}); });
describe('Curve', () => { describe('Curve', () => {
const CURVE_ADDRESS = '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56'; const CURVE_ADDRESS = '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56';
@ -29,7 +37,7 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
it('samples sells from Curve DAI->USDC', async () => { it('samples sells from Curve DAI->USDC', async () => {
const samples = await testContract const samples = await testContract
.sampleSellsFromCurve(CURVE_ADDRESS, DAI_TOKEN_INDEX, USDC_TOKEN_INDEX, [toBaseUnitAmount(1)]) .sampleSellsFromCurve(CURVE_ADDRESS, DAI_TOKEN_INDEX, USDC_TOKEN_INDEX, [toBaseUnitAmount(1)])
.callAsync(); .callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0); expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0); expect(samples[0]).to.be.bignumber.greaterThan(0);
}); });
@ -37,7 +45,7 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
it('samples sells from Curve USDC->DAI', async () => { it('samples sells from Curve USDC->DAI', async () => {
const samples = await testContract const samples = await testContract
.sampleSellsFromCurve(CURVE_ADDRESS, USDC_TOKEN_INDEX, DAI_TOKEN_INDEX, [toBaseUnitAmount(1, 6)]) .sampleSellsFromCurve(CURVE_ADDRESS, USDC_TOKEN_INDEX, DAI_TOKEN_INDEX, [toBaseUnitAmount(1, 6)])
.callAsync(); .callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0); expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0); expect(samples[0]).to.be.bignumber.greaterThan(0);
}); });
@ -49,7 +57,7 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
// I want to buy 1 USDC // I want to buy 1 USDC
const samples = await testContract const samples = await testContract
.sampleBuysFromCurve(CURVE_ADDRESS, DAI_TOKEN_INDEX, USDC_TOKEN_INDEX, [toBaseUnitAmount(1, 6)]) .sampleBuysFromCurve(CURVE_ADDRESS, DAI_TOKEN_INDEX, USDC_TOKEN_INDEX, [toBaseUnitAmount(1, 6)])
.callAsync(); .callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0); expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0); expect(samples[0]).to.be.bignumber.greaterThan(0);
}); });
@ -59,7 +67,7 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
// I want to buy 1 DAI // I want to buy 1 DAI
const samples = await testContract const samples = await testContract
.sampleBuysFromCurve(CURVE_ADDRESS, USDC_TOKEN_INDEX, DAI_TOKEN_INDEX, [toBaseUnitAmount(1)]) .sampleBuysFromCurve(CURVE_ADDRESS, USDC_TOKEN_INDEX, DAI_TOKEN_INDEX, [toBaseUnitAmount(1)])
.callAsync(); .callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0); expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0); expect(samples[0]).to.be.bignumber.greaterThan(0);
}); });
@ -70,16 +78,40 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
targetSlippageBps: new BigNumber(5), targetSlippageBps: new BigNumber(5),
maxIterations: new BigNumber(5), maxIterations: new BigNumber(5),
}; };
const DAI_ADDRESS = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; const WETH = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
const WETH_ADDRESS = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'; const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f';
const USDC = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
describe('sampleSellsFromKyberNetwork()', () => {
it('samples sells from Kyber DAI->WETH', async () => {
const samples = await testContract
.sampleSellsFromKyberNetwork(DAI, WETH, [toBaseUnitAmount(1)])
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});
it('samples sells from Kyber WETH->DAI', async () => {
const samples = await testContract
.sampleSellsFromKyberNetwork(WETH, DAI, [toBaseUnitAmount(1)])
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});
it('samples sells from Kyber DAI->USDC', async () => {
const samples = await testContract
.sampleSellsFromKyberNetwork(DAI, USDC, [toBaseUnitAmount(1)])
.callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0);
});
});
describe('sampleBuysFromKyber()', () => { describe('sampleBuysFromKyber()', () => {
it('samples buys from Kyber WETH->DAI', async () => { it('samples buys from Kyber WETH->DAI', async () => {
// From ETH to DAI // From ETH to DAI
// I want to buy 1 DAI // I want to buy 1 DAI
const samples = await testContract const samples = await testContract
.sampleBuysFromKyberNetwork(WETH_ADDRESS, DAI_ADDRESS, [toBaseUnitAmount(1)], FAKE_BUY_OPTS) .sampleBuysFromKyberNetwork(WETH, DAI, [toBaseUnitAmount(1)], FAKE_BUY_OPTS)
.callAsync(); .callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0); expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0); expect(samples[0]).to.be.bignumber.greaterThan(0);
}); });
@ -88,8 +120,8 @@ blockchainTests.fork.resets('Mainnet Sampler Tests', env => {
// From USDC to DAI // From USDC to DAI
// I want to buy 1 WETH // I want to buy 1 WETH
const samples = await testContract const samples = await testContract
.sampleBuysFromKyberNetwork(DAI_ADDRESS, WETH_ADDRESS, [toBaseUnitAmount(1)], FAKE_BUY_OPTS) .sampleBuysFromKyberNetwork(DAI, WETH, [toBaseUnitAmount(1)], FAKE_BUY_OPTS)
.callAsync(); .callAsync({ overrides });
expect(samples.length).to.be.bignumber.greaterThan(0); expect(samples.length).to.be.bignumber.greaterThan(0);
expect(samples[0]).to.be.bignumber.greaterThan(0); expect(samples[0]).to.be.bignumber.greaterThan(0);
}); });

View File

@ -61,7 +61,7 @@
"@0x/contracts-gen": "^2.0.9", "@0x/contracts-gen": "^2.0.9",
"@0x/contracts-utils": "^4.5.0", "@0x/contracts-utils": "^4.5.0",
"@0x/dev-utils": "^3.2.2", "@0x/dev-utils": "^3.2.2",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0", "@0x/sol-compiler": "^4.1.0",
"@0x/ts-doc-gen": "^0.0.22", "@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0", "@0x/tslint-config": "^4.0.0",

View File

@ -47,9 +47,9 @@
"@0x/contract-addresses": "^4.10.0", "@0x/contract-addresses": "^4.10.0",
"@0x/dev-utils": "^3.2.2", "@0x/dev-utils": "^3.2.2",
"@0x/json-schemas": "^5.0.8", "@0x/json-schemas": "^5.0.8",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/sol-coverage": "^4.0.9", "@0x/sol-coverage": "^4.0.9",
"@0x/sol-profiler": "^4.1.0", "@0x/sol-profiler": "^4.0.9",
"@0x/sol-trace": "^3.0.9", "@0x/sol-trace": "^3.0.9",
"@0x/subproviders": "^6.1.0", "@0x/subproviders": "^6.1.0",
"@0x/types": "^3.1.3", "@0x/types": "^3.1.3",

View File

@ -27,7 +27,7 @@ contract DeploymentConstants {
/// @dev Mainnet address of the WETH contract. /// @dev Mainnet address of the WETH contract.
address constant private WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address constant private WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
/// @dev Mainnet address of the KyberNetworkProxy contract. /// @dev Mainnet address of the KyberNetworkProxy contract.
address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x818E6FECD516Ecc3849DAf6845e3EC868087B755; address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x9AAb3f75489902f3a48495025729a0AF77d4b11e;
/// @dev Mainnet address of the `UniswapExchangeFactory` contract. /// @dev Mainnet address of the `UniswapExchangeFactory` contract.
address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95; address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
/// @dev Mainnet address of the `UniswapV2Router01` contract. /// @dev Mainnet address of the `UniswapV2Router01` contract.

View File

@ -54,7 +54,7 @@
"@0x/contracts-gen": "^2.0.9", "@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.3", "@0x/contracts-test-utils": "^5.3.3",
"@0x/dev-utils": "^3.2.2", "@0x/dev-utils": "^3.2.2",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0", "@0x/sol-compiler": "^4.1.0",
"@0x/tslint-config": "^4.0.0", "@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3", "@0x/types": "^3.1.3",

View File

@ -57,7 +57,7 @@
"@0x/contracts-gen": "^2.0.9", "@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.3", "@0x/contracts-test-utils": "^5.3.3",
"@0x/dev-utils": "^3.2.2", "@0x/dev-utils": "^3.2.2",
"@0x/order-utils": "^10.3.0", "@0x/order-utils": "^10.2.5",
"@0x/sol-compiler": "^4.1.0", "@0x/sol-compiler": "^4.1.0",
"@0x/ts-doc-gen": "^0.0.22", "@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0", "@0x/tslint-config": "^4.0.0",

View File

@ -37,6 +37,10 @@
{ {
"note": "Change gas/fee schedule values from constants to functions returning numbers", "note": "Change gas/fee schedule values from constants to functions returning numbers",
"pr": 2613 "pr": 2613
},
{
"note": "Specify overrides to the ERC20Sampler contract, by default the latest bytecode is the override",
"pr": 2629
} }
] ]
}, },

View File

@ -49,6 +49,7 @@
"@0x/assert": "^3.0.8", "@0x/assert": "^3.0.8",
"@0x/contract-addresses": "^4.10.0", "@0x/contract-addresses": "^4.10.0",
"@0x/contract-wrappers": "^13.7.0", "@0x/contract-wrappers": "^13.7.0",
"@0x/contract-artifacts": "^3.7.0",
"@0x/json-schemas": "^5.0.8", "@0x/json-schemas": "^5.0.8",
"@0x/order-utils": "^10.2.5", "@0x/order-utils": "^10.2.5",
"@0x/orderbook": "^2.2.6", "@0x/orderbook": "^2.2.6",

View File

@ -12,15 +12,18 @@ export {
SRAPollingOrderProviderOpts, SRAPollingOrderProviderOpts,
SRAWebsocketOrderProviderOpts, SRAWebsocketOrderProviderOpts,
} from '@0x/orderbook'; } from '@0x/orderbook';
export { RFQTIndicativeQuote, RFQTFirmQuote } from '@0x/quote-server'; export { RFQTFirmQuote, RFQTIndicativeQuote } from '@0x/quote-server';
export { APIOrder, Asset, AssetPairsItem, SignedOrder } from '@0x/types'; export { APIOrder, Asset, AssetPairsItem, SignedOrder } from '@0x/types';
export { BigNumber } from '@0x/utils'; export { BigNumber } from '@0x/utils';
export { export {
BlockParam,
BlockParamLiteral,
DataItem, DataItem,
EIP1193Event, EIP1193Event,
EIP1193Provider, EIP1193Provider,
EventParameter, EventParameter,
GanacheProvider, GanacheProvider,
GethCallOverrides,
JSONRPCErrorCallback, JSONRPCErrorCallback,
JSONRPCRequestPayload, JSONRPCRequestPayload,
JSONRPCResponseError, JSONRPCResponseError,
@ -38,6 +41,7 @@ export { SwapQuoteConsumer } from './quote_consumers/swap_quote_consumer';
export { SwapQuoter } from './swap_quoter'; export { SwapQuoter } from './swap_quoter';
export { export {
CalldataInfo, CalldataInfo,
ExchangeProxyContractOpts,
ExtensionContractType, ExtensionContractType,
ForwarderExtensionContractOpts, ForwarderExtensionContractOpts,
GetExtensionContractTypeOpts, GetExtensionContractTypeOpts,
@ -49,34 +53,34 @@ export {
MockedRfqtFirmQuoteResponse, MockedRfqtFirmQuoteResponse,
RfqtMakerAssetOfferings, RfqtMakerAssetOfferings,
RfqtRequestOpts, RfqtRequestOpts,
SamplerOverrides,
SignedOrderWithFillableAmounts,
SwapQuote, SwapQuote,
SwapQuoteConsumerBase, SwapQuoteConsumerBase,
SwapQuoteConsumerError,
SwapQuoteConsumerOpts, SwapQuoteConsumerOpts,
SwapQuoteExecutionOpts, SwapQuoteExecutionOpts,
SwapQuoteGetOutputOpts, SwapQuoteGetOutputOpts,
SwapQuoteInfo, SwapQuoteInfo,
SwapQuoteOrdersBreakdown,
SwapQuoteRequestOpts, SwapQuoteRequestOpts,
SwapQuoterError, SwapQuoterError,
SwapQuoterOpts, SwapQuoterOpts,
SwapQuoteConsumerError,
SignedOrderWithFillableAmounts,
SwapQuoteOrdersBreakdown,
ExchangeProxyContractOpts,
} from './types'; } from './types';
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
export { export {
ERC20BridgeSource, BalancerFillData,
CollapsedFill, CollapsedFill,
NativeCollapsedFill, CurveFillData,
OptimizedMarketOrder, ERC20BridgeSource,
GetMarketOrdersRfqtOpts,
FeeSchedule, FeeSchedule,
FillData, FillData,
GetMarketOrdersRfqtOpts,
NativeCollapsedFill,
NativeFillData, NativeFillData,
CurveFillData, OptimizedMarketOrder,
BalancerFillData,
UniswapV2FillData, UniswapV2FillData,
} from './utils/market_operation_utils/types'; } from './utils/market_operation_utils/types';
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
export { ProtocolFeeUtils } from './utils/protocol_fee_utils'; export { ProtocolFeeUtils } from './utils/protocol_fee_utils';
export { QuoteRequestor } from './utils/quote_requestor'; export { QuoteRequestor } from './utils/quote_requestor';
export { rfqtMocker } from './utils/rfqt_mocker'; export { rfqtMocker } from './utils/rfqt_mocker';

View File

@ -1,10 +1,11 @@
import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses'; import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { DevUtilsContract, IERC20BridgeSamplerContract } from '@0x/contract-wrappers'; import { ERC20BridgeSampler } from '@0x/contract-artifacts';
import { DevUtilsContract, ERC20BridgeSamplerContract } from '@0x/contract-wrappers';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { assetDataUtils, SignedOrder } from '@0x/order-utils'; import { assetDataUtils, SignedOrder } from '@0x/order-utils';
import { MeshOrderProviderOpts, Orderbook, SRAPollingOrderProviderOpts } from '@0x/orderbook'; import { MeshOrderProviderOpts, Orderbook, SRAPollingOrderProviderOpts } from '@0x/orderbook';
import { BigNumber, providerUtils } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { SupportedProvider, ZeroExProvider } from 'ethereum-types'; import { BlockParamLiteral, SupportedProvider, ZeroExProvider } from 'ethereum-types';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { constants } from './constants'; import { constants } from './constants';
@ -185,13 +186,27 @@ export class SwapQuoter {
rfqt ? rfqt.infoLogger : undefined, rfqt ? rfqt.infoLogger : undefined,
expiryBufferMs, expiryBufferMs,
); );
const sampler = new DexOrderSampler( // Allow the sampler bytecode to be overwritten using geths override functionality
new IERC20BridgeSamplerContract(this._contractAddresses.erc20BridgeSampler, this.provider, { const samplerBytecode = _.get(ERC20BridgeSampler, 'compilerOutput.evm.deployedBytecode.object');
const defaultCodeOverrides = samplerBytecode
? {
[this._contractAddresses.erc20BridgeSampler]: { code: samplerBytecode },
}
: {};
const samplerOverrides = _.merge(
{},
{ block: BlockParamLiteral.Latest, overrides: defaultCodeOverrides },
options.samplerOverrides,
);
const samplerContract = new ERC20BridgeSamplerContract(
this._contractAddresses.erc20BridgeSampler,
this.provider,
{
gas: samplerGasLimit, gas: samplerGasLimit,
}), },
); );
this._marketOperationUtils = new MarketOperationUtils( this._marketOperationUtils = new MarketOperationUtils(
sampler, new DexOrderSampler(samplerContract, samplerOverrides),
this._contractAddresses, this._contractAddresses,
{ {
chainId, chainId,

View File

@ -1,4 +1,4 @@
import { ContractAddresses } from '@0x/contract-wrappers'; import { BlockParam, ContractAddresses, GethCallOverrides } from '@0x/contract-wrappers';
import { SignedOrder } from '@0x/types'; import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
@ -253,6 +253,7 @@ export interface SwapQuoterOpts extends OrderPrunerOpts {
warningLogger?: LogFunction; warningLogger?: LogFunction;
infoLogger?: LogFunction; infoLogger?: LogFunction;
}; };
samplerOverrides?: SamplerOverrides;
} }
/** /**
@ -328,3 +329,8 @@ export interface MockedRfqtIndicativeQuoteResponse {
responseData: any; responseData: any;
responseCode: number; responseCode: number;
} }
export interface SamplerOverrides {
overrides: GethCallOverrides;
block: BlockParam;
}

View File

@ -83,7 +83,7 @@ export class MarketOperationUtils {
// Call the sampler contract. // Call the sampler contract.
const samplerPromise = this._sampler.executeAsync( const samplerPromise = this._sampler.executeAsync(
// Get native order fillable amounts. // Get native order fillable amounts.
DexOrderSampler.ops.getOrderFillableTakerAmounts(nativeOrders), DexOrderSampler.ops.getOrderFillableTakerAmounts(nativeOrders, this.contractAddresses.devUtils),
// Get the custom liquidity provider from registry. // Get the custom liquidity provider from registry.
DexOrderSampler.ops.getLiquidityProviderFromRegistry( DexOrderSampler.ops.getLiquidityProviderFromRegistry(
this._liquidityProviderRegistry, this._liquidityProviderRegistry,
@ -187,7 +187,7 @@ export class MarketOperationUtils {
// Call the sampler contract. // Call the sampler contract.
const samplerPromise = this._sampler.executeAsync( const samplerPromise = this._sampler.executeAsync(
// Get native order fillable amounts. // Get native order fillable amounts.
DexOrderSampler.ops.getOrderFillableMakerAmounts(nativeOrders), DexOrderSampler.ops.getOrderFillableMakerAmounts(nativeOrders, this.contractAddresses.devUtils),
// Get the custom liquidity provider from registry. // Get the custom liquidity provider from registry.
DexOrderSampler.ops.getLiquidityProviderFromRegistry( DexOrderSampler.ops.getLiquidityProviderFromRegistry(
this._liquidityProviderRegistry, this._liquidityProviderRegistry,
@ -291,7 +291,9 @@ export class MarketOperationUtils {
const sources = difference(BUY_SOURCES, _opts.excludedSources); const sources = difference(BUY_SOURCES, _opts.excludedSources);
const ops = [ const ops = [
...batchNativeOrders.map(orders => DexOrderSampler.ops.getOrderFillableMakerAmounts(orders)), ...batchNativeOrders.map(orders =>
DexOrderSampler.ops.getOrderFillableMakerAmounts(orders, this.contractAddresses.devUtils),
),
...(await Promise.all( ...(await Promise.all(
batchNativeOrders.map(async orders => batchNativeOrders.map(async orders =>
DexOrderSampler.ops.getMedianSellRateAsync( DexOrderSampler.ops.getMedianSellRateAsync(

View File

@ -1,6 +1,8 @@
import { IERC20BridgeSamplerContract } from '@0x/contract-wrappers'; import { ERC20BridgeSamplerContract } from '@0x/contract-wrappers';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { SamplerOverrides } from '../../types';
import { BalancerPoolsCache } from './balancer_utils'; import { BalancerPoolsCache } from './balancer_utils';
import { samplerOperations } from './sampler_operations'; import { samplerOperations } from './sampler_operations';
import { BatchedOperation } from './types'; import { BatchedOperation } from './types';
@ -35,7 +37,8 @@ export class DexOrderSampler {
public static ops = samplerOperations; public static ops = samplerOperations;
constructor( constructor(
private readonly _samplerContract: IERC20BridgeSamplerContract, private readonly _samplerContract: ERC20BridgeSamplerContract,
private readonly _samplerOverrides?: SamplerOverrides,
public balancerPoolsCache: BalancerPoolsCache = new BalancerPoolsCache(), public balancerPoolsCache: BalancerPoolsCache = new BalancerPoolsCache(),
) {} ) {}
@ -138,8 +141,13 @@ export class DexOrderSampler {
*/ */
public async executeBatchAsync<T extends Array<BatchedOperation<any>>>(ops: T): Promise<any[]> { public async executeBatchAsync<T extends Array<BatchedOperation<any>>>(ops: T): Promise<any[]> {
const callDatas = ops.map(o => o.encodeCall(this._samplerContract)); const callDatas = ops.map(o => o.encodeCall(this._samplerContract));
const { overrides, block } = this._samplerOverrides
? this._samplerOverrides
: { overrides: undefined, block: undefined };
// Execute all non-empty calldatas. // Execute all non-empty calldatas.
const rawCallResults = await this._samplerContract.batchCall(callDatas.filter(cd => cd !== '0x')).callAsync(); const rawCallResults = await this._samplerContract
.batchCall(callDatas.filter(cd => cd !== '0x'))
.callAsync({ overrides }, block);
// Return the parsed results. // Return the parsed results.
let rawCallResultsIdx = 0; let rawCallResultsIdx = 0;
return Promise.all( return Promise.all(

View File

@ -21,11 +21,11 @@ import {
* for use with `DexOrderSampler.executeAsync()`. * for use with `DexOrderSampler.executeAsync()`.
*/ */
export const samplerOperations = { export const samplerOperations = {
getOrderFillableTakerAmounts(orders: SignedOrder[]): BatchedOperation<BigNumber[]> { getOrderFillableTakerAmounts(orders: SignedOrder[], devUtilsAddress: string): BatchedOperation<BigNumber[]> {
return { return {
encodeCall: contract => { encodeCall: contract => {
return contract return contract
.getOrderFillableTakerAssetAmounts(orders, orders.map(o => o.signature)) .getOrderFillableTakerAssetAmounts(orders, orders.map(o => o.signature), devUtilsAddress)
.getABIEncodedTransactionData(); .getABIEncodedTransactionData();
}, },
handleCallResultsAsync: async (contract, callResults) => { handleCallResultsAsync: async (contract, callResults) => {
@ -33,11 +33,11 @@ export const samplerOperations = {
}, },
}; };
}, },
getOrderFillableMakerAmounts(orders: SignedOrder[]): BatchedOperation<BigNumber[]> { getOrderFillableMakerAmounts(orders: SignedOrder[], devUtilsAddress: string): BatchedOperation<BigNumber[]> {
return { return {
encodeCall: contract => { encodeCall: contract => {
return contract return contract
.getOrderFillableMakerAssetAmounts(orders, orders.map(o => o.signature)) .getOrderFillableMakerAssetAmounts(orders, orders.map(o => o.signature), devUtilsAddress)
.getABIEncodedTransactionData(); .getABIEncodedTransactionData();
}, },
handleCallResultsAsync: async (contract, callResults) => { handleCallResultsAsync: async (contract, callResults) => {

View File

@ -1,4 +1,4 @@
import { IERC20BridgeSamplerContract } from '@0x/contract-wrappers'; import { ERC20BridgeSamplerContract } from '@0x/contract-wrappers';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { RfqtRequestOpts, SignedOrderWithFillableAmounts } from '../../types'; import { RfqtRequestOpts, SignedOrderWithFillableAmounts } from '../../types';
@ -220,8 +220,8 @@ export interface GetMarketOrdersOpts {
* A composable operation the be run in `DexOrderSampler.executeAsync()`. * A composable operation the be run in `DexOrderSampler.executeAsync()`.
*/ */
export interface BatchedOperation<TResult> { export interface BatchedOperation<TResult> {
encodeCall(contract: IERC20BridgeSamplerContract): string; encodeCall(contract: ERC20BridgeSamplerContract): string;
handleCallResultsAsync(contract: IERC20BridgeSamplerContract, callResults: string): Promise<TResult>; handleCallResultsAsync(contract: ERC20BridgeSamplerContract, callResults: string): Promise<TResult>;
} }
export interface SourceQuoteOperation<TFillData extends FillData = FillData> extends BatchedOperation<BigNumber[]> { export interface SourceQuoteOperation<TFillData extends FillData = FillData> extends BatchedOperation<BigNumber[]> {

View File

@ -32,6 +32,7 @@ describe('DexSampler tests', () => {
const TAKER_ASSET_DATA = assetDataUtils.encodeERC20AssetData(TAKER_TOKEN); const TAKER_ASSET_DATA = assetDataUtils.encodeERC20AssetData(TAKER_TOKEN);
const wethAddress = getContractAddressesForChainOrThrow(CHAIN_ID).etherToken; const wethAddress = getContractAddressesForChainOrThrow(CHAIN_ID).etherToken;
const devUtilsAddress = getContractAddressesForChainOrThrow(CHAIN_ID).devUtils;
describe('getSampleAmounts()', () => { describe('getSampleAmounts()', () => {
const FILL_AMOUNT = getRandomInteger(1, 1e18); const FILL_AMOUNT = getRandomInteger(1, 1e18);
@ -105,7 +106,7 @@ describe('DexSampler tests', () => {
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(sampler);
const [fillableAmounts] = await dexOrderSampler.executeAsync( const [fillableAmounts] = await dexOrderSampler.executeAsync(
DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS), DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS, devUtilsAddress),
); );
expect(fillableAmounts).to.deep.eq(expectedFillableAmounts); expect(fillableAmounts).to.deep.eq(expectedFillableAmounts);
}); });
@ -121,7 +122,7 @@ describe('DexSampler tests', () => {
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(sampler);
const [fillableAmounts] = await dexOrderSampler.executeAsync( const [fillableAmounts] = await dexOrderSampler.executeAsync(
DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS), DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS, devUtilsAddress),
); );
expect(fillableAmounts).to.deep.eq(expectedFillableAmounts); expect(fillableAmounts).to.deep.eq(expectedFillableAmounts);
}); });
@ -483,7 +484,7 @@ describe('DexSampler tests', () => {
return Promise.resolve(pools); return Promise.resolve(pools);
}, },
}); });
const dexOrderSampler = new DexOrderSampler(new MockSamplerContract({}), balancerPoolsCache); const dexOrderSampler = new DexOrderSampler(new MockSamplerContract({}), undefined, balancerPoolsCache);
const [quotes] = await dexOrderSampler.executeAsync( const [quotes] = await dexOrderSampler.executeAsync(
await DexOrderSampler.ops.getSellQuotesAsync( await DexOrderSampler.ops.getSellQuotesAsync(
[ERC20BridgeSource.Balancer], [ERC20BridgeSource.Balancer],
@ -589,7 +590,7 @@ describe('DexSampler tests', () => {
return Promise.resolve(pools); return Promise.resolve(pools);
}, },
}); });
const dexOrderSampler = new DexOrderSampler(new MockSamplerContract({}), balancerPoolsCache); const dexOrderSampler = new DexOrderSampler(new MockSamplerContract({}), undefined, balancerPoolsCache);
const [quotes] = await dexOrderSampler.executeAsync( const [quotes] = await dexOrderSampler.executeAsync(
await DexOrderSampler.ops.getBuyQuotesAsync( await DexOrderSampler.ops.getBuyQuotesAsync(
[ERC20BridgeSource.Balancer], [ERC20BridgeSource.Balancer],
@ -631,8 +632,8 @@ describe('DexSampler tests', () => {
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(sampler);
const [fillableMakerAmounts, fillableTakerAmounts] = await dexOrderSampler.executeAsync( const [fillableMakerAmounts, fillableTakerAmounts] = await dexOrderSampler.executeAsync(
DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS), DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS, devUtilsAddress),
DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS), DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS, devUtilsAddress),
); );
expect(fillableMakerAmounts).to.deep.eq(expectedFillableMakerAmounts); expect(fillableMakerAmounts).to.deep.eq(expectedFillableMakerAmounts);
expect(fillableTakerAmounts).to.deep.eq(expectedFillableTakerAmounts); expect(fillableTakerAmounts).to.deep.eq(expectedFillableTakerAmounts);

View File

@ -1,5 +1,5 @@
import { ContractFunctionObj } from '@0x/base-contract'; import { ContractFunctionObj } from '@0x/base-contract';
import { IERC20BridgeSamplerContract } from '@0x/contract-wrappers'; import { ERC20BridgeSamplerContract } from '@0x/contract-wrappers';
import { constants } from '@0x/contracts-test-utils'; import { constants } from '@0x/contracts-test-utils';
import { Order } from '@0x/types'; import { Order } from '@0x/types';
import { BigNumber, hexUtils } from '@0x/utils'; import { BigNumber, hexUtils } from '@0x/utils';
@ -8,6 +8,7 @@ export type GetOrderFillableAssetAmountResult = BigNumber[];
export type GetOrderFillableAssetAmountHandler = ( export type GetOrderFillableAssetAmountHandler = (
orders: Order[], orders: Order[],
signatures: string[], signatures: string[],
devUtilsAddress: string,
) => GetOrderFillableAssetAmountResult; ) => GetOrderFillableAssetAmountResult;
export type SampleResults = BigNumber[]; export type SampleResults = BigNumber[];
@ -58,7 +59,7 @@ interface Handlers {
sampleBuysFromLiquidityProviderRegistry: SampleSellsLPHandler; sampleBuysFromLiquidityProviderRegistry: SampleSellsLPHandler;
} }
export class MockSamplerContract extends IERC20BridgeSamplerContract { export class MockSamplerContract extends ERC20BridgeSamplerContract {
private readonly _handlers: Partial<Handlers> = {}; private readonly _handlers: Partial<Handlers> = {};
public constructor(handlers: Partial<Handlers> = {}) { public constructor(handlers: Partial<Handlers> = {}) {
@ -82,6 +83,7 @@ export class MockSamplerContract extends IERC20BridgeSamplerContract {
this._handlers.getOrderFillableMakerAssetAmounts, this._handlers.getOrderFillableMakerAssetAmounts,
orders, orders,
signatures, signatures,
constants.NULL_ADDRESS,
); );
} }
@ -94,6 +96,7 @@ export class MockSamplerContract extends IERC20BridgeSamplerContract {
this._handlers.getOrderFillableTakerAssetAmounts, this._handlers.getOrderFillableTakerAssetAmounts,
orders, orders,
signatures, signatures,
constants.NULL_ADDRESS,
); );
} }

View File

@ -1,4 +1,17 @@
[ [
{
"version": "3.7.0",
"changes": [
{
"note": "Provide devUtils address as a function parameter in ERC20BridgeSampler",
"pr": 2629
},
{
"note": "Remove devUtils address from ERC20BridgeSampler constructor",
"pr": 2629
}
]
},
{ {
"version": "3.7.0", "version": "3.7.0",
"changes": [ "changes": [

File diff suppressed because one or more lines are too long

View File

@ -49,7 +49,8 @@
"name": "orders", "name": "orders",
"type": "tuple[]" "type": "tuple[]"
}, },
{ "internalType": "bytes[]", "name": "orderSignatures", "type": "bytes[]" } { "internalType": "bytes[]", "name": "orderSignatures", "type": "bytes[]" },
{ "internalType": "address", "name": "devUtilsAddress", "type": "address" }
], ],
"name": "getOrderFillableMakerAssetAmounts", "name": "getOrderFillableMakerAssetAmounts",
"outputs": [ "outputs": [
@ -83,7 +84,8 @@
"name": "orders", "name": "orders",
"type": "tuple[]" "type": "tuple[]"
}, },
{ "internalType": "bytes[]", "name": "orderSignatures", "type": "bytes[]" } { "internalType": "bytes[]", "name": "orderSignatures", "type": "bytes[]" },
{ "internalType": "address", "name": "devUtilsAddress", "type": "address" }
], ],
"name": "getOrderFillableTakerAssetAmounts", "name": "getOrderFillableTakerAssetAmounts",
"outputs": [ "outputs": [
@ -300,17 +302,19 @@
}, },
"return": "providerAddress Address of the liquidity provider." "return": "providerAddress Address of the liquidity provider."
}, },
"getOrderFillableMakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[])": { "getOrderFillableMakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)": {
"details": "Queries the fillable maker asset amounts of native orders.", "details": "Queries the fillable maker asset amounts of native orders.",
"params": { "params": {
"devUtilsAddress": "Address to the DevUtils contract.",
"orderSignatures": "Signatures for each respective order in `orders`.", "orderSignatures": "Signatures for each respective order in `orders`.",
"orders": "Native orders to query." "orders": "Native orders to query."
}, },
"return": "orderFillableMakerAssetAmounts How much maker asset can be filled by each order in `orders`." "return": "orderFillableMakerAssetAmounts How much maker asset can be filled by each order in `orders`."
}, },
"getOrderFillableTakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[])": { "getOrderFillableTakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)": {
"details": "Queries the fillable taker asset amounts of native orders.", "details": "Queries the fillable taker asset amounts of native orders.",
"params": { "params": {
"devUtilsAddress": "Address to the DevUtils contract.",
"orderSignatures": "Signatures for each respective order in `orders`.", "orderSignatures": "Signatures for each respective order in `orders`.",
"orders": "Native orders to query." "orders": "Native orders to query."
}, },

View File

@ -7,6 +7,8 @@ import * as DummyERC20Token from '../artifacts/DummyERC20Token.json';
import * as DummyERC721Token from '../artifacts/DummyERC721Token.json'; import * as DummyERC721Token from '../artifacts/DummyERC721Token.json';
import * as ERC1155Mintable from '../artifacts/ERC1155Mintable.json'; import * as ERC1155Mintable from '../artifacts/ERC1155Mintable.json';
import * as ERC1155Proxy from '../artifacts/ERC1155Proxy.json'; import * as ERC1155Proxy from '../artifacts/ERC1155Proxy.json';
import * as ERC20BridgeProxy from '../artifacts/ERC20BridgeProxy.json';
import * as ERC20BridgeSampler from '../artifacts/ERC20BridgeSampler.json';
import * as ERC20Proxy from '../artifacts/ERC20Proxy.json'; import * as ERC20Proxy from '../artifacts/ERC20Proxy.json';
import * as ERC20Token from '../artifacts/ERC20Token.json'; import * as ERC20Token from '../artifacts/ERC20Token.json';
import * as ERC721Proxy from '../artifacts/ERC721Proxy.json'; import * as ERC721Proxy from '../artifacts/ERC721Proxy.json';
@ -15,6 +17,7 @@ import * as Exchange from '../artifacts/Exchange.json';
import * as Forwarder from '../artifacts/Forwarder.json'; import * as Forwarder from '../artifacts/Forwarder.json';
import * as GodsUnchainedValidator from '../artifacts/GodsUnchainedValidator.json'; import * as GodsUnchainedValidator from '../artifacts/GodsUnchainedValidator.json';
import * as IAssetProxy from '../artifacts/IAssetProxy.json'; import * as IAssetProxy from '../artifacts/IAssetProxy.json';
import * as ITransformERC20 from '../artifacts/ITransformERC20.json';
import * as IValidator from '../artifacts/IValidator.json'; import * as IValidator from '../artifacts/IValidator.json';
import * as IWallet from '../artifacts/IWallet.json'; import * as IWallet from '../artifacts/IWallet.json';
import * as MultiAssetProxy from '../artifacts/MultiAssetProxy.json'; import * as MultiAssetProxy from '../artifacts/MultiAssetProxy.json';
@ -23,10 +26,7 @@ import * as StakingProxy from '../artifacts/StakingProxy.json';
import * as StaticCallProxy from '../artifacts/StaticCallProxy.json'; import * as StaticCallProxy from '../artifacts/StaticCallProxy.json';
import * as WETH9 from '../artifacts/WETH9.json'; import * as WETH9 from '../artifacts/WETH9.json';
import * as ZRXToken from '../artifacts/ZRXToken.json'; import * as ZRXToken from '../artifacts/ZRXToken.json';
import * as ERC20BridgeProxy from '../artifacts/ERC20BridgeProxy.json';
import * as ZrxVault from '../artifacts/ZrxVault.json'; import * as ZrxVault from '../artifacts/ZrxVault.json';
import * as IERC20BridgeSampler from '../artifacts/IERC20BridgeSampler.json';
import * as ITransformERC20 from '../artifacts/ITransformERC20.json';
export { export {
AssetProxyOwner, AssetProxyOwner,
@ -56,6 +56,6 @@ export {
Staking, Staking,
StakingProxy, StakingProxy,
ZrxVault, ZrxVault,
IERC20BridgeSampler, ERC20BridgeSampler,
ITransformERC20, ITransformERC20,
}; };

View File

@ -36,7 +36,7 @@
"./artifacts/StakingProxy.json", "./artifacts/StakingProxy.json",
"./artifacts/ZrxVault.json", "./artifacts/ZrxVault.json",
"./artifacts/ERC20BridgeProxy.json", "./artifacts/ERC20BridgeProxy.json",
"./artifacts/IERC20BridgeSampler.json", "./artifacts/ERC20BridgeSampler.json",
"./artifacts/ITransformERC20.json" "./artifacts/ITransformERC20.json"
] ]
} }

View File

@ -49,7 +49,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>, txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
devUtilsAddress: string,
): Promise<ERC20BridgeSamplerContract> { ): Promise<ERC20BridgeSamplerContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema, schemas.addressSchema,
@ -74,7 +73,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
provider, provider,
txDefaults, txDefaults,
logDecodeDependenciesAbiOnly, logDecodeDependenciesAbiOnly,
devUtilsAddress,
); );
} }
@ -84,7 +82,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>, txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
devUtilsAddress: string,
): Promise<ERC20BridgeSamplerContract> { ): Promise<ERC20BridgeSamplerContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema, schemas.addressSchema,
@ -115,7 +112,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
provider, provider,
txDefaults, txDefaults,
logDecodeDependenciesAbiOnly, logDecodeDependenciesAbiOnly,
devUtilsAddress,
); );
} }
@ -125,7 +121,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>, txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractAbi }, logDecodeDependencies: { [contractName: string]: ContractAbi },
devUtilsAddress: string,
): Promise<ERC20BridgeSamplerContract> { ): Promise<ERC20BridgeSamplerContract> {
assert.isHexString('bytecode', bytecode); assert.isHexString('bytecode', bytecode);
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
@ -135,14 +130,10 @@ export class ERC20BridgeSamplerContract extends BaseContract {
]); ]);
const provider = providerUtils.standardizeOrThrow(supportedProvider); const provider = providerUtils.standardizeOrThrow(supportedProvider);
const constructorAbi = BaseContract._lookupConstructorAbi(abi); const constructorAbi = BaseContract._lookupConstructorAbi(abi);
[devUtilsAddress] = BaseContract._formatABIDataItemList( [] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString);
constructorAbi.inputs,
[devUtilsAddress],
BaseContract._bigNumberToString,
);
const iface = new ethers.utils.Interface(abi); const iface = new ethers.utils.Interface(abi);
const deployInfo = iface.deployFunction; const deployInfo = iface.deployFunction;
const txData = deployInfo.encode(bytecode, [devUtilsAddress]); const txData = deployInfo.encode(bytecode, []);
const web3Wrapper = new Web3Wrapper(provider); const web3Wrapper = new Web3Wrapper(provider);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync( const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{ {
@ -161,7 +152,7 @@ export class ERC20BridgeSamplerContract extends BaseContract {
txDefaults, txDefaults,
logDecodeDependencies, logDecodeDependencies,
); );
contractInstance.constructorArgs = [devUtilsAddress]; contractInstance.constructorArgs = [];
return contractInstance; return contractInstance;
} }
@ -170,18 +161,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
*/ */
public static ABI(): ContractAbi { public static ABI(): ContractAbi {
const abi = [ const abi = [
{
inputs: [
{
name: 'devUtilsAddress',
type: 'address',
},
],
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'constructor',
},
{ {
constant: true, constant: true,
inputs: [ inputs: [
@ -297,6 +276,10 @@ export class ERC20BridgeSamplerContract extends BaseContract {
name: 'orderSignatures', name: 'orderSignatures',
type: 'bytes[]', type: 'bytes[]',
}, },
{
name: 'devUtilsAddress',
type: 'address',
},
], ],
name: 'getOrderFillableMakerAssetAmounts', name: 'getOrderFillableMakerAssetAmounts',
outputs: [ outputs: [
@ -378,6 +361,10 @@ export class ERC20BridgeSamplerContract extends BaseContract {
name: 'orderSignatures', name: 'orderSignatures',
type: 'bytes[]', type: 'bytes[]',
}, },
{
name: 'devUtilsAddress',
type: 'address',
},
], ],
name: 'getOrderFillableTakerAssetAmounts', name: 'getOrderFillableTakerAssetAmounts',
outputs: [ outputs: [
@ -965,6 +952,7 @@ export class ERC20BridgeSamplerContract extends BaseContract {
* Effectively ignores orders that have empty signatures or * Effectively ignores orders that have empty signatures or
* @param orders Native orders to query. * @param orders Native orders to query.
* @param orderSignatures Signatures for each respective order in `orders`. * @param orderSignatures Signatures for each respective order in `orders`.
* @param devUtilsAddress Address to the DevUtils contract.
* @returns orderFillableMakerAssetAmounts How much maker asset can be filled by each order in &#x60;orders&#x60;. * @returns orderFillableMakerAssetAmounts How much maker asset can be filled by each order in &#x60;orders&#x60;.
*/ */
public getOrderFillableMakerAssetAmounts( public getOrderFillableMakerAssetAmounts(
@ -985,12 +973,14 @@ export class ERC20BridgeSamplerContract extends BaseContract {
takerFeeAssetData: string; takerFeeAssetData: string;
}>, }>,
orderSignatures: string[], orderSignatures: string[],
devUtilsAddress: string,
): ContractFunctionObj<BigNumber[]> { ): ContractFunctionObj<BigNumber[]> {
const self = (this as any) as ERC20BridgeSamplerContract; const self = (this as any) as ERC20BridgeSamplerContract;
assert.isArray('orders', orders); assert.isArray('orders', orders);
assert.isArray('orderSignatures', orderSignatures); assert.isArray('orderSignatures', orderSignatures);
assert.isString('devUtilsAddress', devUtilsAddress);
const functionSignature = const functionSignature =
'getOrderFillableMakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[])'; 'getOrderFillableMakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)';
return { return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> { async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> {
@ -1004,7 +994,11 @@ export class ERC20BridgeSamplerContract extends BaseContract {
return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult); return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult);
}, },
getABIEncodedTransactionData(): string { getABIEncodedTransactionData(): string {
return self._strictEncodeArguments(functionSignature, [orders, orderSignatures]); return self._strictEncodeArguments(functionSignature, [
orders,
orderSignatures,
devUtilsAddress.toLowerCase(),
]);
}, },
}; };
} }
@ -1014,6 +1008,7 @@ export class ERC20BridgeSamplerContract extends BaseContract {
* maker/taker asset amounts (returning 0). * maker/taker asset amounts (returning 0).
* @param orders Native orders to query. * @param orders Native orders to query.
* @param orderSignatures Signatures for each respective order in `orders`. * @param orderSignatures Signatures for each respective order in `orders`.
* @param devUtilsAddress Address to the DevUtils contract.
* @returns orderFillableTakerAssetAmounts How much taker asset can be filled by each order in &#x60;orders&#x60;. * @returns orderFillableTakerAssetAmounts How much taker asset can be filled by each order in &#x60;orders&#x60;.
*/ */
public getOrderFillableTakerAssetAmounts( public getOrderFillableTakerAssetAmounts(
@ -1034,12 +1029,14 @@ export class ERC20BridgeSamplerContract extends BaseContract {
takerFeeAssetData: string; takerFeeAssetData: string;
}>, }>,
orderSignatures: string[], orderSignatures: string[],
devUtilsAddress: string,
): ContractFunctionObj<BigNumber[]> { ): ContractFunctionObj<BigNumber[]> {
const self = (this as any) as ERC20BridgeSamplerContract; const self = (this as any) as ERC20BridgeSamplerContract;
assert.isArray('orders', orders); assert.isArray('orders', orders);
assert.isArray('orderSignatures', orderSignatures); assert.isArray('orderSignatures', orderSignatures);
assert.isString('devUtilsAddress', devUtilsAddress);
const functionSignature = const functionSignature =
'getOrderFillableTakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[])'; 'getOrderFillableTakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)';
return { return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> { async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> {
@ -1053,7 +1050,11 @@ export class ERC20BridgeSamplerContract extends BaseContract {
return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult); return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult);
}, },
getABIEncodedTransactionData(): string { getABIEncodedTransactionData(): string {
return self._strictEncodeArguments(functionSignature, [orders, orderSignatures]); return self._strictEncodeArguments(functionSignature, [
orders,
orderSignatures,
devUtilsAddress.toLowerCase(),
]);
}, },
}; };
} }

View File

@ -276,6 +276,10 @@ export class IERC20BridgeSamplerContract extends BaseContract {
name: 'orderSignatures', name: 'orderSignatures',
type: 'bytes[]', type: 'bytes[]',
}, },
{
name: 'devUtilsAddress',
type: 'address',
},
], ],
name: 'getOrderFillableMakerAssetAmounts', name: 'getOrderFillableMakerAssetAmounts',
outputs: [ outputs: [
@ -357,6 +361,10 @@ export class IERC20BridgeSamplerContract extends BaseContract {
name: 'orderSignatures', name: 'orderSignatures',
type: 'bytes[]', type: 'bytes[]',
}, },
{
name: 'devUtilsAddress',
type: 'address',
},
], ],
name: 'getOrderFillableTakerAssetAmounts', name: 'getOrderFillableTakerAssetAmounts',
outputs: [ outputs: [
@ -912,6 +920,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
* Queries the fillable maker asset amounts of native orders. * Queries the fillable maker asset amounts of native orders.
* @param orders Native orders to query. * @param orders Native orders to query.
* @param orderSignatures Signatures for each respective order in `orders`. * @param orderSignatures Signatures for each respective order in `orders`.
* @param devUtilsAddress Address to the DevUtils contract.
* @returns orderFillableMakerAssetAmounts How much maker asset can be filled by each order in &#x60;orders&#x60;. * @returns orderFillableMakerAssetAmounts How much maker asset can be filled by each order in &#x60;orders&#x60;.
*/ */
public getOrderFillableMakerAssetAmounts( public getOrderFillableMakerAssetAmounts(
@ -932,12 +941,14 @@ export class IERC20BridgeSamplerContract extends BaseContract {
takerFeeAssetData: string; takerFeeAssetData: string;
}>, }>,
orderSignatures: string[], orderSignatures: string[],
devUtilsAddress: string,
): ContractFunctionObj<BigNumber[]> { ): ContractFunctionObj<BigNumber[]> {
const self = (this as any) as IERC20BridgeSamplerContract; const self = (this as any) as IERC20BridgeSamplerContract;
assert.isArray('orders', orders); assert.isArray('orders', orders);
assert.isArray('orderSignatures', orderSignatures); assert.isArray('orderSignatures', orderSignatures);
assert.isString('devUtilsAddress', devUtilsAddress);
const functionSignature = const functionSignature =
'getOrderFillableMakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[])'; 'getOrderFillableMakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)';
return { return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> { async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> {
@ -951,7 +962,11 @@ export class IERC20BridgeSamplerContract extends BaseContract {
return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult); return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult);
}, },
getABIEncodedTransactionData(): string { getABIEncodedTransactionData(): string {
return self._strictEncodeArguments(functionSignature, [orders, orderSignatures]); return self._strictEncodeArguments(functionSignature, [
orders,
orderSignatures,
devUtilsAddress.toLowerCase(),
]);
}, },
}; };
} }
@ -959,6 +974,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
* Queries the fillable taker asset amounts of native orders. * Queries the fillable taker asset amounts of native orders.
* @param orders Native orders to query. * @param orders Native orders to query.
* @param orderSignatures Signatures for each respective order in `orders`. * @param orderSignatures Signatures for each respective order in `orders`.
* @param devUtilsAddress Address to the DevUtils contract.
* @returns orderFillableTakerAssetAmounts How much taker asset can be filled by each order in &#x60;orders&#x60;. * @returns orderFillableTakerAssetAmounts How much taker asset can be filled by each order in &#x60;orders&#x60;.
*/ */
public getOrderFillableTakerAssetAmounts( public getOrderFillableTakerAssetAmounts(
@ -979,12 +995,14 @@ export class IERC20BridgeSamplerContract extends BaseContract {
takerFeeAssetData: string; takerFeeAssetData: string;
}>, }>,
orderSignatures: string[], orderSignatures: string[],
devUtilsAddress: string,
): ContractFunctionObj<BigNumber[]> { ): ContractFunctionObj<BigNumber[]> {
const self = (this as any) as IERC20BridgeSamplerContract; const self = (this as any) as IERC20BridgeSamplerContract;
assert.isArray('orders', orders); assert.isArray('orders', orders);
assert.isArray('orderSignatures', orderSignatures); assert.isArray('orderSignatures', orderSignatures);
assert.isString('devUtilsAddress', devUtilsAddress);
const functionSignature = const functionSignature =
'getOrderFillableTakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[])'; 'getOrderFillableTakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)';
return { return {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> { async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> {
@ -998,7 +1016,11 @@ export class IERC20BridgeSamplerContract extends BaseContract {
return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult); return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult);
}, },
getABIEncodedTransactionData(): string { getABIEncodedTransactionData(): string {
return self._strictEncodeArguments(functionSignature, [orders, orderSignatures]); return self._strictEncodeArguments(functionSignature, [
orders,
orderSignatures,
devUtilsAddress.toLowerCase(),
]);
}, },
}; };
} }

View File

@ -28,7 +28,7 @@
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts-gen/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts-gen/README.md",
"dependencies": { "dependencies": {
"@0x/sol-compiler": "^4.1.0", "@0x/sol-compiler": "^4.1.0",
"@0x/sol-resolver": "^3.1.0", "@0x/sol-resolver": "^3.0.4",
"@0x/types": "^3.1.3", "@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0", "@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0", "@0x/utils": "^5.5.0",

View File

@ -300,7 +300,6 @@ export async function runMigrationsAsync(
provider, provider,
txDefaults, txDefaults,
allArtifacts, allArtifacts,
devUtils.address,
); );
// Exchange Proxy ////////////////////////////////////////////////////////// // Exchange Proxy //////////////////////////////////////////////////////////

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/order-utils", "name": "@0x/order-utils",
"version": "10.3.0", "version": "10.2.5",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },

View File

@ -76,7 +76,7 @@
"dependencies": { "dependencies": {
"@0x/assert": "^3.0.8", "@0x/assert": "^3.0.8",
"@0x/json-schemas": "^5.0.8", "@0x/json-schemas": "^5.0.8",
"@0x/sol-resolver": "^3.1.0", "@0x/sol-resolver": "^3.0.4",
"@0x/types": "^3.1.3", "@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0", "@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0", "@0x/utils": "^5.5.0",

View File

@ -33,7 +33,7 @@
}, },
"homepage": "https://github.com/0xProject/0x-monorepo/packages/sol-coverage/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/packages/sol-coverage/README.md",
"dependencies": { "dependencies": {
"@0x/sol-tracing-utils": "^7.1.0", "@0x/sol-tracing-utils": "^7.0.9",
"@0x/subproviders": "^6.1.0", "@0x/subproviders": "^6.1.0",
"@0x/typescript-typings": "^5.1.0", "@0x/typescript-typings": "^5.1.0",
"@types/minimatch": "^3.0.3", "@types/minimatch": "^3.0.3",

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/sol-profiler", "name": "@0x/sol-profiler",
"version": "4.1.0", "version": "4.0.9",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -33,7 +33,7 @@
}, },
"homepage": "https://github.com/0xProject/0x-monorepo/packages/sol-profiler/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/packages/sol-profiler/README.md",
"dependencies": { "dependencies": {
"@0x/sol-tracing-utils": "^7.1.0", "@0x/sol-tracing-utils": "^7.0.9",
"@0x/subproviders": "^6.1.0", "@0x/subproviders": "^6.1.0",
"@0x/typescript-typings": "^5.1.0", "@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0", "@0x/utils": "^5.5.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/sol-resolver", "name": "@0x/sol-resolver",
"version": "3.1.0", "version": "3.0.4",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },

View File

@ -33,7 +33,7 @@
}, },
"homepage": "https://github.com/0xProject/0x-monorepo/packages/sol-trace/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/packages/sol-trace/README.md",
"dependencies": { "dependencies": {
"@0x/sol-tracing-utils": "^7.1.0", "@0x/sol-tracing-utils": "^7.0.9",
"@0x/subproviders": "^6.1.0", "@0x/subproviders": "^6.1.0",
"@0x/typescript-typings": "^5.1.0", "@0x/typescript-typings": "^5.1.0",
"chalk": "^2.3.0", "chalk": "^2.3.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/sol-tracing-utils", "name": "@0x/sol-tracing-utils",
"version": "7.1.0", "version": "7.0.9",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -40,7 +40,7 @@
"dependencies": { "dependencies": {
"@0x/dev-utils": "^3.2.2", "@0x/dev-utils": "^3.2.2",
"@0x/sol-compiler": "^4.1.0", "@0x/sol-compiler": "^4.1.0",
"@0x/sol-resolver": "^3.1.0", "@0x/sol-resolver": "^3.0.4",
"@0x/subproviders": "^6.1.0", "@0x/subproviders": "^6.1.0",
"@0x/typescript-typings": "^5.1.0", "@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0", "@0x/utils": "^5.5.0",

View File

@ -5,6 +5,10 @@
{ {
"note": "Add geth eth_call support", "note": "Add geth eth_call support",
"pr": 2620 "pr": 2620
},
{
"note": "Remove duplicate overrides data from the eth_call rpc call",
"pr": 2629
} }
] ]
}, },

View File

@ -16,8 +16,6 @@ import {
import ethUtil = require('ethereumjs-util'); import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash'; import * as _ from 'lodash';
import { utils } from './utils';
import { import {
BlockWithoutTransactionDataRPC, BlockWithoutTransactionDataRPC,
BlockWithTransactionDataRPC, BlockWithTransactionDataRPC,
@ -28,6 +26,7 @@ import {
TransactionRPC, TransactionRPC,
TxDataRPC, TxDataRPC,
} from './types'; } from './types';
import { utils } from './utils';
/** /**
* Utils to convert ethereum structures from user-space format to RPC format. (marshall/unmarshall) * Utils to convert ethereum structures from user-space format to RPC format. (marshall/unmarshall)
@ -163,6 +162,7 @@ export const marshaller = {
...callData, ...callData,
}; };
delete callTxDataBase.from; delete callTxDataBase.from;
delete callTxDataBase.overrides;
const callTxDataBaseRPC = marshaller._marshalCallTxDataBase(callTxDataBase); const callTxDataBaseRPC = marshaller._marshalCallTxDataBase(callTxDataBase);
const callDataRPC = { const callDataRPC = {
...callTxDataBaseRPC, ...callTxDataBaseRPC,