UniswapFeature (#2703)

* Minimal Uniswap accessor.

* Add comments

* Safe math

* mainnet gas benchmark

* Assembler Uniswap

* Selectors and addresses

* Fix bugs in ABI encoders

* Typo

* AsmUniswap test

* Fix wantAmount computation

* Golfing

* Bypass AllowanceTarget

* Generalized asm uniswapper

* Implement ordering

* Fix pair computation

* #6 Golfing Iron

* Remove 'to' argument (saves 377 gas)

* New contract api

* `@0x/contracts-zero-ex`: Add `UniswapFeature`

* `@0x/contract-artifacts`: Regenerate artifacts

* `@0x/contract-wrappers`: Regenerate wrappers

* `@0x/asset-swapper`: Add Uniswap VIP support.
`@0x/asset-swapper`: Add `includeSources` support.

* `@0x/contracts-zero-ex`: Fix misleading comments in `UniswapFeature`.
`@0x/asset-swapper`: Fix linter errors.

* `@0x/asset-swapper`: Fix source filter bugs.

* `@0x/contracts-zero-ex`: `UniswapFeature`: Reduce calldata size for AllowanceTarget call
`@0x/asset-swapper`: Fix failing test.

* `@0x/contracts-zero-ex`: Fix ETH buy tokens not being normalized to WETH.

* `@0x/asset-swapper`: Fix multi-hop weirdness with source filters.

* `@0x/asset-swapper`: Fix failing test.

* `@0x/asset-swapper`: Really fix that broken AS test.

* `@0x/asset-swapper`: use filter objects instead of source array for valid buy and sell sources/

* `@0x/asset-swapper`: Move some source filtering logic into the sampler operations.

* `@0x/contracts-zero-ex`: Address PR feedback

* `@0x/contracts-zero-ex`: Fix feature version bug.

* `@0x/asset-swapper`: Did I actually fix AS tests this time? Who knows.

Co-authored-by: Remco Bloemen <remco@0x.org>
Co-authored-by: Michael Zhu <mchl.zhu.96@gmail.com>
Co-authored-by: Lawrence Forman <me@merklejerk.com>
This commit is contained in:
Lawrence Forman
2020-09-23 02:27:48 -04:00
committed by GitHub
parent 32d11d1ba5
commit f84b375cde
27 changed files with 1044 additions and 179 deletions

View File

@@ -49,6 +49,14 @@
{
"note": "Add updated Kyber and Mooniswap rollup to FQT",
"pr": 2692
},
{
"note": "Add `UniswapFeature`",
"pr": 2703
},
{
"note": "Fix versioning (`_encodeVersion()`) bug",
"pr": 2703
}
]
},

View File

@@ -25,6 +25,7 @@ import "./features/ITokenSpenderFeature.sol";
import "./features/ISignatureValidatorFeature.sol";
import "./features/ITransformERC20Feature.sol";
import "./features/IMetaTransactionsFeature.sol";
import "./features/IUniswapFeature.sol";
/// @dev Interface for a fully featured Exchange Proxy.
@@ -34,7 +35,8 @@ interface IZeroEx is
ITokenSpenderFeature,
ISignatureValidatorFeature,
ITransformERC20Feature,
IMetaTransactionsFeature
IMetaTransactionsFeature,
IUniswapFeature
{
// solhint-disable state-visibility

View File

@@ -0,0 +1,43 @@
/*
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-erc20/contracts/src/v06/IERC20TokenV06.sol";
/// @dev VIP uniswap fill functions.
interface IUniswapFeature {
/// @dev Efficiently sell directly to uniswap/sushiswap.
/// @param tokens Sell path.
/// @param sellAmount of `tokens[0]` Amount to sell.
/// @param minBuyAmount Minimum amount of `tokens[-1]` to buy.
/// @param isSushi Use sushiswap if true.
/// @return buyAmount Amount of `tokens[-1]` bought.
function sellToUniswap(
IERC20TokenV06[] calldata tokens,
uint256 sellAmount,
uint256 minBuyAmount,
bool isSushi
)
external
payable
returns (uint256 buyAmount);
}

View File

@@ -0,0 +1,366 @@
/*
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-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
import "../migrations/LibMigrate.sol";
import "../external/IAllowanceTarget.sol";
import "../fixins/FixinCommon.sol";
import "./IFeature.sol";
import "./IUniswapFeature.sol";
/// @dev VIP uniswap fill functions.
contract UniswapFeature is
IFeature,
IUniswapFeature,
FixinCommon
{
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "UniswapFeature";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
/// @dev WETH contract.
IEtherTokenV06 private immutable WETH;
/// @dev AllowanceTarget instance.
IAllowanceTarget private immutable ALLOWANCE_TARGET;
// 0xFF + address of the UniswapV2Factory contract.
uint256 constant private FF_UNISWAP_FACTORY = 0xFF5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f0000000000000000000000;
// 0xFF + address of the (Sushiswap) UniswapV2Factory contract.
uint256 constant private FF_SUSHISWAP_FACTORY = 0xFFC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac0000000000000000000000;
// Init code hash of the UniswapV2Pair contract.
uint256 constant private UNISWAP_PAIR_INIT_CODE_HASH = 0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f;
// Init code hash of the (Sushiswap) UniswapV2Pair contract.
uint256 constant private SUSHISWAP_PAIR_INIT_CODE_HASH = 0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303;
// Mask of the lower 20 bytes of a bytes32.
uint256 constant private ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
// ETH pseudo-token address.
uint256 constant private ETH_TOKEN_ADDRESS_32 = 0x000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee;
// Maximum token quantity that can be swapped against the UniswapV2Pair contract.
uint256 constant private MAX_SWAP_AMOUNT = 2**112;
// bytes4(keccak256("executeCall(address,bytes)"))
uint256 constant private ALLOWANCE_TARGET_EXECUTE_CALL_SELECTOR_32 = 0xbca8c7b500000000000000000000000000000000000000000000000000000000;
// bytes4(keccak256("getReserves()"))
uint256 constant private UNISWAP_PAIR_RESERVES_CALL_SELECTOR_32 = 0x0902f1ac00000000000000000000000000000000000000000000000000000000;
// bytes4(keccak256("swap(uint256,uint256,address,bytes)"))
uint256 constant private UNISWAP_PAIR_SWAP_CALL_SELECTOR_32 = 0x022c0d9f00000000000000000000000000000000000000000000000000000000;
// bytes4(keccak256("transferFrom(address,address,uint256)"))
uint256 constant private TRANSFER_FROM_CALL_SELECTOR_32 = 0x23b872dd00000000000000000000000000000000000000000000000000000000;
// bytes4(keccak256("withdraw(uint256)"))
uint256 constant private WETH_WITHDRAW_CALL_SELECTOR_32 = 0x2e1a7d4d00000000000000000000000000000000000000000000000000000000;
// bytes4(keccak256("deposit()"))
uint256 constant private WETH_DEPOSIT_CALL_SELECTOR_32 = 0xd0e30db000000000000000000000000000000000000000000000000000000000;
// bytes4(keccak256("transfer(address,uint256)"))
uint256 constant private ERC20_TRANSFER_CALL_SELECTOR_32 = 0xa9059cbb00000000000000000000000000000000000000000000000000000000;
/// @dev Construct this contract.
/// @param weth The WETH contract.
/// @param allowanceTarget The AllowanceTarget contract.
constructor(IEtherTokenV06 weth, IAllowanceTarget allowanceTarget) public {
WETH = weth;
ALLOWANCE_TARGET = allowanceTarget;
}
/// @dev Initialize and register this feature.
/// Should be delegatecalled by `Migrate.migrate()`.
/// @return success `LibMigrate.SUCCESS` on success.
function migrate()
external
returns (bytes4 success)
{
_registerFeatureFunction(this.sellToUniswap.selector);
return LibMigrate.MIGRATE_SUCCESS;
}
/// @dev Efficiently sell directly to uniswap/sushiswap.
/// @param tokens Sell path.
/// @param sellAmount of `tokens[0]` Amount to sell.
/// @param minBuyAmount Minimum amount of `tokens[-1]` to buy.
/// @param isSushi Use sushiswap if true.
/// @return buyAmount Amount of `tokens[-1]` bought.
function sellToUniswap(
IERC20TokenV06[] calldata tokens,
uint256 sellAmount,
uint256 minBuyAmount,
bool isSushi
)
external
payable
override
returns (uint256 buyAmount)
{
require(tokens.length > 1, "UniswapFeature/InvalidTokensLength");
{
// Load immutables onto the stack.
IEtherTokenV06 weth = WETH;
IAllowanceTarget allowanceTarget = ALLOWANCE_TARGET;
// Store some vars in memory to get around stack limits.
assembly {
// calldataload(mload(0xA00)) == first element of `tokens` array
mstore(0xA00, add(calldataload(0x04), 0x24))
// mload(0xA20) == isSushi
mstore(0xA20, isSushi)
// mload(0xA40) == WETH
mstore(0xA40, weth)
// mload(0xA60) == ALLOWANCE_TARGET
mstore(0xA60, allowanceTarget)
}
}
assembly {
// numPairs == tokens.length - 1
let numPairs := sub(calldataload(add(calldataload(0x04), 0x4)), 1)
// We use the previous buy amount as the sell amount for the next
// pair in a path. So for the first swap we want to set it to `sellAmount`.
buyAmount := sellAmount
let buyToken
let nextPair := 0
for {let i := 0} lt(i, numPairs) {i := add(i, 1)} {
// sellToken = tokens[i]
let sellToken := loadTokenAddress(i)
// buyToken = tokens[i+1]
buyToken := loadTokenAddress(add(i, 1))
// The canonical ordering of this token pair.
let pairOrder := lt(normalizeToken(sellToken), normalizeToken(buyToken))
// Compute the pair address if it hasn't already been computed
// from the last iteration.
let pair := nextPair
if iszero(pair) {
pair := computePairAddress(sellToken, buyToken)
nextPair := 0
}
if iszero(i) {
switch eq(sellToken, ETH_TOKEN_ADDRESS_32)
case 0 {
// For the first pair we need to transfer sellTokens into the
// pair contract using `AllowanceTarget.executeCall()`
mstore(0xB00, ALLOWANCE_TARGET_EXECUTE_CALL_SELECTOR_32)
mstore(0xB04, sellToken)
mstore(0xB24, 0x40)
mstore(0xB44, 0x64)
mstore(0xB64, TRANSFER_FROM_CALL_SELECTOR_32)
mstore(0xB68, caller())
mstore(0xB88, pair)
mstore(0xBA8, sellAmount)
if iszero(call(gas(), mload(0xA60), 0, 0xB00, 0xC8, 0x00, 0x0)) {
bubbleRevert()
}
}
default {
// If selling ETH, we need to wrap it to WETH and transfer to the
// pair contract.
if iszero(eq(callvalue(), sellAmount)) {
revert(0, 0)
}
sellToken := mload(0xA40)// Re-assign to WETH
// Call `WETH.deposit{value: sellAmount}()`
mstore(0xB00, WETH_DEPOSIT_CALL_SELECTOR_32)
if iszero(call(gas(), sellToken, sellAmount, 0xB00, 0x4, 0x00, 0x0)) {
bubbleRevert()
}
// Call `WETH.transfer(pair, sellAmount)`
mstore(0xB00, ERC20_TRANSFER_CALL_SELECTOR_32)
mstore(0xB04, pair)
mstore(0xB24, sellAmount)
if iszero(call(gas(), sellToken, 0, 0xB00, 0x44, 0x00, 0x0)) {
bubbleRevert()
}
}
// No need to check results, if deposit/transfers failed the UniswapV2Pair will
// reject our trade (or it may succeed if somehow the reserve was out of sync)
// this is fine for the taker.
}
// Call pair.getReserves(), store the results at `0xC00`
mstore(0xB00, UNISWAP_PAIR_RESERVES_CALL_SELECTOR_32)
if iszero(staticcall(gas(), pair, 0xB00, 0x4, 0xC00, 0x40)) {
bubbleRevert()
}
// Sell amount for this hop is the previous buy amount.
let pairSellAmount := buyAmount
// Compute the buy amount based on the pair reserves.
{
let sellReserve
let buyReserve
switch iszero(pairOrder)
case 0 {
// Transpose if pair order is different.
sellReserve := mload(0xC00)
buyReserve := mload(0xC20)
}
default {
sellReserve := mload(0xC20)
buyReserve := mload(0xC00)
}
// Ensure that the sellAmount is < 2¹¹².
if gt(pairSellAmount, MAX_SWAP_AMOUNT) {
revert(0, 0)
}
// Pairs are in the range (0, 2¹¹²) so this shouldn't overflow.
// buyAmount = (pairSellAmount * 997 * buyReserve) /
// (pairSellAmount * 997 + sellReserve * 1000);
let sellAmountWithFee := mul(pairSellAmount, 997)
buyAmount := div(
mul(sellAmountWithFee, buyReserve),
add(sellAmountWithFee, mul(sellReserve, 1000))
)
}
let receiver
// Is this the last pair contract?
switch eq(add(i, 1), numPairs)
case 0 {
// Not the last pair contract, so forward bought tokens to
// the next pair contract.
nextPair := computePairAddress(
buyToken,
loadTokenAddress(add(i, 2))
)
receiver := nextPair
}
default {
// The last pair contract.
// Forward directly to taker UNLESS they want ETH back.
switch eq(buyToken, ETH_TOKEN_ADDRESS_32)
case 0 {
receiver := caller()
}
default {
receiver := address()
}
}
// Call pair.swap()
mstore(0xB00, UNISWAP_PAIR_SWAP_CALL_SELECTOR_32)
switch pairOrder
case 0 {
mstore(0xB04, buyAmount)
mstore(0xB24, 0)
}
default {
mstore(0xB04, 0)
mstore(0xB24, buyAmount)
}
mstore(0xB44, receiver)
mstore(0xB64, 0x80)
mstore(0xB84, 0)
if iszero(call(gas(), pair, 0, 0xB00, 0xA4, 0, 0)) {
bubbleRevert()
}
} // End for-loop.
// If buying ETH, unwrap the WETH first
if eq(buyToken, ETH_TOKEN_ADDRESS_32) {
// Call `WETH.withdraw(buyAmount)`
mstore(0xB00, WETH_WITHDRAW_CALL_SELECTOR_32)
mstore(0xB04, buyAmount)
if iszero(call(gas(), mload(0xA40), 0, 0xB00, 0x24, 0x00, 0x0)) {
bubbleRevert()
}
// Transfer ETH to the caller.
if iszero(call(gas(), caller(), buyAmount, 0xB00, 0x0, 0x00, 0x0)) {
bubbleRevert()
}
}
// Functions ///////////////////////////////////////////////////////
// Load a token address from the `tokens` calldata argument.
function loadTokenAddress(idx) -> addr {
addr := and(ADDRESS_MASK, calldataload(add(mload(0xA00), mul(idx, 0x20))))
}
// Convert ETH pseudo-token addresses to WETH.
function normalizeToken(token) -> normalized {
normalized := token
// Translate ETH pseudo-tokens to WETH.
if eq(token, ETH_TOKEN_ADDRESS_32) {
normalized := mload(0xA40)
}
}
// Compute the address of the UniswapV2Pair contract given two
// tokens.
function computePairAddress(tokenA, tokenB) -> pair {
// Convert ETH pseudo-token addresses to WETH.
tokenA := normalizeToken(tokenA)
tokenB := normalizeToken(tokenB)
// There is one contract for every combination of tokens,
// which is deployed using CREATE2.
// The derivation of this address is given by:
// address(keccak256(abi.encodePacked(
// bytes(0xFF),
// address(UNISWAP_FACTORY_ADDRESS),
// keccak256(abi.encodePacked(
// tokenA < tokenB ? tokenA : tokenB,
// tokenA < tokenB ? tokenB : tokenA,
// )),
// bytes32(UNISWAP_PAIR_INIT_CODE_HASH),
// )));
// Compute the salt (the hash of the sorted tokens).
// Tokens are written in reverse memory order to packed encode
// them as two 20-byte values in a 40-byte chunk of memory
// starting at 0xB0C.
switch lt(tokenA, tokenB)
case 0 {
mstore(0xB14, tokenA)
mstore(0xB00, tokenB)
}
default {
mstore(0xB14, tokenB)
mstore(0xB00, tokenA)
}
let salt := keccak256(0xB0C, 0x28)
// Compute the pair address by hashing all the components together.
switch mload(0xA20) // isSushi
case 0 {
mstore(0xB00, FF_UNISWAP_FACTORY)
mstore(0xB15, salt)
mstore(0xB35, UNISWAP_PAIR_INIT_CODE_HASH)
}
default {
mstore(0xB00, FF_SUSHISWAP_FACTORY)
mstore(0xB15, salt)
mstore(0xB35, SUSHISWAP_PAIR_INIT_CODE_HASH)
}
pair := and(ADDRESS_MASK, keccak256(0xB00, 0x55))
}
// Revert with the return data from the most recent call.
function bubbleRevert() {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
// Revert if we bought too little.
// TODO: replace with rich revert?
require(buyAmount >= minBuyAmount, "UniswapFeature/UnderBought");
}
}

View File

@@ -81,6 +81,6 @@ abstract contract FixinCommon {
pure
returns (uint256 encodedVersion)
{
return (major << 64) | (minor << 32) | revision;
return (uint256(major) << 64) | (uint256(minor) << 32) | uint256(revision);
}
}

View File

@@ -29,6 +29,8 @@ library LibERC20Transformer {
/// @dev ETH pseudo-token address.
address constant internal ETH_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev ETH pseudo-token.
IERC20TokenV06 constant internal ETH_TOKEN = IERC20TokenV06(ETH_TOKEN_ADDRESS);
/// @dev Return value indicating success in `IERC20Transformer.transform()`.
/// This is just `keccak256('TRANSFORMER_SUCCESS')`.
bytes4 constant internal TRANSFORMER_SUCCESS = 0x13c9929e;

View File

@@ -41,7 +41,7 @@
"config": {
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITokenSpenderFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,TokenSpenderFeature,AffiliateFeeTransformer,SignatureValidatorFeature,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinReentrancyGuard|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|IMetaTransactionsFeature|IOwnableFeature|ISignatureValidatorFeature|ISimpleFunctionRegistryFeature|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignatureRichErrors|LibSignedCallData|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LogMetadataTransformer|MetaTransactionsFeature|MixinAdapterAddresses|MixinBalancer|MixinCurve|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|OwnableFeature|PayTakerTransformer|SignatureValidatorFeature|SimpleFunctionRegistryFeature|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFullMigration|TestInitialMigration|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|WethTransformer|ZeroEx).json"
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinReentrancyGuard|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|IMetaTransactionsFeature|IOwnableFeature|ISignatureValidatorFeature|ISimpleFunctionRegistryFeature|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignatureRichErrors|LibSignedCallData|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LogMetadataTransformer|MetaTransactionsFeature|MixinAdapterAddresses|MixinBalancer|MixinCurve|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|OwnableFeature|PayTakerTransformer|SignatureValidatorFeature|SimpleFunctionRegistryFeature|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFullMigration|TestInitialMigration|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx).json"
},
"repository": {
"type": "git",

View File

@@ -32,6 +32,7 @@ import * as ISimpleFunctionRegistryFeature from '../test/generated-artifacts/ISi
import * as ITestSimpleFunctionRegistryFeature from '../test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json';
import * as ITokenSpenderFeature from '../test/generated-artifacts/ITokenSpenderFeature.json';
import * as ITransformERC20Feature from '../test/generated-artifacts/ITransformERC20Feature.json';
import * as IUniswapFeature from '../test/generated-artifacts/IUniswapFeature.json';
import * as IZeroEx from '../test/generated-artifacts/IZeroEx.json';
import * as LibBootstrap from '../test/generated-artifacts/LibBootstrap.json';
import * as LibCommonRichErrors from '../test/generated-artifacts/LibCommonRichErrors.json';
@@ -96,6 +97,7 @@ import * as TokenSpenderFeature from '../test/generated-artifacts/TokenSpenderFe
import * as Transformer from '../test/generated-artifacts/Transformer.json';
import * as TransformERC20Feature from '../test/generated-artifacts/TransformERC20Feature.json';
import * as TransformerDeployer from '../test/generated-artifacts/TransformerDeployer.json';
import * as UniswapFeature from '../test/generated-artifacts/UniswapFeature.json';
import * as WethTransformer from '../test/generated-artifacts/WethTransformer.json';
import * as ZeroEx from '../test/generated-artifacts/ZeroEx.json';
export const artifacts = {
@@ -124,12 +126,14 @@ export const artifacts = {
ISimpleFunctionRegistryFeature: ISimpleFunctionRegistryFeature as ContractArtifact,
ITokenSpenderFeature: ITokenSpenderFeature as ContractArtifact,
ITransformERC20Feature: ITransformERC20Feature as ContractArtifact,
IUniswapFeature: IUniswapFeature as ContractArtifact,
MetaTransactionsFeature: MetaTransactionsFeature as ContractArtifact,
OwnableFeature: OwnableFeature as ContractArtifact,
SignatureValidatorFeature: SignatureValidatorFeature as ContractArtifact,
SimpleFunctionRegistryFeature: SimpleFunctionRegistryFeature as ContractArtifact,
TokenSpenderFeature: TokenSpenderFeature as ContractArtifact,
TransformERC20Feature: TransformERC20Feature as ContractArtifact,
UniswapFeature: UniswapFeature as ContractArtifact,
LibSignedCallData: LibSignedCallData as ContractArtifact,
FixinCommon: FixinCommon as ContractArtifact,
FixinEIP712: FixinEIP712 as ContractArtifact,

View File

@@ -29,6 +29,7 @@ export * from '../test/generated-wrappers/i_simple_function_registry_feature';
export * from '../test/generated-wrappers/i_test_simple_function_registry_feature';
export * from '../test/generated-wrappers/i_token_spender_feature';
export * from '../test/generated-wrappers/i_transform_erc20_feature';
export * from '../test/generated-wrappers/i_uniswap_feature';
export * from '../test/generated-wrappers/i_zero_ex';
export * from '../test/generated-wrappers/initial_migration';
export * from '../test/generated-wrappers/lib_bootstrap';
@@ -94,5 +95,6 @@ export * from '../test/generated-wrappers/token_spender_feature';
export * from '../test/generated-wrappers/transform_erc20_feature';
export * from '../test/generated-wrappers/transformer';
export * from '../test/generated-wrappers/transformer_deployer';
export * from '../test/generated-wrappers/uniswap_feature';
export * from '../test/generated-wrappers/weth_transformer';
export * from '../test/generated-wrappers/zero_ex';

View File

@@ -52,6 +52,7 @@
"test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json",
"test/generated-artifacts/ITokenSpenderFeature.json",
"test/generated-artifacts/ITransformERC20Feature.json",
"test/generated-artifacts/IUniswapFeature.json",
"test/generated-artifacts/IZeroEx.json",
"test/generated-artifacts/InitialMigration.json",
"test/generated-artifacts/LibBootstrap.json",
@@ -117,6 +118,7 @@
"test/generated-artifacts/TransformERC20Feature.json",
"test/generated-artifacts/Transformer.json",
"test/generated-artifacts/TransformerDeployer.json",
"test/generated-artifacts/UniswapFeature.json",
"test/generated-artifacts/WethTransformer.json",
"test/generated-artifacts/ZeroEx.json"
],