@0x/contracts-erc20-bridge-sampler: Get contracts compiling.

This commit is contained in:
Lawrence Forman 2019-11-15 12:39:37 -05:00
parent 0af346aad8
commit a26c3036a7
16 changed files with 241 additions and 64 deletions

5
.gitignore vendored
View File

@ -79,6 +79,8 @@ TODO.md
.vscode
# generated contract artifacts/
contracts/erc20-bridge-sampler/generated-artifacts/
contracts/erc20-bridge-sampler/test/generated-artifacts/
contracts/integrations/generated-artifacts/
contracts/integrations/test/generated-artifacts/
contracts/staking/generated-artifacts/
@ -111,6 +113,7 @@ packages/sol-tracing-utils/test/fixtures/artifacts/
python-packages/contract_artifacts/src/zero_ex/contract_artifacts/artifacts/
# generated truffle contract artifacts/
contracts/erc20-bridge-sampler/build/
contracts/staking/build/
contracts/coordinator/build/
contracts/exchange/build/
@ -127,6 +130,8 @@ contracts/dev-utils/build/
# generated contract wrappers
packages/python-contract-wrappers/generated/
contracts/erc20-bridge-sampler/generated-wrappers/
contracts/erc20-bridge-sampler/test/generated-wrappers/
contracts/integrations/generated-wrappers/
contracts/integrations/test/generated-wrappers/
contracts/staking/generated-wrappers/

View File

@ -1,4 +1,4 @@
pragma solidity ^0.5;
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol";
@ -7,7 +7,7 @@ import "./IERC20BridgeSampler.sol";
import "./IExchange.sol";
import "./IEth2Dai.sol";
import "./IKyberNetwork.sol";
import "./IUniswapExchange.sol";
import "./IUniswapExchangeQuotes.sol";
contract ERC20BridgeSampler is
@ -21,6 +21,14 @@ contract ERC20BridgeSampler is
address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address constant public KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev Query native orders and sample sell quotes on multiple DEXes at once.
/// @param orders Native orders to query.
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return orderInfos `OrderInfo`s for each order in `orders`.
/// @return makerTokenAmountsBySource Maker amounts bought for each source at
/// each taker token amount. First indexed by source index, then sample
/// index.
function queryOrdersAndSampleSells(
IExchange.Order[] memory orders,
address[] memory sources,
@ -43,6 +51,14 @@ contract ERC20BridgeSampler is
);
}
/// @dev Query native orders and sample buy quotes on multiple DEXes at once.
/// @param orders Native orders to query.
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return orderInfos `OrderInfo`s for each order in `orders`.
/// @return takerTokenAmountsBySource Taker amounts sold for each source at
/// each maker token amount. First indexed by source index, then sample
/// index.
function queryOrdersAndSampleBuys(
IExchange.Order[] memory orders,
address[] memory sources,
@ -64,6 +80,9 @@ contract ERC20BridgeSampler is
);
}
/// @dev Queries the status of several native orders.
/// @param orders Native orders to query.
/// @return orderInfos Order info for each respective order.
function queryOrders(IExchange.Order[] memory orders)
public
view
@ -76,6 +95,14 @@ contract ERC20BridgeSampler is
}
}
/// @dev Sample sell quotes on multiple DEXes at once.
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmountsBySource Maker amounts bought for each source at
/// each taker token amount. First indexed by source index, then sample
/// index.
function sampleSells(
address[] memory sources,
address takerToken,
@ -98,6 +125,14 @@ contract ERC20BridgeSampler is
}
}
/// @dev Query native orders and sample buy quotes on multiple DEXes at once.
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmountsBySource Taker amounts sold for each source at
/// each maker token amount. First indexed by source index, then sample
/// index.
function sampleBuys(
address[] memory sources,
address takerToken,
@ -120,6 +155,12 @@ contract ERC20BridgeSampler is
}
}
/// @dev Sample sell quotes from Kyber.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellFromKyberNetwork(
address takerToken,
address makerToken,
@ -131,8 +172,8 @@ contract ERC20BridgeSampler is
{
address _takerToken = takerToken == WETH_ADDRESS ? KYBER_ETH_ADDRESS : takerToken;
address _makerToken = makerToken == WETH_ADDRESS ? KYBER_ETH_ADDRESS : makerToken;
uint256 takerTokenDecimals = LibERC20Token(takerToken).decimals();
uint256 makerTokenDecimals = LibERC20Token(makerToken).decimals();
uint256 takerTokenDecimals = LibERC20Token.decimals(takerToken);
uint256 makerTokenDecimals = LibERC20Token.decimals(makerToken);
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
@ -149,6 +190,12 @@ contract ERC20BridgeSampler is
}
}
/// @dev Sample sell quotes from Eth2Dai/Oasis.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellFromEth2Dai(
address takerToken,
address makerToken,
@ -169,6 +216,12 @@ contract ERC20BridgeSampler is
}
}
/// @dev Sample buy quotes from Eth2Dai/Oasis.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Maker token sell amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuyFromEth2Dai(
address takerToken,
address makerToken,
@ -189,6 +242,12 @@ contract ERC20BridgeSampler is
}
}
/// @dev Sample sell quotes from Uniswap.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellFromUniswap(
address takerToken,
address makerToken,
@ -200,12 +259,10 @@ contract ERC20BridgeSampler is
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
IUniswapExchange takerTokenExchange = takerToken == WETH_ADDRESS ?
IUniswapExchange(0) :
IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS).getExchange(takerToken);
IUniswapExchange makerTokenExchange = makerToken == WETH_ADDRESS ?
IUniswapExchange(0) :
IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS).getExchange(makerToken);
IUniswapExchangeQuotes takerTokenExchange = takerToken == WETH_ADDRESS ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(takerToken);
IUniswapExchangeQuotes makerTokenExchange = makerToken == WETH_ADDRESS ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(makerToken);
for (uint256 i = 0; i < numSamples; i++) {
if (makerToken == WETH_ADDRESS) {
makerTokenAmounts[i] = takerTokenExchange.getTokenToEthInputPrice(
@ -226,6 +283,12 @@ contract ERC20BridgeSampler is
}
}
/// @dev Sample buy quotes from Uniswap.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token sell amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuyFromUniswap(
address takerToken,
address makerToken,
@ -237,12 +300,10 @@ contract ERC20BridgeSampler is
{
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
IUniswapExchange takerTokenExchange = takerToken == WETH_ADDRESS ?
IUniswapExchange(0) :
IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS).getExchange(takerToken);
IUniswapExchange makerTokenExchange = makerToken == WETH_ADDRESS ?
IUniswapExchange(0) :
IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS).getExchange(makerToken);
IUniswapExchangeQuotes takerTokenExchange = takerToken == WETH_ADDRESS ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(takerToken);
IUniswapExchangeQuotes makerTokenExchange = makerToken == WETH_ADDRESS ?
IUniswapExchangeQuotes(0) : _getUniswapExchange(makerToken);
for (uint256 i = 0; i < numSamples; i++) {
if (makerToken == WETH_ADDRESS) {
takerTokenAmounts[i] = takerTokenExchange.getTokenToEthOutputPrice(
@ -263,6 +324,12 @@ contract ERC20BridgeSampler is
}
}
/// @dev Samples a supported sell source, defined by its address.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function _sampleSellSource(
address source,
address takerToken,
@ -285,6 +352,12 @@ contract ERC20BridgeSampler is
revert("UNSUPPORTED_SOURCE");
}
/// @dev Samples a supported buy source, defined by its address.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token sell amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function _sampleBuySource(
address source,
address takerToken,
@ -304,6 +377,27 @@ contract ERC20BridgeSampler is
revert("UNSUPPORTED_SOURCE");
}
/// @dev Retrive an existing Uniswap exchange contract.
/// Throws if the exchange does not exist.
/// @param tokenAddress Address of the token contract.
/// @return exchange `IUniswapExchangeQuotes` for the token.
function _getUniswapExchange(address tokenAddress)
private
view
returns (IUniswapExchangeQuotes exchange)
{
exchange = IUniswapExchangeQuotes(
address(
IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS)
.getExchange(tokenAddress)
)
);
require(address(exchange) != address(0), "UNSUPPORTED_UNISWAP_EXCHANGE");
}
/// @dev Extract the token address from ERC20 proxy asset data.
/// @param assetData ERC20 asset data.
/// @return tokenAddress The decoded token address.
function _assetDataToTokenAddress(bytes memory assetData)
private
pure

View File

@ -1,4 +1,4 @@
pragma solidity ^0.5;
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "./IExchange.sol";
@ -45,4 +45,48 @@ interface IERC20BridgeSampler {
IExchange.OrderInfo[] memory orderInfos,
uint256[][] memory makerTokenAmountsBySource
);
/// @dev Queries the status of several native orders.
/// @param orders Native orders to query.
/// @return orderInfos Order info for each respective order.
function queryOrders(IExchange.Order[] calldata orders)
external
view
returns (IExchange.OrderInfo[] memory orderInfos);
/// @dev Sample sell quotes on multiple DEXes at once.
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmountsBySource Maker amounts bought for each source at
/// each taker token amount. First indexed by source index, then sample
/// index.
function sampleSells(
address[] calldata sources,
address takerToken,
address makerToken,
uint256[] calldata takerTokenAmounts
)
external
view
returns (uint256[][] memory makerTokenAmountsBySource);
/// @dev Query native orders and sample buy quotes on multiple DEXes at once.
/// @param sources Address of each DEX. Passing in an unsupported DEX will throw.
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmountsBySource Taker amounts sold for each source at
/// each maker token amount. First indexed by source index, then sample
/// index.
function sampleBuys(
address[] calldata sources,
address takerToken,
address makerToken,
uint256[] calldata makerTokenAmounts
)
external
view
returns (uint256[][] memory takerTokenAmountsBySource);
}

View File

@ -1,6 +1,8 @@
pragma solidity ^0.5;
pragma solidity ^0.5.9;
contract IEth2Dai {
function getBuyAmount(
address buyToken,
address payToken,

View File

@ -1,7 +1,9 @@
pragma solidity ^0.5;
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
interface IExchange {
struct Order {
address makerAddress;
address takerAddress;

View File

@ -1,6 +1,8 @@
pragma solidity ^0.5;
pragma solidity ^0.5.9;
contract IKyberNetwork {
function getExpectedRate(
address fromToken,
address toToken,

View File

@ -1,6 +1,8 @@
pragma solidity ^0.5;
pragma solidity ^0.5.9;
interface IUniswapExchangeQuotes {
interface IUniswapExchange {
function getEthToTokenInputPrice(
uint256 ethSold
)

View File

@ -1,4 +1,4 @@
pragma solidity ^0.5;
pragma solidity ^0.5.9;
library LibERC20Token {

View File

@ -36,9 +36,9 @@
"compile:truffle": "truffle compile"
},
"config": {
"publicInterfaceContracts": "ERC20BridgeSampler",
"publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(Exchange|IAssetProxy|IAssetProxyDispatcher|IEIP1271Data|IEIP1271Wallet|IExchange|IExchangeCore|IMatchOrders|IProtocolFees|ISignatureValidator|ITransactions|ITransferSimulator|IWallet|IWrapperFunctions|IsolatedExchange|LibExchangeRichErrorDecoder|MixinAssetProxyDispatcher|MixinExchangeCore|MixinMatchOrders|MixinProtocolFees|MixinSignatureValidator|MixinTransactions|MixinTransferSimulator|MixinWrapperFunctions|ReentrancyTester|TestAssetProxyDispatcher|TestExchangeInternals|TestFillRounding|TestLibExchangeRichErrorDecoder|TestProtocolFeeCollector|TestProtocolFees|TestProtocolFeesReceiver|TestSignatureValidator|TestTransactions|TestValidatorWallet|TestWrapperFunctions).json"
"abis": "./test/generated-artifacts/@(ERC20BridgeSampler|IERC20BridgeSampler|IEth2Dai|IExchange|IKyberNetwork|IUniswapExchangeQuotes|LibERC20Token).json"
},
"repository": {
"type": "git",

View File

@ -0,0 +1,13 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
import { ContractArtifact } from 'ethereum-types';
import * as ERC20BridgeSampler from '../generated-artifacts/ERC20BridgeSampler.json';
import * as IERC20BridgeSampler from '../generated-artifacts/IERC20BridgeSampler.json';
export const artifacts = {
ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact,
IERC20BridgeSampler: IERC20BridgeSampler as ContractArtifact,
};

View File

@ -0,0 +1,7 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/erc20_bridge_sampler';
export * from '../generated-wrappers/i_erc20_bridge_sampler';

View File

@ -0,0 +1,23 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
import { ContractArtifact } from 'ethereum-types';
import * as ERC20BridgeSampler from '../test/generated-artifacts/ERC20BridgeSampler.json';
import * as IERC20BridgeSampler from '../test/generated-artifacts/IERC20BridgeSampler.json';
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
import * as IExchange from '../test/generated-artifacts/IExchange.json';
import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json';
import * as IUniswapExchangeQuotes from '../test/generated-artifacts/IUniswapExchangeQuotes.json';
import * as LibERC20Token from '../test/generated-artifacts/LibERC20Token.json';
export const artifacts = {
ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact,
IERC20BridgeSampler: IERC20BridgeSampler as ContractArtifact,
IEth2Dai: IEth2Dai as ContractArtifact,
IExchange: IExchange as ContractArtifact,
IKyberNetwork: IKyberNetwork as ContractArtifact,
IUniswapExchangeQuotes: IUniswapExchangeQuotes as ContractArtifact,
LibERC20Token: LibERC20Token as ContractArtifact,
};

View File

@ -0,0 +1,12 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../test/generated-wrappers/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_exchange';
export * from '../test/generated-wrappers/i_kyber_network';
export * from '../test/generated-wrappers/i_uniswap_exchange_quotes';
export * from '../test/generated-wrappers/lib_erc20_token';

View File

@ -3,44 +3,15 @@
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
"files": [
"generated-artifacts/Exchange.json",
"generated-artifacts/IExchange.json",
"test/generated-artifacts/Exchange.json",
"test/generated-artifacts/IAssetProxy.json",
"test/generated-artifacts/IAssetProxyDispatcher.json",
"test/generated-artifacts/IEIP1271Data.json",
"test/generated-artifacts/IEIP1271Wallet.json",
"generated-artifacts/ERC20BridgeSampler.json",
"generated-artifacts/IERC20BridgeSampler.json",
"test/generated-artifacts/ERC20BridgeSampler.json",
"test/generated-artifacts/IERC20BridgeSampler.json",
"test/generated-artifacts/IEth2Dai.json",
"test/generated-artifacts/IExchange.json",
"test/generated-artifacts/IExchangeCore.json",
"test/generated-artifacts/IMatchOrders.json",
"test/generated-artifacts/IProtocolFees.json",
"test/generated-artifacts/ISignatureValidator.json",
"test/generated-artifacts/ITransactions.json",
"test/generated-artifacts/ITransferSimulator.json",
"test/generated-artifacts/IWallet.json",
"test/generated-artifacts/IWrapperFunctions.json",
"test/generated-artifacts/IsolatedExchange.json",
"test/generated-artifacts/LibExchangeRichErrorDecoder.json",
"test/generated-artifacts/MixinAssetProxyDispatcher.json",
"test/generated-artifacts/MixinExchangeCore.json",
"test/generated-artifacts/MixinMatchOrders.json",
"test/generated-artifacts/MixinProtocolFees.json",
"test/generated-artifacts/MixinSignatureValidator.json",
"test/generated-artifacts/MixinTransactions.json",
"test/generated-artifacts/MixinTransferSimulator.json",
"test/generated-artifacts/MixinWrapperFunctions.json",
"test/generated-artifacts/ReentrancyTester.json",
"test/generated-artifacts/TestAssetProxyDispatcher.json",
"test/generated-artifacts/TestExchangeInternals.json",
"test/generated-artifacts/TestFillRounding.json",
"test/generated-artifacts/TestLibExchangeRichErrorDecoder.json",
"test/generated-artifacts/TestProtocolFeeCollector.json",
"test/generated-artifacts/TestProtocolFees.json",
"test/generated-artifacts/TestProtocolFeesReceiver.json",
"test/generated-artifacts/TestSignatureValidator.json",
"test/generated-artifacts/TestTransactions.json",
"test/generated-artifacts/TestValidatorWallet.json",
"test/generated-artifacts/TestWrapperFunctions.json"
"test/generated-artifacts/IKyberNetwork.json",
"test/generated-artifacts/IUniswapExchangeQuotes.json",
"test/generated-artifacts/LibERC20Token.json"
],
"exclude": ["./deploy/solc/solc_bin"]
}

View File

@ -5,6 +5,6 @@
"max-file-line-count": false
},
"linterOptions": {
"exclude": ["src/artifacts.ts"]
"exclude": ["src/artifacts.ts", "test/artifacts.ts"]
}
}

View File

@ -51,7 +51,7 @@
"lint:contracts": "wsrun lint -p ${npm_package_config_contractsPackages} -c --fast-exit --stages --exclude-missing"
},
"config": {
"contractsPackages": "@0x/contracts-asset-proxy @0x/contracts-dev-utils @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-exchange-libs @0x/contracts-integrations @0x/contracts-multisig @0x/contracts-staking @0x/contracts-test-utils @0x/contracts-utils @0x/contracts-coordinator @0x/contracts-tests",
"contractsPackages": "@0x/contracts-asset-proxy @0x/contracts-dev-utils @0x/contracts-erc20 @0x/contracts-erc20-bridge-sampler @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-exchange-libs @0x/contracts-integrations @0x/contracts-multisig @0x/contracts-staking @0x/contracts-test-utils @0x/contracts-utils @0x/contracts-coordinator @0x/contracts-tests @0x/contracts-erc20-bridge-sampler",
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic",
"packagesWithDocPages": "0x.js @0x/contract-wrappers @0x/connect @0x/json-schemas @0x/subproviders @0x/web3-wrapper @0x/order-utils @0x/sol-compiler @0x/sol-coverage @0x/sol-profiler @0x/sol-trace @0x/dev-utils @0x/asset-swapper @0x/migrations @0x/orderbook @0x/contracts-asset-proxy @0x/contracts-coordinator @0x/contracts-dev-utils @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-exchange-libs @0x/contracts-extensions @0x/contracts-staking",
"ignoreDependencyVersions": "@types/styled-components @types/node",