Compare commits
	
		
			21 Commits
		
	
	
		
			@0x/contra
			...
			protocol@d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | dcde12dd70 | ||
|  | 84a60ec982 | ||
|  | 9615570dc6 | ||
|  | 880a9c3da0 | ||
|  | c44bd9d42d | ||
|  | 90b441330b | ||
|  | e12ed1eddf | ||
|  | ac94023ab3 | ||
|  | 281e6acca5 | ||
|  | 2f1b520409 | ||
|  | 21b4eb3d26 | ||
|  | 644f6c7d28 | ||
|  | 0647b9e4f8 | ||
|  | 82d42eeede | ||
|  | 6ef4d95043 | ||
|  | 6044140f86 | ||
|  | 4da1ef0f56 | ||
|  | 8c668a3918 | ||
|  | f1ff1cde39 | ||
|  | 1668a24e31 | ||
|  | 4b7c376d96 | 
| @@ -1,4 +1,13 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1638390144, | ||||
|         "version": "3.3.24", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1637102971, | ||||
|         "version": "3.3.23", | ||||
|   | ||||
| @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v3.3.24 - _December 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.3.23 - _November 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-erc20", | ||||
|     "version": "3.3.23", | ||||
|     "version": "3.3.24", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -53,8 +53,8 @@ | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.6.2", | ||||
|         "@0x/contracts-gen": "^2.0.40", | ||||
|         "@0x/contracts-test-utils": "^5.4.14", | ||||
|         "@0x/contracts-utils": "^4.8.4", | ||||
|         "@0x/contracts-test-utils": "^5.4.15", | ||||
|         "@0x/contracts-utils": "^4.8.5", | ||||
|         "@0x/dev-utils": "^4.2.9", | ||||
|         "@0x/sol-compiler": "^4.7.5", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|   | ||||
| @@ -1,4 +1,13 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1638390144, | ||||
|         "version": "5.4.15", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1637102971, | ||||
|         "version": "5.4.14", | ||||
|   | ||||
| @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v5.4.15 - _December 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v5.4.14 - _November 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-test-utils", | ||||
|     "version": "5.4.14", | ||||
|     "version": "5.4.15", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -44,7 +44,7 @@ | ||||
|     "dependencies": { | ||||
|         "@0x/assert": "^3.0.29", | ||||
|         "@0x/base-contract": "^6.4.2", | ||||
|         "@0x/contract-addresses": "^6.9.0", | ||||
|         "@0x/contract-addresses": "^6.10.0", | ||||
|         "@0x/dev-utils": "^4.2.9", | ||||
|         "@0x/json-schemas": "^6.3.0", | ||||
|         "@0x/order-utils": "^10.4.28", | ||||
|   | ||||
| @@ -1,4 +1,13 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1638390144, | ||||
|         "version": "1.4.7", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1637102971, | ||||
|         "version": "1.4.6", | ||||
|   | ||||
| @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v1.4.7 - _December 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.4.6 - _November 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-treasury", | ||||
|     "version": "1.4.6", | ||||
|     "version": "1.4.7", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -47,12 +47,12 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.6.2", | ||||
|         "@0x/contract-addresses": "^6.9.0", | ||||
|         "@0x/contract-addresses": "^6.10.0", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.19", | ||||
|         "@0x/contracts-erc20": "^3.3.23", | ||||
|         "@0x/contracts-erc20": "^3.3.24", | ||||
|         "@0x/contracts-gen": "^2.0.40", | ||||
|         "@0x/contracts-staking": "^2.0.45", | ||||
|         "@0x/contracts-test-utils": "^5.4.14", | ||||
|         "@0x/contracts-test-utils": "^5.4.15", | ||||
|         "@0x/sol-compiler": "^4.7.5", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.4", | ||||
| @@ -73,7 +73,7 @@ | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.4.2", | ||||
|         "@0x/protocol-utils": "^1.9.5", | ||||
|         "@0x/protocol-utils": "^1.10.0", | ||||
|         "@0x/subproviders": "^6.6.0", | ||||
|         "@0x/types": "^3.3.4", | ||||
|         "@0x/typescript-typings": "^5.2.1", | ||||
|   | ||||
| @@ -1,4 +1,13 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1638390144, | ||||
|         "version": "4.8.5", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1637102971, | ||||
|         "version": "4.8.4", | ||||
|   | ||||
| @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v4.8.5 - _December 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v4.8.4 - _November 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-utils", | ||||
|     "version": "4.8.4", | ||||
|     "version": "4.8.5", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -52,7 +52,7 @@ | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.6.2", | ||||
|         "@0x/contracts-gen": "^2.0.40", | ||||
|         "@0x/contracts-test-utils": "^5.4.14", | ||||
|         "@0x/contracts-test-utils": "^5.4.15", | ||||
|         "@0x/dev-utils": "^4.2.9", | ||||
|         "@0x/order-utils": "^10.4.28", | ||||
|         "@0x/sol-compiler": "^4.7.5", | ||||
|   | ||||
| @@ -1,4 +1,14 @@ | ||||
| [ | ||||
|     { | ||||
|         "version": "0.30.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add `AaveV2` and `Compound` deposit/withdrawal liquidity source", | ||||
|                 "pr": 321 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1638390144 | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1637102971, | ||||
|         "version": "0.29.5", | ||||
|   | ||||
| @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v0.30.0 - _December 1, 2021_ | ||||
|  | ||||
|     * Add `AaveV2` and `Compound` deposit/withdrawal liquidity source (#321) | ||||
|  | ||||
| ## v0.29.5 - _November 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -22,10 +22,12 @@ pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./IBridgeAdapter.sol"; | ||||
| import "./BridgeProtocols.sol"; | ||||
| import "./mixins/MixinAaveV2.sol"; | ||||
| import "./mixins/MixinBalancer.sol"; | ||||
| import "./mixins/MixinBalancerV2.sol"; | ||||
| import "./mixins/MixinBancor.sol"; | ||||
| import "./mixins/MixinCoFiX.sol"; | ||||
| import "./mixins/MixinCompound.sol"; | ||||
| import "./mixins/MixinCurve.sol"; | ||||
| import "./mixins/MixinCurveV2.sol"; | ||||
| import "./mixins/MixinCryptoCom.sol"; | ||||
| @@ -47,10 +49,12 @@ import "./mixins/MixinZeroExBridge.sol"; | ||||
|  | ||||
| contract BridgeAdapter is | ||||
|     IBridgeAdapter, | ||||
|     MixinAaveV2, | ||||
|     MixinBalancer, | ||||
|     MixinBalancerV2, | ||||
|     MixinBancor, | ||||
|     MixinCoFiX, | ||||
|     MixinCompound, | ||||
|     MixinCurve, | ||||
|     MixinCurveV2, | ||||
|     MixinCryptoCom, | ||||
| @@ -72,10 +76,12 @@ contract BridgeAdapter is | ||||
| { | ||||
|     constructor(IEtherTokenV06 weth) | ||||
|         public | ||||
|         MixinAaveV2() | ||||
|         MixinBalancer() | ||||
|         MixinBalancerV2() | ||||
|         MixinBancor(weth) | ||||
|         MixinCoFiX() | ||||
|         MixinCompound(weth) | ||||
|         MixinCurve(weth) | ||||
|         MixinCurveV2() | ||||
|         MixinCryptoCom() | ||||
| @@ -245,6 +251,20 @@ contract BridgeAdapter is | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.AAVEV2) { | ||||
|             boughtAmount = _tradeAaveV2( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.COMPOUND) { | ||||
|             boughtAmount = _tradeCompound( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else { | ||||
|             boughtAmount = _tradeZeroExBridge( | ||||
|                 sellToken, | ||||
|   | ||||
| @@ -50,4 +50,6 @@ library BridgeProtocols { | ||||
|     uint128 internal constant CURVEV2     = 20; | ||||
|     uint128 internal constant LIDO        = 21; | ||||
|     uint128 internal constant CLIPPER     = 22; // Not used: Clipper is now using PLP interface | ||||
|     uint128 internal constant AAVEV2      = 23; | ||||
|     uint128 internal constant COMPOUND    = 24; | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,93 @@ | ||||
| // 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/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
|  | ||||
| // Minimal Aave V2 LendingPool interface | ||||
| interface ILendingPool { | ||||
|     /** | ||||
|    * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. | ||||
|    * - E.g. User deposits 100 USDC and gets in return 100 aUSDC | ||||
|    * @param asset The address of the underlying asset to deposit | ||||
|    * @param amount The amount to be deposited | ||||
|    * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user | ||||
|    *   wants to receive them on his own wallet, or a different address if the beneficiary of aTokens | ||||
|    *   is a different wallet | ||||
|    * @param referralCode Code used to register the integrator originating the operation, for potential rewards. | ||||
|    *   0 if the action is executed directly by the user, without any middle-man | ||||
|    **/ | ||||
|   function deposit( | ||||
|     address asset, | ||||
|     uint256 amount, | ||||
|     address onBehalfOf, | ||||
|     uint16 referralCode | ||||
|   ) external; | ||||
|  | ||||
|   /** | ||||
|    * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned | ||||
|    * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC | ||||
|    * @param asset The address of the underlying asset to withdraw | ||||
|    * @param amount The underlying amount to be withdrawn | ||||
|    *   - Send the value type(uint256).max in order to withdraw the whole aToken balance | ||||
|    * @param to Address that will receive the underlying, same as msg.sender if the user | ||||
|    *   wants to receive it on his own wallet, or a different address if the beneficiary is a | ||||
|    *   different wallet | ||||
|    * @return The final amount withdrawn | ||||
|    **/ | ||||
|   function withdraw( | ||||
|     address asset, | ||||
|     uint256 amount, | ||||
|     address to | ||||
|   ) external returns (uint256); | ||||
| } | ||||
|  | ||||
| contract MixinAaveV2 { | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|  | ||||
|     function _tradeAaveV2( | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (uint256) | ||||
|     { | ||||
|         (ILendingPool lendingPool, address aToken) = abi.decode(bridgeData, (ILendingPool, address)); | ||||
|  | ||||
|           sellToken.approveIfBelow( | ||||
|               address(lendingPool), | ||||
|               sellAmount | ||||
|           ); | ||||
|  | ||||
|         if (address(buyToken) == aToken) { | ||||
|             lendingPool.deposit(address(sellToken), sellAmount, address(this), 0); | ||||
|             // 1:1 mapping token -> aToken and have the same number of decimals as the underlying token | ||||
|             return sellAmount; | ||||
|         } else if (address(sellToken) == aToken) { | ||||
|             return lendingPool.withdraw(address(buyToken), sellAmount, address(this)); | ||||
|         } | ||||
|  | ||||
|         revert("MixinAaveV2/UNSUPPORTED_TOKEN_PAIR"); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,110 @@ | ||||
| // 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/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; | ||||
|  | ||||
|  | ||||
| /// @dev Minimal CToken interface | ||||
| interface ICToken { | ||||
|     /// @dev deposits specified amount underlying tokens and mints cToken for the sender | ||||
|     /// @param mintAmountInUnderlying amount of underlying tokens to deposit to mint cTokens | ||||
|     /// @return status code of whether the mint was successful or not | ||||
|     function mint(uint256 mintAmountInUnderlying) external returns (uint256); | ||||
|     /// @dev redeems specified amount of cTokens and returns the underlying token to the sender | ||||
|     /// @param redeemTokensInCtokens amount of cTokens to redeem for underlying collateral | ||||
|     /// @return status code of whether the redemption was successful or not | ||||
|     function redeem(uint256 redeemTokensInCtokens) external returns (uint256); | ||||
| } | ||||
| /// @dev Minimal CEther interface | ||||
| interface ICEther { | ||||
|     /// @dev deposits the amount of Ether sent as value and return mints cEther for the sender | ||||
|     function mint() payable external; | ||||
|     /// @dev redeems specified amount of cETH and returns the underlying ether to the sender | ||||
|     /// @dev redeemTokensInCEther amount of cETH to redeem for underlying ether | ||||
|     /// @return status code of whether the redemption was successful or not | ||||
|     function redeem(uint256 redeemTokensInCEther) external returns (uint256); | ||||
| } | ||||
|  | ||||
| contract MixinCompound { | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|     using LibSafeMathV06 for uint256; | ||||
|  | ||||
|     IEtherTokenV06 private immutable WETH; | ||||
|  | ||||
|     constructor(IEtherTokenV06 weth) | ||||
|         public | ||||
|     { | ||||
|         WETH = weth; | ||||
|     } | ||||
|  | ||||
|     uint256 constant private COMPOUND_SUCCESS_CODE = 0; | ||||
|  | ||||
|     function _tradeCompound( | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (uint256) | ||||
|     { | ||||
|         (address cTokenAddress) = abi.decode(bridgeData, (address)); | ||||
|         uint256 beforeBalance = buyToken.balanceOf(address(this)); | ||||
|  | ||||
|         if (address(buyToken) == cTokenAddress) { | ||||
|             if (address(sellToken) == address(WETH)) { | ||||
|                 // ETH/WETH -> cETH | ||||
|                 ICEther cETH = ICEther(cTokenAddress); | ||||
|                 // Compound expects ETH to be sent with mint call | ||||
|                 WETH.withdraw(sellAmount); | ||||
|                 // NOTE: cETH mint will revert on failure instead of returning a status code | ||||
|                 cETH.mint{value: sellAmount}(); | ||||
|             } else { | ||||
|                 sellToken.approveIfBelow( | ||||
|                     cTokenAddress, | ||||
|                     sellAmount | ||||
|                 ); | ||||
|                 // Token -> cToken | ||||
|                 ICToken cToken = ICToken(cTokenAddress); | ||||
|                 require(cToken.mint(sellAmount) == COMPOUND_SUCCESS_CODE, "MixinCompound/FAILED_TO_MINT_CTOKEN"); | ||||
|             } | ||||
|         } else if (address(sellToken) == cTokenAddress) { | ||||
|             if (address(buyToken) == address(WETH)) { | ||||
|                 // cETH -> ETH/WETH | ||||
|                 uint256 etherBalanceBefore = address(this).balance; | ||||
|                 ICEther cETH = ICEther(cTokenAddress); | ||||
|                 require(cETH.redeem(sellAmount) == COMPOUND_SUCCESS_CODE, "MixinCompound/FAILED_TO_REDEEM_CETHER"); | ||||
|                 uint256 etherBalanceAfter = address(this).balance; | ||||
|                 uint256 receivedEtherBalance = etherBalanceAfter.safeSub(etherBalanceBefore); | ||||
|                 WETH.deposit{value: receivedEtherBalance}(); | ||||
|             } else { | ||||
|                 ICToken cToken = ICToken(cTokenAddress); | ||||
|                 require(cToken.redeem(sellAmount) == COMPOUND_SUCCESS_CODE, "MixinCompound/FAILED_TO_REDEEM_CTOKEN"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return buyToken.balanceOf(address(this)).safeSub(beforeBalance); | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-zero-ex", | ||||
|     "version": "0.29.5", | ||||
|     "version": "0.30.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -43,7 +43,7 @@ | ||||
|     "config": { | ||||
|         "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,OtcOrdersFeature,IOtcOrdersFeature", | ||||
|         "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", | ||||
|         "abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBalancerV2|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinKyber|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OtcOrdersFeature|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|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json" | ||||
|         "abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAaveV2|MixinBalancer|MixinBalancerV2|MixinBancor|MixinCoFiX|MixinCompound|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinKyber|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OtcOrdersFeature|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|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json" | ||||
|     }, | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
| @@ -56,10 +56,10 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/zero-ex", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.6.2", | ||||
|         "@0x/contract-addresses": "^6.9.0", | ||||
|         "@0x/contracts-erc20": "^3.3.23", | ||||
|         "@0x/contract-addresses": "^6.10.0", | ||||
|         "@0x/contracts-erc20": "^3.3.24", | ||||
|         "@0x/contracts-gen": "^2.0.40", | ||||
|         "@0x/contracts-test-utils": "^5.4.14", | ||||
|         "@0x/contracts-test-utils": "^5.4.15", | ||||
|         "@0x/dev-utils": "^4.2.9", | ||||
|         "@0x/order-utils": "^10.4.28", | ||||
|         "@0x/sol-compiler": "^4.7.5", | ||||
| @@ -83,7 +83,7 @@ | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.4.2", | ||||
|         "@0x/protocol-utils": "^1.9.5", | ||||
|         "@0x/protocol-utils": "^1.10.0", | ||||
|         "@0x/subproviders": "^6.6.0", | ||||
|         "@0x/types": "^3.3.4", | ||||
|         "@0x/typescript-typings": "^5.2.1", | ||||
|   | ||||
| @@ -81,10 +81,12 @@ import * as LiquidityProviderFeature from '../test/generated-artifacts/Liquidity | ||||
| import * as LiquidityProviderSandbox from '../test/generated-artifacts/LiquidityProviderSandbox.json'; | ||||
| import * as LogMetadataTransformer from '../test/generated-artifacts/LogMetadataTransformer.json'; | ||||
| import * as MetaTransactionsFeature from '../test/generated-artifacts/MetaTransactionsFeature.json'; | ||||
| import * as MixinAaveV2 from '../test/generated-artifacts/MixinAaveV2.json'; | ||||
| import * as MixinBalancer from '../test/generated-artifacts/MixinBalancer.json'; | ||||
| import * as MixinBalancerV2 from '../test/generated-artifacts/MixinBalancerV2.json'; | ||||
| import * as MixinBancor from '../test/generated-artifacts/MixinBancor.json'; | ||||
| import * as MixinCoFiX from '../test/generated-artifacts/MixinCoFiX.json'; | ||||
| import * as MixinCompound from '../test/generated-artifacts/MixinCompound.json'; | ||||
| import * as MixinCryptoCom from '../test/generated-artifacts/MixinCryptoCom.json'; | ||||
| import * as MixinCurve from '../test/generated-artifacts/MixinCurve.json'; | ||||
| import * as MixinCurveV2 from '../test/generated-artifacts/MixinCurveV2.json'; | ||||
| @@ -272,10 +274,12 @@ export const artifacts = { | ||||
|     BridgeAdapter: BridgeAdapter as ContractArtifact, | ||||
|     BridgeProtocols: BridgeProtocols as ContractArtifact, | ||||
|     IBridgeAdapter: IBridgeAdapter as ContractArtifact, | ||||
|     MixinAaveV2: MixinAaveV2 as ContractArtifact, | ||||
|     MixinBalancer: MixinBalancer as ContractArtifact, | ||||
|     MixinBalancerV2: MixinBalancerV2 as ContractArtifact, | ||||
|     MixinBancor: MixinBancor as ContractArtifact, | ||||
|     MixinCoFiX: MixinCoFiX as ContractArtifact, | ||||
|     MixinCompound: MixinCompound as ContractArtifact, | ||||
|     MixinCryptoCom: MixinCryptoCom as ContractArtifact, | ||||
|     MixinCurve: MixinCurve as ContractArtifact, | ||||
|     MixinCurveV2: MixinCurveV2 as ContractArtifact, | ||||
|   | ||||
| @@ -79,10 +79,12 @@ export * from '../test/generated-wrappers/liquidity_provider_feature'; | ||||
| export * from '../test/generated-wrappers/liquidity_provider_sandbox'; | ||||
| export * from '../test/generated-wrappers/log_metadata_transformer'; | ||||
| export * from '../test/generated-wrappers/meta_transactions_feature'; | ||||
| export * from '../test/generated-wrappers/mixin_aave_v2'; | ||||
| export * from '../test/generated-wrappers/mixin_balancer'; | ||||
| export * from '../test/generated-wrappers/mixin_balancer_v2'; | ||||
| export * from '../test/generated-wrappers/mixin_bancor'; | ||||
| export * from '../test/generated-wrappers/mixin_co_fi_x'; | ||||
| export * from '../test/generated-wrappers/mixin_compound'; | ||||
| export * from '../test/generated-wrappers/mixin_crypto_com'; | ||||
| export * from '../test/generated-wrappers/mixin_curve'; | ||||
| export * from '../test/generated-wrappers/mixin_curve_v2'; | ||||
|   | ||||
| @@ -112,10 +112,12 @@ | ||||
|         "test/generated-artifacts/LiquidityProviderSandbox.json", | ||||
|         "test/generated-artifacts/LogMetadataTransformer.json", | ||||
|         "test/generated-artifacts/MetaTransactionsFeature.json", | ||||
|         "test/generated-artifacts/MixinAaveV2.json", | ||||
|         "test/generated-artifacts/MixinBalancer.json", | ||||
|         "test/generated-artifacts/MixinBalancerV2.json", | ||||
|         "test/generated-artifacts/MixinBancor.json", | ||||
|         "test/generated-artifacts/MixinCoFiX.json", | ||||
|         "test/generated-artifacts/MixinCompound.json", | ||||
|         "test/generated-artifacts/MixinCryptoCom.json", | ||||
|         "test/generated-artifacts/MixinCurve.json", | ||||
|         "test/generated-artifacts/MixinCurveV2.json", | ||||
|   | ||||
| @@ -1,4 +1,63 @@ | ||||
| [ | ||||
|     { | ||||
|         "version": "16.40.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add `AaveV2` and `Compound` deposit/withdrawal liquidity source", | ||||
|                 "pr": 321 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1638390144 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.39.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Curve ETH/CRV pool", | ||||
|                 "pr": 378 | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.38.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Capture sampler metrics", | ||||
|                 "pr": 374 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1638228231 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.37.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Changed Sushiswap router address", | ||||
|                 "pr": 373 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1637349338 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.36.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Specify liquid routes for FEI/TRIBE FXS/FRAX and OHM/FRAX", | ||||
|                 "pr": 371 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1637290768 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.35.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add Beethoven X, MorpheusSwap and JetSwap to Fantom", | ||||
|                 "pr": 370 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1637206290 | ||||
|     }, | ||||
|     { | ||||
|         "version": "16.34.0", | ||||
|         "changes": [ | ||||
|   | ||||
| @@ -5,6 +5,30 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v16.40.0 - _December 1, 2021_ | ||||
|  | ||||
|     * Add `AaveV2` and `Compound` deposit/withdrawal liquidity source (#321) | ||||
|  | ||||
| ## v16.39.0 - _Invalid date_ | ||||
|  | ||||
|     * Curve ETH/CRV pool (#378) | ||||
|  | ||||
| ## v16.38.0 - _November 29, 2021_ | ||||
|  | ||||
|     * Capture sampler metrics (#374) | ||||
|  | ||||
| ## v16.37.0 - _November 19, 2021_ | ||||
|  | ||||
|     * Changed Sushiswap router address (#373) | ||||
|  | ||||
| ## v16.36.0 - _November 19, 2021_ | ||||
|  | ||||
|     * Specify liquid routes for FEI/TRIBE FXS/FRAX and OHM/FRAX (#371) | ||||
|  | ||||
| ## v16.35.0 - _November 18, 2021_ | ||||
|  | ||||
|     * Add Beethoven X, MorpheusSwap and JetSwap to Fantom (#370) | ||||
|  | ||||
| ## v16.34.0 - _November 16, 2021_ | ||||
|  | ||||
|     * Add support Celo (#367) | ||||
|   | ||||
							
								
								
									
										96
									
								
								packages/asset-swapper/contracts/src/CompoundSampler.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								packages/asset-swapper/contracts/src/CompoundSampler.sol
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| // 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; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./SamplerUtils.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
|  | ||||
| // Minimal CToken interface | ||||
| interface ICToken { | ||||
|     function mint(uint mintAmount) external returns (uint); | ||||
|     function redeem(uint redeemTokens) external returns (uint); | ||||
|     function redeemUnderlying(uint redeemAmount) external returns (uint); | ||||
|     function exchangeRateStored() external view returns (uint); | ||||
|     function decimals() external view returns (uint8); | ||||
| } | ||||
|  | ||||
| contract CompoundSampler is SamplerUtils { | ||||
|     uint256 constant private EXCHANGE_RATE_SCALE = 1e10; | ||||
|  | ||||
|     function sampleSellsFromCompound( | ||||
|         ICToken cToken, | ||||
|         IERC20TokenV06 takerToken, | ||||
|         IERC20TokenV06 makerToken, | ||||
|         uint256[] memory takerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (uint256[] memory makerTokenAmounts) | ||||
|     { | ||||
|         uint256 numSamples = takerTokenAmounts.length; | ||||
|         makerTokenAmounts = new uint256[](numSamples); | ||||
|         // Exchange rate is scaled by 1 * 10^(18 - 8 + Underlying Token Decimals | ||||
|         uint256 exchangeRate = cToken.exchangeRateStored(); | ||||
|         uint256 cTokenDecimals = uint256(cToken.decimals()); | ||||
|  | ||||
|         if (address(makerToken) == address(cToken)) { | ||||
|             // mint | ||||
|             for (uint256 i = 0; i < numSamples; i++) { | ||||
|                 makerTokenAmounts[i] = (takerTokenAmounts[i] * EXCHANGE_RATE_SCALE * 10 ** cTokenDecimals) / exchangeRate; | ||||
|             } | ||||
|  | ||||
|         } else if (address(takerToken) == address(cToken)) { | ||||
|             // redeem | ||||
|             for (uint256 i = 0; i < numSamples; i++) { | ||||
|                 makerTokenAmounts[i] = (takerTokenAmounts[i] * exchangeRate) / (EXCHANGE_RATE_SCALE * 10 ** cTokenDecimals); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function sampleBuysFromCompound( | ||||
|         ICToken cToken, | ||||
|         IERC20TokenV06 takerToken, | ||||
|         IERC20TokenV06 makerToken, | ||||
|         uint256[] memory makerTokenAmounts | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (uint256[] memory takerTokenAmounts) | ||||
|     { | ||||
|         uint256 numSamples = makerTokenAmounts.length; | ||||
|         takerTokenAmounts = new uint256[](numSamples); | ||||
|         // Exchange rate is scaled by 1 * 10^(18 - 8 + Underlying Token Decimals | ||||
|         uint256 exchangeRate = cToken.exchangeRateStored(); | ||||
|         uint256 cTokenDecimals = uint256(cToken.decimals()); | ||||
|  | ||||
|         if (address(makerToken) == address(cToken)) { | ||||
|             // mint | ||||
|             for (uint256 i = 0; i < numSamples; i++) { | ||||
|                 takerTokenAmounts[i] = makerTokenAmounts[i] * exchangeRate / (EXCHANGE_RATE_SCALE * 10 ** cTokenDecimals); | ||||
|             } | ||||
|         } else if (address(takerToken) == address(cToken)) { | ||||
|             // redeem | ||||
|             for (uint256 i = 0; i < numSamples; i++) { | ||||
|                 takerTokenAmounts[i] = (makerTokenAmounts[i] * EXCHANGE_RATE_SCALE * 10 ** cTokenDecimals)/exchangeRate; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -23,6 +23,7 @@ pragma experimental ABIEncoderV2; | ||||
| import "./BalancerSampler.sol"; | ||||
| import "./BalancerV2Sampler.sol"; | ||||
| import "./BancorSampler.sol"; | ||||
| import "./CompoundSampler.sol"; | ||||
| import "./CurveSampler.sol"; | ||||
| import "./DODOSampler.sol"; | ||||
| import "./DODOV2Sampler.sol"; | ||||
| @@ -48,6 +49,7 @@ contract ERC20BridgeSampler is | ||||
|     BalancerSampler, | ||||
|     BalancerV2Sampler, | ||||
|     BancorSampler, | ||||
|     CompoundSampler, | ||||
|     CurveSampler, | ||||
|     DODOSampler, | ||||
|     DODOV2Sampler, | ||||
|   | ||||
| @@ -77,4 +77,19 @@ contract UtilitySampler { | ||||
|         assembly { size := extcodesize(account) } | ||||
|         return size > 0; | ||||
|     } | ||||
|  | ||||
|     function getGasLeft() | ||||
|         public | ||||
|         returns (uint256) | ||||
|     { | ||||
|         return gasleft(); | ||||
|     } | ||||
|  | ||||
|     function getBlockNumber() | ||||
|         public | ||||
|         view | ||||
|         returns (uint256) | ||||
|     { | ||||
|         return block.number; | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/asset-swapper", | ||||
|     "version": "16.34.0", | ||||
|     "version": "16.40.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -39,7 +39,7 @@ | ||||
|     "config": { | ||||
|         "publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker", | ||||
|         "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", | ||||
|         "abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BalancerV2Sampler|BancorSampler|CurveSampler|DODOSampler|DODOV2Sampler|DummyLiquidityProvider|ERC20BridgeSampler|FakeTaker|IBalancer|IBancor|ICurve|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|ISmoothy|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|KyberSampler|LidoSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SmoothySampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler).json", | ||||
|         "abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BalancerV2Sampler|BancorSampler|CompoundSampler|CurveSampler|DODOSampler|DODOV2Sampler|DummyLiquidityProvider|ERC20BridgeSampler|FakeTaker|IBalancer|IBancor|ICurve|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|ISmoothy|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|KyberSampler|LidoSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SmoothySampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler).json", | ||||
|         "postpublish": { | ||||
|             "assets": [] | ||||
|         } | ||||
| @@ -60,14 +60,14 @@ | ||||
|     "dependencies": { | ||||
|         "@0x/assert": "^3.0.29", | ||||
|         "@0x/base-contract": "^6.4.2", | ||||
|         "@0x/contract-addresses": "^6.9.0", | ||||
|         "@0x/contract-wrappers": "^13.18.3", | ||||
|         "@0x/contracts-erc20": "^3.3.23", | ||||
|         "@0x/contracts-zero-ex": "^0.29.5", | ||||
|         "@0x/contract-addresses": "^6.10.0", | ||||
|         "@0x/contract-wrappers": "^13.18.4", | ||||
|         "@0x/contracts-erc20": "^3.3.24", | ||||
|         "@0x/contracts-zero-ex": "^0.30.0", | ||||
|         "@0x/dev-utils": "^4.2.9", | ||||
|         "@0x/json-schemas": "^6.3.0", | ||||
|         "@0x/neon-router": "^0.2.1", | ||||
|         "@0x/protocol-utils": "^1.9.5", | ||||
|         "@0x/protocol-utils": "^1.10.0", | ||||
|         "@0x/quote-server": "^6.0.6", | ||||
|         "@0x/types": "^3.3.4", | ||||
|         "@0x/typescript-typings": "^5.2.1", | ||||
| @@ -98,10 +98,10 @@ | ||||
|         "@0x/contracts-exchange": "^3.2.38", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.37", | ||||
|         "@0x/contracts-gen": "^2.0.40", | ||||
|         "@0x/contracts-test-utils": "^5.4.14", | ||||
|         "@0x/contracts-utils": "^4.8.4", | ||||
|         "@0x/contracts-test-utils": "^5.4.15", | ||||
|         "@0x/contracts-utils": "^4.8.5", | ||||
|         "@0x/mesh-rpc-client": "^9.4.2", | ||||
|         "@0x/migrations": "^8.1.12", | ||||
|         "@0x/migrations": "^8.1.13", | ||||
|         "@0x/sol-compiler": "^4.7.5", | ||||
|         "@0x/subproviders": "^6.6.0", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|   | ||||
| @@ -28,7 +28,6 @@ const ONE_SECOND_MS = 1000; | ||||
| const ONE_MINUTE_SECS = 60; | ||||
| const ONE_MINUTE_MS = ONE_SECOND_MS * ONE_MINUTE_SECS; | ||||
| const DEFAULT_PER_PAGE = 1000; | ||||
| const ZERO_AMOUNT = new BigNumber(0); | ||||
| const ALT_MM_IMPUTED_INDICATIVE_EXPIRY_SECONDS = 180; | ||||
|  | ||||
| const DEFAULT_ORDER_PRUNER_OPTS: OrderPrunerOpts = { | ||||
| @@ -43,6 +42,7 @@ const PROTOCOL_FEE_MULTIPLIER = new BigNumber(0); | ||||
| // default 50% buffer for selecting native orders to be aggregated with other sources | ||||
| const MARKET_UTILS_AMOUNT_BUFFER_PERCENTAGE = 0.5; | ||||
|  | ||||
| export const ZERO_AMOUNT = new BigNumber(0); | ||||
| const DEFAULT_SWAP_QUOTER_OPTS: SwapQuoterOpts = { | ||||
|     chainId: ChainId.Mainnet, | ||||
|     orderRefreshIntervalMs: 10000, // 10 seconds | ||||
|   | ||||
| @@ -113,6 +113,7 @@ export { | ||||
|     SwapQuoterError, | ||||
|     SwapQuoterOpts, | ||||
|     SwapQuoterRfqOpts, | ||||
|     SamplerMetrics, | ||||
| } from './types'; | ||||
| export { affiliateFeeUtils } from './utils/affiliate_fee_utils'; | ||||
| export { | ||||
|   | ||||
							
								
								
									
										57
									
								
								packages/asset-swapper/src/noop_samplers/AaveV2Sampler.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								packages/asset-swapper/src/noop_samplers/AaveV2Sampler.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| import { BigNumber } from '@0x/utils'; | ||||
|  | ||||
| import { ZERO_AMOUNT } from '../constants'; | ||||
| export interface AaveInfo { | ||||
|     lendingPool: string; | ||||
|     aToken: string; | ||||
|     underlyingToken: string; | ||||
| } | ||||
| // tslint:disable-next-line:no-unnecessary-class | ||||
| export class AaveV2Sampler { | ||||
|     public static sampleSellsFromAaveV2( | ||||
|         aaveInfo: AaveInfo, | ||||
|         takerToken: string, | ||||
|         makerToken: string, | ||||
|         takerTokenAmounts: BigNumber[], | ||||
|     ): BigNumber[] { | ||||
|         // Deposit/Withdrawal underlying <-> aToken is always 1:1 | ||||
|         if ( | ||||
|             (takerToken.toLowerCase() === aaveInfo.aToken.toLowerCase() && | ||||
|                 makerToken.toLowerCase() === aaveInfo.underlyingToken.toLowerCase()) || | ||||
|             (takerToken.toLowerCase() === aaveInfo.underlyingToken.toLowerCase() && | ||||
|                 makerToken.toLowerCase() === aaveInfo.aToken.toLowerCase()) | ||||
|         ) { | ||||
|             return takerTokenAmounts; | ||||
|         } | ||||
|  | ||||
|         // Not matching the reserve return 0 results | ||||
|         const numSamples = takerTokenAmounts.length; | ||||
|  | ||||
|         const makerTokenAmounts = new Array(numSamples); | ||||
|         makerTokenAmounts.fill(ZERO_AMOUNT); | ||||
|         return makerTokenAmounts; | ||||
|     } | ||||
|  | ||||
|     public static sampleBuysFromAaveV2( | ||||
|         aaveInfo: AaveInfo, | ||||
|         takerToken: string, | ||||
|         makerToken: string, | ||||
|         makerTokenAmounts: BigNumber[], | ||||
|     ): BigNumber[] { | ||||
|         // Deposit/Withdrawal underlying <-> aToken is always 1:1 | ||||
|         if ( | ||||
|             (takerToken.toLowerCase() === aaveInfo.aToken.toLowerCase() && | ||||
|                 makerToken.toLowerCase() === aaveInfo.underlyingToken.toLowerCase()) || | ||||
|             (takerToken.toLowerCase() === aaveInfo.underlyingToken.toLowerCase() && | ||||
|                 makerToken.toLowerCase() === aaveInfo.aToken.toLowerCase()) | ||||
|         ) { | ||||
|             return makerTokenAmounts; | ||||
|         } | ||||
|  | ||||
|         // Not matching the reserve return 0 results | ||||
|         const numSamples = makerTokenAmounts.length; | ||||
|         const takerTokenAmounts = new Array(numSamples); | ||||
|         takerTokenAmounts.fill(ZERO_AMOUNT); | ||||
|         return takerTokenAmounts; | ||||
|     } | ||||
| } | ||||
| @@ -19,6 +19,7 @@ import { | ||||
|     OptimizedMarketOrder, | ||||
|     TokenAdjacencyGraph, | ||||
| } from './utils/market_operation_utils/types'; | ||||
| export { SamplerMetrics } from './utils/market_operation_utils/types'; | ||||
| import { ExtendedQuoteReportSources, PriceComparisonsReport, QuoteReport } from './utils/quote_report_generator'; | ||||
| import { MetricsProxy } from './utils/quote_requestor'; | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,106 @@ | ||||
| import { logUtils } from '@0x/utils'; | ||||
| import { gql, request } from 'graphql-request'; | ||||
|  | ||||
| import { constants } from '../../constants'; | ||||
|  | ||||
| const RESERVES_GQL_QUERY = gql` | ||||
|     { | ||||
|         reserves( | ||||
|             first: 300 | ||||
|             where: { isActive: true, isFrozen: false } | ||||
|             orderBy: totalLiquidity | ||||
|             orderDirection: desc | ||||
|         ) { | ||||
|             id | ||||
|             underlyingAsset | ||||
|             aToken { | ||||
|                 id | ||||
|             } | ||||
|             pool { | ||||
|                 id | ||||
|                 lendingPool | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| `; | ||||
|  | ||||
| export interface AaveReserve { | ||||
|     id: string; | ||||
|     underlyingAsset: string; | ||||
|     aToken: { | ||||
|         id: string; | ||||
|     }; | ||||
|     pool: { | ||||
|         id: string; | ||||
|         lendingPool: string; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| interface Cache { | ||||
|     [key: string]: AaveReserve[]; | ||||
| } | ||||
|  | ||||
| // tslint:disable-next-line:custom-no-magic-numbers | ||||
| const RESERVES_REFRESH_INTERVAL_MS = 30 * constants.ONE_MINUTE_MS; | ||||
|  | ||||
| /** | ||||
|  * Fetches Aave V2 reserve information from the official subgraph(s). | ||||
|  * The reserve information is updated every 30 minutes and cached | ||||
|  * so that it can be accessed with the underlying token's address | ||||
|  */ | ||||
| export class AaveV2ReservesCache { | ||||
|     private _cache: Cache = {}; | ||||
|     constructor(private readonly _subgraphUrl: string) { | ||||
|         const resfreshReserves = async () => this.fetchAndUpdateReservesAsync(); | ||||
|         // tslint:disable-next-line:no-floating-promises | ||||
|         resfreshReserves(); | ||||
|         setInterval(resfreshReserves, RESERVES_REFRESH_INTERVAL_MS); | ||||
|     } | ||||
|     /** | ||||
|      * Fetches Aave V2 reserves from the subgraph and updates the cache | ||||
|      */ | ||||
|     public async fetchAndUpdateReservesAsync(): Promise<void> { | ||||
|         try { | ||||
|             const { reserves } = await request<{ reserves: AaveReserve[] }>(this._subgraphUrl, RESERVES_GQL_QUERY); | ||||
|             const newCache = reserves.reduce<Cache>((memo, reserve) => { | ||||
|                 const underlyingAsset = reserve.underlyingAsset.toLowerCase(); | ||||
|                 if (!memo[underlyingAsset]) { | ||||
|                     memo[underlyingAsset] = []; | ||||
|                 } | ||||
|  | ||||
|                 memo[underlyingAsset].push(reserve); | ||||
|                 return memo; | ||||
|             }, {}); | ||||
|  | ||||
|             this._cache = newCache; | ||||
|         } catch (err) { | ||||
|             logUtils.warn(`Failed to update Aave V2 reserves cache: ${err.message}`); | ||||
|             // Empty cache just to be safe | ||||
|             this._cache = {}; | ||||
|         } | ||||
|     } | ||||
|     public get(takerToken: string, makerToken: string): AaveReserve | undefined { | ||||
|         // Deposit takerToken into reserve | ||||
|         if (this._cache[takerToken.toLowerCase()]) { | ||||
|             const matchingReserve = this._cache[takerToken.toLowerCase()].find( | ||||
|                 r => r.aToken.id === makerToken.toLowerCase(), | ||||
|             ); | ||||
|             if (matchingReserve) { | ||||
|                 return matchingReserve; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Withdraw makerToken from reserve | ||||
|         if (this._cache[makerToken.toLowerCase()]) { | ||||
|             const matchingReserve = this._cache[makerToken.toLowerCase()].find( | ||||
|                 r => r.aToken.id === takerToken.toLowerCase(), | ||||
|             ); | ||||
|             if (matchingReserve) { | ||||
|                 return matchingReserve; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // No match | ||||
|         return undefined; | ||||
|     } | ||||
| } | ||||
| @@ -30,6 +30,7 @@ import { | ||||
|     KYBER_BRIDGED_LIQUIDITY_PREFIX, | ||||
|     MAX_DODOV2_POOLS_QUERIED, | ||||
|     MAX_KYBER_RESERVES_QUERIED, | ||||
|     MORPHEUSSWAP_ROUTER_BY_CHAIN_ID, | ||||
|     MSTABLE_POOLS_BY_CHAIN_ID, | ||||
|     NERVE_BSC_INFOS, | ||||
|     NULL_ADDRESS, | ||||
| @@ -488,6 +489,7 @@ export function uniswapV2LikeRouterAddress( | ||||
|         | ERC20BridgeSource.TraderJoe | ||||
|         | ERC20BridgeSource.Pangolin | ||||
|         | ERC20BridgeSource.UbeSwap | ||||
|         | ERC20BridgeSource.MorpheusSwap | ||||
|         | ERC20BridgeSource.SpookySwap | ||||
|         | ERC20BridgeSource.SpiritSwap, | ||||
| ): string { | ||||
| @@ -532,6 +534,8 @@ export function uniswapV2LikeRouterAddress( | ||||
|             return TRADER_JOE_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.UbeSwap: | ||||
|             return UBESWAP_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.MorpheusSwap: | ||||
|             return MORPHEUSSWAP_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.SpookySwap: | ||||
|             return SPOOKYSWAP_ROUTER_BY_CHAIN_ID[chainId]; | ||||
|         case ERC20BridgeSource.SpiritSwap: | ||||
|   | ||||
| @@ -0,0 +1,78 @@ | ||||
| import { logUtils } from '@0x/utils'; | ||||
| import axios from 'axios'; | ||||
|  | ||||
| import { constants } from '../../constants'; | ||||
|  | ||||
| export interface CToken { | ||||
|     tokenAddress: string; | ||||
|     underlyingAddress: string; | ||||
| } | ||||
|  | ||||
| interface CTokenApiResponse { | ||||
|     cToken: Array<{ | ||||
|         token_address: string; | ||||
|         underlying_address: string; | ||||
|     }>; | ||||
| } | ||||
|  | ||||
| interface Cache { | ||||
|     [key: string]: CToken; | ||||
| } | ||||
|  | ||||
| // tslint:disable-next-line:custom-no-magic-numbers | ||||
| const CTOKEN_REFRESH_INTERVAL_MS = 30 * constants.ONE_MINUTE_MS; | ||||
|  | ||||
| /** | ||||
|  * Fetches a list of CTokens from Compound's official API. | ||||
|  * The token information is updated every 30 minutes and cached | ||||
|  * so that it can be accessed with the underlying token's address. | ||||
|  */ | ||||
| export class CompoundCTokenCache { | ||||
|     private _cache: Cache = {}; | ||||
|     constructor(private readonly _apiUrl: string, private readonly _wethAddress: string) { | ||||
|         const refreshCTokenCache = async () => this.fetchAndUpdateCTokensAsync(); | ||||
|         // tslint:disable-next-line:no-floating-promises | ||||
|         refreshCTokenCache(); | ||||
|         setInterval(refreshCTokenCache, CTOKEN_REFRESH_INTERVAL_MS); | ||||
|     } | ||||
|  | ||||
|     public async fetchAndUpdateCTokensAsync(): Promise<void> { | ||||
|         try { | ||||
|             const { data } = await axios.get<CTokenApiResponse>(`${this._apiUrl}/ctoken`); | ||||
|             const newCache = data?.cToken.reduce<Cache>((memo, cToken) => { | ||||
|                 // NOTE: Re-map cETH with null underlying token address to WETH address (we only handle WETH internally) | ||||
|                 const underlyingAddressClean = cToken.underlying_address | ||||
|                     ? cToken.underlying_address.toLowerCase() | ||||
|                     : this._wethAddress; | ||||
|  | ||||
|                 const tokenData: CToken = { | ||||
|                     tokenAddress: cToken.token_address.toLowerCase(), | ||||
|                     underlyingAddress: underlyingAddressClean, | ||||
|                 }; | ||||
|                 memo[underlyingAddressClean] = tokenData; | ||||
|                 return memo; | ||||
|             }, {}); | ||||
|  | ||||
|             this._cache = newCache; | ||||
|         } catch (err) { | ||||
|             logUtils.warn(`Failed to update Compound cToken cache: ${err.message}`); | ||||
|             // NOTE: Safe to keep already cached data as tokens should only be added to the list | ||||
|         } | ||||
|     } | ||||
|     public get(takerToken: string, makerToken: string): CToken | undefined { | ||||
|         // mint cToken | ||||
|         let cToken = this._cache[takerToken.toLowerCase()]; | ||||
|         if (cToken && makerToken.toLowerCase() === cToken.tokenAddress.toLowerCase()) { | ||||
|             return cToken; | ||||
|         } | ||||
|  | ||||
|         // redeem cToken | ||||
|         cToken = this._cache[makerToken.toLowerCase()]; | ||||
|         if (cToken && takerToken.toLowerCase() === cToken.tokenAddress.toLowerCase()) { | ||||
|             return cToken; | ||||
|         } | ||||
|  | ||||
|         // No match | ||||
|         return undefined; | ||||
|     } | ||||
| } | ||||
| @@ -7,7 +7,9 @@ import { TokenAdjacencyGraphBuilder } from '../token_adjacency_graph_builder'; | ||||
|  | ||||
| import { SourceFilters } from './source_filters'; | ||||
| import { | ||||
|     AaveV2FillData, | ||||
|     BancorFillData, | ||||
|     CompoundFillData, | ||||
|     CurveFillData, | ||||
|     CurveFunctionSelectors, | ||||
|     CurveInfo, | ||||
| @@ -101,6 +103,9 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>( | ||||
|             ERC20BridgeSource.UniswapV3, | ||||
|             ERC20BridgeSource.CurveV2, | ||||
|             ERC20BridgeSource.ShibaSwap, | ||||
|             // TODO: enable after FQT has been redeployed on Ethereum mainnet | ||||
|             // ERC20BridgeSource.AaveV2, | ||||
|             // ERC20BridgeSource.Compound, | ||||
|         ]), | ||||
|         [ChainId.Ropsten]: new SourceFilters([ | ||||
|             ERC20BridgeSource.Kyber, | ||||
| @@ -159,6 +164,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>( | ||||
|             ERC20BridgeSource.MultiHop, | ||||
|             ERC20BridgeSource.JetSwap, | ||||
|             ERC20BridgeSource.IronSwap, | ||||
|             ERC20BridgeSource.AaveV2, | ||||
|         ]), | ||||
|         [ChainId.Avalanche]: new SourceFilters([ | ||||
|             ERC20BridgeSource.MultiHop, | ||||
| @@ -168,11 +174,15 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>( | ||||
|             ERC20BridgeSource.Curve, | ||||
|             ERC20BridgeSource.CurveV2, | ||||
|             ERC20BridgeSource.KyberDmm, | ||||
|             ERC20BridgeSource.AaveV2, | ||||
|         ]), | ||||
|         [ChainId.Fantom]: new SourceFilters([ | ||||
|             ERC20BridgeSource.MultiHop, | ||||
|             ERC20BridgeSource.Beethovenx, | ||||
|             ERC20BridgeSource.Curve, | ||||
|             ERC20BridgeSource.CurveV2, | ||||
|             ERC20BridgeSource.JetSwap, | ||||
|             ERC20BridgeSource.MorpheusSwap, | ||||
|             ERC20BridgeSource.SpiritSwap, | ||||
|             ERC20BridgeSource.SpookySwap, | ||||
|             ERC20BridgeSource.SushiSwap, | ||||
| @@ -224,6 +234,9 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>( | ||||
|             ERC20BridgeSource.UniswapV3, | ||||
|             ERC20BridgeSource.CurveV2, | ||||
|             ERC20BridgeSource.ShibaSwap, | ||||
|             // TODO: enable after FQT has been redeployed on Ethereum mainnet | ||||
|             // ERC20BridgeSource.AaveV2, | ||||
|             // ERC20BridgeSource.Compound, | ||||
|         ]), | ||||
|         [ChainId.Ropsten]: new SourceFilters([ | ||||
|             ERC20BridgeSource.Kyber, | ||||
| @@ -282,6 +295,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>( | ||||
|             ERC20BridgeSource.MultiHop, | ||||
|             ERC20BridgeSource.JetSwap, | ||||
|             ERC20BridgeSource.IronSwap, | ||||
|             ERC20BridgeSource.AaveV2, | ||||
|         ]), | ||||
|         [ChainId.Avalanche]: new SourceFilters([ | ||||
|             ERC20BridgeSource.MultiHop, | ||||
| @@ -291,11 +305,15 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>( | ||||
|             ERC20BridgeSource.Curve, | ||||
|             ERC20BridgeSource.CurveV2, | ||||
|             ERC20BridgeSource.KyberDmm, | ||||
|             ERC20BridgeSource.AaveV2, | ||||
|         ]), | ||||
|         [ChainId.Fantom]: new SourceFilters([ | ||||
|             ERC20BridgeSource.MultiHop, | ||||
|             ERC20BridgeSource.Beethovenx, | ||||
|             ERC20BridgeSource.Curve, | ||||
|             ERC20BridgeSource.CurveV2, | ||||
|             ERC20BridgeSource.JetSwap, | ||||
|             ERC20BridgeSource.MorpheusSwap, | ||||
|             ERC20BridgeSource.SpiritSwap, | ||||
|             ERC20BridgeSource.SpookySwap, | ||||
|             ERC20BridgeSource.SushiSwap, | ||||
| @@ -422,9 +440,16 @@ export const MAINNET_TOKENS = { | ||||
|     // StableSwap "open pools" (crv.finance) | ||||
|     STABLEx: '0xcd91538b91b4ba7797d39a2f66e63810b50a33d0', | ||||
|     alUSD: '0xbc6da0fe9ad5f3b0d58160288917aa56653660e9', | ||||
|     // Frax ecosystem | ||||
|     FRAX: '0x853d955acef822db058eb8505911ed77f175b99e', | ||||
|     FXS: '0x3432b6a60d23ca0dfca7761b7ab56459d9c964d0', | ||||
|     OHM: '0x383518188c0c6d7730d91b2c03a03c837814a899', | ||||
|     // | ||||
|     LUSD: '0x5f98805a4e8be255a32880fdec7f6728c6568ba0', | ||||
|     // Fei Ecosystem | ||||
|     FEI: '0x956f47f50a910163d8bf957cf5846d573e7f87ca', | ||||
|     TRIBE: '0xc7283b66eb1eb5fb86327f08e1b5816b0720212b', | ||||
|     // | ||||
|     DSU: '0x605d26fbd5be761089281d5cec2ce86eea667109', | ||||
|     ESS: '0x24ae124c4cc33d6791f8e8b63520ed7107ac8b3e', | ||||
|     cvxCRV: '0x62b9c7356a2dc64a1969e19c23e4f579f9810aa7', | ||||
| @@ -538,6 +563,7 @@ export const CURVE_POOLS = { | ||||
|     cvxcrv: '0x9d0464996170c6b9e75eed71c68b99ddedf279e8', | ||||
|     mim: '0x5a6a4d54456819380173272a5e8e9b9904bdf41b', | ||||
|     eurt: '0xfd5db7463a3ab53fd211b4af195c5bccc1a03890', | ||||
|     ethcrv: '0x8301ae4fc9c624d1d396cbdaa1ed877821d7c511', | ||||
| }; | ||||
|  | ||||
| export const CURVE_V2_POOLS = { | ||||
| @@ -690,6 +716,11 @@ export const DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID = valueByChainId<TokenAdj | ||||
|                 builder.add(MAINNET_TOKENS.MIR, MAINNET_TOKENS.UST); | ||||
|                 // Convex and Curve | ||||
|                 builder.add(MAINNET_TOKENS.cvxCRV, MAINNET_TOKENS.CRV).add(MAINNET_TOKENS.CRV, MAINNET_TOKENS.cvxCRV); | ||||
|                 // FEI TRIBE liquid in UniV2 | ||||
|                 builder.add(MAINNET_TOKENS.FEI, MAINNET_TOKENS.TRIBE).add(MAINNET_TOKENS.TRIBE, MAINNET_TOKENS.FEI); | ||||
|                 // FRAX ecosystem | ||||
|                 builder.add(MAINNET_TOKENS.FRAX, MAINNET_TOKENS.FXS).add(MAINNET_TOKENS.FXS, MAINNET_TOKENS.FRAX); | ||||
|                 builder.add(MAINNET_TOKENS.FRAX, MAINNET_TOKENS.OHM).add(MAINNET_TOKENS.OHM, MAINNET_TOKENS.FRAX); | ||||
|             }) | ||||
|             // Build | ||||
|             .build(), | ||||
| @@ -998,6 +1029,17 @@ export const CURVE_MAINNET_INFOS: { [name: string]: CurveInfo } = { | ||||
|         pool: CURVE_POOLS.cvxcrv, | ||||
|         gasSchedule: 105e3, | ||||
|     }), | ||||
|     [CURVE_POOLS.ethcrv]: { | ||||
|         ...createCurveExchangePool({ | ||||
|             // This pool uses ETH | ||||
|             tokens: [MAINNET_TOKENS.WETH, MAINNET_TOKENS.CRV], | ||||
|             pool: CURVE_POOLS.ethcrv, | ||||
|             gasSchedule: 350e3, | ||||
|         }), | ||||
|         // This pool has a custom get_dy and exchange selector with uint256 | ||||
|         sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_uint256, | ||||
|         exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying_uint256, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| export const CURVE_V2_MAINNET_INFOS: { [name: string]: CurveInfo } = { | ||||
| @@ -1396,7 +1438,7 @@ export const SUSHISWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>( | ||||
|         [ChainId.Polygon]: '0x1b02da8cb0d097eb8d57a175b88c7d8b47997506', | ||||
|         [ChainId.Avalanche]: '0x1b02da8cb0d097eb8d57a175b88c7d8b47997506', | ||||
|         [ChainId.Fantom]: '0x1b02da8cb0d097eb8d57a175b88c7d8b47997506', | ||||
|         [ChainId.Celo]: '0x1b02da8cb0d097eb8d57a175b88c7d8b47997506', | ||||
|         [ChainId.Celo]: '0x1421bde4b10e8dd459b3bcb598810b1337d56842', | ||||
|     }, | ||||
|     NULL_ADDRESS, | ||||
| ); | ||||
| @@ -1618,6 +1660,13 @@ export const BALANCER_V2_VAULT_ADDRESS_BY_CHAIN = valueByChainId<string>( | ||||
|     NULL_ADDRESS, | ||||
| ); | ||||
|  | ||||
| export const BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN = valueByChainId<string>( | ||||
|     { | ||||
|         [ChainId.Fantom]: '0x20dd72ed959b6147912c2e529f0a0c651c33c9ce', | ||||
|     }, | ||||
|     NULL_ADDRESS, | ||||
| ); | ||||
|  | ||||
| export const LIDO_INFO_BY_CHAIN = valueByChainId<LidoInfo>( | ||||
|     { | ||||
|         [ChainId.Mainnet]: { | ||||
| @@ -1642,6 +1691,13 @@ export const BALANCER_V2_SUBGRAPH_URL_BY_CHAIN = valueByChainId<string>( | ||||
|     'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2', | ||||
| ); | ||||
|  | ||||
| export const BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN = valueByChainId<string>( | ||||
|     { | ||||
|         [ChainId.Fantom]: 'https://graph-node.beets-ftm-node.com/subgraphs/name/beethovenx-v4', | ||||
|     }, | ||||
|     'https://graph-node.beets-ftm-node.com/subgraphs/name/beethovenx-v4', | ||||
| ); | ||||
|  | ||||
| export const UNISWAPV3_CONFIG_BY_CHAIN_ID = valueByChainId( | ||||
|     { | ||||
|         [ChainId.Mainnet]: { | ||||
| @@ -1656,6 +1712,24 @@ export const UNISWAPV3_CONFIG_BY_CHAIN_ID = valueByChainId( | ||||
|     { quoter: NULL_ADDRESS, router: NULL_ADDRESS }, | ||||
| ); | ||||
|  | ||||
| export const AAVE_V2_SUBGRAPH_URL_BY_CHAIN_ID = valueByChainId( | ||||
|     { | ||||
|         // TODO: enable after FQT has been redeployed on Ethereum mainnet | ||||
|         // [ChainId.Mainnet]: 'https://api.thegraph.com/subgraphs/name/aave/protocol-v2', | ||||
|         [ChainId.Polygon]: 'https://api.thegraph.com/subgraphs/name/aave/aave-v2-matic', | ||||
|         [ChainId.Avalanche]: 'https://api.thegraph.com/subgraphs/name/aave/protocol-v2-avalanche', | ||||
|     }, | ||||
|     null, | ||||
| ); | ||||
|  | ||||
| export const COMPOUND_API_URL_BY_CHAIN_ID = valueByChainId( | ||||
|     { | ||||
|         // TODO: enable after FQT has been redeployed on Ethereum mainnet | ||||
|         // [ChainId.Mainnet]: 'https://api.compound.finance/api/v2', | ||||
|     }, | ||||
|     null, | ||||
| ); | ||||
|  | ||||
| // | ||||
| // BSC | ||||
| // | ||||
| @@ -1752,6 +1826,7 @@ export const JETSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>( | ||||
|     { | ||||
|         [ChainId.BSC]: '0xbe65b8f75b9f20f4c522e0067a3887fada714800', | ||||
|         [ChainId.Polygon]: '0x5c6ec38fb0e2609672bdf628b1fd605a523e5923', | ||||
|         [ChainId.Fantom]: '0x845e76a8691423fbc4ecb8dd77556cb61c09ee25', | ||||
|     }, | ||||
|     NULL_ADDRESS, | ||||
| ); | ||||
| @@ -1777,6 +1852,13 @@ export const UBESWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>( | ||||
|     NULL_ADDRESS, | ||||
| ); | ||||
|  | ||||
| export const MORPHEUSSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>( | ||||
|     { | ||||
|         [ChainId.Fantom]: '0x8ac868293d97761a1fed6d4a01e9ff17c5594aa3', | ||||
|     }, | ||||
|     NULL_ADDRESS, | ||||
| ); | ||||
|  | ||||
| export const SPIRITSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>( | ||||
|     { | ||||
|         [ChainId.Fantom]: '0x16327e3fbdaca3bcf7e38f5af2599d2ddc33ae52', | ||||
| @@ -1913,6 +1995,21 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = { | ||||
|         return gas; | ||||
|     }, | ||||
|     [ERC20BridgeSource.Lido]: () => 226e3, | ||||
|     [ERC20BridgeSource.AaveV2]: (fillData?: FillData) => { | ||||
|         const aaveFillData = fillData as AaveV2FillData; | ||||
|         // NOTE: The Aave deposit method is more expensive than the withdraw | ||||
|         return aaveFillData.takerToken === aaveFillData.underlyingToken ? 400e3 : 300e3; | ||||
|     }, | ||||
|     [ERC20BridgeSource.Compound]: (fillData?: FillData) => { | ||||
|         // NOTE: cETH is handled differently than other cTokens | ||||
|         const wethAddress = NATIVE_FEE_TOKEN_BY_CHAIN_ID[ChainId.Mainnet]; | ||||
|         const compoundFillData = fillData as CompoundFillData; | ||||
|         if (compoundFillData.takerToken === compoundFillData.cToken) { | ||||
|             return compoundFillData.makerToken === wethAddress ? 120e3 : 150e3; | ||||
|         } else { | ||||
|             return compoundFillData.takerToken === wethAddress ? 210e3 : 250e3; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     // | ||||
|     // BSC | ||||
| @@ -1950,8 +2047,10 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = { | ||||
|     // | ||||
|     // Fantom | ||||
|     // | ||||
|     [ERC20BridgeSource.MorpheusSwap]: uniswapV2CloneGasSchedule, | ||||
|     [ERC20BridgeSource.SpiritSwap]: uniswapV2CloneGasSchedule, | ||||
|     [ERC20BridgeSource.SpookySwap]: uniswapV2CloneGasSchedule, | ||||
|     [ERC20BridgeSource.Beethovenx]: () => 100e3, | ||||
| }; | ||||
|  | ||||
| export const DEFAULT_FEE_SCHEDULE: Required<FeeSchedule> = { ...DEFAULT_GAS_SCHEDULE }; | ||||
|   | ||||
| @@ -158,6 +158,8 @@ export class MarketOperationUtils { | ||||
|  | ||||
|         // Call the sampler contract. | ||||
|         const samplerPromise = this._sampler.executeAsync( | ||||
|             this._sampler.getBlockNumber(), | ||||
|             this._sampler.getGasLeft(), | ||||
|             this._sampler.getTokenDecimals([makerToken, takerToken]), | ||||
|             // Get native order fillable amounts. | ||||
|             this._sampler.getLimitOrderFillableTakerAmounts(nativeOrders, this.contractAddresses.exchangeProxy), | ||||
| @@ -184,6 +186,7 @@ export class MarketOperationUtils { | ||||
|                 takerAmount, | ||||
|             ), | ||||
|             this._sampler.isAddressContract(txOrigin), | ||||
|             this._sampler.getGasLeft(), | ||||
|         ); | ||||
|  | ||||
|         // Refresh the cached pools asynchronously if required | ||||
| @@ -191,6 +194,8 @@ export class MarketOperationUtils { | ||||
|  | ||||
|         const [ | ||||
|             [ | ||||
|                 blockNumber, | ||||
|                 gasBefore, | ||||
|                 tokenDecimals, | ||||
|                 orderFillableTakerAmounts, | ||||
|                 outputAmountPerEth, | ||||
| @@ -198,9 +203,14 @@ export class MarketOperationUtils { | ||||
|                 dexQuotes, | ||||
|                 rawTwoHopQuotes, | ||||
|                 isTxOriginContract, | ||||
|                 gasAfter, | ||||
|             ], | ||||
|         ] = await Promise.all([samplerPromise]); | ||||
|  | ||||
|         // Log the gas metrics | ||||
|         _opts.samplerMetrics?.logGasDetails({ gasBefore, gasAfter }); | ||||
|         _opts.samplerMetrics?.logBlockNumber(blockNumber); | ||||
|  | ||||
|         // Filter out any invalid two hop quotes where we couldn't find a route | ||||
|         const twoHopQuotes = rawTwoHopQuotes.filter( | ||||
|             q => q && q.fillData && q.fillData.firstHopSource && q.fillData.secondHopSource, | ||||
|   | ||||
| @@ -5,11 +5,13 @@ import { AssetSwapperContractAddresses, MarketOperation } from '../../types'; | ||||
|  | ||||
| import { MAX_UINT256, ZERO_AMOUNT } from './constants'; | ||||
| import { | ||||
|     AaveV2FillData, | ||||
|     AggregationError, | ||||
|     BalancerFillData, | ||||
|     BalancerV2FillData, | ||||
|     BancorFillData, | ||||
|     CollapsedFill, | ||||
|     CompoundFillData, | ||||
|     CurveFillData, | ||||
|     DexSample, | ||||
|     DODOFillData, | ||||
| @@ -186,10 +188,18 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'TraderJoe'); | ||||
|         case ERC20BridgeSource.UbeSwap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'UbeSwap'); | ||||
|         case ERC20BridgeSource.Beethovenx: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.BalancerV2, 'Beethovenx'); | ||||
|         case ERC20BridgeSource.SpiritSwap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'SpiritSwap'); | ||||
|         case ERC20BridgeSource.SpookySwap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'SpookySwap'); | ||||
|         case ERC20BridgeSource.MorpheusSwap: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'MorpheusSwap'); | ||||
|         case ERC20BridgeSource.AaveV2: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.AaveV2, 'AaveV2'); | ||||
|         case ERC20BridgeSource.Compound: | ||||
|             return encodeBridgeSourceId(BridgeProtocol.Compound, 'Compound'); | ||||
|         default: | ||||
|             throw new Error(AggregationError.NoBridgeForSource); | ||||
|     } | ||||
| @@ -238,6 +248,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder | ||||
|             bridgeData = encoder.encode([balancerFillData.poolAddress]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.BalancerV2: | ||||
|         case ERC20BridgeSource.Beethovenx: | ||||
|             const balancerV2FillData = (order as OptimizedMarketBridgeOrder<BalancerV2FillData>).fillData; | ||||
|             const { vault, poolId } = balancerV2FillData; | ||||
|             bridgeData = encoder.encode([vault, poolId]); | ||||
| @@ -269,6 +280,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder | ||||
|         case ERC20BridgeSource.UbeSwap: | ||||
|         case ERC20BridgeSource.SpiritSwap: | ||||
|         case ERC20BridgeSource.SpookySwap: | ||||
|         case ERC20BridgeSource.MorpheusSwap: | ||||
|             const uniswapV2FillData = (order as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData; | ||||
|             bridgeData = encoder.encode([uniswapV2FillData.router, uniswapV2FillData.tokenAddressPath]); | ||||
|             break; | ||||
| @@ -333,6 +345,15 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder | ||||
|             const lidoFillData = (order as OptimizedMarketBridgeOrder<LidoFillData>).fillData; | ||||
|             bridgeData = encoder.encode([lidoFillData.stEthTokenAddress]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.AaveV2: | ||||
|             const aaveFillData = (order as OptimizedMarketBridgeOrder<AaveV2FillData>).fillData; | ||||
|             bridgeData = encoder.encode([aaveFillData.lendingPool, aaveFillData.aToken]); | ||||
|             break; | ||||
|         case ERC20BridgeSource.Compound: | ||||
|             const compoundFillData = (order as OptimizedMarketBridgeOrder<CompoundFillData>).fillData; | ||||
|             bridgeData = encoder.encode([compoundFillData.cToken]); | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             throw new Error(AggregationError.NoBridgeForSource); | ||||
|     } | ||||
| @@ -461,6 +482,7 @@ export const BRIDGE_ENCODERS: { | ||||
|     [ERC20BridgeSource.TraderJoe]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.SpiritSwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.SpookySwap]: routerAddressPathEncoder, | ||||
|     [ERC20BridgeSource.MorpheusSwap]: routerAddressPathEncoder, | ||||
|     // Celo | ||||
|     [ERC20BridgeSource.UbeSwap]: routerAddressPathEncoder, | ||||
|     // BSC | ||||
| @@ -490,12 +512,15 @@ export const BRIDGE_ENCODERS: { | ||||
|     // Custom integrations | ||||
|     [ERC20BridgeSource.MakerPsm]: makerPsmEncoder, | ||||
|     [ERC20BridgeSource.BalancerV2]: balancerV2Encoder, | ||||
|     [ERC20BridgeSource.Beethovenx]: balancerV2Encoder, | ||||
|     [ERC20BridgeSource.UniswapV3]: AbiEncoder.create([ | ||||
|         { name: 'router', type: 'address' }, | ||||
|         { name: 'path', type: 'bytes' }, | ||||
|     ]), | ||||
|     [ERC20BridgeSource.KyberDmm]: AbiEncoder.create('(address,address[],address[])'), | ||||
|     [ERC20BridgeSource.Lido]: AbiEncoder.create('(address)'), | ||||
|     [ERC20BridgeSource.AaveV2]: AbiEncoder.create('(address,address)'), | ||||
|     [ERC20BridgeSource.Compound]: AbiEncoder.create('(address)'), | ||||
| }; | ||||
|  | ||||
| function getFillTokenAmounts(fill: CollapsedFill, side: MarketOperation): [BigNumber, BigNumber] { | ||||
|   | ||||
| @@ -130,6 +130,37 @@ export class DexOrderSampler extends SamplerOperations { | ||||
|         BatchedOperationResult<T8> | ||||
|     ]>; | ||||
|  | ||||
|     // prettier-ignore | ||||
|     public async executeAsync< | ||||
|         T1, T2, T3, T4, T5, T6, T7, T8, T9 | ||||
|     >(...ops: [T1, T2, T3, T4, T5, T6, T7, T8, T9]): Promise<[ | ||||
|         BatchedOperationResult<T1>, | ||||
|         BatchedOperationResult<T2>, | ||||
|         BatchedOperationResult<T3>, | ||||
|         BatchedOperationResult<T4>, | ||||
|         BatchedOperationResult<T5>, | ||||
|         BatchedOperationResult<T6>, | ||||
|         BatchedOperationResult<T7>, | ||||
|         BatchedOperationResult<T8>, | ||||
|         BatchedOperationResult<T9> | ||||
|     ]>; | ||||
|  | ||||
|     // prettier-ignore | ||||
|     public async executeAsync< | ||||
|         T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 | ||||
|     >(...ops: [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]): Promise<[ | ||||
|         BatchedOperationResult<T1>, | ||||
|         BatchedOperationResult<T2>, | ||||
|         BatchedOperationResult<T3>, | ||||
|         BatchedOperationResult<T4>, | ||||
|         BatchedOperationResult<T5>, | ||||
|         BatchedOperationResult<T6>, | ||||
|         BatchedOperationResult<T7>, | ||||
|         BatchedOperationResult<T8>, | ||||
|         BatchedOperationResult<T9>, | ||||
|         BatchedOperationResult<T10>, | ||||
|     ]>; | ||||
|  | ||||
|     /** | ||||
|      * Run a series of operations from `DexOrderSampler.ops` in a single transaction. | ||||
|      */ | ||||
|   | ||||
| @@ -0,0 +1,36 @@ | ||||
| import { BigNumber, logUtils, NULL_BYTES } from '@0x/utils'; | ||||
|  | ||||
| import { ERC20BridgeSource, FillData, SourceQuoteOperation } from './types'; | ||||
|  | ||||
| interface SamplerNoOperationCall { | ||||
|     callback: () => BigNumber[]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * SamplerNoOperation can be used for sources where we already have all the necessary information | ||||
|  * required to perform the sample operations, without needing access to any on-chain data. Using a noop sample | ||||
|  * you can skip the eth_call, and just calculate the results directly in typescript land. | ||||
|  */ | ||||
| export class SamplerNoOperation<TFillData extends FillData = FillData> implements SourceQuoteOperation<TFillData> { | ||||
|     public readonly source: ERC20BridgeSource; | ||||
|     public fillData: TFillData; | ||||
|     private readonly _callback: () => BigNumber[]; | ||||
|  | ||||
|     constructor(opts: { source: ERC20BridgeSource; fillData?: TFillData } & SamplerNoOperationCall) { | ||||
|         this.source = opts.source; | ||||
|         this.fillData = opts.fillData || ({} as TFillData); // tslint:disable-line:no-object-literal-type-assertion | ||||
|         this._callback = opts.callback; | ||||
|     } | ||||
|  | ||||
|     // tslint:disable-next-line:prefer-function-over-method | ||||
|     public encodeCall(): string { | ||||
|         return NULL_BYTES; | ||||
|     } | ||||
|     public handleCallResults(_callResults: string): BigNumber[] { | ||||
|         return this._callback(); | ||||
|     } | ||||
|     public handleRevert(_callResults: string): BigNumber[] { | ||||
|         logUtils.warn(`SamplerNoOperation: ${this.source} reverted`); | ||||
|         return []; | ||||
|     } | ||||
| } | ||||
| @@ -3,9 +3,11 @@ import { LimitOrderFields } from '@0x/protocol-utils'; | ||||
| import { BigNumber, logUtils } from '@0x/utils'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { AaveV2Sampler } from '../../noop_samplers/AaveV2Sampler'; | ||||
| import { SamplerCallResult, SignedNativeOrder } from '../../types'; | ||||
| import { ERC20BridgeSamplerContract } from '../../wrappers'; | ||||
|  | ||||
| import { AaveV2ReservesCache } from './aave_reserves_cache'; | ||||
| import { BancorService } from './bancor_service'; | ||||
| import { | ||||
|     getCurveLikeInfosForPair, | ||||
| @@ -17,9 +19,14 @@ import { | ||||
|     isValidAddress, | ||||
|     uniswapV2LikeRouterAddress, | ||||
| } from './bridge_source_utils'; | ||||
| import { CompoundCTokenCache } from './compound_ctoken_cache'; | ||||
| import { | ||||
|     AAVE_V2_SUBGRAPH_URL_BY_CHAIN_ID, | ||||
|     BALANCER_V2_VAULT_ADDRESS_BY_CHAIN, | ||||
|     BANCOR_REGISTRY_BY_CHAIN_ID, | ||||
|     BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN, | ||||
|     BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN, | ||||
|     COMPOUND_API_URL_BY_CHAIN_ID, | ||||
|     DODOV1_CONFIG_BY_CHAIN_ID, | ||||
|     DODOV2_FACTORIES_BY_CHAIN_ID, | ||||
|     KYBER_CONFIG_BY_CHAIN_ID, | ||||
| @@ -43,13 +50,17 @@ import { getLiquidityProvidersForPair } from './liquidity_provider_utils'; | ||||
| import { getIntermediateTokens } from './multihop_utils'; | ||||
| import { BalancerPoolsCache, BalancerV2PoolsCache, CreamPoolsCache, PoolsCache } from './pools_cache'; | ||||
| import { SamplerContractOperation } from './sampler_contract_operation'; | ||||
| import { SamplerNoOperation } from './sampler_no_operation'; | ||||
| import { SourceFilters } from './source_filters'; | ||||
| import { | ||||
|     AaveV2FillData, | ||||
|     AaveV2Info, | ||||
|     BalancerFillData, | ||||
|     BalancerV2FillData, | ||||
|     BalancerV2PoolInfo, | ||||
|     BancorFillData, | ||||
|     BatchedOperation, | ||||
|     CompoundFillData, | ||||
|     CurveFillData, | ||||
|     CurveInfo, | ||||
|     DexSample, | ||||
| @@ -97,6 +108,8 @@ export const BATCH_SOURCE_FILTERS = SourceFilters.all().exclude([ERC20BridgeSour | ||||
| export class SamplerOperations { | ||||
|     public readonly liquidityProviderRegistry: LiquidityProviderRegistry; | ||||
|     public readonly poolsCaches: { [key in SourcesWithPoolsCache]: PoolsCache }; | ||||
|     public readonly aaveReservesCache: AaveV2ReservesCache | undefined; | ||||
|     public readonly compoundCTokenCache: CompoundCTokenCache | undefined; | ||||
|     protected _bancorService?: BancorService; | ||||
|     public static constant<T>(result: T): BatchedOperation<T> { | ||||
|         return { | ||||
| @@ -122,9 +135,26 @@ export class SamplerOperations { | ||||
|             ? poolsCaches | ||||
|             : { | ||||
|                   [ERC20BridgeSource.BalancerV2]: new BalancerV2PoolsCache(chainId), | ||||
|                   [ERC20BridgeSource.Beethovenx]: new BalancerV2PoolsCache( | ||||
|                       chainId, | ||||
|                       BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN[chainId], | ||||
|                   ), | ||||
|                   [ERC20BridgeSource.Balancer]: new BalancerPoolsCache(), | ||||
|                   [ERC20BridgeSource.Cream]: new CreamPoolsCache(), | ||||
|               }; | ||||
|  | ||||
|         const aaveSubgraphUrl = AAVE_V2_SUBGRAPH_URL_BY_CHAIN_ID[chainId]; | ||||
|         if (aaveSubgraphUrl) { | ||||
|             this.aaveReservesCache = new AaveV2ReservesCache(aaveSubgraphUrl); | ||||
|         } | ||||
|  | ||||
|         const compoundApiUrl = COMPOUND_API_URL_BY_CHAIN_ID[chainId]; | ||||
|         if (compoundApiUrl) { | ||||
|             this.compoundCTokenCache = new CompoundCTokenCache( | ||||
|                 compoundApiUrl, | ||||
|                 NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId], | ||||
|             ); | ||||
|         } | ||||
|         // Initialize the Bancor service, fetching paths in the background | ||||
|         bancorServiceFn() | ||||
|             .then(service => (this._bancorService = service)) | ||||
| @@ -152,6 +182,30 @@ export class SamplerOperations { | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     public getGasLeft(): BatchedOperation<BigNumber> { | ||||
|         return { | ||||
|             encodeCall: () => this._samplerContract.getGasLeft().getABIEncodedTransactionData(), | ||||
|             handleCallResults: (callResults: string) => | ||||
|                 this._samplerContract.getABIDecodedReturnData<BigNumber>('getGasLeft', callResults), | ||||
|             handleRevert: () => { | ||||
|                 /* should never happen */ | ||||
|                 throw new Error('Invalid result for getGasLeft'); | ||||
|             }, | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     public getBlockNumber(): BatchedOperation<BigNumber> { | ||||
|         return { | ||||
|             encodeCall: () => this._samplerContract.getBlockNumber().getABIEncodedTransactionData(), | ||||
|             handleCallResults: (callResults: string) => | ||||
|                 this._samplerContract.getABIDecodedReturnData<BigNumber>('getBlockNumber', callResults), | ||||
|             handleRevert: () => { | ||||
|                 /* should never happen */ | ||||
|                 throw new Error('Invalid result for getBlockNumber'); | ||||
|             }, | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     public getLimitOrderFillableTakerAmounts( | ||||
|         orders: SignedNativeOrder[], | ||||
|         exchangeAddress: string, | ||||
| @@ -1069,6 +1123,64 @@ export class SamplerOperations { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     // tslint:disable-next-line:prefer-function-over-method | ||||
|     public getAaveV2SellQuotes( | ||||
|         aaveInfo: AaveV2Info, | ||||
|         makerToken: string, | ||||
|         takerToken: string, | ||||
|         takerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<AaveV2FillData> { | ||||
|         return new SamplerNoOperation({ | ||||
|             source: ERC20BridgeSource.AaveV2, | ||||
|             fillData: { ...aaveInfo, takerToken }, | ||||
|             callback: () => AaveV2Sampler.sampleSellsFromAaveV2(aaveInfo, takerToken, makerToken, takerFillAmounts), | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     // tslint:disable-next-line:prefer-function-over-method | ||||
|     public getAaveV2BuyQuotes( | ||||
|         aaveInfo: AaveV2Info, | ||||
|         makerToken: string, | ||||
|         takerToken: string, | ||||
|         makerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<AaveV2FillData> { | ||||
|         return new SamplerNoOperation({ | ||||
|             source: ERC20BridgeSource.AaveV2, | ||||
|             fillData: { ...aaveInfo, takerToken }, | ||||
|             callback: () => AaveV2Sampler.sampleBuysFromAaveV2(aaveInfo, takerToken, makerToken, makerFillAmounts), | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getCompoundSellQuotes( | ||||
|         cToken: string, | ||||
|         makerToken: string, | ||||
|         takerToken: string, | ||||
|         takerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<CompoundFillData> { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.Compound, | ||||
|             fillData: { cToken, takerToken, makerToken }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleSellsFromCompound, | ||||
|             params: [cToken, takerToken, makerToken, takerFillAmounts], | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getCompoundBuyQuotes( | ||||
|         cToken: string, | ||||
|         makerToken: string, | ||||
|         takerToken: string, | ||||
|         makerFillAmounts: BigNumber[], | ||||
|     ): SourceQuoteOperation<CompoundFillData> { | ||||
|         return new SamplerContractOperation({ | ||||
|             source: ERC20BridgeSource.Compound, | ||||
|             fillData: { cToken, takerToken, makerToken }, | ||||
|             contract: this._samplerContract, | ||||
|             function: this._samplerContract.sampleBuysFromCompound, | ||||
|             params: [cToken, takerToken, makerToken, makerFillAmounts], | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public getMedianSellRate( | ||||
|         sources: ERC20BridgeSource[], | ||||
|         makerToken: string, | ||||
| @@ -1200,6 +1312,7 @@ export class SamplerOperations { | ||||
|                     case ERC20BridgeSource.UbeSwap: | ||||
|                     case ERC20BridgeSource.SpiritSwap: | ||||
|                     case ERC20BridgeSource.SpookySwap: | ||||
|                     case ERC20BridgeSource.MorpheusSwap: | ||||
|                         const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source); | ||||
|                         if (!isValidAddress(uniLikeRouter)) { | ||||
|                             return []; | ||||
| @@ -1301,13 +1414,14 @@ export class SamplerOperations { | ||||
|                             ), | ||||
|                         ); | ||||
|                     case ERC20BridgeSource.BalancerV2: | ||||
|                     case ERC20BridgeSource.Beethovenx: | ||||
|                         const poolIds = | ||||
|                             this.poolsCaches[ERC20BridgeSource.BalancerV2].getCachedPoolAddressesForPair( | ||||
|                                 takerToken, | ||||
|                                 makerToken, | ||||
|                             ) || []; | ||||
|                             this.poolsCaches[source].getCachedPoolAddressesForPair(takerToken, makerToken) || []; | ||||
|  | ||||
|                         const vault = BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId]; | ||||
|                         const vault = | ||||
|                             source === ERC20BridgeSource.BalancerV2 | ||||
|                                 ? BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId] | ||||
|                                 : BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId]; | ||||
|                         if (vault === NULL_ADDRESS) { | ||||
|                             return []; | ||||
|                         } | ||||
| @@ -1317,10 +1431,9 @@ export class SamplerOperations { | ||||
|                                 makerToken, | ||||
|                                 takerToken, | ||||
|                                 takerFillAmounts, | ||||
|                                 ERC20BridgeSource.BalancerV2, | ||||
|                                 source, | ||||
|                             ), | ||||
|                         ); | ||||
|  | ||||
|                     case ERC20BridgeSource.Cream: | ||||
|                         return ( | ||||
|                             this.poolsCaches[ERC20BridgeSource.Cream].getCachedPoolAddressesForPair( | ||||
| @@ -1418,6 +1531,38 @@ export class SamplerOperations { | ||||
|  | ||||
|                         return this.getLidoSellQuotes(lidoInfo, makerToken, takerToken, takerFillAmounts); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.AaveV2: { | ||||
|                         if (!this.aaveReservesCache) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         const reserve = this.aaveReservesCache.get(takerToken, makerToken); | ||||
|                         if (!reserve) { | ||||
|                             return []; | ||||
|                         } | ||||
|  | ||||
|                         const info: AaveV2Info = { | ||||
|                             lendingPool: reserve.pool.lendingPool, | ||||
|                             aToken: reserve.aToken.id, | ||||
|                             underlyingToken: reserve.underlyingAsset, | ||||
|                         }; | ||||
|                         return this.getAaveV2SellQuotes(info, makerToken, takerToken, takerFillAmounts); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Compound: { | ||||
|                         if (!this.compoundCTokenCache) { | ||||
|                             return []; | ||||
|                         } | ||||
|  | ||||
|                         const cToken = this.compoundCTokenCache.get(takerToken, makerToken); | ||||
|                         if (!cToken) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         return this.getCompoundSellQuotes( | ||||
|                             cToken.tokenAddress, | ||||
|                             makerToken, | ||||
|                             takerToken, | ||||
|                             takerFillAmounts, | ||||
|                         ); | ||||
|                     } | ||||
|                     default: | ||||
|                         throw new Error(`Unsupported sell sample source: ${source}`); | ||||
|                 } | ||||
| @@ -1472,6 +1617,7 @@ export class SamplerOperations { | ||||
|                     case ERC20BridgeSource.UbeSwap: | ||||
|                     case ERC20BridgeSource.SpiritSwap: | ||||
|                     case ERC20BridgeSource.SpookySwap: | ||||
|                     case ERC20BridgeSource.MorpheusSwap: | ||||
|                         const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source); | ||||
|                         if (!isValidAddress(uniLikeRouter)) { | ||||
|                             return []; | ||||
| @@ -1573,13 +1719,14 @@ export class SamplerOperations { | ||||
|                             ), | ||||
|                         ); | ||||
|                     case ERC20BridgeSource.BalancerV2: | ||||
|                     case ERC20BridgeSource.Beethovenx: | ||||
|                         const poolIds = | ||||
|                             this.poolsCaches[ERC20BridgeSource.BalancerV2].getCachedPoolAddressesForPair( | ||||
|                                 takerToken, | ||||
|                                 makerToken, | ||||
|                             ) || []; | ||||
|                             this.poolsCaches[source].getCachedPoolAddressesForPair(takerToken, makerToken) || []; | ||||
|  | ||||
|                         const vault = BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId]; | ||||
|                         const vault = | ||||
|                             source === ERC20BridgeSource.BalancerV2 | ||||
|                                 ? BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId] | ||||
|                                 : BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId]; | ||||
|                         if (vault === NULL_ADDRESS) { | ||||
|                             return []; | ||||
|                         } | ||||
| @@ -1589,7 +1736,7 @@ export class SamplerOperations { | ||||
|                                 makerToken, | ||||
|                                 takerToken, | ||||
|                                 makerFillAmounts, | ||||
|                                 ERC20BridgeSource.BalancerV2, | ||||
|                                 source, | ||||
|                             ), | ||||
|                         ); | ||||
|                     case ERC20BridgeSource.Cream: | ||||
| @@ -1685,6 +1832,32 @@ export class SamplerOperations { | ||||
|  | ||||
|                         return this.getLidoBuyQuotes(lidoInfo, makerToken, takerToken, makerFillAmounts); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.AaveV2: { | ||||
|                         if (!this.aaveReservesCache) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         const reserve = this.aaveReservesCache.get(takerToken, makerToken); | ||||
|                         if (!reserve) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         const info: AaveV2Info = { | ||||
|                             lendingPool: reserve.pool.lendingPool, | ||||
|                             aToken: reserve.aToken.id, | ||||
|                             underlyingToken: reserve.underlyingAsset, | ||||
|                         }; | ||||
|                         return this.getAaveV2BuyQuotes(info, makerToken, takerToken, makerFillAmounts); | ||||
|                     } | ||||
|                     case ERC20BridgeSource.Compound: { | ||||
|                         if (!this.compoundCTokenCache) { | ||||
|                             return []; | ||||
|                         } | ||||
|  | ||||
|                         const cToken = this.compoundCTokenCache.get(takerToken, makerToken); | ||||
|                         if (!cToken) { | ||||
|                             return []; | ||||
|                         } | ||||
|                         return this.getCompoundBuyQuotes(cToken.tokenAddress, makerToken, takerToken, makerFillAmounts); | ||||
|                     } | ||||
|                     default: | ||||
|                         throw new Error(`Unsupported buy sample source: ${source}`); | ||||
|                 } | ||||
|   | ||||
| @@ -68,6 +68,8 @@ export enum ERC20BridgeSource { | ||||
|     CurveV2 = 'Curve_V2', | ||||
|     Lido = 'Lido', | ||||
|     ShibaSwap = 'ShibaSwap', | ||||
|     AaveV2 = 'Aave_V2', | ||||
|     Compound = 'Compound', | ||||
|     // BSC only | ||||
|     PancakeSwap = 'PancakeSwap', | ||||
|     PancakeSwapV2 = 'PancakeSwap_V2', | ||||
| @@ -97,8 +99,14 @@ export enum ERC20BridgeSource { | ||||
|     // Fantom | ||||
|     SpiritSwap = 'SpiritSwap', | ||||
|     SpookySwap = 'SpookySwap', | ||||
|     Beethovenx = 'Beethovenx', | ||||
|     MorpheusSwap = 'MorpheusSwap', | ||||
| } | ||||
| export type SourcesWithPoolsCache = ERC20BridgeSource.Balancer | ERC20BridgeSource.BalancerV2 | ERC20BridgeSource.Cream; | ||||
| export type SourcesWithPoolsCache = | ||||
|     | ERC20BridgeSource.Balancer | ||||
|     | ERC20BridgeSource.BalancerV2 | ||||
|     | ERC20BridgeSource.Beethovenx | ||||
|     | ERC20BridgeSource.Cream; | ||||
|  | ||||
| // tslint:disable: enum-naming | ||||
| /** | ||||
| @@ -110,8 +118,10 @@ export enum CurveFunctionSelectors { | ||||
|     exchange_underlying = '0xa6417ed6', | ||||
|     get_dy_underlying = '0x07211ef7', | ||||
|     get_dx_underlying = '0x0e71d1b9', | ||||
|     get_dy = '0x5e0d443f', | ||||
|     get_dy = '0x5e0d443f', // get_dy(int128,int128,uint256) | ||||
|     get_dx = '0x67df02ca', | ||||
|     get_dy_uint256 = '0x556d6e9f', // get_dy(uint256,uint256,uint256) | ||||
|     exchange_underlying_uint256 = '0x65b2489b', // exchange_underlying(uint256,uint256,uint256,uint256) | ||||
|     // Curve V2 | ||||
|     exchange_v2 = '0x5b41b908', | ||||
|     exchange_underlying_v2 = '0x65b2489b', | ||||
| @@ -164,6 +174,12 @@ export interface BalancerV2PoolInfo { | ||||
|     vault: string; | ||||
| } | ||||
|  | ||||
| export interface AaveV2Info { | ||||
|     lendingPool: string; | ||||
|     aToken: string; | ||||
|     underlyingToken: string; | ||||
| } | ||||
|  | ||||
| // Internal `fillData` field for `Fill` objects. | ||||
| export interface FillData {} | ||||
|  | ||||
| @@ -271,6 +287,19 @@ export interface LidoFillData extends FillData { | ||||
|     takerToken: string; | ||||
| } | ||||
|  | ||||
| export interface AaveV2FillData extends FillData { | ||||
|     lendingPool: string; | ||||
|     aToken: string; | ||||
|     underlyingToken: string; | ||||
|     takerToken: string; | ||||
| } | ||||
|  | ||||
| export interface CompoundFillData extends FillData { | ||||
|     cToken: string; | ||||
|     takerToken: string; | ||||
|     makerToken: string; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Represents a node on a fill path. | ||||
|  */ | ||||
| @@ -463,6 +492,28 @@ export interface GetMarketOrdersOpts { | ||||
|      * Gas price to use for quote | ||||
|      */ | ||||
|     gasPrice: BigNumber; | ||||
|  | ||||
|     /** | ||||
|      * Sampler metrics for recording data on the sampler service and operations | ||||
|      */ | ||||
|     samplerMetrics?: SamplerMetrics; | ||||
| } | ||||
|  | ||||
| export interface SamplerMetrics { | ||||
|     /** | ||||
|      * Logs the gas information performed during a sampler call. | ||||
|      * | ||||
|      * @param data.gasBefore The gas remaining measured before any operations have been performed | ||||
|      * @param data.gasAfter The gas remaining measured after all operations have been performed | ||||
|      */ | ||||
|     logGasDetails(data: { gasBefore: BigNumber; gasAfter: BigNumber }): void; | ||||
|  | ||||
|     /** | ||||
|      * Logs the block number | ||||
|      * | ||||
|      * @param blockNumber block number of the sampler call | ||||
|      */ | ||||
|     logBlockNumber(blockNumber: BigNumber): void; | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import * as BalanceChecker from '../test/generated-artifacts/BalanceChecker.json | ||||
| import * as BalancerSampler from '../test/generated-artifacts/BalancerSampler.json'; | ||||
| import * as BalancerV2Sampler from '../test/generated-artifacts/BalancerV2Sampler.json'; | ||||
| import * as BancorSampler from '../test/generated-artifacts/BancorSampler.json'; | ||||
| import * as CompoundSampler from '../test/generated-artifacts/CompoundSampler.json'; | ||||
| import * as CurveSampler from '../test/generated-artifacts/CurveSampler.json'; | ||||
| import * as DODOSampler from '../test/generated-artifacts/DODOSampler.json'; | ||||
| import * as DODOV2Sampler from '../test/generated-artifacts/DODOV2Sampler.json'; | ||||
| @@ -52,6 +53,7 @@ export const artifacts = { | ||||
|     BalancerSampler: BalancerSampler as ContractArtifact, | ||||
|     BalancerV2Sampler: BalancerV2Sampler as ContractArtifact, | ||||
|     BancorSampler: BancorSampler as ContractArtifact, | ||||
|     CompoundSampler: CompoundSampler as ContractArtifact, | ||||
|     CurveSampler: CurveSampler as ContractArtifact, | ||||
|     DODOSampler: DODOSampler as ContractArtifact, | ||||
|     DODOV2Sampler: DODOV2Sampler as ContractArtifact, | ||||
|   | ||||
| @@ -23,6 +23,7 @@ import { | ||||
|     POSITIVE_INF, | ||||
|     SELL_SOURCE_FILTER_BY_CHAIN_ID, | ||||
|     SOURCE_FLAGS, | ||||
|     ZERO_AMOUNT, | ||||
| } from '../src/utils/market_operation_utils/constants'; | ||||
| import { createFills } from '../src/utils/market_operation_utils/fills'; | ||||
| import { PoolsCache } from '../src/utils/market_operation_utils/pools_cache'; | ||||
| @@ -427,6 +428,8 @@ describe('MarketOperationUtils tests', () => { | ||||
|         getTwoHopSellQuotes: (..._params: any[]) => [], | ||||
|         getTwoHopBuyQuotes: (..._params: any[]) => [], | ||||
|         isAddressContract: (..._params: any[]) => false, | ||||
|         getGasLeft: () => ZERO_AMOUNT, | ||||
|         getBlockNumber: () => ZERO_AMOUNT, | ||||
|     }; | ||||
|  | ||||
|     const MOCK_SAMPLER = ({ | ||||
|   | ||||
| @@ -8,6 +8,7 @@ export * from '../test/generated-wrappers/balance_checker'; | ||||
| export * from '../test/generated-wrappers/balancer_sampler'; | ||||
| export * from '../test/generated-wrappers/balancer_v2_sampler'; | ||||
| export * from '../test/generated-wrappers/bancor_sampler'; | ||||
| export * from '../test/generated-wrappers/compound_sampler'; | ||||
| export * from '../test/generated-wrappers/curve_sampler'; | ||||
| export * from '../test/generated-wrappers/d_o_d_o_sampler'; | ||||
| export * from '../test/generated-wrappers/d_o_d_o_v2_sampler'; | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|         "test/generated-artifacts/BalancerSampler.json", | ||||
|         "test/generated-artifacts/BalancerV2Sampler.json", | ||||
|         "test/generated-artifacts/BancorSampler.json", | ||||
|         "test/generated-artifacts/CompoundSampler.json", | ||||
|         "test/generated-artifacts/CurveSampler.json", | ||||
|         "test/generated-artifacts/DODOSampler.json", | ||||
|         "test/generated-artifacts/DODOV2Sampler.json", | ||||
|   | ||||
| @@ -1,4 +1,14 @@ | ||||
| [ | ||||
|     { | ||||
|         "version": "6.10.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add Aave supported FQT addresses for Polygon, Avalanche", | ||||
|                 "pr": 321 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1638390144 | ||||
|     }, | ||||
|     { | ||||
|         "version": "6.9.0", | ||||
|         "changes": [ | ||||
|   | ||||
| @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v6.10.0 - _December 1, 2021_ | ||||
|  | ||||
|     * Add Aave supported FQT addresses for Polygon, Avalanche (#321) | ||||
|  | ||||
| ## v6.9.0 - _November 16, 2021_ | ||||
|  | ||||
|     * Add Celo addresses (#368) | ||||
|   | ||||
| @@ -289,7 +289,7 @@ | ||||
|             "wethTransformer": "0xe309d011cc6f189a3e8dcba85922715a019fed38", | ||||
|             "payTakerTransformer": "0x5ba7b9be86cda01cfbf56e0fb97184783be9dda1", | ||||
|             "affiliateFeeTransformer": "0xbed27284b42e5684e987169cf1da09c5d6c49fa8", | ||||
|             "fillQuoteTransformer": "0xf708d512b8a82e2862543a630403327174410baf", | ||||
|             "fillQuoteTransformer": "0xd3afdf4a8ea9183e76c9c2306cda03ea4afffea5", | ||||
|             "positiveSlippageFeeTransformer": "0x4cd8f1c0df4d40fcc1e073845d5f6f4ed5cc8dab" | ||||
|         } | ||||
|     }, | ||||
| @@ -373,7 +373,7 @@ | ||||
|             "wethTransformer": "0x9b8b52391071d71cd4ad1e61d7f273268fa34c6c", | ||||
|             "payTakerTransformer": "0x898c6fde239d646c73f0a57e3570b6f86a3d62a3", | ||||
|             "affiliateFeeTransformer": "0x34617b855411e52fbc05899435f44cbd0503022c", | ||||
|             "fillQuoteTransformer": "0x8a5417dd7ffde61ec61e11b45797e16686e1d6b9", | ||||
|             "fillQuoteTransformer": "0xd421f50b3ae27f223aa35a04944236d257235412", | ||||
|             "positiveSlippageFeeTransformer": "0x470ba89da18a6db6e8a0567b3c9214b960861857" | ||||
|         } | ||||
|     }, | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contract-addresses", | ||||
|     "version": "6.9.0", | ||||
|     "version": "6.10.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
|   | ||||
| @@ -1,4 +1,13 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1638390144, | ||||
|         "version": "13.18.4", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1637102971, | ||||
|         "version": "13.18.3", | ||||
|   | ||||
| @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v13.18.4 - _December 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v13.18.3 - _November 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contract-wrappers", | ||||
|     "version": "13.18.3", | ||||
|     "version": "13.18.4", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -57,7 +57,7 @@ | ||||
|     "dependencies": { | ||||
|         "@0x/assert": "^3.0.29", | ||||
|         "@0x/base-contract": "^6.4.2", | ||||
|         "@0x/contract-addresses": "^6.9.0", | ||||
|         "@0x/contract-addresses": "^6.10.0", | ||||
|         "@0x/json-schemas": "^6.3.0", | ||||
|         "@0x/types": "^3.3.4", | ||||
|         "@0x/utils": "^6.4.4", | ||||
|   | ||||
| @@ -1,4 +1,13 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1638390144, | ||||
|         "version": "8.1.13", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1637102971, | ||||
|         "version": "8.1.12", | ||||
|   | ||||
| @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v8.1.13 - _December 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v8.1.12 - _November 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/migrations", | ||||
|     "version": "8.1.12", | ||||
|     "version": "8.1.13", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -68,20 +68,20 @@ | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.4.2", | ||||
|         "@0x/contract-addresses": "^6.9.0", | ||||
|         "@0x/contract-addresses": "^6.10.0", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.19", | ||||
|         "@0x/contracts-coordinator": "^3.1.38", | ||||
|         "@0x/contracts-dev-utils": "^1.3.36", | ||||
|         "@0x/contracts-erc1155": "^2.1.37", | ||||
|         "@0x/contracts-erc20": "^3.3.23", | ||||
|         "@0x/contracts-erc20": "^3.3.24", | ||||
|         "@0x/contracts-erc721": "^3.1.37", | ||||
|         "@0x/contracts-exchange": "^3.2.38", | ||||
|         "@0x/contracts-exchange-forwarder": "^4.2.38", | ||||
|         "@0x/contracts-extensions": "^6.2.32", | ||||
|         "@0x/contracts-multisig": "^4.1.38", | ||||
|         "@0x/contracts-staking": "^2.0.45", | ||||
|         "@0x/contracts-utils": "^4.8.4", | ||||
|         "@0x/contracts-zero-ex": "^0.29.5", | ||||
|         "@0x/contracts-utils": "^4.8.5", | ||||
|         "@0x/contracts-zero-ex": "^0.30.0", | ||||
|         "@0x/sol-compiler": "^4.7.5", | ||||
|         "@0x/subproviders": "^6.6.0", | ||||
|         "@0x/typescript-typings": "^5.2.1", | ||||
|   | ||||
| @@ -1,4 +1,14 @@ | ||||
| [ | ||||
|     { | ||||
|         "version": "1.10.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add `AaveV2` and `Compound` deposit/withdrawal liquidity source", | ||||
|                 "pr": 321 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1638390144 | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1637102971, | ||||
|         "version": "1.9.5", | ||||
|   | ||||
| @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v1.10.0 - _December 1, 2021_ | ||||
|  | ||||
|     * Add `AaveV2` and `Compound` deposit/withdrawal liquidity source (#321) | ||||
|  | ||||
| ## v1.9.5 - _November 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/protocol-utils", | ||||
|     "version": "1.9.5", | ||||
|     "version": "1.10.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -63,8 +63,8 @@ | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/assert": "^3.0.29", | ||||
|         "@0x/contract-addresses": "^6.9.0", | ||||
|         "@0x/contract-wrappers": "^13.18.3", | ||||
|         "@0x/contract-addresses": "^6.10.0", | ||||
|         "@0x/contract-wrappers": "^13.18.4", | ||||
|         "@0x/json-schemas": "^6.3.0", | ||||
|         "@0x/subproviders": "^6.6.0", | ||||
|         "@0x/utils": "^6.4.4", | ||||
|   | ||||
| @@ -132,6 +132,8 @@ export enum BridgeProtocol { | ||||
|     CurveV2, | ||||
|     Lido, | ||||
|     Clipper, // Not used: Clipper is now using PLP interface | ||||
|     AaveV2, | ||||
|     Compound, | ||||
| } | ||||
| // tslint:enable: enum-naming | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user