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-erc721": "^3.1.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/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",

View File

@ -85,7 +85,7 @@
},
"dependencies": {
"@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/utils": "^5.5.0",
"ethereum-types": "^3.1.1"

View File

@ -60,7 +60,7 @@
"@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.3",
"@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/ts-doc-gen": "^0.0.22",
"@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",
"changes": [

View File

@ -30,6 +30,8 @@ import "./IERC20BridgeSampler.sol";
import "./IEth2Dai.sol";
import "./IKyberNetwork.sol";
import "./IKyberNetworkProxy.sol";
import "./IKyberStorage.sol";
import "./IKyberHintHandler.sol";
import "./IUniswapExchangeQuotes.sol";
import "./ICurve.sol";
import "./ILiquidityProvider.sol";
@ -58,16 +60,12 @@ contract ERC20BridgeSampler is
/// @dev Default gas limit for liquidity provider calls.
uint256 constant internal DEFAULT_CALL_GAS = 400e3; // 400k
/// @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
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.
/// @param callDatas ABI-encoded call data for each function call.
/// @return callResults ABI-encoded results data for each call.
@ -91,18 +89,19 @@ contract ERC20BridgeSampler is
/// maker/taker asset amounts (returning 0).
/// @param orders Native orders to query.
/// @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
/// by each order in `orders`.
function getOrderFillableTakerAssetAmounts(
LibOrder.Order[] memory orders,
bytes[] memory orderSignatures
bytes[] memory orderSignatures,
address devUtilsAddress
)
public
view
returns (uint256[] memory orderFillableTakerAssetAmounts)
{
orderFillableTakerAssetAmounts = new uint256[](orders.length);
address devUtilsAddress = _devUtilsAddress;
for (uint256 i = 0; i != orders.length; i++) {
// Ignore orders with no signature or empty maker/taker amounts.
if (orderSignatures[i].length == 0 ||
@ -149,11 +148,13 @@ contract ERC20BridgeSampler is
/// Effectively ignores orders that have empty signatures or
/// @param orders Native orders to query.
/// @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
/// by each order in `orders`.
function getOrderFillableMakerAssetAmounts(
LibOrder.Order[] memory orders,
bytes[] memory orderSignatures
bytes[] memory orderSignatures,
address devUtilsAddress
)
public
view
@ -161,7 +162,8 @@ contract ERC20BridgeSampler is
{
orderFillableMakerAssetAmounts = getOrderFillableTakerAssetAmounts(
orders,
orderSignatures
orderSignatures,
devUtilsAddress
);
// `orderFillableMakerAssetAmounts` now holds taker asset amounts, so
// convert them to maker asset amounts.
@ -196,26 +198,15 @@ contract ERC20BridgeSampler is
makerTokenAmounts = new uint256[](numSamples);
address wethAddress = _getWethAddress();
uint256 value;
address reserve;
for (uint256 i = 0; i < numSamples; i++) {
if (takerToken == wethAddress || makerToken == wethAddress) {
// Direct ETH based trade
(value, reserve) = _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;
}
value = _sampleSellFromKyberNetwork(takerToken, makerToken, takerTokenAmounts[i]);
} else {
// Hop to ETH
(value, reserve) = _sampleSellFromKyberNetwork(takerToken, wethAddress, takerTokenAmounts[i]);
value = _sampleSellFromKyberNetwork(takerToken, wethAddress, takerTokenAmounts[i]);
if (value != 0) {
address otherReserve;
(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;
}
value = _sampleSellFromKyberNetwork(wethAddress, makerToken, 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(
address takerToken,
address makerToken,
@ -967,43 +977,67 @@ contract ERC20BridgeSampler is
)
private
view
returns (uint256 makerTokenAmount, address reserve)
returns (uint256 makerTokenAmount)
{
address _takerToken = takerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : takerToken;
address _makerToken = makerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : makerToken;
uint256 takerTokenDecimals = _getTokenDecimals(takerToken);
uint256 makerTokenDecimals = _getTokenDecimals(makerToken);
(bool didSucceed, bytes memory resultData) = _getKyberNetworkProxyAddress().staticcall.gas(DEFAULT_CALL_GAS)(
abi.encodeWithSelector(
IKyberNetworkProxy(0).kyberNetworkContract.selector
));
if (!didSucceed) {
return (0, address(0));
(IKyberHintHandler kyberHint, IKyberStorage kyberStorage) = _getKyberAddresses();
// Ban reserves which can clash with our internal aggregation
bytes32[] memory reserveIds = kyberStorage.getReserveIdsPerTokenSrc(
takerToken == _getWethAddress() ? makerToken : takerToken
);
bytes32[] memory bannedReserveIds = new bytes32[](0);
// Poor mans resize and append
for (uint256 i = 0; i < reserveIds.length; i++) {
if (
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));
(didSucceed, resultData) =
kyberNetworkContract.staticcall.gas(KYBER_CALL_GAS)(
// Sampler either detects X->ETH/ETH->X
// or subsamples as X->ETH-Y. So token->token here is not possible
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(
IKyberNetwork(0).searchBestRate.selector,
_takerToken,
_makerToken,
IKyberNetworkProxy(0).getExpectedRateAfterFee.selector,
takerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : takerToken,
makerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : makerToken,
takerTokenAmount,
false // usePermissionless
0, // fee
hint
));
uint256 rate = 0;
address reserve;
if (didSucceed) {
(reserve, rate) = abi.decode(resultData, (address, uint256));
(rate) = abi.decode(resultData, (uint256));
} else {
return (0, address(0));
return 0;
}
uint256 makerTokenDecimals = _getTokenDecimals(makerToken);
uint256 takerTokenDecimals = _getTokenDecimals(takerToken);
makerTokenAmount =
rate *
takerTokenAmount *
10 ** makerTokenDecimals /
10 ** takerTokenDecimals /
10 ** 18;
return (makerTokenAmount, reserve);
return makerTokenAmount;
}
}

View File

@ -40,11 +40,13 @@ interface IERC20BridgeSampler {
/// @dev Queries the fillable taker asset amounts of native orders.
/// @param orders Native orders to query.
/// @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
/// by each order in `orders`.
function getOrderFillableTakerAssetAmounts(
LibOrder.Order[] calldata orders,
bytes[] calldata orderSignatures
bytes[] calldata orderSignatures,
address devUtilsAddress
)
external
view
@ -53,11 +55,13 @@ interface IERC20BridgeSampler {
/// @dev Queries the fillable maker asset amounts of native orders.
/// @param orders Native orders to query.
/// @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
/// by each order in `orders`.
function getOrderFillableMakerAssetAmounts(
LibOrder.Order[] calldata orders,
bytes[] calldata orderSignatures
bytes[] calldata orderSignatures,
address devUtilsAddress
)
external
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");
you may not use this file except in compliance with the License.
@ -18,16 +18,20 @@
pragma solidity ^0.5.9;
import "./IKyberStorage.sol";
import "./IKyberHintHandler.sol";
interface IKyberNetwork {
function searchBestRate(
address fromToken,
address toToken,
uint256 fromAmount,
bool usePermissionless
)
function getContracts()
external
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");
you may not use this file except in compliance with the License.
@ -21,14 +21,14 @@ pragma solidity ^0.5.9;
interface IKyberNetworkProxy {
function kyberNetworkContract() external view returns (address);
function kyberNetwork() external view returns (address);
function kyberHintHandler() external view returns (address);
function getExpectedRate(
address fromToken,
address toToken,
uint256 fromAmount
)
external
view
returns (uint256 expectedRate, uint256 slippageRate);
function getExpectedRateAfterFee(
address src,
address dest,
uint256 srcQty,
uint256 platformFeeBps,
bytes calldata hint
) external view returns (uint256 expectedRate);
}

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
IKyberNetwork,
DeploymentConstants,
FailTrigger
{
bytes32 constant private SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7;
address constant public ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
function kyberNetworkContract()
enum TradeType {BestOfAll, MaskIn, MaskOut, Split}
function kyberNetwork()
external
view
returns (address)
@ -260,19 +262,91 @@ contract TestERC20BridgeSamplerKyberNetwork is
return address(this);
}
// IKyberNetwork not exposed via IKyberNetworkProxy
function searchBestRate(
address fromToken,
address toToken,
uint256 fromAmount,
bool // usePermissionless
// IKyberNetwork
function getContracts()
external
view
returns (
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
view
returns (address reserve, uint256 expectedRate)
returns (bytes32[] memory reserveIds)
{
(expectedRate, ) = this.getExpectedRate(fromToken, toToken, fromAmount);
return (address(this), expectedRate);
return reserveIds;
}
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()`.
@ -294,6 +368,14 @@ contract TestERC20BridgeSamplerKyberNetwork is
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;
constructor() public ERC20BridgeSampler(address(this)) {
constructor() public ERC20BridgeSampler() {
uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory();
uniswapV2Router = new TestERC20BridgeSamplerUniswapV2Router01();
eth2Dai = new TestERC20BridgeSamplerEth2Dai();

View File

@ -38,7 +38,7 @@
"config": {
"publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler,ILiquidityProvider,ILiquidityProviderRegistry,DummyLiquidityProviderRegistry,DummyLiquidityProvider",
"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": {
"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 IERC20BridgeSampler from '../test/generated-artifacts/IERC20BridgeSampler.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 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 ILiquidityProviderRegistry from '../test/generated-artifacts/ILiquidityProviderRegistry.json';
import * as IMultiBridge from '../test/generated-artifacts/IMultiBridge.json';
@ -28,8 +30,10 @@ export const artifacts = {
IDevUtils: IDevUtils as ContractArtifact,
IERC20BridgeSampler: IERC20BridgeSampler as ContractArtifact,
IEth2Dai: IEth2Dai as ContractArtifact,
IKyberHintHandler: IKyberHintHandler as ContractArtifact,
IKyberNetwork: IKyberNetwork as ContractArtifact,
IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
IKyberStorage: IKyberStorage as ContractArtifact,
ILiquidityProvider: ILiquidityProvider as ContractArtifact,
ILiquidityProviderRegistry: ILiquidityProviderRegistry 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 MAKER_TOKEN = randomAddress();
const TAKER_TOKEN = randomAddress();
let devUtilsAddress: string;
const FAKE_BUY_OPTS = {
targetSlippageBps: new BigNumber(5),
maxIterations: new BigNumber(5),
@ -45,6 +46,8 @@ blockchainTests('erc20-bridge-sampler', env => {
env.txDefaults,
{},
);
// TestERC20BridgeSampler stubs DevUtils
devUtilsAddress = testContract.address;
});
function getPackedHash(...args: string[]): string {
@ -272,12 +275,14 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN);
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
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);
});
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([]);
});
@ -285,7 +290,9 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].makerAssetAmount = constants.ZERO_AMOUNT;
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]);
});
@ -293,14 +300,18 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].takerAssetAmount = constants.ZERO_AMOUNT;
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]);
});
it('returns zero for an order with an empty signature', async () => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
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]);
});
});
@ -310,12 +321,14 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN);
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
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);
});
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([]);
});
@ -323,7 +336,9 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].makerAssetAmount = constants.ZERO_AMOUNT;
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]);
});
@ -331,14 +346,18 @@ blockchainTests('erc20-bridge-sampler', env => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
orders[0].takerAssetAmount = constants.ZERO_AMOUNT;
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]);
});
it('returns zero for an order with an empty signature', async () => {
const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1);
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]);
});
});
@ -1029,7 +1048,9 @@ blockchainTests('erc20-bridge-sampler', env => {
const signatures: string[] = _.times(orders.length, i => hexUtils.random());
const expected = orders.map(getDeterministicFillableTakerAssetAmount);
const calls = [
testContract.getOrderFillableTakerAssetAmounts(orders, signatures).getABIEncodedTransactionData(),
testContract
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
];
const r = await testContract.batchCall(calls).callAsync();
expect(r).to.be.length(1);
@ -1046,8 +1067,12 @@ blockchainTests('erc20-bridge-sampler', env => {
orders[1].map(getDeterministicFillableMakerAssetAmount),
];
const calls = [
testContract.getOrderFillableTakerAssetAmounts(orders[0], signatures).getABIEncodedTransactionData(),
testContract.getOrderFillableMakerAssetAmounts(orders[1], signatures).getABIEncodedTransactionData(),
testContract
.getOrderFillableTakerAssetAmounts(orders[0], signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
testContract
.getOrderFillableMakerAssetAmounts(orders[1], signatures, devUtilsAddress)
.getABIEncodedTransactionData(),
];
const r = await testContract.batchCall(calls).callAsync();
expect(r).to.be.length(2);
@ -1069,7 +1094,7 @@ blockchainTests('erc20-bridge-sampler', env => {
testContract
.batchCall([
testContract
.getOrderFillableTakerAssetAmounts(orders, signatures)
.getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress)
.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_erc20_bridge_sampler';
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_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_registry';
export * from '../test/generated-wrappers/i_multi_bridge';

View File

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

View File

@ -64,7 +64,7 @@
"@0x/contracts-test-utils": "^5.3.3",
"@0x/contracts-utils": "^4.5.0",
"@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/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",

View File

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

View File

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

View File

@ -62,7 +62,7 @@
"@0x/contracts-test-utils": "^5.3.3",
"@0x/contracts-utils": "^4.5.0",
"@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/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",

View File

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

View File

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

View File

@ -47,9 +47,9 @@
"@0x/contract-addresses": "^4.10.0",
"@0x/dev-utils": "^3.2.2",
"@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-profiler": "^4.1.0",
"@0x/sol-profiler": "^4.0.9",
"@0x/sol-trace": "^3.0.9",
"@0x/subproviders": "^6.1.0",
"@0x/types": "^3.1.3",

View File

@ -27,7 +27,7 @@ contract DeploymentConstants {
/// @dev Mainnet address of the WETH contract.
address constant private WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
/// @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.
address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
/// @dev Mainnet address of the `UniswapV2Router01` contract.

View File

@ -54,7 +54,7 @@
"@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.3",
"@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/tslint-config": "^4.0.0",
"@0x/types": "^3.1.3",

View File

@ -57,7 +57,7 @@
"@0x/contracts-gen": "^2.0.9",
"@0x/contracts-test-utils": "^5.3.3",
"@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/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",

View File

@ -37,6 +37,10 @@
{
"note": "Change gas/fee schedule values from constants to functions returning numbers",
"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/contract-addresses": "^4.10.0",
"@0x/contract-wrappers": "^13.7.0",
"@0x/contract-artifacts": "^3.7.0",
"@0x/json-schemas": "^5.0.8",
"@0x/order-utils": "^10.2.5",
"@0x/orderbook": "^2.2.6",

View File

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

View File

@ -1,10 +1,11 @@
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 { assetDataUtils, SignedOrder } from '@0x/order-utils';
import { MeshOrderProviderOpts, Orderbook, SRAPollingOrderProviderOpts } from '@0x/orderbook';
import { BigNumber, providerUtils } from '@0x/utils';
import { SupportedProvider, ZeroExProvider } from 'ethereum-types';
import { BlockParamLiteral, SupportedProvider, ZeroExProvider } from 'ethereum-types';
import * as _ from 'lodash';
import { constants } from './constants';
@ -185,13 +186,27 @@ export class SwapQuoter {
rfqt ? rfqt.infoLogger : undefined,
expiryBufferMs,
);
const sampler = new DexOrderSampler(
new IERC20BridgeSamplerContract(this._contractAddresses.erc20BridgeSampler, this.provider, {
// Allow the sampler bytecode to be overwritten using geths override functionality
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,
}),
},
);
this._marketOperationUtils = new MarketOperationUtils(
sampler,
new DexOrderSampler(samplerContract, samplerOverrides),
this._contractAddresses,
{
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 { BigNumber } from '@0x/utils';
@ -253,6 +253,7 @@ export interface SwapQuoterOpts extends OrderPrunerOpts {
warningLogger?: LogFunction;
infoLogger?: LogFunction;
};
samplerOverrides?: SamplerOverrides;
}
/**
@ -328,3 +329,8 @@ export interface MockedRfqtIndicativeQuoteResponse {
responseData: any;
responseCode: number;
}
export interface SamplerOverrides {
overrides: GethCallOverrides;
block: BlockParam;
}

View File

@ -83,7 +83,7 @@ export class MarketOperationUtils {
// Call the sampler contract.
const samplerPromise = this._sampler.executeAsync(
// Get native order fillable amounts.
DexOrderSampler.ops.getOrderFillableTakerAmounts(nativeOrders),
DexOrderSampler.ops.getOrderFillableTakerAmounts(nativeOrders, this.contractAddresses.devUtils),
// Get the custom liquidity provider from registry.
DexOrderSampler.ops.getLiquidityProviderFromRegistry(
this._liquidityProviderRegistry,
@ -187,7 +187,7 @@ export class MarketOperationUtils {
// Call the sampler contract.
const samplerPromise = this._sampler.executeAsync(
// Get native order fillable amounts.
DexOrderSampler.ops.getOrderFillableMakerAmounts(nativeOrders),
DexOrderSampler.ops.getOrderFillableMakerAmounts(nativeOrders, this.contractAddresses.devUtils),
// Get the custom liquidity provider from registry.
DexOrderSampler.ops.getLiquidityProviderFromRegistry(
this._liquidityProviderRegistry,
@ -291,7 +291,9 @@ export class MarketOperationUtils {
const sources = difference(BUY_SOURCES, _opts.excludedSources);
const ops = [
...batchNativeOrders.map(orders => DexOrderSampler.ops.getOrderFillableMakerAmounts(orders)),
...batchNativeOrders.map(orders =>
DexOrderSampler.ops.getOrderFillableMakerAmounts(orders, this.contractAddresses.devUtils),
),
...(await Promise.all(
batchNativeOrders.map(async orders =>
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 { SamplerOverrides } from '../../types';
import { BalancerPoolsCache } from './balancer_utils';
import { samplerOperations } from './sampler_operations';
import { BatchedOperation } from './types';
@ -35,7 +37,8 @@ export class DexOrderSampler {
public static ops = samplerOperations;
constructor(
private readonly _samplerContract: IERC20BridgeSamplerContract,
private readonly _samplerContract: ERC20BridgeSamplerContract,
private readonly _samplerOverrides?: SamplerOverrides,
public balancerPoolsCache: BalancerPoolsCache = new BalancerPoolsCache(),
) {}
@ -138,8 +141,13 @@ export class DexOrderSampler {
*/
public async executeBatchAsync<T extends Array<BatchedOperation<any>>>(ops: T): Promise<any[]> {
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.
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.
let rawCallResultsIdx = 0;
return Promise.all(

View File

@ -21,11 +21,11 @@ import {
* for use with `DexOrderSampler.executeAsync()`.
*/
export const samplerOperations = {
getOrderFillableTakerAmounts(orders: SignedOrder[]): BatchedOperation<BigNumber[]> {
getOrderFillableTakerAmounts(orders: SignedOrder[], devUtilsAddress: string): BatchedOperation<BigNumber[]> {
return {
encodeCall: contract => {
return contract
.getOrderFillableTakerAssetAmounts(orders, orders.map(o => o.signature))
.getOrderFillableTakerAssetAmounts(orders, orders.map(o => o.signature), devUtilsAddress)
.getABIEncodedTransactionData();
},
handleCallResultsAsync: async (contract, callResults) => {
@ -33,11 +33,11 @@ export const samplerOperations = {
},
};
},
getOrderFillableMakerAmounts(orders: SignedOrder[]): BatchedOperation<BigNumber[]> {
getOrderFillableMakerAmounts(orders: SignedOrder[], devUtilsAddress: string): BatchedOperation<BigNumber[]> {
return {
encodeCall: contract => {
return contract
.getOrderFillableMakerAssetAmounts(orders, orders.map(o => o.signature))
.getOrderFillableMakerAssetAmounts(orders, orders.map(o => o.signature), devUtilsAddress)
.getABIEncodedTransactionData();
},
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 { RfqtRequestOpts, SignedOrderWithFillableAmounts } from '../../types';
@ -220,8 +220,8 @@ export interface GetMarketOrdersOpts {
* A composable operation the be run in `DexOrderSampler.executeAsync()`.
*/
export interface BatchedOperation<TResult> {
encodeCall(contract: IERC20BridgeSamplerContract): string;
handleCallResultsAsync(contract: IERC20BridgeSamplerContract, callResults: string): Promise<TResult>;
encodeCall(contract: ERC20BridgeSamplerContract): string;
handleCallResultsAsync(contract: ERC20BridgeSamplerContract, callResults: string): Promise<TResult>;
}
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 wethAddress = getContractAddressesForChainOrThrow(CHAIN_ID).etherToken;
const devUtilsAddress = getContractAddressesForChainOrThrow(CHAIN_ID).devUtils;
describe('getSampleAmounts()', () => {
const FILL_AMOUNT = getRandomInteger(1, 1e18);
@ -105,7 +106,7 @@ describe('DexSampler tests', () => {
});
const dexOrderSampler = new DexOrderSampler(sampler);
const [fillableAmounts] = await dexOrderSampler.executeAsync(
DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS),
DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS, devUtilsAddress),
);
expect(fillableAmounts).to.deep.eq(expectedFillableAmounts);
});
@ -121,7 +122,7 @@ describe('DexSampler tests', () => {
});
const dexOrderSampler = new DexOrderSampler(sampler);
const [fillableAmounts] = await dexOrderSampler.executeAsync(
DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS),
DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS, devUtilsAddress),
);
expect(fillableAmounts).to.deep.eq(expectedFillableAmounts);
});
@ -483,7 +484,7 @@ describe('DexSampler tests', () => {
return Promise.resolve(pools);
},
});
const dexOrderSampler = new DexOrderSampler(new MockSamplerContract({}), balancerPoolsCache);
const dexOrderSampler = new DexOrderSampler(new MockSamplerContract({}), undefined, balancerPoolsCache);
const [quotes] = await dexOrderSampler.executeAsync(
await DexOrderSampler.ops.getSellQuotesAsync(
[ERC20BridgeSource.Balancer],
@ -589,7 +590,7 @@ describe('DexSampler tests', () => {
return Promise.resolve(pools);
},
});
const dexOrderSampler = new DexOrderSampler(new MockSamplerContract({}), balancerPoolsCache);
const dexOrderSampler = new DexOrderSampler(new MockSamplerContract({}), undefined, balancerPoolsCache);
const [quotes] = await dexOrderSampler.executeAsync(
await DexOrderSampler.ops.getBuyQuotesAsync(
[ERC20BridgeSource.Balancer],
@ -631,8 +632,8 @@ describe('DexSampler tests', () => {
});
const dexOrderSampler = new DexOrderSampler(sampler);
const [fillableMakerAmounts, fillableTakerAmounts] = await dexOrderSampler.executeAsync(
DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS),
DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS),
DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS, devUtilsAddress),
DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS, devUtilsAddress),
);
expect(fillableMakerAmounts).to.deep.eq(expectedFillableMakerAmounts);
expect(fillableTakerAmounts).to.deep.eq(expectedFillableTakerAmounts);

View File

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

File diff suppressed because one or more lines are too long

View File

@ -49,7 +49,8 @@
"name": "orders",
"type": "tuple[]"
},
{ "internalType": "bytes[]", "name": "orderSignatures", "type": "bytes[]" }
{ "internalType": "bytes[]", "name": "orderSignatures", "type": "bytes[]" },
{ "internalType": "address", "name": "devUtilsAddress", "type": "address" }
],
"name": "getOrderFillableMakerAssetAmounts",
"outputs": [
@ -83,7 +84,8 @@
"name": "orders",
"type": "tuple[]"
},
{ "internalType": "bytes[]", "name": "orderSignatures", "type": "bytes[]" }
{ "internalType": "bytes[]", "name": "orderSignatures", "type": "bytes[]" },
{ "internalType": "address", "name": "devUtilsAddress", "type": "address" }
],
"name": "getOrderFillableTakerAssetAmounts",
"outputs": [
@ -300,17 +302,19 @@
},
"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.",
"params": {
"devUtilsAddress": "Address to the DevUtils contract.",
"orderSignatures": "Signatures for each respective order in `orders`.",
"orders": "Native orders to query."
},
"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.",
"params": {
"devUtilsAddress": "Address to the DevUtils contract.",
"orderSignatures": "Signatures for each respective order in `orders`.",
"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 ERC1155Mintable from '../artifacts/ERC1155Mintable.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 ERC20Token from '../artifacts/ERC20Token.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 GodsUnchainedValidator from '../artifacts/GodsUnchainedValidator.json';
import * as IAssetProxy from '../artifacts/IAssetProxy.json';
import * as ITransformERC20 from '../artifacts/ITransformERC20.json';
import * as IValidator from '../artifacts/IValidator.json';
import * as IWallet from '../artifacts/IWallet.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 WETH9 from '../artifacts/WETH9.json';
import * as ZRXToken from '../artifacts/ZRXToken.json';
import * as ERC20BridgeProxy from '../artifacts/ERC20BridgeProxy.json';
import * as ZrxVault from '../artifacts/ZrxVault.json';
import * as IERC20BridgeSampler from '../artifacts/IERC20BridgeSampler.json';
import * as ITransformERC20 from '../artifacts/ITransformERC20.json';
export {
AssetProxyOwner,
@ -56,6 +56,6 @@ export {
Staking,
StakingProxy,
ZrxVault,
IERC20BridgeSampler,
ERC20BridgeSampler,
ITransformERC20,
};

View File

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

View File

@ -49,7 +49,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
devUtilsAddress: string,
): Promise<ERC20BridgeSamplerContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
@ -74,7 +73,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
provider,
txDefaults,
logDecodeDependenciesAbiOnly,
devUtilsAddress,
);
}
@ -84,7 +82,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
devUtilsAddress: string,
): Promise<ERC20BridgeSamplerContract> {
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
schemas.addressSchema,
@ -115,7 +112,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
provider,
txDefaults,
logDecodeDependenciesAbiOnly,
devUtilsAddress,
);
}
@ -125,7 +121,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractAbi },
devUtilsAddress: string,
): Promise<ERC20BridgeSamplerContract> {
assert.isHexString('bytecode', bytecode);
assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
@ -135,14 +130,10 @@ export class ERC20BridgeSamplerContract extends BaseContract {
]);
const provider = providerUtils.standardizeOrThrow(supportedProvider);
const constructorAbi = BaseContract._lookupConstructorAbi(abi);
[devUtilsAddress] = BaseContract._formatABIDataItemList(
constructorAbi.inputs,
[devUtilsAddress],
BaseContract._bigNumberToString,
);
[] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString);
const iface = new ethers.utils.Interface(abi);
const deployInfo = iface.deployFunction;
const txData = deployInfo.encode(bytecode, [devUtilsAddress]);
const txData = deployInfo.encode(bytecode, []);
const web3Wrapper = new Web3Wrapper(provider);
const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
{
@ -161,7 +152,7 @@ export class ERC20BridgeSamplerContract extends BaseContract {
txDefaults,
logDecodeDependencies,
);
contractInstance.constructorArgs = [devUtilsAddress];
contractInstance.constructorArgs = [];
return contractInstance;
}
@ -170,18 +161,6 @@ export class ERC20BridgeSamplerContract extends BaseContract {
*/
public static ABI(): ContractAbi {
const abi = [
{
inputs: [
{
name: 'devUtilsAddress',
type: 'address',
},
],
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'constructor',
},
{
constant: true,
inputs: [
@ -297,6 +276,10 @@ export class ERC20BridgeSamplerContract extends BaseContract {
name: 'orderSignatures',
type: 'bytes[]',
},
{
name: 'devUtilsAddress',
type: 'address',
},
],
name: 'getOrderFillableMakerAssetAmounts',
outputs: [
@ -378,6 +361,10 @@ export class ERC20BridgeSamplerContract extends BaseContract {
name: 'orderSignatures',
type: 'bytes[]',
},
{
name: 'devUtilsAddress',
type: 'address',
},
],
name: 'getOrderFillableTakerAssetAmounts',
outputs: [
@ -965,6 +952,7 @@ export class ERC20BridgeSamplerContract extends BaseContract {
* Effectively ignores orders that have empty signatures or
* @param orders Native orders to query.
* @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;.
*/
public getOrderFillableMakerAssetAmounts(
@ -985,12 +973,14 @@ export class ERC20BridgeSamplerContract extends BaseContract {
takerFeeAssetData: string;
}>,
orderSignatures: string[],
devUtilsAddress: string,
): ContractFunctionObj<BigNumber[]> {
const self = (this as any) as ERC20BridgeSamplerContract;
assert.isArray('orders', orders);
assert.isArray('orderSignatures', orderSignatures);
assert.isString('devUtilsAddress', devUtilsAddress);
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 {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> {
@ -1004,7 +994,11 @@ export class ERC20BridgeSamplerContract extends BaseContract {
return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult);
},
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).
* @param orders Native orders to query.
* @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;.
*/
public getOrderFillableTakerAssetAmounts(
@ -1034,12 +1029,14 @@ export class ERC20BridgeSamplerContract extends BaseContract {
takerFeeAssetData: string;
}>,
orderSignatures: string[],
devUtilsAddress: string,
): ContractFunctionObj<BigNumber[]> {
const self = (this as any) as ERC20BridgeSamplerContract;
assert.isArray('orders', orders);
assert.isArray('orderSignatures', orderSignatures);
assert.isString('devUtilsAddress', devUtilsAddress);
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 {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> {
@ -1053,7 +1050,11 @@ export class ERC20BridgeSamplerContract extends BaseContract {
return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult);
},
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',
type: 'bytes[]',
},
{
name: 'devUtilsAddress',
type: 'address',
},
],
name: 'getOrderFillableMakerAssetAmounts',
outputs: [
@ -357,6 +361,10 @@ export class IERC20BridgeSamplerContract extends BaseContract {
name: 'orderSignatures',
type: 'bytes[]',
},
{
name: 'devUtilsAddress',
type: 'address',
},
],
name: 'getOrderFillableTakerAssetAmounts',
outputs: [
@ -912,6 +920,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
* Queries the fillable maker asset amounts of native orders.
* @param orders Native orders to query.
* @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;.
*/
public getOrderFillableMakerAssetAmounts(
@ -932,12 +941,14 @@ export class IERC20BridgeSamplerContract extends BaseContract {
takerFeeAssetData: string;
}>,
orderSignatures: string[],
devUtilsAddress: string,
): ContractFunctionObj<BigNumber[]> {
const self = (this as any) as IERC20BridgeSamplerContract;
assert.isArray('orders', orders);
assert.isArray('orderSignatures', orderSignatures);
assert.isString('devUtilsAddress', devUtilsAddress);
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 {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> {
@ -951,7 +962,11 @@ export class IERC20BridgeSamplerContract extends BaseContract {
return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult);
},
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.
* @param orders Native orders to query.
* @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;.
*/
public getOrderFillableTakerAssetAmounts(
@ -979,12 +995,14 @@ export class IERC20BridgeSamplerContract extends BaseContract {
takerFeeAssetData: string;
}>,
orderSignatures: string[],
devUtilsAddress: string,
): ContractFunctionObj<BigNumber[]> {
const self = (this as any) as IERC20BridgeSamplerContract;
assert.isArray('orders', orders);
assert.isArray('orderSignatures', orderSignatures);
assert.isString('devUtilsAddress', devUtilsAddress);
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 {
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber[]> {
@ -998,7 +1016,11 @@ export class IERC20BridgeSamplerContract extends BaseContract {
return abiEncoder.strictDecodeReturnValue<BigNumber[]>(rawCallResult);
},
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",
"dependencies": {
"@0x/sol-compiler": "^4.1.0",
"@0x/sol-resolver": "^3.1.0",
"@0x/sol-resolver": "^3.0.4",
"@0x/types": "^3.1.3",
"@0x/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",

View File

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

View File

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

View File

@ -76,7 +76,7 @@
"dependencies": {
"@0x/assert": "^3.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/typescript-typings": "^5.1.0",
"@0x/utils": "^5.5.0",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,6 +5,10 @@
{
"note": "Add geth eth_call support",
"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 * as _ from 'lodash';
import { utils } from './utils';
import {
BlockWithoutTransactionDataRPC,
BlockWithTransactionDataRPC,
@ -28,6 +26,7 @@ import {
TransactionRPC,
TxDataRPC,
} from './types';
import { utils } from './utils';
/**
* Utils to convert ethereum structures from user-space format to RPC format. (marshall/unmarshall)
@ -163,6 +162,7 @@ export const marshaller = {
...callData,
};
delete callTxDataBase.from;
delete callTxDataBase.overrides;
const callTxDataBaseRPC = marshaller._marshalCallTxDataBase(callTxDataBase);
const callDataRPC = {
...callTxDataBaseRPC,