diff --git a/contracts/zero-ex/compiler.json b/contracts/zero-ex/compiler.json index c804e91245..20f8637f21 100644 --- a/contracts/zero-ex/compiler.json +++ b/contracts/zero-ex/compiler.json @@ -7,7 +7,7 @@ "compilerSettings": { "evmVersion": "istanbul", "optimizer": { - "enabled": false, + "enabled": true, "runs": 1000000, "details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true } }, diff --git a/contracts/zero-ex/contracts/src/transformers/FillQuoteTransformer.sol b/contracts/zero-ex/contracts/src/transformers/FillQuoteTransformer.sol new file mode 100644 index 0000000000..0c63182bad --- /dev/null +++ b/contracts/zero-ex/contracts/src/transformers/FillQuoteTransformer.sol @@ -0,0 +1,264 @@ +/* + + 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.6.5; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol"; +import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; +import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol"; +import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; +import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; +import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol"; +import "@0x/contracts-utils/contracts/src/v06/ReentrancyGuardV06.sol"; +import "../errors/LibTransformERC20RichErrors.sol"; +import "../vendor/v3/IExchange.sol"; +import "./IERC20Transformer.sol"; +import "./LibERC20Transformer.sol"; + + +/// @dev A transformer that fills an ERC20 market sell/buy quote. +contract FillQuoteTransformer is + IERC20Transformer, + ReentrancyGuardV06 +{ + // solhint-disable indent,no-empty-blocks,no-unused-vars + + /// @dev Data to encode and pass to `transform()`. + struct FillSellQuoteTransformData { + // The token being sold. + // This should be an actual token, not the ETH pseudo-token. + IERC20TokenV06 sellToken; + // The token being bought. + // This should be an actual token, not the ETH pseudo-token. + IERC20TokenV06 buyToken; + // The orders to fill. + IExchange.Order[] orders; + // Signatures for each respective order in `orders`. + bytes[] signatures; + // Amount of `sellToken` to sell. Zero if performing a market buy. + uint256 sellAmount; + // Amount of `buyToken` to buy. Zero if performing a market sell. + uint256 buyAmount; + } + + /// @dev Results of a call to `_fillOrder()`. + struct FillOrderResults { + // The amount of taker tokens sold, according to balance checks. + uint256 takerTokenSoldAmount; + // The amount of maker tokens sold, according to balance checks. + uint256 makerTokenBoughtAmount; + } + + /// @dev The Exchange contract. + IExchange public immutable exchange; + /// @dev The ERC20Proxy address. + address public immutable erc20Proxy; + /// @dev The ERC20Proxy ID. + bytes4 constant private ERC20_ASSET_PROXY_ID = 0xf47261b0; + + using LibERC20TokenV06 for IERC20TokenV06; + using LibSafeMathV06 for uint256; + using LibRichErrorsV06 for bytes; + + constructor(IExchange exchange_) public { + exchange = exchange_; + erc20Proxy = exchange_.getAssetProxy(ERC20_ASSET_PROXY_ID); + } + + /// @dev Sell this contract's entire balance of of `sellToken` in exchange + /// for `buyToken` by filling `orders`. Protocol fees should be attached + /// to this call. `buyToken` and excess ETH will be transferred back to the caller. + /// This function cannot be re-entered. + /// @param data_ ABI-encoded `FillSellQuoteTransformData`. + /// @return success `TRANSFORMER_SUCCESS` on success. + function transform( + bytes32, // callDataHash, + address payable, // taker, + IERC20TokenV06[] calldata, // tokens, + uint256[] calldata, // amounts, + bytes calldata data_ + ) + external + override + payable + nonReentrant + returns (bytes4 success) + { + FillSellQuoteTransformData memory data = + abi.decode(data_, (FillSellQuoteTransformData)); + + // If `sellAmount == -1` and `buyAmount == 0` then we are selling + // our entire balance of `sellToken`. This is useful in cases where + // the exact sell amount is not known in advance, like when unwrapping + // Chai/cUSDC/cDAI. + if (data.sellAmount == uint256(-1) && data.buyAmount == 0) { + data.sellAmount = data.sellToken.balanceOf(address(this)); + } + + // Approve the ERC20 proxy to spend `sellToken`. + data.sellToken.approveIfBelow(erc20Proxy, data.sellAmount); + + // Fill the orders. + uint256 singleProtocolFee = exchange.protocolFeeMultiplier().safeMul(tx.gasprice); + uint256 boughtAmount = 0; + uint256 soldAmount = 0; + for (uint256 i = 0; i < data.orders.length; ++i) { + // Check if we've hit our targets. + if (data.buyAmount == 0) { + // Market sell check. + if (data.sellAmount >= soldAmount) { + break; + } + } else { + // Market buy check. + if (data.buyAmount >= boughtAmount) { + break; + } + } + + // Approve the taker fee token. + if (data.orders[i].takerFee != 0) { + IERC20TokenV06 takerFeeToken = _getTokenFromAssetData(data.orders[i].takerFeeAssetData); + if (address(takerFeeToken) != address(0) && takerFeeToken != data.sellToken) { + // HACK(dorothy-zbornak): It isn't worth computing the actual taker fee + // since `approveIfBelow()` will set the allowance to infinite. We + // just need a reasonable upper bound to avoid unnecessarily re-approving. + takerFeeToken.approveIfBelow(erc20Proxy, data.orders[i].takerFee); + } + } + + // Compute the remaining fill amount. + uint256 fillAmount = (data.buyAmount == 0) + // Market sell. + ? data.sellAmount.safeSub(soldAmount) + // Market buy, so compute the fill amount from the bought amount. + : data.sellAmount.safeSub( + LibMathV06.getPartialAmountFloor( + boughtAmount, + data.buyAmount, + data.sellAmount + ) + ); + + // Fill the order. + FillOrderResults memory results = _fillOrder( + data.buyToken, + data.orders[i], + fillAmount, + data.signatures[i], + singleProtocolFee + ); + + // Accumulate totals. + soldAmount = soldAmount.safeAdd(results.takerTokenSoldAmount); + boughtAmount = boughtAmount.safeAdd(results.makerTokenBoughtAmount); + } + + // Ensure we hit our targets. + if (data.buyAmount == 0) { + // Market sell check. + if (soldAmount < data.sellAmount) { + LibTransformERC20RichErrors + .IncompleteFillSellQuoteError( + address(data.sellToken), + soldAmount, + data.sellAmount + ).rrevert(); + } + } else { + // Market buy check. + if (boughtAmount < data.buyAmount) { + LibTransformERC20RichErrors + .IncompleteFillBuyQuoteError( + address(data.buyToken), + boughtAmount, + data.buyAmount + ).rrevert(); + } + } + + // Transfer buy tokens. + data.buyToken.compatTransfer(msg.sender, data.buyToken.balanceOf(address(this))); + // Return unused sell tokens. + data.sellToken.compatTransfer(msg.sender, data.sellToken.balanceOf(address(this))); + // Return unused ETH. + if (address(this).balance != 0) { + msg.sender.transfer(address(this).balance); + } + return LibERC20Transformer.TRANSFORMER_SUCCESS; + } + + function _fillOrder( + IERC20TokenV06 makerToken, + IExchange.Order memory order, + uint256 takerTokenFillAmount, + bytes memory signature, + uint256 protocolFee + ) + private + returns (FillOrderResults memory results) + { + // Track changes in the maker token balance. + results.makerTokenBoughtAmount = makerToken.balanceOf(address(this)); + + // Ensure we have enough ETH to cover the protocol fee. + if (address(this).balance < protocolFee) { + LibTransformERC20RichErrors + .InsufficientProtocolFeeError(address(this).balance, protocolFee) + .rrevert(); + } + + // Perform the fill. + try + exchange.fillOrder + {value: protocolFee} + (order, takerTokenFillAmount, signature) + returns (IExchange.FillResults memory fillResults) + { + // We can trust the taker asset filled amount from fill results, but + // not the maker asset filled amount because bridges can fill more + // than the order specifies. + results.takerTokenSoldAmount = fillResults.takerAssetFilledAmount; + // Update maker quantity based on changes in token balances. + results.makerTokenBoughtAmount = makerToken.balanceOf(address(this)) + .safeSub(results.makerTokenBoughtAmount); + } + catch (bytes memory) { + // If the fill fails, zero out fill quantities. + results.takerTokenSoldAmount = 0; + } + } + + function _getTokenFromAssetData(bytes memory assetData) + private + pure + returns (IERC20TokenV06 token) + { + if (assetData.length != 36) { + return token; + } + // We only support plain ERC20 asset data. + if (LibBytesV06.readBytes4(assetData, 0) != ERC20_ASSET_PROXY_ID) { + LibTransformERC20RichErrors + .InvalidERC20AssetDataError(assetData) + .rrevert(); + } + return IERC20TokenV06(LibBytesV06.readAddress(assetData, 4)); + } +} diff --git a/contracts/zero-ex/contracts/src/transformers/PayTakerTransformer.sol b/contracts/zero-ex/contracts/src/transformers/PayTakerTransformer.sol new file mode 100644 index 0000000000..96fee7a2c5 --- /dev/null +++ b/contracts/zero-ex/contracts/src/transformers/PayTakerTransformer.sol @@ -0,0 +1,86 @@ +/* + + 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.6.5; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol"; +import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; +import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; +import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; +import "../errors/LibTransformERC20RichErrors.sol"; +import "./IERC20Transformer.sol"; +import "./LibERC20Transformer.sol"; + + +/// @dev A transformer that transfers any tokens it receives to the taker. +contract PayTakerTransformer is + IERC20Transformer +{ + + /// @dev Data to encode and pass to `transform()`. + struct PayTakerTransformData { + // Amounts to transfer. + uint256[] amounts; + } + + using LibRichErrorsV06 for bytes; + using LibSafeMathV06 for uint256; + using LibERC20Transformer for IERC20TokenV06; + + /// @dev Forwards any tokens transffered to the taker. + /// @param taker The taker address (caller of `TransformERC20.transformERC20()`). + /// @param tokens The tokens that were transferred to this contract. ETH may + /// be included as 0xeee... + /// @param amounts The amount of each token in `tokens` that were transferred + /// to this contract. + /// @param data_ ABI-encoded `PayTakerTransformData`. May be omitted. + /// @return success `TRANSFORMER_SUCCESS` on success. + function transform( + bytes32, // callDataHash, + address payable taker, + IERC20TokenV06[] calldata tokens, + uint256[] calldata amounts, + bytes calldata data_ + ) + external + override + payable + returns (bytes4 success) + { + // If `data_` is empty then just use the entire balances transferred. + uint256[] memory takerAmounts = data_.length == 0 + ? amounts + : abi.decode(data_, (PayTakerTransformData)).amounts; + + if (tokens.length != amounts.length) { + LibTransformERC20RichErrors + .WrongNumberOfTokensReceivedError(tokens.length, takerAmounts.length) + .rrevert(); + } + + for (uint256 i = 0; i < takerAmounts.length; ++i) { + // Transfer tokens directly to the taker. + tokens[i].transformerTransfer(taker, takerAmounts[i]); + // Transfer unused tokens back to the sender. + tokens[i].transformerTransfer(msg.sender, amounts[0].safeSub(takerAmounts[i])); + } + + return LibERC20Transformer.TRANSFORMER_SUCCESS; + } +} diff --git a/contracts/zero-ex/contracts/src/transformers/WethTransformer.sol b/contracts/zero-ex/contracts/src/transformers/WethTransformer.sol new file mode 100644 index 0000000000..e3f596add1 --- /dev/null +++ b/contracts/zero-ex/contracts/src/transformers/WethTransformer.sol @@ -0,0 +1,112 @@ +/* + + 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.6.5; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol"; +import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; +import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; +import "../errors/LibTransformERC20RichErrors.sol"; +import "./IERC20Transformer.sol"; +import "./LibERC20Transformer.sol"; + + +/// @dev A transformer that wraps or unwraps WETH. +contract WethTransformer is + IERC20Transformer +{ + // solhint-disable indent + + /// @dev Data to encode and pass to `transform()`. + struct WethTransformData { + // Amount to wrap/unwrap. + uint256 amount; + } + + /// @dev The WETH contract address. + IEtherTokenV06 public immutable weth; + + using LibRichErrorsV06 for bytes; + using LibSafeMathV06 for uint256; + + constructor(IEtherTokenV06 weth_) public { + weth = weth_; + } + + /// @dev Wraps and unwraps WETH, depending on the token transferred. + /// If WETH is transferred, it will be unwrapped to ETH. + /// If ETH is transferred, it will be wrapped to WETH. + /// @param tokens The tokens that were transferred to this contract. ETH may + /// be included as 0xeee... + /// @param amounts The amount of each token in `tokens` that were transferred + /// to this contract. + /// @param data_ ABI-encoded `WethTransformData`. May be omitted. + /// @return success `TRANSFORMER_SUCCESS` on success. + function transform( + bytes32, // callDataHash, + address payable, // taker, + IERC20TokenV06[] calldata tokens, + uint256[] calldata amounts, + bytes calldata data_ + ) + external + override + payable + returns (bytes4 success) + { + if (tokens.length != 1) { + LibTransformERC20RichErrors + .WrongNumberOfTokensReceivedError(tokens.length, 1) + .rrevert(); + } + + // If `data_` is empty then just use the entire balance transferred. + uint256 amount = data_.length == 0 + ? amounts[0] + : abi.decode(data_, (WethTransformData)).amount; + uint256 unusedAmount = amounts[0].safeSub(amount); + + if (address(tokens[0]) == LibERC20Transformer.ETH_TOKEN_ADDRESS) { + // Wrap ETH. + weth.deposit{value: amount}(); + // Transfer WETH to sender. + weth.transfer(msg.sender, amount); + // Transfer unused ETH to sender. + if (unusedAmount != 0) { + msg.sender.transfer(unusedAmount); + } + } else if (address(tokens[0]) == address(weth)) { + // Unwrap WETH. + weth.withdraw(amount); + // Transfer ETH to sender. + msg.sender.transfer(amount); + // Transfer unused WETH to sender. + if (unusedAmount != 0) { + weth.transfer(msg.sender, unusedAmount); + } + } else { + // Token must be either WETH or ETH. + LibTransformERC20RichErrors + .InvalidTokenReceivedError(address(tokens[0])) + .rrevert(); + } + + return LibERC20Transformer.TRANSFORMER_SUCCESS; + } +} diff --git a/contracts/zero-ex/package.json b/contracts/zero-ex/package.json index a9f6e4c5e5..0fa86498bb 100644 --- a/contracts/zero-ex/package.json +++ b/contracts/zero-ex/package.json @@ -40,7 +40,7 @@ "config": { "publicInterfaceContracts": "ZeroEx,FullMigration,InitialMigration,Puppet,IERC20Transformer,IOwnable,ISimpleFunctionRegistry,ITokenSpender,IPuppetPool,ITransformERC20", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", - "abis": "./test/generated-artifacts/@(Bootstrap|FixinCommon|FullMigration|IBootstrap|IERC20Transformer|IExchange|IFeature|IOwnable|IPuppet|IPuppetPool|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|ITokenSpender|ITransformERC20|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibPuppetPoolStorage|LibPuppetRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|Ownable|Puppet|PuppetPool|SimpleFunctionRegistry|TestInitialMigration|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestPuppetPool|TestPuppetTarget|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestZeroExFeature|TokenSpender|TransformERC20|ZeroEx).json" + "abis": "./test/generated-artifacts/@(Bootstrap|FillQuoteTransformer|FixinCommon|FullMigration|IBootstrap|IERC20Transformer|IExchange|IFeature|IOwnable|IPuppet|IPuppetPool|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|ITokenSpender|ITransformERC20|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibPuppetPoolStorage|LibPuppetRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|Ownable|PayTakerTransformer|Puppet|PuppetPool|SimpleFunctionRegistry|TestInitialMigration|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestPuppetPool|TestPuppetTarget|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestZeroExFeature|TokenSpender|TransformERC20|WethTransformer|ZeroEx).json" }, "repository": { "type": "git", diff --git a/contracts/zero-ex/test/artifacts.ts b/contracts/zero-ex/test/artifacts.ts index a47f9b3c9a..0e3c036809 100644 --- a/contracts/zero-ex/test/artifacts.ts +++ b/contracts/zero-ex/test/artifacts.ts @@ -6,6 +6,7 @@ import { ContractArtifact } from 'ethereum-types'; import * as Bootstrap from '../test/generated-artifacts/Bootstrap.json'; +import * as FillQuoteTransformer from '../test/generated-artifacts/FillQuoteTransformer.json'; import * as FixinCommon from '../test/generated-artifacts/FixinCommon.json'; import * as FullMigration from '../test/generated-artifacts/FullMigration.json'; import * as IBootstrap from '../test/generated-artifacts/IBootstrap.json'; @@ -37,6 +38,7 @@ import * as LibStorage from '../test/generated-artifacts/LibStorage.json'; import * as LibTokenSpenderStorage from '../test/generated-artifacts/LibTokenSpenderStorage.json'; import * as LibTransformERC20RichErrors from '../test/generated-artifacts/LibTransformERC20RichErrors.json'; import * as Ownable from '../test/generated-artifacts/Ownable.json'; +import * as PayTakerTransformer from '../test/generated-artifacts/PayTakerTransformer.json'; import * as Puppet from '../test/generated-artifacts/Puppet.json'; import * as PuppetPool from '../test/generated-artifacts/PuppetPool.json'; import * as SimpleFunctionRegistry from '../test/generated-artifacts/SimpleFunctionRegistry.json'; @@ -54,6 +56,7 @@ import * as TestTransformERC20 from '../test/generated-artifacts/TestTransformER import * as TestZeroExFeature from '../test/generated-artifacts/TestZeroExFeature.json'; import * as TokenSpender from '../test/generated-artifacts/TokenSpender.json'; import * as TransformERC20 from '../test/generated-artifacts/TransformERC20.json'; +import * as WethTransformer from '../test/generated-artifacts/WethTransformer.json'; import * as ZeroEx from '../test/generated-artifacts/ZeroEx.json'; export const artifacts = { ZeroEx: ZeroEx as ContractArtifact, @@ -90,8 +93,11 @@ export const artifacts = { LibSimpleFunctionRegistryStorage: LibSimpleFunctionRegistryStorage as ContractArtifact, LibStorage: LibStorage as ContractArtifact, LibTokenSpenderStorage: LibTokenSpenderStorage as ContractArtifact, + FillQuoteTransformer: FillQuoteTransformer as ContractArtifact, IERC20Transformer: IERC20Transformer as ContractArtifact, LibERC20Transformer: LibERC20Transformer as ContractArtifact, + PayTakerTransformer: PayTakerTransformer as ContractArtifact, + WethTransformer: WethTransformer as ContractArtifact, IExchange: IExchange as ContractArtifact, ITestSimpleFunctionRegistryFeature: ITestSimpleFunctionRegistryFeature as ContractArtifact, TestInitialMigration: TestInitialMigration as ContractArtifact, diff --git a/contracts/zero-ex/test/wrappers.ts b/contracts/zero-ex/test/wrappers.ts index 1dcc36af5a..2e5da0584e 100644 --- a/contracts/zero-ex/test/wrappers.ts +++ b/contracts/zero-ex/test/wrappers.ts @@ -4,6 +4,7 @@ * ----------------------------------------------------------------------------- */ export * from '../test/generated-wrappers/bootstrap'; +export * from '../test/generated-wrappers/fill_quote_transformer'; export * from '../test/generated-wrappers/fixin_common'; export * from '../test/generated-wrappers/full_migration'; export * from '../test/generated-wrappers/i_bootstrap'; @@ -35,6 +36,7 @@ export * from '../test/generated-wrappers/lib_storage'; export * from '../test/generated-wrappers/lib_token_spender_storage'; export * from '../test/generated-wrappers/lib_transform_erc20_rich_errors'; export * from '../test/generated-wrappers/ownable'; +export * from '../test/generated-wrappers/pay_taker_transformer'; export * from '../test/generated-wrappers/puppet'; export * from '../test/generated-wrappers/puppet_pool'; export * from '../test/generated-wrappers/simple_function_registry'; @@ -52,4 +54,5 @@ export * from '../test/generated-wrappers/test_transform_erc20'; export * from '../test/generated-wrappers/test_zero_ex_feature'; export * from '../test/generated-wrappers/token_spender'; export * from '../test/generated-wrappers/transform_erc20'; +export * from '../test/generated-wrappers/weth_transformer'; export * from '../test/generated-wrappers/zero_ex'; diff --git a/contracts/zero-ex/tsconfig.json b/contracts/zero-ex/tsconfig.json index 82ce231619..8232024dbb 100644 --- a/contracts/zero-ex/tsconfig.json +++ b/contracts/zero-ex/tsconfig.json @@ -14,6 +14,7 @@ "generated-artifacts/Puppet.json", "generated-artifacts/ZeroEx.json", "test/generated-artifacts/Bootstrap.json", + "test/generated-artifacts/FillQuoteTransformer.json", "test/generated-artifacts/FixinCommon.json", "test/generated-artifacts/FullMigration.json", "test/generated-artifacts/IBootstrap.json", @@ -45,6 +46,7 @@ "test/generated-artifacts/LibTokenSpenderStorage.json", "test/generated-artifacts/LibTransformERC20RichErrors.json", "test/generated-artifacts/Ownable.json", + "test/generated-artifacts/PayTakerTransformer.json", "test/generated-artifacts/Puppet.json", "test/generated-artifacts/PuppetPool.json", "test/generated-artifacts/SimpleFunctionRegistry.json", @@ -62,6 +64,7 @@ "test/generated-artifacts/TestZeroExFeature.json", "test/generated-artifacts/TokenSpender.json", "test/generated-artifacts/TransformERC20.json", + "test/generated-artifacts/WethTransformer.json", "test/generated-artifacts/ZeroEx.json" ], "exclude": ["./deploy/solc/solc_bin"]