bsc<->development rebase (#189)

* FQT: Pack Protocol/source name into source ID (#162)

* `@0x/contracts-zero-ex`: Encode protocol ID and source name in bridge source ID
`@0x/asset-swapper`: Use new bridge source ID encoding.

* fix linter issues

* contracts cleanup (#164)

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

* `@0x/contracts-zero-ex`: Remove tokenspender/allowance target/greedy tokens stuff.'
`@0x/contract-addresses`: Add BSC addresses. Remove exchangeProxyAllowanceTarget.
`@0x/migrations`: Remove exchangeProxyAllowanceTarget.

* Update contracts/zero-ex/contracts/src/features/IPancakeSwapFeature.sol

Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com>

* `@0x/contracts-zero-ex`: Add sushiswap support to PancakeSwap

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

* `@0x/contract-addresses`: Add BSC addresses

Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com>

Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com>

* feat: Better chain support (#163)

* feat: Better chain support

* feat: better chain support refactor deployment constants (#166)

* proliferate the chainId

* Refactor sampler to remove DeploymentConstants dependency and fixed addresses

* Rework WETH out, replacing with address(0)

* wat

* hack DeploymentConstants for now

* proliferate the chainId

* Refactor sampler to remove DeploymentConstants dependency and fixed addresses

* remove duped network addresses

* Rework the bridge source encoder

* Use the constants NATIVE_FEE_TOKEN in EP consumer

* `@0x/contract-addresses`: Fix WBNB address (#170)

Co-authored-by: Lawrence Forman <lawrence@0xproject.com>

* multichain enable cakez vip (#171)

* feat: Better chain support

* feat: better chain support refactor deployment constants (#166)

* proliferate the chainId

* Refactor sampler to remove DeploymentConstants dependency and fixed addresses

* Rework WETH out, replacing with address(0)

* wat

* hack DeploymentConstants for now

* proliferate the chainId

* Refactor sampler to remove DeploymentConstants dependency and fixed addresses

* remove duped network addresses

* `asset-swapper`: enable pancake VIP route generation

Co-authored-by: Jacob Evans <jacob@dekz.net>
Co-authored-by: Lawrence Forman <me@merklejerk.com>

* `@0x/contracts-zero-ex`: Fix `PancakeSwapFeature` sushi values (#172)

* `@0x/contracts-zero-ex`: Fix `PancakeSwapFeature` sushi values

* `@0x/contracts-zero-ex`: I am a bad protocologist

Co-authored-by: Lawrence Forman <me@merklejerk.com>

* feat: BSC Nerve + Dodo + Nerve + Ellipsis (#181)

* feat: BSC Nerve + DODO v1

* CHANGELOGs

* Remove extra balance fetch

* Add Belt

* Added Ellipsis

* Update FQT address

* `@0x/contracts-zero-ex`: Delete TokenSpenderFeature and get stuff compiling

* `@0x/asset-swapper`: fix compilation

* prettier

* `@0x/asset-swapper`: Truncate LiquidityProvider source ID name

* Update packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts

Co-authored-by: Jacob Evans <jacob@dekz.net>

* Update packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts

Co-authored-by: Jacob Evans <jacob@dekz.net>

* `@0x/contracts-zero-ex`: Fix BakerySwap on PackageSwapFeature (#190)

* address review comments

Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com>
Co-authored-by: Jacob Evans <jacob@dekz.net>
Co-authored-by: Lawrence Forman <me@merklejerk.com>
This commit is contained in:
Lawrence Forman
2021-03-31 18:49:44 -04:00
committed by GitHub
parent 70ddab0231
commit 164a5d44d9
99 changed files with 2559 additions and 3029 deletions

View File

@@ -1,4 +1,33 @@
[
{
"version": "0.21.0",
"changes": [
{
"note": "Encoding protocol ID and source name in bridge source ID",
"pr": 162
},
{
"note": "Add PancakeSwapFeature",
"pr": 164
},
{
"note": "Remove TokenSpender/AllowanceTarget/greedy tokens stuff",
"pr": 164
},
{
"note": "Added Nerve in BridgeAdapter",
"pr": 181
},
{
"note": "Delete TokenSpenderFeature",
"pr": 189
},
{
"note": "Fix PancakeSwapFeature BakerySwap swap selector",
"pr": 190
}
]
},
{
"version": "0.20.0",
"changes": [

View File

@@ -26,6 +26,7 @@ import "./features/interfaces/ITokenSpenderFeature.sol";
import "./features/interfaces/ITransformERC20Feature.sol";
import "./features/interfaces/IMetaTransactionsFeature.sol";
import "./features/interfaces/IUniswapFeature.sol";
import "./features/interfaces/IPancakeSwapFeature.sol";
import "./features/interfaces/ILiquidityProviderFeature.sol";
import "./features/interfaces/INativeOrdersFeature.sol";
import "./features/interfaces/IBatchFillNativeOrdersFeature.sol";
@@ -36,10 +37,10 @@ import "./features/interfaces/IMultiplexFeature.sol";
interface IZeroEx is
IOwnableFeature,
ISimpleFunctionRegistryFeature,
ITokenSpenderFeature,
ITransformERC20Feature,
IMetaTransactionsFeature,
IUniswapFeature,
IPancakeSwapFeature,
ILiquidityProviderFeature,
INativeOrdersFeature,
IBatchFillNativeOrdersFeature,

View File

@@ -1,47 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
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;
library LibSpenderRichErrors {
// solhint-disable func-name-mixedcase
function SpenderERC20TransferFromFailedError(
address token,
address owner,
address to,
uint256 amount,
bytes memory errorData
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
bytes4(keccak256("SpenderERC20TransferFromFailedError(address,address,address,uint256,bytes)")),
token,
owner,
to,
amount,
errorData
);
}
}

View File

@@ -1,56 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
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/AuthorizableV06.sol";
import "../errors/LibSpenderRichErrors.sol";
import "./IAllowanceTarget.sol";
/// @dev The allowance target for the TokenSpender feature.
contract AllowanceTarget is
IAllowanceTarget,
AuthorizableV06
{
// solhint-disable no-unused-vars,indent,no-empty-blocks
using LibRichErrorsV06 for bytes;
/// @dev Execute an arbitrary call. Only an authority can call this.
/// @param target The call target.
/// @param callData The call data.
/// @return resultData The data returned by the call.
function executeCall(
address payable target,
bytes calldata callData
)
external
override
onlyAuthorized
returns (bytes memory resultData)
{
bool success;
(success, resultData) = target.call(callData);
if (!success) {
resultData.rrevert();
}
}
}

View File

@@ -1,40 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
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/interfaces/IAuthorizableV06.sol";
/// @dev The allowance target for the TokenSpender feature.
interface IAllowanceTarget is
IAuthorizableV06
{
/// @dev Execute an arbitrary call. Only an authority can call this.
/// @param target The call target.
/// @param callData The call data.
/// @return resultData The data returned by the call.
function executeCall(
address payable target,
bytes calldata callData
)
external
returns (bytes memory resultData);
}

View File

@@ -47,15 +47,14 @@ contract LiquidityProviderFeature is
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "LiquidityProviderFeature";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 3);
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 4);
/// @dev The sandbox contract address.
ILiquidityProviderSandbox public immutable sandbox;
constructor(LiquidityProviderSandbox sandbox_, bytes32 greedyTokensBloomFilter)
constructor(LiquidityProviderSandbox sandbox_)
public
FixinCommon()
FixinTokenSpender(greedyTokensBloomFilter)
{
sandbox = sandbox_;
}

View File

@@ -78,7 +78,7 @@ contract MetaTransactionsFeature is
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "MetaTransactions";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 0);
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 1);
/// @dev EIP712 typehash of the `MetaTransactionData` struct.
bytes32 public immutable MTX_EIP712_TYPEHASH = keccak256(
"MetaTransactionData("
@@ -105,11 +105,10 @@ contract MetaTransactionsFeature is
}
}
constructor(address zeroExAddress, bytes32 greedyTokensBloomFilter)
constructor(address zeroExAddress)
public
FixinCommon()
FixinEIP712(zeroExAddress)
FixinTokenSpender(greedyTokensBloomFilter)
{
// solhint-disable-next-line no-empty-blocks
}

View File

@@ -55,7 +55,7 @@ contract MultiplexFeature is
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "MultiplexFeature";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1);
/// @dev The WETH token contract.
IEtherTokenV06 private immutable weth;
@@ -73,12 +73,10 @@ contract MultiplexFeature is
constructor(
address zeroExAddress,
IEtherTokenV06 weth_,
ILiquidityProviderSandbox sandbox_,
bytes32 greedyTokensBloomFilter
ILiquidityProviderSandbox sandbox_
)
public
FixinEIP712(zeroExAddress)
FixinTokenSpender(greedyTokensBloomFilter)
{
weth = weth_;
sandbox = sandbox_;

View File

@@ -34,15 +34,14 @@ contract NativeOrdersFeature is
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "LimitOrders";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1);
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 0);
constructor(
address zeroExAddress,
IEtherTokenV06 weth,
IStaking staking,
FeeCollectorController feeCollectorController,
uint32 protocolFeeMultiplier,
bytes32 greedyTokensBloomFilter
uint32 protocolFeeMultiplier
)
public
NativeOrdersSettlement(
@@ -50,8 +49,7 @@ contract NativeOrdersFeature is
weth,
staking,
feeCollectorController,
protocolFeeMultiplier,
greedyTokensBloomFilter
protocolFeeMultiplier
)
{
// solhint-disable no-empty-blocks

View File

@@ -0,0 +1,423 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 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 "../fixins/FixinCommon.sol";
import "./interfaces/IFeature.sol";
import "./interfaces/IPancakeSwapFeature.sol";
/// @dev VIP pancake fill functions.
contract PancakeSwapFeature is
IFeature,
IPancakeSwapFeature,
FixinCommon
{
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "PancakeSwapFeature";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1);
/// @dev WBNB contract.
IEtherTokenV06 private immutable WBNB;
// 0xFF + address of the PancakeSwap factory contract.
uint256 constant private FF_PANCAKESWAP_FACTORY = 0xffbcfccbde45ce874adcb698cc183debcf179528120000000000000000000000;
// 0xFF + address of the BakerySwap factory contract.
uint256 constant private FF_BAKERYSWAP_FACTORY = 0xff01bf7c66c6bd861915cdaae475042d3c4bae16a70000000000000000000000;
// 0xFF + address of the SushiSwap factory contract.
uint256 constant private FF_SUSHISWAP_FACTORY = 0xffc35DADB65012eC5796536bD9864eD8773aBc74C40000000000000000000000;
// Init code hash of the PancakeSwap pair contract.
uint256 constant private PANCAKESWAP_PAIR_INIT_CODE_HASH = 0xd0d4c4cd0848c93cb4fd1f498d7013ee6bfb25783ea21593d5834f5d250ece66;
// Init code hash of the BakerySwap pair contract.
uint256 constant private BAKERYSWAP_PAIR_INIT_CODE_HASH = 0xe2e87433120e32c4738a7d8f3271f3d872cbe16241d67537139158d90bac61d3;
// Init code hash of the SushiSwap pair 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;
// BNB pseudo-token address.
uint256 constant private ETH_TOKEN_ADDRESS_32 = 0x000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee;
// Maximum token quantity that can be swapped against the PancakeSwapPair 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 PANCAKESWAP_PAIR_RESERVES_CALL_SELECTOR_32 = 0x0902f1ac00000000000000000000000000000000000000000000000000000000;
// bytes4(keccak256("swap(uint256,uint256,address,bytes)"))
uint256 constant private PANCAKESWAP_PAIR_SWAP_CALL_SELECTOR_32 = 0x022c0d9f00000000000000000000000000000000000000000000000000000000;
// bytes4(keccak256("swap(uint256,uint256,address)"))
uint256 constant private BAKERYSWAP_PAIR_SWAP_CALL_SELECTOR_32 = 0x6d9a640a00000000000000000000000000000000000000000000000000000000;
// bytes4(keccak256("transferFrom(address,address,uint256)"))
uint256 constant private TRANSFER_FROM_CALL_SELECTOR_32 = 0x23b872dd00000000000000000000000000000000000000000000000000000000;
// bytes4(keccak256("allowance(address,address)"))
uint256 constant private ALLOWANCE_CALL_SELECTOR_32 = 0xdd62ed3e00000000000000000000000000000000000000000000000000000000;
// 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 wbnb The WBNB contract.
constructor(IEtherTokenV06 wbnb) public {
WBNB = wbnb;
}
/// @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.sellToPancakeSwap.selector);
return LibMigrate.MIGRATE_SUCCESS;
}
/// @dev Efficiently sell directly to pancake/BakerySwap/SushiSwap.
/// @param tokens Sell path.
/// @param sellAmount of `tokens[0]` Amount to sell.
/// @param minBuyAmount Minimum amount of `tokens[-1]` to buy.
/// @param fork The protocol fork to use.
/// @return buyAmount Amount of `tokens[-1]` bought.
function sellToPancakeSwap(
IERC20TokenV06[] calldata tokens,
uint256 sellAmount,
uint256 minBuyAmount,
ProtocolFork fork
)
external
payable
override
returns (uint256 buyAmount)
{
require(tokens.length > 1, "PancakeSwapFeature/InvalidTokensLength");
{
// Load immutables onto the stack.
IEtherTokenV06 wbnb = WBNB;
// 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) == fork
mstore(0xA20, fork)
// mload(0xA40) == WBNB
mstore(0xA40, wbnb)
}
}
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) {
// This is the first token in the path.
switch eq(sellToken, ETH_TOKEN_ADDRESS_32)
case 0 { // Not selling BNB. Selling an ERC20 instead.
// Make sure BNB was not attached to the call.
if gt(callvalue(), 0) {
revert(0, 0)
}
// For the first pair we need to transfer sellTokens into the
// pair contract.
moveTakerTokensTo(sellToken, pair, sellAmount)
}
default {
// If selling BNB, we need to wrap it to WBNB and transfer to the
// pair contract.
if iszero(eq(callvalue(), sellAmount)) {
revert(0, 0)
}
sellToken := mload(0xA40)// Re-assign to WBNB
// Call `WBNB.deposit{value: sellAmount}()`
mstore(0xB00, WETH_DEPOSIT_CALL_SELECTOR_32)
if iszero(call(gas(), sellToken, sellAmount, 0xB00, 0x4, 0x00, 0x0)) {
bubbleRevert()
}
// Call `WBNB.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 PancakeSwapPair 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, PANCAKESWAP_PAIR_RESERVES_CALL_SELECTOR_32)
if iszero(staticcall(gas(), pair, 0xB00, 0x4, 0xC00, 0x40)) {
bubbleRevert()
}
// Revert if the pair contract does not return at least two words.
if lt(returndatasize(), 0x40) {
mstore(0, pair)
revert(0, 32)
}
// 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 BNB back.
switch eq(buyToken, ETH_TOKEN_ADDRESS_32)
case 0 {
receiver := caller()
}
default {
receiver := address()
}
}
// Call pair.swap()
switch mload(0xA20) // fork
case 1 {
mstore(0xB00, BAKERYSWAP_PAIR_SWAP_CALL_SELECTOR_32)
}
default {
mstore(0xB00, PANCAKESWAP_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 BNB, unwrap the WBNB first
if eq(buyToken, ETH_TOKEN_ADDRESS_32) {
// Call `WBNB.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 BNB 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 BNB pseudo-token addresses to WBNB.
function normalizeToken(token) -> normalized {
normalized := token
// Translate BNB pseudo-tokens to WBNB.
if eq(token, ETH_TOKEN_ADDRESS_32) {
normalized := mload(0xA40)
}
}
// Compute the address of the PancakeSwapPair contract given two
// tokens.
function computePairAddress(tokenA, tokenB) -> pair {
// Convert BNB pseudo-token addresses to WBNB.
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(PANCAKESWAP_FACTORY_ADDRESS),
// keccak256(abi.encodePacked(
// tokenA < tokenB ? tokenA : tokenB,
// tokenA < tokenB ? tokenB : tokenA,
// )),
// bytes32(PANCAKESWAP_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) // fork
case 0 {
mstore(0xB00, FF_PANCAKESWAP_FACTORY)
mstore(0xB15, salt)
mstore(0xB35, PANCAKESWAP_PAIR_INIT_CODE_HASH)
}
case 1 {
mstore(0xB00, FF_BAKERYSWAP_FACTORY)
mstore(0xB15, salt)
mstore(0xB35, BAKERYSWAP_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())
}
// Move `amount` tokens from the taker/caller to `to`.
function moveTakerTokensTo(token, to, amount) {
// Perform a `transferFrom()`
mstore(0xB00, TRANSFER_FROM_CALL_SELECTOR_32)
mstore(0xB04, caller())
mstore(0xB24, to)
mstore(0xB44, amount)
let success := call(
gas(),
token,
0,
0xB00,
0x64,
0xC00,
// Copy only the first 32 bytes of return data. We
// only care about reading a boolean in the success
// case. We will use returndatacopy() in the failure case.
0x20
)
let rdsize := returndatasize()
// Check for ERC20 success. ERC20 tokens should
// return a boolean, but some return nothing or
// extra data. We accept 0-length return data as
// success, or at least 32 bytes that starts with
// a 32-byte boolean true.
success := and(
success, // call itself succeeded
or(
iszero(rdsize), // no return data, or
and(
iszero(lt(rdsize, 32)), // at least 32 bytes
eq(mload(0xC00), 1) // starts with uint256(1)
)
)
)
if iszero(success) {
// Revert with the data returned from the transferFrom call.
returndatacopy(0, 0, rdsize)
revert(0, rdsize)
}
}
}
// Revert if we bought too little.
require(buyAmount >= minBuyAmount, "PancakeSwapFeature/UnderBought");
}
}

View File

@@ -1,137 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
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/LibSpenderRichErrors.sol";
import "../fixins/FixinCommon.sol";
import "../migrations/LibMigrate.sol";
import "../external/IAllowanceTarget.sol";
import "../storage/LibTokenSpenderStorage.sol";
import "./interfaces/IFeature.sol";
import "./interfaces/ITokenSpenderFeature.sol";
/// @dev Feature that allows spending token allowances.
contract TokenSpenderFeature is
IFeature,
ITokenSpenderFeature,
FixinCommon
{
// solhint-disable
/// @dev Name of this feature.
string public constant override FEATURE_NAME = "TokenSpender";
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
// solhint-enable
using LibRichErrorsV06 for bytes;
/// @dev Initialize and register this feature. Should be delegatecalled
/// into during a `Migrate.migrate()`.
/// @param allowanceTarget An `allowanceTarget` instance, configured to have
/// the ZeroeEx contract as an authority.
/// @return success `MIGRATE_SUCCESS` on success.
function migrate(IAllowanceTarget allowanceTarget)
external
returns (bytes4 success)
{
LibTokenSpenderStorage.getStorage().allowanceTarget = allowanceTarget;
_registerFeatureFunction(this.getAllowanceTarget.selector);
_registerFeatureFunction(this._spendERC20Tokens.selector);
_registerFeatureFunction(this.getSpendableERC20BalanceOf.selector);
return LibMigrate.MIGRATE_SUCCESS;
}
/// @dev Transfers ERC20 tokens from `owner` to `to`. Only callable from within.
/// @param token The token to spend.
/// @param owner The owner of the tokens.
/// @param to The recipient of the tokens.
/// @param amount The amount of `token` to transfer.
function _spendERC20Tokens(
IERC20TokenV06 token,
address owner,
address to,
uint256 amount
)
external
override
onlySelf
{
IAllowanceTarget spender = LibTokenSpenderStorage.getStorage().allowanceTarget;
// Have the allowance target execute an ERC20 `transferFrom()`.
(bool didSucceed, bytes memory resultData) = address(spender).call(
abi.encodeWithSelector(
IAllowanceTarget.executeCall.selector,
address(token),
abi.encodeWithSelector(
IERC20TokenV06.transferFrom.selector,
owner,
to,
amount
)
)
);
if (didSucceed) {
resultData = abi.decode(resultData, (bytes));
}
if (!didSucceed || !LibERC20TokenV06.isSuccessfulResult(resultData)) {
LibSpenderRichErrors.SpenderERC20TransferFromFailedError(
address(token),
owner,
to,
amount,
resultData
).rrevert();
}
}
/// @dev Gets the maximum amount of an ERC20 token `token` that can be
/// pulled from `owner` by the token spender.
/// @param token The token to spend.
/// @param owner The owner of the tokens.
/// @return amount The amount of tokens that can be pulled.
function getSpendableERC20BalanceOf(IERC20TokenV06 token, address owner)
external
override
view
returns (uint256 amount)
{
return LibSafeMathV06.min256(
token.allowance(owner, address(LibTokenSpenderStorage.getStorage().allowanceTarget)),
token.balanceOf(owner)
);
}
/// @dev Get the address of the allowance target.
/// @return target The target of token allowances.
function getAllowanceTarget()
external
override
view
returns (address target)
{
return address(LibTokenSpenderStorage.getStorage().allowanceTarget);
}
}

View File

@@ -60,10 +60,7 @@ contract TransformERC20Feature is
/// @dev Version of this feature.
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 3, 1);
constructor(bytes32 greedyTokensBloomFilter)
public
FixinTokenSpender(greedyTokensBloomFilter)
{}
constructor() public {}
/// @dev Initialize and register this feature.
/// Should be delegatecalled by `Migrate.migrate()`.

View File

@@ -23,7 +23,6 @@ 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 "./interfaces/IFeature.sol";
import "./interfaces/IUniswapFeature.sol";
@@ -38,13 +37,9 @@ contract UniswapFeature is
/// @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, 1, 1);
/// @dev A bloom filter for tokens that consume all gas when `transferFrom()` fails.
bytes32 public immutable GREEDY_TOKENS_BLOOM_FILTER;
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 2);
/// @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;
@@ -80,16 +75,8 @@ contract UniswapFeature is
/// @dev Construct this contract.
/// @param weth The WETH contract.
/// @param allowanceTarget The AllowanceTarget contract.
/// @param greedyTokensBloomFilter The bloom filter for greedy tokens.
constructor(
IEtherTokenV06 weth,
IAllowanceTarget allowanceTarget,
bytes32 greedyTokensBloomFilter
) public {
constructor(IEtherTokenV06 weth) public {
WETH = weth;
ALLOWANCE_TARGET = allowanceTarget;
GREEDY_TOKENS_BLOOM_FILTER = greedyTokensBloomFilter;
}
/// @dev Initialize and register this feature.
@@ -124,8 +111,6 @@ contract UniswapFeature is
{
// Load immutables onto the stack.
IEtherTokenV06 weth = WETH;
IAllowanceTarget allowanceTarget = ALLOWANCE_TARGET;
bytes32 greedyTokensBloomFilter = GREEDY_TOKENS_BLOOM_FILTER;
// Store some vars in memory to get around stack limits.
assembly {
@@ -135,10 +120,6 @@ contract UniswapFeature is
mstore(0xA20, isSushi)
// mload(0xA40) == WETH
mstore(0xA40, weth)
// mload(0xA60) == ALLOWANCE_TARGET
mstore(0xA60, allowanceTarget)
// mload(0xA80) == GREEDY_TOKENS_BLOOM_FILTER
mstore(0xA80, greedyTokensBloomFilter)
}
}
@@ -373,38 +354,7 @@ contract UniswapFeature is
// Move `amount` tokens from the taker/caller to `to`.
function moveTakerTokensTo(token, to, amount) {
// If the token is possibly greedy, we check the allowance rather
// than relying on letting the transferFrom() call fail and
// falling through to legacy allowance target because the token
// will eat all our gas.
if isTokenPossiblyGreedy(token) {
// Check if we have enough direct allowance by calling
// `token.allowance()`
mstore(0xB00, ALLOWANCE_CALL_SELECTOR_32)
mstore(0xB04, caller())
mstore(0xB24, address())
let success := staticcall(gas(), token, 0xB00, 0x44, 0xC00, 0x20)
if iszero(success) {
// Call to allowance() failed.
bubbleRevert()
}
// Make sure the allowance call returned at least a word.
if lt(returndatasize(), 0x20) {
revert(0, 0)
}
// Call succeeded.
// Result is stored in 0xC00-0xC20.
if lt(mload(0xC00), amount) {
// We don't have enough direct allowance, so try
// going through the legacy allowance taregt.
moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount)
leave
}
}
// Otherwise we will optimistically try to perform a `transferFrom()`
// directly then if it fails we will go through the legacy allowance target.
// Perform a `transferFrom()`
mstore(0xB00, TRANSFER_FROM_CALL_SELECTOR_32)
mstore(0xB04, caller())
mstore(0xB24, to)
@@ -419,8 +369,7 @@ contract UniswapFeature is
0xC00,
// Copy only the first 32 bytes of return data. We
// only care about reading a boolean in the success
// case, and we discard the return data in the
// failure case.
// case. We will use returndatacopy() in the failure case.
0x20
)
@@ -443,37 +392,11 @@ contract UniswapFeature is
)
if iszero(success) {
// Try to fall back to the allowance target.
moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount)
// Revert with the data returned from the transferFrom call.
returndatacopy(0, 0, rdsize)
revert(0, rdsize)
}
}
// Move tokens by going through the legacy allowance target contract.
function moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount) {
mstore(0xB00, ALLOWANCE_TARGET_EXECUTE_CALL_SELECTOR_32)
mstore(0xB04, token)
mstore(0xB24, 0x40)
mstore(0xB44, 0x64)
mstore(0xB64, TRANSFER_FROM_CALL_SELECTOR_32)
mstore(0xB68, caller())
mstore(0xB88, to)
mstore(0xBA8, amount)
if iszero(call(gas(), mload(0xA60), 0, 0xB00, 0xC8, 0x00, 0x0)) {
bubbleRevert()
}
// If this fall back failed, the swap will most likely fail
// so there's no need to validate the result.
}
// Checks if a token possibly belongs to the GREEDY_TOKENS_BLOOM_FILTER
// bloom filter.
function isTokenPossiblyGreedy(token) -> isPossiblyGreedy {
// The hash is given by:
// (1 << (keccak256(token) % 256)) | (1 << (token % 256))
mstore(0, token)
let h := or(shl(mod(keccak256(0, 32), 256), 1), shl(mod(token, 256), 1))
isPossiblyGreedy := eq(and(h, mload(0xA80)), h)
}
}
// Revert if we bought too little.

View File

@@ -0,0 +1,50 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 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 PancakeSwap/BakerySwap/SushiSwap fill functions.
interface IPancakeSwapFeature {
enum ProtocolFork {
PancakeSwap,
BakerySwap,
SushiSwap
}
/// @dev Efficiently sell directly to PancakeSwap/BakerySwap/Sushiswap.
/// @param tokens Sell path.
/// @param sellAmount of `tokens[0]` Amount to sell.
/// @param minBuyAmount Minimum amount of `tokens[-1]` to buy.
/// @param fork The protocol fork to use.
/// @return buyAmount Amount of `tokens[-1]` bought.
function sellToPancakeSwap(
IERC20TokenV06[] calldata tokens,
uint256 sellAmount,
uint256 minBuyAmount,
ProtocolFork fork
)
external
payable
returns (uint256 buyAmount);
}

View File

@@ -40,11 +40,10 @@ abstract contract NativeOrdersCancellation is
uint256 private constant HIGH_BIT = 1 << 255;
constructor(
address zeroExAddress,
bytes32 greedyTokensBloomFilter
address zeroExAddress
)
internal
NativeOrdersInfo(zeroExAddress, greedyTokensBloomFilter)
NativeOrdersInfo(zeroExAddress)
{
// solhint-disable no-empty-blocks
}

View File

@@ -51,12 +51,10 @@ abstract contract NativeOrdersInfo is
uint256 private constant HIGH_BIT = 1 << 255;
constructor(
address zeroExAddress,
bytes32 greedyTokensBloomFilter
address zeroExAddress
)
internal
FixinEIP712(zeroExAddress)
FixinTokenSpender(greedyTokensBloomFilter)
{
// solhint-disable no-empty-blocks
}

View File

@@ -96,11 +96,10 @@ abstract contract NativeOrdersSettlement is
IEtherTokenV06 weth,
IStaking staking,
FeeCollectorController feeCollectorController,
uint32 protocolFeeMultiplier,
bytes32 greedyTokensBloomFilter
uint32 protocolFeeMultiplier
)
public
NativeOrdersCancellation(zeroExAddress, greedyTokensBloomFilter)
NativeOrdersCancellation(zeroExAddress)
NativeOrdersProtocolFees(weth, staking, feeCollectorController, protocolFeeMultiplier)
{
// solhint-disable no-empty-blocks

View File

@@ -22,28 +22,13 @@ pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "../features/interfaces/ITokenSpenderFeature.sol";
import "../errors/LibSpenderRichErrors.sol";
import "../external/FeeCollector.sol";
import "../vendor/v3/IStaking.sol";
import "../vendor/v3/IStaking.sol";
/// @dev Helpers for moving tokens around.
abstract contract FixinTokenSpender {
using LibRichErrorsV06 for bytes;
// Mask of the lower 20 bytes of a bytes32.
uint256 constant private ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
/// @dev A bloom filter for tokens that consume all gas when `transferFrom()` fails.
bytes32 public immutable GREEDY_TOKENS_BLOOM_FILTER;
/// @param greedyTokensBloomFilter The bloom filter for all greedy tokens.
constructor(bytes32 greedyTokensBloomFilter)
internal
{
GREEDY_TOKENS_BLOOM_FILTER = greedyTokensBloomFilter;
}
/// @dev Transfers ERC20 tokens from `owner` to `to`.
/// @param token The token to spend.
@@ -58,29 +43,8 @@ abstract contract FixinTokenSpender {
)
internal
{
bool success;
bytes memory revertData;
require(address(token) != address(this), "FixinTokenSpender/CANNOT_INVOKE_SELF");
// If the token eats all gas when failing, we do not want to perform
// optimistic fall through to the old AllowanceTarget contract if the
// direct transferFrom() fails.
if (_isTokenPossiblyGreedy(token)) {
// If the token does not have a direct allowance on us then we use
// the allowance target.
if (token.allowance(owner, address(this)) < amount) {
_transferFromLegacyAllowanceTarget(
token,
owner,
to,
amount,
""
);
return;
}
}
assembly {
let ptr := mload(0x40) // free memory pointer
@@ -90,20 +54,18 @@ abstract contract FixinTokenSpender {
mstore(add(ptr, 0x24), and(to, ADDRESS_MASK))
mstore(add(ptr, 0x44), amount)
success := call(
let success := call(
gas(),
and(token, ADDRESS_MASK),
0,
ptr,
0x64,
0,
0
ptr,
32
)
let rdsize := returndatasize()
returndatacopy(add(ptr, 0x20), 0, rdsize) // reuse memory
// Check for ERC20 success. ERC20 tokens should return a boolean,
// but some don't. We accept 0-length return data as success, or at
// least 32 bytes that starts with a 32-byte boolean true.
@@ -113,30 +75,16 @@ abstract contract FixinTokenSpender {
iszero(rdsize), // no return data, or
and(
iszero(lt(rdsize, 32)), // at least 32 bytes
eq(mload(add(ptr, 0x20)), 1) // starts with uint256(1)
eq(mload(ptr), 1) // starts with uint256(1)
)
)
)
if iszero(success) {
// revertData is a bytes, so length-prefixed data
mstore(ptr, rdsize)
revertData := ptr
// update free memory pointer (ptr + 32-byte length + return data)
mstore(0x40, add(add(ptr, 0x20), rdsize))
returndatacopy(ptr, 0, rdsize)
revert(ptr, rdsize)
}
}
if (!success) {
_transferFromLegacyAllowanceTarget(
token,
owner,
to,
amount,
revertData
);
}
}
/// @dev Gets the maximum amount of an ERC20 token `token` that can be
@@ -157,53 +105,4 @@ abstract contract FixinTokenSpender {
token.balanceOf(owner)
);
}
/// @dev Check if a token possibly belongs to the `GREEDY_TOKENS_BLOOM_FILTER`
/// bloom filter.
function _isTokenPossiblyGreedy(IERC20TokenV06 token)
internal
view
returns (bool isPossiblyGreedy)
{
// The hash is given by:
// (1 << (keccak256(token) % 256)) | (1 << (token % 256))
bytes32 h;
assembly {
mstore(0, token)
h := or(shl(mod(keccak256(0, 32), 256), 1), shl(mod(token, 256), 1))
}
return (h & GREEDY_TOKENS_BLOOM_FILTER) == h;
}
/// @dev Transfer tokens using the legacy allowance target instead of
/// allowances directly set on the exchange proxy.
function _transferFromLegacyAllowanceTarget(
IERC20TokenV06 token,
address owner,
address to,
uint256 amount,
bytes memory initialRevertData
)
private
{
// Try the old AllowanceTarget.
try ITokenSpenderFeature(address(this))._spendERC20Tokens(
token,
owner,
to,
amount
) {
} catch (bytes memory revertData) {
// Bubble up the first error message. (In general, the fallback to the
// allowance target is opportunistic. We ignore the specific error
// message if it fails.)
LibSpenderRichErrors.SpenderERC20TransferFromFailedError(
address(token),
owner,
to,
amount,
initialRevertData.length != 0 ? initialRevertData : revertData
).rrevert();
}
}
}

View File

@@ -22,11 +22,9 @@ pragma experimental ABIEncoderV2;
import "../ZeroEx.sol";
import "../features/interfaces/IOwnableFeature.sol";
import "../features/TokenSpenderFeature.sol";
import "../features/TransformERC20Feature.sol";
import "../features/MetaTransactionsFeature.sol";
import "../features/NativeOrdersFeature.sol";
import "../external/AllowanceTarget.sol";
import "./InitialMigration.sol";
@@ -39,7 +37,6 @@ contract FullMigration {
struct Features {
SimpleFunctionRegistryFeature registry;
OwnableFeature ownable;
TokenSpenderFeature tokenSpender;
TransformERC20Feature transformERC20;
MetaTransactionsFeature metaTransactions;
NativeOrdersFeature nativeOrders;
@@ -107,7 +104,7 @@ contract FullMigration {
);
// Add features.
_addFeatures(zeroEx, owner, features, migrateOpts);
_addFeatures(zeroEx, features, migrateOpts);
// Transfer ownership to the real owner.
IOwnableFeature(address(zeroEx)).transferOwnership(owner);
@@ -132,36 +129,16 @@ contract FullMigration {
/// @dev Deploy and register features to the ZeroEx contract.
/// @param zeroEx The bootstrapped ZeroEx contract.
/// @param owner The ultimate owner of the ZeroEx contract.
/// @param features Features to add to the proxy.
/// @param migrateOpts Parameters needed to initialize features.
function _addFeatures(
ZeroEx zeroEx,
address owner,
Features memory features,
MigrateOpts memory migrateOpts
)
private
{
IOwnableFeature ownable = IOwnableFeature(address(zeroEx));
// TokenSpenderFeature
{
// Create the allowance target.
AllowanceTarget allowanceTarget = new AllowanceTarget();
// Let the ZeroEx contract use the allowance target.
allowanceTarget.addAuthorizedAddress(address(zeroEx));
// Transfer ownership of the allowance target to the (real) owner.
allowanceTarget.transferOwnership(owner);
// Register the feature.
ownable.migrate(
address(features.tokenSpender),
abi.encodeWithSelector(
TokenSpenderFeature.migrate.selector,
allowanceTarget
),
address(this)
);
}
// TransformERC20Feature
{
// Register the feature.

View File

@@ -1,46 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
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 "./LibStorage.sol";
import "../external/IAllowanceTarget.sol";
/// @dev Storage helpers for the `TokenSpender` feature.
library LibTokenSpenderStorage {
/// @dev Storage bucket for this feature.
struct Storage {
// Allowance target contract.
IAllowanceTarget allowanceTarget;
}
/// @dev Get the storage bucket for this contract.
function getStorage() internal pure returns (Storage storage stor) {
uint256 storageSlot = LibStorage.getStorageSlot(
LibStorage.StorageId.TokenSpender
);
// Dip into assembly to change the slot pointed to by the local
// variable `stor`.
// See https://solidity.readthedocs.io/en/v0.6.8/assembly.html?highlight=slot#access-to-external-variables-functions-and-libraries
assembly { stor_slot := storageSlot }
}
}

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Copyright 2021 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,7 +21,7 @@ pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "./IBridgeAdapter.sol";
import "./BridgeSource.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinBalancer.sol";
import "./mixins/MixinBancor.sol";
import "./mixins/MixinCoFiX.sol";
@@ -32,9 +32,9 @@ import "./mixins/MixinDodoV2.sol";
import "./mixins/MixinKyber.sol";
import "./mixins/MixinMooniswap.sol";
import "./mixins/MixinMStable.sol";
import "./mixins/MixinNerve.sol";
import "./mixins/MixinOasis.sol";
import "./mixins/MixinShell.sol";
import "./mixins/MixinSushiswap.sol";
import "./mixins/MixinUniswap.sol";
import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinZeroExBridge.sol";
@@ -51,9 +51,9 @@ contract BridgeAdapter is
MixinKyber,
MixinMooniswap,
MixinMStable,
MixinNerve,
MixinOasis,
MixinShell,
MixinSushiswap,
MixinUniswap,
MixinUniswapV2,
MixinZeroExBridge
@@ -70,9 +70,9 @@ contract BridgeAdapter is
MixinKyber(weth)
MixinMooniswap(weth)
MixinMStable()
MixinNerve()
MixinOasis()
MixinShell()
MixinSushiswap()
MixinUniswap(weth)
MixinUniswapV2()
MixinZeroExBridge()
@@ -88,109 +88,106 @@ contract BridgeAdapter is
override
returns (uint256 boughtAmount)
{
if (order.source == BridgeSource.CURVE ||
order.source == BridgeSource.SWERVE ||
order.source == BridgeSource.SNOWSWAP) {
uint128 protocolId = uint128(uint256(order.source) >> 128);
if (protocolId == BridgeProtocols.CURVE) {
boughtAmount = _tradeCurve(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.SUSHISWAP) {
boughtAmount = _tradeSushiswap(
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.UNISWAPV2 ||
order.source == BridgeSource.LINKSWAP) {
} else if (protocolId == BridgeProtocols.UNISWAPV2) {
boughtAmount = _tradeUniswapV2(
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.UNISWAP) {
} else if (protocolId == BridgeProtocols.UNISWAP) {
boughtAmount = _tradeUniswap(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.BALANCER ||
order.source == BridgeSource.CREAM) {
} else if (protocolId == BridgeProtocols.BALANCER) {
boughtAmount = _tradeBalancer(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.KYBER) {
} else if (protocolId == BridgeProtocols.KYBER) {
boughtAmount = _tradeKyber(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.MOONISWAP) {
} else if (protocolId == BridgeProtocols.MOONISWAP) {
boughtAmount = _tradeMooniswap(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.MSTABLE) {
} else if (protocolId == BridgeProtocols.MSTABLE) {
boughtAmount = _tradeMStable(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.OASIS) {
} else if (protocolId == BridgeProtocols.OASIS) {
boughtAmount = _tradeOasis(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.SHELL) {
} else if (protocolId == BridgeProtocols.SHELL) {
boughtAmount = _tradeShell(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.DODO) {
} else if (protocolId == BridgeProtocols.DODO) {
boughtAmount = _tradeDodo(
sellToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.DODOV2) {
} else if (protocolId == BridgeProtocols.DODOV2) {
boughtAmount = _tradeDodoV2(
sellToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.CRYPTOCOM) {
} else if (protocolId == BridgeProtocols.CRYPTOCOM) {
boughtAmount = _tradeCryptoCom(
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.BANCOR) {
} else if (protocolId == BridgeProtocols.BANCOR) {
boughtAmount = _tradeBancor(
buyToken,
sellAmount,
order.bridgeData
);
} else if (order.source == BridgeSource.COFIX) {
} else if (protocolId == BridgeProtocols.COFIX) {
boughtAmount = _tradeCoFiX(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.NERVE) {
boughtAmount = _tradeNerve(
sellToken,
sellAmount,
order.bridgeData
);
} else {
boughtAmount = _tradeZeroExBridge(
sellToken,

View File

@@ -0,0 +1,46 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 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";
library BridgeProtocols {
// A incrementally increasing, append-only list of protocol IDs.
// We don't use an enum so solidity doesn't throw when we pass in a
// new protocol ID that hasn't been rolled up yet.
uint128 internal constant UNKNOWN = 0;
uint128 internal constant CURVE = 1;
uint128 internal constant UNISWAPV2 = 2;
uint128 internal constant UNISWAP = 3;
uint128 internal constant BALANCER = 4;
uint128 internal constant KYBER = 5;
uint128 internal constant MOONISWAP = 6;
uint128 internal constant MSTABLE = 7;
uint128 internal constant OASIS = 8;
uint128 internal constant SHELL = 9;
uint128 internal constant DODO = 10;
uint128 internal constant DODOV2 = 11;
uint128 internal constant CRYPTOCOM = 12;
uint128 internal constant BANCOR = 13;
uint128 internal constant COFIX = 14;
uint128 internal constant NERVE = 15;
}

View File

@@ -1,47 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
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;
library BridgeSource {
uint256 constant internal BALANCER = 0;
uint256 constant internal BANCOR = 1;
uint256 constant internal COFIX = 2;
uint256 constant internal CURVE = 3;
uint256 constant internal CREAM = 4;
uint256 constant internal CRYPTOCOM = 5;
uint256 constant internal DODO = 6;
uint256 constant internal KYBER = 7;
uint256 constant internal LIQUIDITYPROVIDER = 8;
uint256 constant internal MOONISWAP = 9;
uint256 constant internal MSTABLE = 10;
uint256 constant internal OASIS = 11;
uint256 constant internal SHELL = 12;
uint256 constant internal SNOWSWAP = 13;
uint256 constant internal SUSHISWAP = 14;
uint256 constant internal SWERVE = 15;
uint256 constant internal UNISWAP = 16;
uint256 constant internal UNISWAPV2 = 17;
uint256 constant internal DODOV2 = 18;
uint256 constant internal LINKSWAP = 19;
// New sources should be APPENDED to this list, taking the next highest
// integer value.
}

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2020 ZeroEx Intl.
Copyright 2021 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -26,20 +26,24 @@ import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
interface IBridgeAdapter {
struct BridgeOrder {
uint256 source;
// Upper 16 bytes: uint128 protocol ID (right-aligned)
// Lower 16 bytes: ASCII source name (left-aligned)
bytes32 source;
uint256 takerTokenAmount;
uint256 makerTokenAmount;
bytes bridgeData;
}
/// @dev Emitted when tokens are swapped with an external source.
/// @param source The unique ID for the source. See `BridgeSource.sol`
/// @param source A unique ID for the source, where the upper 16 bytes
/// encodes the (right-aligned) uint128 protocol ID and the
/// lower 16 bytes encodes an ASCII source name.
/// @param inputToken The token the bridge is converting from.
/// @param outputToken The token the bridge is converting to.
/// @param inputTokenAmount Amount of input token sold.
/// @param outputTokenAmount Amount of output token bought.
event BridgeFill(
uint256 source,
bytes32 source,
IERC20TokenV06 inputToken,
IERC20TokenV06 outputToken,
uint256 inputTokenAmount,

View File

@@ -0,0 +1,72 @@
// SPDX-License-Identifier: Apache-2.0
/*
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/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
contract MixinNerve {
using LibERC20TokenV06 for IERC20TokenV06;
using LibSafeMathV06 for uint256;
using LibRichErrorsV06 for bytes;
struct NerveBridgeData {
address pool;
bytes4 exchangeFunctionSelector;
int128 fromCoinIdx;
int128 toCoinIdx;
}
function _tradeNerve(
IERC20TokenV06 sellToken,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
// Basically a Curve fork but the swap option has a deadline
// Decode the bridge data to get the Curve metadata.
NerveBridgeData memory data = abi.decode(bridgeData, (NerveBridgeData));
sellToken.approveIfBelow(data.pool, sellAmount);
(bool success, bytes memory resultData) =
data.pool.call(abi.encodeWithSelector(
data.exchangeFunctionSelector,
data.fromCoinIdx,
data.toCoinIdx,
// dx
sellAmount,
// min dy
1,
// deadline
block.timestamp
));
if (!success) {
resultData.rrevert();
}
return abi.decode(resultData, (uint256));
}
}

View File

@@ -1,75 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
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/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "./MixinUniswapV2.sol";
contract MixinSushiswap {
using LibERC20TokenV06 for IERC20TokenV06;
function _tradeSushiswap(
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
IERC20TokenV06[] memory path;
IUniswapV2Router02 router;
{
address[] memory _path;
(router, _path) =
abi.decode(bridgeData, (IUniswapV2Router02, address[]));
// To get around `abi.decode()` not supporting interface array types.
assembly { path := _path }
}
require(path.length >= 2, "MixinSushiswap/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
require(
path[path.length - 1] == buyToken,
"MixinSushiswap/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"
);
// Grant the Uniswap router an allowance to sell the first token.
path[0].approveIfBelow(
address(router),
sellAmount
);
uint[] memory amounts = router.swapExactTokensForTokens(
// Sell all tokens we hold.
sellAmount,
// Minimum buy amount.
1,
// Convert to `buyToken` along this path.
path,
// Recipient is `this`.
address(this),
// Expires after this block.
block.timestamp
);
return amounts[amounts.length-1];
}
}

View File

@@ -26,12 +26,7 @@ import "../src/fixins/FixinTokenSpender.sol";
contract TestFixinTokenSpender is
FixinTokenSpender
{
uint256 constant private TRIGGER_FALLBACK_SUCCESS_AMOUNT = 1340;
constructor(bytes32 greedyTokensBloomFilter)
public
FixinTokenSpender(greedyTokensBloomFilter)
{}
constructor() public {}
function transferERC20Tokens(
IERC20TokenV06 token,
@@ -56,21 +51,6 @@ contract TestFixinTokenSpender is
uint256 amount
);
// This is called as a fallback when the original transferFrom() fails.
function _spendERC20Tokens(
IERC20TokenV06 token,
address owner,
address to,
uint256 amount
)
external
{
require(amount == TRIGGER_FALLBACK_SUCCESS_AMOUNT,
"TokenSpenderFallback/FAILURE_AMOUNT");
emit FallbackCalled(address(token), owner, to, amount);
}
function getSpendableERC20BalanceOf(
IERC20TokenV06 token,
address owner
@@ -81,12 +61,4 @@ contract TestFixinTokenSpender is
{
return _getSpendableERC20BalanceOf(token, owner);
}
function isTokenPossiblyGreedy(IERC20TokenV06 token)
external
view
returns (bool)
{
return _isTokenPossiblyGreedy(token);
}
}

View File

@@ -35,8 +35,7 @@ contract TestMetaTransactionsNativeOrdersFeature is
IEtherTokenV06(0),
IStaking(0),
FeeCollectorController(address(new TestFeeCollectorController())),
0,
bytes32(0)
0
)
{}

View File

@@ -38,7 +38,7 @@ contract TestMetaTransactionsTransformERC20Feature is
Transformation[] transformations
);
constructor() public TransformERC20Feature(0) {}
constructor() public TransformERC20Feature() {}
function _transformERC20(TransformERC20Args memory args)
public

View File

@@ -13,8 +13,7 @@ contract TestNativeOrdersFeature is
IEtherTokenV06 weth,
IStaking staking,
FeeCollectorController _feeCollectorController, // Unused but necessary for artifact compatibility.
uint32 protocolFeeMultiplier,
bytes32 greedyTokensBloomFilter
uint32 protocolFeeMultiplier
)
public
NativeOrdersFeature(
@@ -22,8 +21,7 @@ contract TestNativeOrdersFeature is
weth,
staking,
FeeCollectorController(address(new TestFeeCollectorController())),
protocolFeeMultiplier,
greedyTokensBloomFilter
protocolFeeMultiplier
)
{
// solhint-disable no-empty-blocks

View File

@@ -1,31 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
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 "../src/features/TokenSpenderFeature.sol";
contract TestTokenSpender is
TokenSpenderFeature
{
modifier onlySelf() override {
_;
}
}

View File

@@ -30,5 +30,5 @@ contract TestTransformERC20 is
_;
}
constructor() public TransformERC20Feature(0) {}
constructor() public TransformERC20Feature() {}
}

View File

@@ -41,9 +41,9 @@
"rollback": "node ./lib/scripts/rollback.js"
},
"config": {
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITokenSpenderFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,TokenSpenderFeature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature",
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeSource|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IAllowanceTarget|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOwnableFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinShell|MixinSushiswap|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OwnableFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestMooniswap|TestNativeOrdersFeature|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinMStable|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestMooniswap|TestNativeOrdersFeature|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
},
"repository": {
"type": "git",

View File

@@ -23,7 +23,6 @@ import * as INativeOrdersFeature from '../generated-artifacts/INativeOrdersFeatu
import * as InitialMigration from '../generated-artifacts/InitialMigration.json';
import * as IOwnableFeature from '../generated-artifacts/IOwnableFeature.json';
import * as ISimpleFunctionRegistryFeature from '../generated-artifacts/ISimpleFunctionRegistryFeature.json';
import * as ITokenSpenderFeature from '../generated-artifacts/ITokenSpenderFeature.json';
import * as ITransformERC20Feature from '../generated-artifacts/ITransformERC20Feature.json';
import * as IZeroEx from '../generated-artifacts/IZeroEx.json';
import * as LiquidityProviderFeature from '../generated-artifacts/LiquidityProviderFeature.json';
@@ -35,7 +34,6 @@ import * as OwnableFeature from '../generated-artifacts/OwnableFeature.json';
import * as PayTakerTransformer from '../generated-artifacts/PayTakerTransformer.json';
import * as PositiveSlippageFeeTransformer from '../generated-artifacts/PositiveSlippageFeeTransformer.json';
import * as SimpleFunctionRegistryFeature from '../generated-artifacts/SimpleFunctionRegistryFeature.json';
import * as TokenSpenderFeature from '../generated-artifacts/TokenSpenderFeature.json';
import * as TransformERC20Feature from '../generated-artifacts/TransformERC20Feature.json';
import * as WethTransformer from '../generated-artifacts/WethTransformer.json';
import * as ZeroEx from '../generated-artifacts/ZeroEx.json';
@@ -49,7 +47,6 @@ export const artifacts = {
IERC20Transformer: IERC20Transformer as ContractArtifact,
IOwnableFeature: IOwnableFeature as ContractArtifact,
ISimpleFunctionRegistryFeature: ISimpleFunctionRegistryFeature as ContractArtifact,
ITokenSpenderFeature: ITokenSpenderFeature as ContractArtifact,
ITransformERC20Feature: ITransformERC20Feature as ContractArtifact,
FillQuoteTransformer: FillQuoteTransformer as ContractArtifact,
PayTakerTransformer: PayTakerTransformer as ContractArtifact,
@@ -58,7 +55,6 @@ export const artifacts = {
OwnableFeature: OwnableFeature as ContractArtifact,
SimpleFunctionRegistryFeature: SimpleFunctionRegistryFeature as ContractArtifact,
TransformERC20Feature: TransformERC20Feature as ContractArtifact,
TokenSpenderFeature: TokenSpenderFeature as ContractArtifact,
AffiliateFeeTransformer: AffiliateFeeTransformer as ContractArtifact,
MetaTransactionsFeature: MetaTransactionsFeature as ContractArtifact,
LogMetadataTransformer: LogMetadataTransformer as ContractArtifact,

View File

@@ -41,7 +41,6 @@ export {
IOwnableFeatureEvents,
ISimpleFunctionRegistryFeatureContract,
ISimpleFunctionRegistryFeatureEvents,
ITokenSpenderFeatureContract,
ITransformERC20FeatureContract,
IZeroExContract,
LogMetadataTransformerContract,

View File

@@ -5,7 +5,6 @@ import { TxData } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { ZERO_BYTES32 } from './constants';
import {
FeeCollectorControllerContract,
FullMigrationContract,
@@ -15,7 +14,6 @@ import {
NativeOrdersFeatureContract,
OwnableFeatureContract,
SimpleFunctionRegistryFeatureContract,
TokenSpenderFeatureContract,
TransformERC20FeatureContract,
ZeroExContract,
} from './wrappers';
@@ -108,7 +106,6 @@ export async function initialMigrateAsync(
* Addresses of features for a full deployment of the Exchange Proxy.
*/
export interface FullFeatures extends BootstrapFeatures {
tokenSpender: string;
transformERC20: string;
metaTransactions: string;
nativeOrders: string;
@@ -118,7 +115,6 @@ export interface FullFeatures extends BootstrapFeatures {
* Artifacts to use when deploying full features.
*/
export interface FullFeatureArtifacts extends BootstrapFeatureArtifacts {
tokenSpender: SimpleContractArtifact;
transformERC20: SimpleContractArtifact;
metaTransactions: SimpleContractArtifact;
nativeOrders: SimpleContractArtifact;
@@ -133,7 +129,6 @@ export interface FullFeaturesDeployConfig {
wethAddress: string;
stakingAddress: string;
protocolFeeMultiplier: number;
greedyTokensBloomFilter: string;
}
/**
@@ -149,11 +144,9 @@ const DEFAULT_FULL_FEATURES_DEPLOY_CONFIG = {
stakingAddress: NULL_ADDRESS,
feeCollectorController: NULL_ADDRESS,
protocolFeeMultiplier: 70e3,
greedyTokensBloomFilter: ZERO_BYTES32,
};
const DEFAULT_FULL_FEATURES_ARTIFACTS = {
tokenSpender: artifacts.TokenSpenderFeature,
transformERC20: artifacts.TransformERC20Feature,
metaTransactions: artifacts.MetaTransactionsFeature,
nativeOrders: artifacts.NativeOrdersFeature,
@@ -187,14 +180,6 @@ export async function deployFullFeaturesAsync(
}
return {
...(await deployBootstrapFeaturesAsync(provider, txDefaults)),
tokenSpender:
features.tokenSpender ||
(await TokenSpenderFeatureContract.deployFrom0xArtifactAsync(
_featureArtifacts.tokenSpender,
provider,
txDefaults,
artifacts,
)).address,
transformERC20:
features.transformERC20 ||
(await TransformERC20FeatureContract.deployFrom0xArtifactAsync(
@@ -202,7 +187,6 @@ export async function deployFullFeaturesAsync(
provider,
txDefaults,
artifacts,
_config.greedyTokensBloomFilter,
)).address,
metaTransactions:
features.metaTransactions ||
@@ -212,7 +196,6 @@ export async function deployFullFeaturesAsync(
txDefaults,
artifacts,
_config.zeroExAddress,
_config.greedyTokensBloomFilter,
)).address,
nativeOrders:
features.nativeOrders ||
@@ -226,7 +209,6 @@ export async function deployFullFeaturesAsync(
_config.stakingAddress,
_config.feeCollectorController,
_config.protocolFeeMultiplier,
_config.greedyTokensBloomFilter,
)).address,
};
}

View File

@@ -20,7 +20,6 @@ export * from '../generated-wrappers/i_multiplex_feature';
export * from '../generated-wrappers/i_native_orders_feature';
export * from '../generated-wrappers/i_ownable_feature';
export * from '../generated-wrappers/i_simple_function_registry_feature';
export * from '../generated-wrappers/i_token_spender_feature';
export * from '../generated-wrappers/i_transform_erc20_feature';
export * from '../generated-wrappers/i_zero_ex';
export * from '../generated-wrappers/initial_migration';
@@ -33,7 +32,6 @@ export * from '../generated-wrappers/ownable_feature';
export * from '../generated-wrappers/pay_taker_transformer';
export * from '../generated-wrappers/positive_slippage_fee_transformer';
export * from '../generated-wrappers/simple_function_registry_feature';
export * from '../generated-wrappers/token_spender_feature';
export * from '../generated-wrappers/transform_erc20_feature';
export * from '../generated-wrappers/weth_transformer';
export * from '../generated-wrappers/zero_ex';

View File

@@ -1,82 +0,0 @@
import { blockchainTests, constants, expect, randomAddress, verifyEventsFromLogs } from '@0x/contracts-test-utils';
import { AuthorizableRevertErrors, hexUtils, StringRevertError } from '@0x/utils';
import { artifacts } from './artifacts';
import { AllowanceTargetContract, TestCallTargetContract, TestCallTargetEvents } from './wrappers';
blockchainTests.resets('AllowanceTarget', env => {
let owner: string;
let authority: string;
let allowanceTarget: AllowanceTargetContract;
let callTarget: TestCallTargetContract;
before(async () => {
[owner, authority] = await env.getAccountAddressesAsync();
allowanceTarget = await AllowanceTargetContract.deployFrom0xArtifactAsync(
artifacts.AllowanceTarget,
env.provider,
env.txDefaults,
artifacts,
);
await allowanceTarget.addAuthorizedAddress(authority).awaitTransactionSuccessAsync();
callTarget = await TestCallTargetContract.deployFrom0xArtifactAsync(
artifacts.TestCallTarget,
env.provider,
env.txDefaults,
artifacts,
);
});
const TARGET_RETURN_VALUE = hexUtils.rightPad('0x12345678');
const REVERTING_DATA = '0x1337';
describe('executeCall()', () => {
it('non-authority cannot call executeCall()', async () => {
const notAuthority = randomAddress();
const tx = allowanceTarget
.executeCall(randomAddress(), hexUtils.random())
.callAsync({ from: notAuthority });
return expect(tx).to.revertWith(new AuthorizableRevertErrors.SenderNotAuthorizedError(notAuthority));
});
it('authority can call executeCall()', async () => {
const targetData = hexUtils.random(128);
const receipt = await allowanceTarget
.executeCall(callTarget.address, targetData)
.awaitTransactionSuccessAsync({ from: authority });
verifyEventsFromLogs(
receipt.logs,
[
{
context: callTarget.address,
sender: allowanceTarget.address,
data: targetData,
value: constants.ZERO_AMOUNT,
},
],
TestCallTargetEvents.CallTargetCalled,
);
});
it('AllowanceTarget returns call result', async () => {
const result = await allowanceTarget
.executeCall(callTarget.address, hexUtils.random(128))
.callAsync({ from: authority });
expect(result).to.eq(TARGET_RETURN_VALUE);
});
it('AllowanceTarget returns raw call revert', async () => {
const tx = allowanceTarget.executeCall(callTarget.address, REVERTING_DATA).callAsync({ from: authority });
return expect(tx).to.revertWith(new StringRevertError('TestCallTarget/REVERT'));
});
it('AllowanceTarget cannot receive ETH', async () => {
const tx = env.web3Wrapper.sendTransactionAsync({
to: allowanceTarget.address,
from: owner,
value: 0,
});
return expect(tx).to.eventually.be.rejected();
});
});
});

View File

@@ -6,11 +6,10 @@
import { ContractArtifact } from 'ethereum-types';
import * as AffiliateFeeTransformer from '../test/generated-artifacts/AffiliateFeeTransformer.json';
import * as AllowanceTarget from '../test/generated-artifacts/AllowanceTarget.json';
import * as BatchFillNativeOrdersFeature from '../test/generated-artifacts/BatchFillNativeOrdersFeature.json';
import * as BootstrapFeature from '../test/generated-artifacts/BootstrapFeature.json';
import * as BridgeAdapter from '../test/generated-artifacts/BridgeAdapter.json';
import * as BridgeSource from '../test/generated-artifacts/BridgeSource.json';
import * as BridgeProtocols from '../test/generated-artifacts/BridgeProtocols.json';
import * as CurveLiquidityProvider from '../test/generated-artifacts/CurveLiquidityProvider.json';
import * as FeeCollector from '../test/generated-artifacts/FeeCollector.json';
import * as FeeCollectorController from '../test/generated-artifacts/FeeCollectorController.json';
@@ -22,7 +21,6 @@ import * as FixinReentrancyGuard from '../test/generated-artifacts/FixinReentran
import * as FixinTokenSpender from '../test/generated-artifacts/FixinTokenSpender.json';
import * as FlashWallet from '../test/generated-artifacts/FlashWallet.json';
import * as FullMigration from '../test/generated-artifacts/FullMigration.json';
import * as IAllowanceTarget from '../test/generated-artifacts/IAllowanceTarget.json';
import * as IBatchFillNativeOrdersFeature from '../test/generated-artifacts/IBatchFillNativeOrdersFeature.json';
import * as IBootstrapFeature from '../test/generated-artifacts/IBootstrapFeature.json';
import * as IBridgeAdapter from '../test/generated-artifacts/IBridgeAdapter.json';
@@ -40,6 +38,7 @@ import * as INativeOrdersEvents from '../test/generated-artifacts/INativeOrdersE
import * as INativeOrdersFeature from '../test/generated-artifacts/INativeOrdersFeature.json';
import * as InitialMigration from '../test/generated-artifacts/InitialMigration.json';
import * as IOwnableFeature from '../test/generated-artifacts/IOwnableFeature.json';
import * as IPancakeSwapFeature from '../test/generated-artifacts/IPancakeSwapFeature.json';
import * as ISimpleFunctionRegistryFeature from '../test/generated-artifacts/ISimpleFunctionRegistryFeature.json';
import * as IStaking from '../test/generated-artifacts/IStaking.json';
import * as ITestSimpleFunctionRegistryFeature from '../test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json';
@@ -68,9 +67,7 @@ import * as LibSignature from '../test/generated-artifacts/LibSignature.json';
import * as LibSignatureRichErrors from '../test/generated-artifacts/LibSignatureRichErrors.json';
import * as LibSimpleFunctionRegistryRichErrors from '../test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json';
import * as LibSimpleFunctionRegistryStorage from '../test/generated-artifacts/LibSimpleFunctionRegistryStorage.json';
import * as LibSpenderRichErrors from '../test/generated-artifacts/LibSpenderRichErrors.json';
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 LibTransformERC20Storage from '../test/generated-artifacts/LibTransformERC20Storage.json';
import * as LibWalletRichErrors from '../test/generated-artifacts/LibWalletRichErrors.json';
@@ -88,9 +85,9 @@ import * as MixinDodoV2 from '../test/generated-artifacts/MixinDodoV2.json';
import * as MixinKyber from '../test/generated-artifacts/MixinKyber.json';
import * as MixinMooniswap from '../test/generated-artifacts/MixinMooniswap.json';
import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json';
import * as MixinNerve from '../test/generated-artifacts/MixinNerve.json';
import * as MixinOasis from '../test/generated-artifacts/MixinOasis.json';
import * as MixinShell from '../test/generated-artifacts/MixinShell.json';
import * as MixinSushiswap from '../test/generated-artifacts/MixinSushiswap.json';
import * as MixinUniswap from '../test/generated-artifacts/MixinUniswap.json';
import * as MixinUniswapV2 from '../test/generated-artifacts/MixinUniswapV2.json';
import * as MixinZeroExBridge from '../test/generated-artifacts/MixinZeroExBridge.json';
@@ -102,6 +99,7 @@ import * as NativeOrdersInfo from '../test/generated-artifacts/NativeOrdersInfo.
import * as NativeOrdersProtocolFees from '../test/generated-artifacts/NativeOrdersProtocolFees.json';
import * as NativeOrdersSettlement from '../test/generated-artifacts/NativeOrdersSettlement.json';
import * as OwnableFeature from '../test/generated-artifacts/OwnableFeature.json';
import * as PancakeSwapFeature from '../test/generated-artifacts/PancakeSwapFeature.json';
import * as PayTakerTransformer from '../test/generated-artifacts/PayTakerTransformer.json';
import * as PermissionlessTransformerDeployer from '../test/generated-artifacts/PermissionlessTransformerDeployer.json';
import * as PositiveSlippageFeeTransformer from '../test/generated-artifacts/PositiveSlippageFeeTransformer.json';
@@ -134,7 +132,6 @@ import * as TestRfqOriginRegistration from '../test/generated-artifacts/TestRfqO
import * as TestSimpleFunctionRegistryFeatureImpl1 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json';
import * as TestSimpleFunctionRegistryFeatureImpl2 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json';
import * as TestStaking from '../test/generated-artifacts/TestStaking.json';
import * as TestTokenSpender from '../test/generated-artifacts/TestTokenSpender.json';
import * as TestTokenSpenderERC20Token from '../test/generated-artifacts/TestTokenSpenderERC20Token.json';
import * as TestTransformerBase from '../test/generated-artifacts/TestTransformerBase.json';
import * as TestTransformERC20 from '../test/generated-artifacts/TestTransformERC20.json';
@@ -143,7 +140,6 @@ import * as TestTransformerHost from '../test/generated-artifacts/TestTransforme
import * as TestWeth from '../test/generated-artifacts/TestWeth.json';
import * as TestWethTransformerHost from '../test/generated-artifacts/TestWethTransformerHost.json';
import * as TestZeroExFeature from '../test/generated-artifacts/TestZeroExFeature.json';
import * as TokenSpenderFeature from '../test/generated-artifacts/TokenSpenderFeature.json';
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';
@@ -163,14 +159,11 @@ export const artifacts = {
LibProxyRichErrors: LibProxyRichErrors as ContractArtifact,
LibSignatureRichErrors: LibSignatureRichErrors as ContractArtifact,
LibSimpleFunctionRegistryRichErrors: LibSimpleFunctionRegistryRichErrors as ContractArtifact,
LibSpenderRichErrors: LibSpenderRichErrors as ContractArtifact,
LibTransformERC20RichErrors: LibTransformERC20RichErrors as ContractArtifact,
LibWalletRichErrors: LibWalletRichErrors as ContractArtifact,
AllowanceTarget: AllowanceTarget as ContractArtifact,
FeeCollector: FeeCollector as ContractArtifact,
FeeCollectorController: FeeCollectorController as ContractArtifact,
FlashWallet: FlashWallet as ContractArtifact,
IAllowanceTarget: IAllowanceTarget as ContractArtifact,
IFlashWallet: IFlashWallet as ContractArtifact,
ILiquidityProviderSandbox: ILiquidityProviderSandbox as ContractArtifact,
LibFeeCollector: LibFeeCollector as ContractArtifact,
@@ -184,8 +177,8 @@ export const artifacts = {
MultiplexFeature: MultiplexFeature as ContractArtifact,
NativeOrdersFeature: NativeOrdersFeature as ContractArtifact,
OwnableFeature: OwnableFeature as ContractArtifact,
PancakeSwapFeature: PancakeSwapFeature as ContractArtifact,
SimpleFunctionRegistryFeature: SimpleFunctionRegistryFeature as ContractArtifact,
TokenSpenderFeature: TokenSpenderFeature as ContractArtifact,
TransformERC20Feature: TransformERC20Feature as ContractArtifact,
UniswapFeature: UniswapFeature as ContractArtifact,
IBatchFillNativeOrdersFeature: IBatchFillNativeOrdersFeature as ContractArtifact,
@@ -197,6 +190,7 @@ export const artifacts = {
INativeOrdersEvents: INativeOrdersEvents as ContractArtifact,
INativeOrdersFeature: INativeOrdersFeature as ContractArtifact,
IOwnableFeature: IOwnableFeature as ContractArtifact,
IPancakeSwapFeature: IPancakeSwapFeature as ContractArtifact,
ISimpleFunctionRegistryFeature: ISimpleFunctionRegistryFeature as ContractArtifact,
ITokenSpenderFeature: ITokenSpenderFeature as ContractArtifact,
ITransformERC20Feature: ITransformERC20Feature as ContractArtifact,
@@ -225,7 +219,6 @@ export const artifacts = {
LibReentrancyGuardStorage: LibReentrancyGuardStorage as ContractArtifact,
LibSimpleFunctionRegistryStorage: LibSimpleFunctionRegistryStorage as ContractArtifact,
LibStorage: LibStorage as ContractArtifact,
LibTokenSpenderStorage: LibTokenSpenderStorage as ContractArtifact,
LibTransformERC20Storage: LibTransformERC20Storage as ContractArtifact,
AffiliateFeeTransformer: AffiliateFeeTransformer as ContractArtifact,
FillQuoteTransformer: FillQuoteTransformer as ContractArtifact,
@@ -237,7 +230,7 @@ export const artifacts = {
Transformer: Transformer as ContractArtifact,
WethTransformer: WethTransformer as ContractArtifact,
BridgeAdapter: BridgeAdapter as ContractArtifact,
BridgeSource: BridgeSource as ContractArtifact,
BridgeProtocols: BridgeProtocols as ContractArtifact,
IBridgeAdapter: IBridgeAdapter as ContractArtifact,
MixinBalancer: MixinBalancer as ContractArtifact,
MixinBancor: MixinBancor as ContractArtifact,
@@ -249,9 +242,9 @@ export const artifacts = {
MixinKyber: MixinKyber as ContractArtifact,
MixinMStable: MixinMStable as ContractArtifact,
MixinMooniswap: MixinMooniswap as ContractArtifact,
MixinNerve: MixinNerve as ContractArtifact,
MixinOasis: MixinOasis as ContractArtifact,
MixinShell: MixinShell as ContractArtifact,
MixinSushiswap: MixinSushiswap as ContractArtifact,
MixinUniswap: MixinUniswap as ContractArtifact,
MixinUniswapV2: MixinUniswapV2 as ContractArtifact,
MixinZeroExBridge: MixinZeroExBridge as ContractArtifact,
@@ -289,7 +282,6 @@ export const artifacts = {
TestSimpleFunctionRegistryFeatureImpl1: TestSimpleFunctionRegistryFeatureImpl1 as ContractArtifact,
TestSimpleFunctionRegistryFeatureImpl2: TestSimpleFunctionRegistryFeatureImpl2 as ContractArtifact,
TestStaking: TestStaking as ContractArtifact,
TestTokenSpender: TestTokenSpender as ContractArtifact,
TestTokenSpenderERC20Token: TestTokenSpenderERC20Token as ContractArtifact,
TestTransformERC20: TestTransformERC20 as ContractArtifact,
TestTransformerBase: TestTransformerBase as ContractArtifact,

View File

@@ -2,7 +2,6 @@ import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contra
import { blockchainTests, constants, expect, verifyEventsFromLogs } from '@0x/contracts-test-utils';
import { BigNumber, OwnableRevertErrors, ZeroExRevertErrors } from '@0x/utils';
import { ZERO_BYTES32 } from '../../src/constants';
import { IOwnableFeatureContract, IZeroExContract, LiquidityProviderFeatureContract } from '../../src/wrappers';
import { artifacts } from '../artifacts';
import { abis } from '../utils/abis';
@@ -63,7 +62,6 @@ blockchainTests('LiquidityProvider feature', env => {
env.txDefaults,
artifacts,
sandbox.address,
ZERO_BYTES32,
);
await new IOwnableFeatureContract(zeroEx.address, env.provider, env.txDefaults, abis)
.migrate(featureImpl.address, featureImpl.migrate().getABIEncodedTransactionData(), owner)

View File

@@ -8,7 +8,8 @@ import {
} from '@0x/contracts-erc20';
import { blockchainTests, constants, expect, filterLogsToArguments, toBaseUnitAmount } from '@0x/contracts-test-utils';
import {
BridgeSource,
BridgeProtocol,
encodeBridgeSourceId,
encodeFillQuoteTransformerData,
encodePayTakerTransformerData,
FillQuoteTransformerOrderType,
@@ -72,8 +73,9 @@ blockchainTests.fork.skip('Multiplex feature', env => {
const WETH_DAI_PLP_ADDRESS = '0x1db681925786441ba82adefac7bf492089665ca0';
const WETH_USDC_PLP_ADDRESS = '0x8463c03c0c57ff19fa8b431e0d3a34e2df89888e';
const USDC_USDT_PLP_ADDRESS = '0xc340ef96449514cea4dfa11d847a06d7f03d437c';
const GREEDY_TOKENS_BLOOM_FILTER = '0x0000100800000480002c00401000000820000000000000020000001010800001';
const BALANCER_WETH_DAI = '0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a';
const CURVE_BRIDGE_SOURCE_ID = encodeBridgeSourceId(BridgeProtocol.Curve, 'Curve');
const BALANCER_BRIDGE_SOURCE_ID = encodeBridgeSourceId(BridgeProtocol.Bancor, 'Balancer');
const fqtNonce = findTransformerNonce(
'0xfa6282736af206cb4cfc5cb786d82aecdf1186f9',
'0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb',
@@ -112,7 +114,6 @@ blockchainTests.fork.skip('Multiplex feature', env => {
zeroEx.address,
WETH_ADDRESS,
PLP_SANDBOX_ADDRESS,
GREEDY_TOKENS_BLOOM_FILTER,
);
await registry
.extend(multiplex.getSelector('batchFill'), multiplexImpl.address)
@@ -283,7 +284,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
buyToken: WETH_ADDRESS,
bridgeOrders: [
{
source: BridgeSource.Balancer,
source: BALANCER_BRIDGE_SOURCE_ID,
takerTokenAmount: expiredRfqCall.sellAmount,
makerTokenAmount: expiredRfqCall.sellAmount,
bridgeData: poolEncoder.encode([BALANCER_WETH_DAI]),
@@ -339,7 +340,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
tx.logs,
BridgeAdapterEvents.BridgeFill,
);
expect(bridgeFillEvent.source).to.bignumber.equal(BridgeSource.Balancer);
expect(bridgeFillEvent.source).to.bignumber.equal(BALANCER_BRIDGE_SOURCE_ID);
expect(bridgeFillEvent.inputToken).to.equal(DAI_ADDRESS);
expect(bridgeFillEvent.outputToken).to.equal(WETH_ADDRESS);
expect(bridgeFillEvent.inputTokenAmount).to.bignumber.equal(expiredRfqCall.sellAmount);
@@ -472,7 +473,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
buyToken: USDC_ADDRESS,
bridgeOrders: [
{
source: BridgeSource.Curve,
source: CURVE_BRIDGE_SOURCE_ID,
takerTokenAmount: sellAmount,
makerTokenAmount: sellAmount,
bridgeData: curveEncoder.encode([
@@ -531,7 +532,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
tx.logs,
BridgeAdapterEvents.BridgeFill,
);
expect(bridgeFillEvent.source).to.bignumber.equal(BridgeSource.Curve);
expect(bridgeFillEvent.source).to.bignumber.equal(CURVE_BRIDGE_SOURCE_ID);
expect(bridgeFillEvent.inputToken).to.equal(DAI_ADDRESS);
expect(bridgeFillEvent.outputToken).to.equal(USDC_ADDRESS);
expect(bridgeFillEvent.inputTokenAmount).to.bignumber.equal(sellAmount);
@@ -563,7 +564,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
buyToken: DAI_ADDRESS,
bridgeOrders: [
{
source: BridgeSource.Curve,
source: CURVE_BRIDGE_SOURCE_ID,
takerTokenAmount: constants.MAX_UINT256,
makerTokenAmount: constants.MAX_UINT256,
bridgeData: curveEncoder.encode([
@@ -640,7 +641,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
tx.logs,
BridgeAdapterEvents.BridgeFill,
);
expect(bridgeFillEvent.source).to.bignumber.equal(BridgeSource.Curve);
expect(bridgeFillEvent.source).to.bignumber.equal(CURVE_BRIDGE_SOURCE_ID);
expect(bridgeFillEvent.inputToken).to.equal(USDC_ADDRESS);
expect(bridgeFillEvent.outputToken).to.equal(DAI_ADDRESS);
expect(bridgeFillEvent.inputTokenAmount).to.bignumber.equal(uniswapOutputAmount);

View File

@@ -1,137 +0,0 @@
import {
blockchainTests,
expect,
getRandomInteger,
randomAddress,
verifyEventsFromLogs,
} from '@0x/contracts-test-utils';
import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
import { IZeroExContract, TokenSpenderFeatureContract } from '../../src/wrappers';
import { artifacts } from '../artifacts';
import { abis } from '../utils/abis';
import { fullMigrateAsync } from '../utils/migration';
import { TestTokenSpenderERC20TokenContract, TestTokenSpenderERC20TokenEvents } from '../wrappers';
blockchainTests.resets('TokenSpender feature', env => {
let zeroEx: IZeroExContract;
let feature: TokenSpenderFeatureContract;
let token: TestTokenSpenderERC20TokenContract;
let allowanceTarget: string;
before(async () => {
const [owner] = await env.getAccountAddressesAsync();
zeroEx = await fullMigrateAsync(owner, env.provider, env.txDefaults, {
tokenSpender: (await TokenSpenderFeatureContract.deployFrom0xArtifactAsync(
artifacts.TestTokenSpender,
env.provider,
env.txDefaults,
artifacts,
)).address,
});
feature = new TokenSpenderFeatureContract(zeroEx.address, env.provider, env.txDefaults, abis);
token = await TestTokenSpenderERC20TokenContract.deployFrom0xArtifactAsync(
artifacts.TestTokenSpenderERC20Token,
env.provider,
env.txDefaults,
artifacts,
);
allowanceTarget = await feature.getAllowanceTarget().callAsync();
});
describe('_spendERC20Tokens()', () => {
const EMPTY_RETURN_AMOUNT = 1337;
const FALSE_RETURN_AMOUNT = 1338;
const REVERT_RETURN_AMOUNT = 1339;
it('_spendERC20Tokens() successfully calls compliant ERC20 token', async () => {
const tokenFrom = randomAddress();
const tokenTo = randomAddress();
const tokenAmount = new BigNumber(123456);
const receipt = await feature
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
.awaitTransactionSuccessAsync();
verifyEventsFromLogs(
receipt.logs,
[
{
sender: allowanceTarget,
from: tokenFrom,
to: tokenTo,
amount: tokenAmount,
},
],
TestTokenSpenderERC20TokenEvents.TransferFromCalled,
);
});
it('_spendERC20Tokens() successfully calls non-compliant ERC20 token', async () => {
const tokenFrom = randomAddress();
const tokenTo = randomAddress();
const tokenAmount = new BigNumber(EMPTY_RETURN_AMOUNT);
const receipt = await feature
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
.awaitTransactionSuccessAsync();
verifyEventsFromLogs(
receipt.logs,
[
{
sender: allowanceTarget,
from: tokenFrom,
to: tokenTo,
amount: tokenAmount,
},
],
TestTokenSpenderERC20TokenEvents.TransferFromCalled,
);
});
it('_spendERC20Tokens() reverts if ERC20 token reverts', async () => {
const tokenFrom = randomAddress();
const tokenTo = randomAddress();
const tokenAmount = new BigNumber(REVERT_RETURN_AMOUNT);
const tx = feature
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
.awaitTransactionSuccessAsync();
const expectedError = new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
token.address,
tokenFrom,
tokenTo,
tokenAmount,
new StringRevertError('TestTokenSpenderERC20Token/Revert').encode(),
);
return expect(tx).to.revertWith(expectedError);
});
it('_spendERC20Tokens() reverts if ERC20 token returns false', async () => {
const tokenFrom = randomAddress();
const tokenTo = randomAddress();
const tokenAmount = new BigNumber(FALSE_RETURN_AMOUNT);
const tx = feature
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
.awaitTransactionSuccessAsync();
return expect(tx).to.revertWith(
new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
token.address,
tokenFrom,
tokenTo,
tokenAmount,
hexUtils.leftPad(0),
),
);
});
});
describe('getSpendableERC20BalanceOf()', () => {
it("returns the minimum of the owner's balance and allowance", async () => {
const balance = getRandomInteger(1, '1e18');
const allowance = getRandomInteger(1, '1e18');
const tokenOwner = randomAddress();
await token
.setBalanceAndAllowanceOf(tokenOwner, balance, allowanceTarget, allowance)
.awaitTransactionSuccessAsync();
const spendableBalance = await feature.getSpendableERC20BalanceOf(token.address, tokenOwner).callAsync();
expect(spendableBalance).to.bignumber.eq(BigNumber.min(balance, allowance));
});
});
});

View File

@@ -5,14 +5,11 @@ import {
randomAddress,
verifyEventsFromLogs,
} from '@0x/contracts-test-utils';
import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
import { getTokenListBloomFilter } from '../src/bloom_filter_utils';
import { BigNumber, hexUtils, RawRevertError, StringRevertError } from '@0x/utils';
import { artifacts } from './artifacts';
import {
TestFixinTokenSpenderContract,
TestFixinTokenSpenderEvents,
TestTokenSpenderERC20TokenContract,
TestTokenSpenderERC20TokenEvents,
} from './wrappers';
@@ -21,7 +18,6 @@ blockchainTests.resets('FixinTokenSpender', env => {
let tokenSpender: TestFixinTokenSpenderContract;
let token: TestTokenSpenderERC20TokenContract;
let greedyToken: TestTokenSpenderERC20TokenContract;
let greedyTokensBloomFilter: string;
before(async () => {
token = await TestTokenSpenderERC20TokenContract.deployFrom0xArtifactAsync(
@@ -38,14 +34,11 @@ blockchainTests.resets('FixinTokenSpender', env => {
);
await greedyToken.setGreedyRevert(true).awaitTransactionSuccessAsync();
greedyTokensBloomFilter = getTokenListBloomFilter([greedyToken.address]);
tokenSpender = await TestFixinTokenSpenderContract.deployFrom0xArtifactAsync(
artifacts.TestFixinTokenSpender,
env.provider,
env.txDefaults,
artifacts,
greedyTokensBloomFilter,
);
});
@@ -53,7 +46,6 @@ blockchainTests.resets('FixinTokenSpender', env => {
const EMPTY_RETURN_AMOUNT = 1337;
const FALSE_RETURN_AMOUNT = 1338;
const REVERT_RETURN_AMOUNT = 1339;
const TRIGGER_FALLBACK_SUCCESS_AMOUNT = 1340;
const EXTRA_RETURN_TRUE_AMOUNT = 1341;
const EXTRA_RETURN_FALSE_AMOUNT = 1342;
@@ -106,13 +98,7 @@ blockchainTests.resets('FixinTokenSpender', env => {
const tx = tokenSpender
.transferERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
.awaitTransactionSuccessAsync();
const expectedError = new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
token.address,
tokenFrom,
tokenTo,
tokenAmount,
new StringRevertError('TestTokenSpenderERC20Token/Revert').encode(),
);
const expectedError = new StringRevertError('TestTokenSpenderERC20Token/Revert');
return expect(tx).to.revertWith(expectedError);
});
@@ -123,36 +109,7 @@ blockchainTests.resets('FixinTokenSpender', env => {
const tx = tokenSpender
.transferERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
.awaitTransactionSuccessAsync();
return expect(tx).to.revertWith(
new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
token.address,
tokenFrom,
tokenTo,
tokenAmount,
hexUtils.leftPad(0),
),
);
});
it('transferERC20Tokens() falls back successfully to TokenSpender._spendERC20Tokens()', async () => {
const tokenFrom = randomAddress();
const tokenTo = randomAddress();
const tokenAmount = new BigNumber(TRIGGER_FALLBACK_SUCCESS_AMOUNT);
const receipt = await tokenSpender
.transferERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
.awaitTransactionSuccessAsync();
verifyEventsFromLogs(
receipt.logs,
[
{
token: token.address,
owner: tokenFrom,
to: tokenTo,
amount: tokenAmount,
},
],
TestFixinTokenSpenderEvents.FallbackCalled,
);
return expect(tx).to.revertWith(new RawRevertError(hexUtils.leftPad(0)));
});
it('transferERC20Tokens() allows extra data after true', async () => {
@@ -185,15 +142,7 @@ blockchainTests.resets('FixinTokenSpender', env => {
const tx = tokenSpender
.transferERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
.awaitTransactionSuccessAsync();
return expect(tx).to.revertWith(
new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
token.address,
tokenFrom,
tokenTo,
tokenAmount,
hexUtils.leftPad(EXTRA_RETURN_FALSE_AMOUNT, 64),
),
);
return expect(tx).to.revertWith(new RawRevertError(hexUtils.leftPad(EXTRA_RETURN_FALSE_AMOUNT, 64)));
});
it('transferERC20Tokens() cannot call self', async () => {
@@ -206,73 +155,6 @@ blockchainTests.resets('FixinTokenSpender', env => {
.awaitTransactionSuccessAsync();
return expect(tx).to.revertWith('FixinTokenSpender/CANNOT_INVOKE_SELF');
});
it('calls transferFrom() directly for a greedy token with allowance', async () => {
const tokenFrom = randomAddress();
const tokenTo = randomAddress();
const tokenAmount = new BigNumber(123456);
await greedyToken.approveAs(tokenFrom, tokenSpender.address, tokenAmount).awaitTransactionSuccessAsync();
const receipt = await tokenSpender
.transferERC20Tokens(greedyToken.address, tokenFrom, tokenTo, tokenAmount)
.awaitTransactionSuccessAsync();
// Because there is an allowance set, we will call transferFrom()
// directly, which succeds and emits an event.
verifyEventsFromLogs(
receipt.logs,
[
{
sender: tokenSpender.address,
from: tokenFrom,
to: tokenTo,
amount: tokenAmount,
},
], // No events.
TestTokenSpenderERC20TokenEvents.TransferFromCalled,
);
});
it('calls only the fallback for a greedy token with no allowance', async () => {
const tokenFrom = randomAddress();
const tokenTo = randomAddress();
const tokenAmount = new BigNumber(TRIGGER_FALLBACK_SUCCESS_AMOUNT);
const receipt = await tokenSpender
.transferERC20Tokens(greedyToken.address, tokenFrom, tokenTo, tokenAmount)
.awaitTransactionSuccessAsync();
// Because this is a greedy token and there is no allowance set, transferFrom()
// will not be called before hitting the fallback, which only emits an event
// in the test contract.
verifyEventsFromLogs(
receipt.logs,
[], // No events.
TestTokenSpenderERC20TokenEvents.TransferFromCalled,
);
verifyEventsFromLogs(
receipt.logs,
[
{
token: greedyToken.address,
owner: tokenFrom,
to: tokenTo,
amount: tokenAmount,
},
],
TestFixinTokenSpenderEvents.FallbackCalled,
);
});
});
describe('isTokenPossiblyGreedy()', () => {
it('returns true for greedy token', async () => {
const isGreedy = await tokenSpender.isTokenPossiblyGreedy(greedyToken.address).callAsync();
expect(isGreedy).to.eq(true);
});
it('returns false for non-greedy token', async () => {
const isGreedy = await tokenSpender.isTokenPossiblyGreedy(token.address).callAsync();
expect(isGreedy).to.eq(false);
});
});
describe('getSpendableERC20BalanceOf()', () => {

View File

@@ -8,11 +8,9 @@ import { artifacts } from './artifacts';
import { abis } from './utils/abis';
import { deployFullFeaturesAsync, FullFeatures } from './utils/migration';
import {
AllowanceTargetContract,
IMetaTransactionsFeatureContract,
INativeOrdersFeatureContract,
IOwnableFeatureContract,
ITokenSpenderFeatureContract,
ITransformERC20FeatureContract,
TestFullMigrationContract,
ZeroExContract,
@@ -69,10 +67,6 @@ blockchainTests.resets('Full migration', env => {
});
const FEATURE_FNS = {
TokenSpender: {
contractType: ITokenSpenderFeatureContract,
fns: ['_spendERC20Tokens'],
},
TransformERC20: {
contractType: ITransformERC20FeatureContract,
fns: [
@@ -207,27 +201,6 @@ blockchainTests.resets('Full migration', env => {
});
}
describe("TokenSpender's allowance target", () => {
let allowanceTarget: AllowanceTargetContract;
before(async () => {
const contract = new ITokenSpenderFeatureContract(zeroEx.address, env.provider, env.txDefaults);
allowanceTarget = new AllowanceTargetContract(
await contract.getAllowanceTarget().callAsync(),
env.provider,
env.txDefaults,
);
});
it('is owned by owner', async () => {
return expect(allowanceTarget.owner().callAsync()).to.become(owner);
});
it('Proxy is authorized', async () => {
return expect(allowanceTarget.authorized(zeroEx.address).callAsync()).to.become(true);
});
});
describe('TransformERC20', () => {
let feature: ITransformERC20FeatureContract;

View File

@@ -52,7 +52,7 @@ blockchainTests.resets('FillQuoteTransformer', env => {
let singleProtocolFee: BigNumber;
const GAS_PRICE = 1337;
const TEST_BRIDGE_SOURCE = 12345678;
const TEST_BRIDGE_SOURCE = hexUtils.random(32);
const HIGH_BIT = new BigNumber(2).pow(255);
const REVERT_AMOUNT = new BigNumber('0xdeadbeef');

View File

@@ -4,11 +4,10 @@
* -----------------------------------------------------------------------------
*/
export * from '../test/generated-wrappers/affiliate_fee_transformer';
export * from '../test/generated-wrappers/allowance_target';
export * from '../test/generated-wrappers/batch_fill_native_orders_feature';
export * from '../test/generated-wrappers/bootstrap_feature';
export * from '../test/generated-wrappers/bridge_adapter';
export * from '../test/generated-wrappers/bridge_source';
export * from '../test/generated-wrappers/bridge_protocols';
export * from '../test/generated-wrappers/curve_liquidity_provider';
export * from '../test/generated-wrappers/fee_collector';
export * from '../test/generated-wrappers/fee_collector_controller';
@@ -20,7 +19,6 @@ export * from '../test/generated-wrappers/fixin_reentrancy_guard';
export * from '../test/generated-wrappers/fixin_token_spender';
export * from '../test/generated-wrappers/flash_wallet';
export * from '../test/generated-wrappers/full_migration';
export * from '../test/generated-wrappers/i_allowance_target';
export * from '../test/generated-wrappers/i_batch_fill_native_orders_feature';
export * from '../test/generated-wrappers/i_bootstrap_feature';
export * from '../test/generated-wrappers/i_bridge_adapter';
@@ -37,6 +35,7 @@ export * from '../test/generated-wrappers/i_multiplex_feature';
export * from '../test/generated-wrappers/i_native_orders_events';
export * from '../test/generated-wrappers/i_native_orders_feature';
export * from '../test/generated-wrappers/i_ownable_feature';
export * from '../test/generated-wrappers/i_pancake_swap_feature';
export * from '../test/generated-wrappers/i_simple_function_registry_feature';
export * from '../test/generated-wrappers/i_staking';
export * from '../test/generated-wrappers/i_test_simple_function_registry_feature';
@@ -66,9 +65,7 @@ export * from '../test/generated-wrappers/lib_signature';
export * from '../test/generated-wrappers/lib_signature_rich_errors';
export * from '../test/generated-wrappers/lib_simple_function_registry_rich_errors';
export * from '../test/generated-wrappers/lib_simple_function_registry_storage';
export * from '../test/generated-wrappers/lib_spender_rich_errors';
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/lib_transform_erc20_storage';
export * from '../test/generated-wrappers/lib_wallet_rich_errors';
@@ -86,9 +83,9 @@ export * from '../test/generated-wrappers/mixin_dodo_v2';
export * from '../test/generated-wrappers/mixin_kyber';
export * from '../test/generated-wrappers/mixin_m_stable';
export * from '../test/generated-wrappers/mixin_mooniswap';
export * from '../test/generated-wrappers/mixin_nerve';
export * from '../test/generated-wrappers/mixin_oasis';
export * from '../test/generated-wrappers/mixin_shell';
export * from '../test/generated-wrappers/mixin_sushiswap';
export * from '../test/generated-wrappers/mixin_uniswap';
export * from '../test/generated-wrappers/mixin_uniswap_v2';
export * from '../test/generated-wrappers/mixin_zero_ex_bridge';
@@ -100,6 +97,7 @@ export * from '../test/generated-wrappers/native_orders_info';
export * from '../test/generated-wrappers/native_orders_protocol_fees';
export * from '../test/generated-wrappers/native_orders_settlement';
export * from '../test/generated-wrappers/ownable_feature';
export * from '../test/generated-wrappers/pancake_swap_feature';
export * from '../test/generated-wrappers/pay_taker_transformer';
export * from '../test/generated-wrappers/permissionless_transformer_deployer';
export * from '../test/generated-wrappers/positive_slippage_fee_transformer';
@@ -132,7 +130,6 @@ export * from '../test/generated-wrappers/test_rfq_origin_registration';
export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl1';
export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl2';
export * from '../test/generated-wrappers/test_staking';
export * from '../test/generated-wrappers/test_token_spender';
export * from '../test/generated-wrappers/test_token_spender_erc20_token';
export * from '../test/generated-wrappers/test_transform_erc20';
export * from '../test/generated-wrappers/test_transformer_base';
@@ -141,7 +138,6 @@ export * from '../test/generated-wrappers/test_transformer_host';
export * from '../test/generated-wrappers/test_weth';
export * from '../test/generated-wrappers/test_weth_transformer_host';
export * from '../test/generated-wrappers/test_zero_ex_feature';
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';

View File

@@ -20,7 +20,6 @@
"generated-artifacts/INativeOrdersFeature.json",
"generated-artifacts/IOwnableFeature.json",
"generated-artifacts/ISimpleFunctionRegistryFeature.json",
"generated-artifacts/ITokenSpenderFeature.json",
"generated-artifacts/ITransformERC20Feature.json",
"generated-artifacts/IZeroEx.json",
"generated-artifacts/InitialMigration.json",
@@ -33,16 +32,14 @@
"generated-artifacts/PayTakerTransformer.json",
"generated-artifacts/PositiveSlippageFeeTransformer.json",
"generated-artifacts/SimpleFunctionRegistryFeature.json",
"generated-artifacts/TokenSpenderFeature.json",
"generated-artifacts/TransformERC20Feature.json",
"generated-artifacts/WethTransformer.json",
"generated-artifacts/ZeroEx.json",
"test/generated-artifacts/AffiliateFeeTransformer.json",
"test/generated-artifacts/AllowanceTarget.json",
"test/generated-artifacts/BatchFillNativeOrdersFeature.json",
"test/generated-artifacts/BootstrapFeature.json",
"test/generated-artifacts/BridgeAdapter.json",
"test/generated-artifacts/BridgeSource.json",
"test/generated-artifacts/BridgeProtocols.json",
"test/generated-artifacts/CurveLiquidityProvider.json",
"test/generated-artifacts/FeeCollector.json",
"test/generated-artifacts/FeeCollectorController.json",
@@ -54,7 +51,6 @@
"test/generated-artifacts/FixinTokenSpender.json",
"test/generated-artifacts/FlashWallet.json",
"test/generated-artifacts/FullMigration.json",
"test/generated-artifacts/IAllowanceTarget.json",
"test/generated-artifacts/IBatchFillNativeOrdersFeature.json",
"test/generated-artifacts/IBootstrapFeature.json",
"test/generated-artifacts/IBridgeAdapter.json",
@@ -71,6 +67,7 @@
"test/generated-artifacts/INativeOrdersEvents.json",
"test/generated-artifacts/INativeOrdersFeature.json",
"test/generated-artifacts/IOwnableFeature.json",
"test/generated-artifacts/IPancakeSwapFeature.json",
"test/generated-artifacts/ISimpleFunctionRegistryFeature.json",
"test/generated-artifacts/IStaking.json",
"test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json",
@@ -100,9 +97,7 @@
"test/generated-artifacts/LibSignatureRichErrors.json",
"test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json",
"test/generated-artifacts/LibSimpleFunctionRegistryStorage.json",
"test/generated-artifacts/LibSpenderRichErrors.json",
"test/generated-artifacts/LibStorage.json",
"test/generated-artifacts/LibTokenSpenderStorage.json",
"test/generated-artifacts/LibTransformERC20RichErrors.json",
"test/generated-artifacts/LibTransformERC20Storage.json",
"test/generated-artifacts/LibWalletRichErrors.json",
@@ -120,9 +115,9 @@
"test/generated-artifacts/MixinKyber.json",
"test/generated-artifacts/MixinMStable.json",
"test/generated-artifacts/MixinMooniswap.json",
"test/generated-artifacts/MixinNerve.json",
"test/generated-artifacts/MixinOasis.json",
"test/generated-artifacts/MixinShell.json",
"test/generated-artifacts/MixinSushiswap.json",
"test/generated-artifacts/MixinUniswap.json",
"test/generated-artifacts/MixinUniswapV2.json",
"test/generated-artifacts/MixinZeroExBridge.json",
@@ -134,6 +129,7 @@
"test/generated-artifacts/NativeOrdersProtocolFees.json",
"test/generated-artifacts/NativeOrdersSettlement.json",
"test/generated-artifacts/OwnableFeature.json",
"test/generated-artifacts/PancakeSwapFeature.json",
"test/generated-artifacts/PayTakerTransformer.json",
"test/generated-artifacts/PermissionlessTransformerDeployer.json",
"test/generated-artifacts/PositiveSlippageFeeTransformer.json",
@@ -166,7 +162,6 @@
"test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json",
"test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json",
"test/generated-artifacts/TestStaking.json",
"test/generated-artifacts/TestTokenSpender.json",
"test/generated-artifacts/TestTokenSpenderERC20Token.json",
"test/generated-artifacts/TestTransformERC20.json",
"test/generated-artifacts/TestTransformerBase.json",
@@ -175,7 +170,6 @@
"test/generated-artifacts/TestWeth.json",
"test/generated-artifacts/TestWethTransformerHost.json",
"test/generated-artifacts/TestZeroExFeature.json",
"test/generated-artifacts/TokenSpenderFeature.json",
"test/generated-artifacts/TransformERC20Feature.json",
"test/generated-artifacts/Transformer.json",
"test/generated-artifacts/TransformerDeployer.json",