Compare commits

...

21 Commits

Author SHA1 Message Date
Github Actions
dcde12dd70 Publish
- @0x/contracts-erc20@3.3.24
 - @0x/contracts-test-utils@5.4.15
 - @0x/contracts-treasury@1.4.7
 - @0x/contracts-utils@4.8.5
 - @0x/contracts-zero-ex@0.30.0
 - @0x/asset-swapper@16.40.0
 - @0x/contract-addresses@6.10.0
 - @0x/contract-wrappers@13.18.4
 - @0x/migrations@8.1.13
 - @0x/protocol-utils@1.10.0
2021-12-01 20:22:43 +00:00
Github Actions
84a60ec982 Updated CHANGELOGS & MD docs 2021-12-01 20:22:39 +00:00
Kim Persson
9615570dc6 feat: deploy interest tokens (#321)
* feat: Aave aToken deposit/withdrawal [TKR-111] (#293)

* feat: AaveV2 deposit/withdrawal integration WIP

* feat: add basic Aave Reserves cache with data from subgraphs WIP

* feat: hook up Aave Reserves integration

* fix: set allowance before trade & use ERC20 token interface

* refactor: pass aToken to mixin to avoid lookup

* fix: migrate from swap/revert to normal sampling

* fix: Aave gas estimate & refactor to clean up code

* feat: Create a sampler no operation type and make AaveV2Sampler a no-op

* fix: Clipper merge conflict resolution issues

* fix: don't fetch unnecessary Aave pool data & clean up code

* chore: Add changelog entries

* feat: cToken deposit/withdrawal [TKR-222] (#294)

* feat: first stab at a CompoundSampler implementation

* feat: MixinCompound implementation WIP

* feat: Compound integration with cache WIP

* fix: decimals scaling in CompoundSampler

* feat: handle minting and redeeming of cETH

* fix: adjust Compound gas schedule

* refactor: clean up code and add comments in cToken cache

* fix: MixinCompound check allowance on WETH withdrawal & fix indentation

* fix: address review comments and clean up code

* chore: add changelog entries

* feat: enable AaveV2 on Avalanche

* chore: add freshly deployed FQT on Polygon, Avalanche

* fix: temporarily disable on Ethereum mainnet until we redeploy EP

* fix: address PR comments and update changelogs

* fix: correct contract-addresses changelog note
2021-12-01 17:10:22 +01:00
Jacob Evans
880a9c3da0 chore: Curve added ETH/CRV pool (#378) 2021-12-01 14:51:47 +10:00
Jacob Evans
c44bd9d42d Revert "chore: Curve added ETH/CRV pool"
This reverts commit 90b441330b.
2021-12-01 14:19:49 +10:00
Jacob Evans
90b441330b chore: Curve added ETH/CRV pool 2021-12-01 14:17:40 +10:00
Github Actions
e12ed1eddf Publish
- @0x/asset-swapper@16.38.0
2021-11-29 23:23:57 +00:00
Github Actions
ac94023ab3 Updated CHANGELOGS & MD docs 2021-11-29 23:23:54 +00:00
Jacob Evans
281e6acca5 chore: Add ability to capture sampler metrics (#374)
* chore: Add ability to capture sampler metrics

* Added block number metrics
2021-11-30 09:06:05 +10:00
Github Actions
2f1b520409 Publish
- @0x/asset-swapper@16.37.0
2021-11-19 19:15:43 +00:00
Github Actions
21b4eb3d26 Updated CHANGELOGS & MD docs 2021-11-19 19:15:40 +00:00
Noah Khamliche
644f6c7d28 removed comma 2021-11-19 13:46:57 -05:00
Noah Khamliche
0647b9e4f8 Update CHANGELOG.json 2021-11-19 13:46:57 -05:00
Noah Khamliche
82d42eeede address to lowercase 2021-11-19 13:46:57 -05:00
Noah Khamliche
6ef4d95043 Updated Sushiswap router on CELO
Sushi address in the docs was incorrect, this is the correct address `0x1421bDe4B10e8dd459b3BCb598810B1337D56842`.
2021-11-19 13:46:57 -05:00
Github Actions
6044140f86 Publish
- @0x/asset-swapper@16.36.0
2021-11-19 02:59:33 +00:00
Github Actions
4da1ef0f56 Updated CHANGELOGS & MD docs 2021-11-19 02:59:30 +00:00
Jacob Evans
8c668a3918 feat: Specify FEI/TRIBE liquid pool (#371)
* feat: Specify FEI/TRIBE liquid pool

* CHANGELOG

* FXS/FRAX and OHM/FRAX
2021-11-18 15:39:07 +10:00
Github Actions
f1ff1cde39 Publish
- @0x/asset-swapper@16.35.0
2021-11-18 03:31:36 +00:00
Github Actions
1668a24e31 Updated CHANGELOGS & MD docs 2021-11-18 03:31:32 +00:00
Shawn
4b7c376d96 feat: Add Beethoven X, MorpheusSwap and JetSwap on Fantom (#370)
* Rebase to development branch

* add support for MorpheusSwap and JetSwap on Fantom

* fix lint

* modify changelog.json for asset-swapper

* fix the comments

* prettier

* Use BalancerV2PoolsCache for BeethovenX

Co-authored-by: Romain Butteaud <romain.butteaud@gmail.com>
2021-11-17 19:14:01 -08:00
60 changed files with 1288 additions and 58 deletions

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1638390144,
"version": "3.3.24",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1637102971,
"version": "3.3.23",

View File

@@ -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

View File

@@ -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",

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1638390144,
"version": "5.4.15",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1637102971,
"version": "5.4.14",

View File

@@ -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

View File

@@ -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",

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1638390144,
"version": "1.4.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1637102971,
"version": "1.4.6",

View File

@@ -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

View File

@@ -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",

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1638390144,
"version": "4.8.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1637102971,
"version": "4.8.4",

View File

@@ -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

View File

@@ -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",

View File

@@ -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",

View File

@@ -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

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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");
}
}

View File

@@ -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);
}
}

View File

@@ -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",

View File

@@ -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,

View File

@@ -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';

View File

@@ -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",

View File

@@ -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": [

View File

@@ -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)

View 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;
}
}
}
}

View File

@@ -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,

View File

@@ -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;
}
}

View File

@@ -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",

View File

@@ -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

View File

@@ -113,6 +113,7 @@ export {
SwapQuoterError,
SwapQuoterOpts,
SwapQuoterRfqOpts,
SamplerMetrics,
} from './types';
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
export {

View 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;
}
}

View File

@@ -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';

View File

@@ -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;
}
}

View File

@@ -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:

View File

@@ -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;
}
}

View File

@@ -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 };

View File

@@ -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,

View File

@@ -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] {

View File

@@ -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.
*/

View File

@@ -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 [];
}
}

View File

@@ -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}`);
}

View File

@@ -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;
}
/**

View File

@@ -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,

View File

@@ -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 = ({

View File

@@ -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';

View File

@@ -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",

View File

@@ -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": [

View File

@@ -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)

View File

@@ -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"
}
},

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contract-addresses",
"version": "6.9.0",
"version": "6.10.0",
"engines": {
"node": ">=6.12"
},

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1638390144,
"version": "13.18.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1637102971,
"version": "13.18.3",

View File

@@ -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

View File

@@ -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",

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1638390144,
"version": "8.1.13",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1637102971,
"version": "8.1.12",

View File

@@ -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

View File

@@ -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",

View File

@@ -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",

View File

@@ -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

View File

@@ -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",

View File

@@ -132,6 +132,8 @@ export enum BridgeProtocol {
CurveV2,
Lido,
Clipper, // Not used: Clipper is now using PLP interface
AaveV2,
Compound,
}
// tslint:enable: enum-naming