feat: adding AAVE V3 to selected Bridge Adapters [TKR-659] (#624)

* adding AAVE V3 to selected Bridge Adapters

* prettier fix

* Adding L2 optimizations for Arbitrum and Optimism

* Adding l2 encoded parameters to Aave V3 MixIn

* Removing L2 Encoder interface from MixinAaveV3.sol

* Updating FQT addresses

* prettier fix for MixinAaveV3.sol
This commit is contained in:
Savarn Dontamsetti (Sav) 2022-11-23 15:09:18 -05:00 committed by GitHub
parent d31cc43ed6
commit 09bc48671c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 172 additions and 10 deletions

View File

@ -22,6 +22,7 @@ pragma experimental ABIEncoderV2;
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinAaveV3.sol";
import "./mixins/MixinBalancerV2.sol";
import "./mixins/MixinBalancerV2Batch.sol";
import "./mixins/MixinCurve.sol";
@ -36,6 +37,7 @@ import "./mixins/MixinZeroExBridge.sol";
contract ArbitrumBridgeAdapter is
AbstractBridgeAdapter(42161, "Arbitrum"),
MixinAaveV3,
MixinBalancerV2,
MixinBalancerV2Batch,
MixinCurve,
@ -48,7 +50,7 @@ contract ArbitrumBridgeAdapter is
MixinUniswapV2,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth) public MixinCurve(weth) {}
constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(true) {}
function _trade(
BridgeOrder memory order,
@ -113,6 +115,11 @@ contract ArbitrumBridgeAdapter is
return (0, true);
}
boughtAmount = _tradeZeroExBridge(sellToken, buyToken, sellAmount, order.bridgeData);
} else if (protocolId == BridgeProtocols.AAVEV3) {
if (dryRun) {
return (0, true);
}
boughtAmount = _tradeAaveV3(sellToken, buyToken, sellAmount, order.bridgeData);
}
emit BridgeFill(order.source, sellToken, buyToken, sellAmount, boughtAmount);

View File

@ -22,6 +22,7 @@ pragma experimental ABIEncoderV2;
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinAaveV3.sol";
import "./mixins/MixinCurve.sol";
import "./mixins/MixinCurveV2.sol";
import "./mixins/MixinGMX.sol";
@ -35,6 +36,7 @@ import "./mixins/MixinZeroExBridge.sol";
contract AvalancheBridgeAdapter is
AbstractBridgeAdapter(43114, "Avalanche"),
MixinAaveV3,
MixinCurve,
MixinCurveV2,
MixinGMX,
@ -46,7 +48,7 @@ contract AvalancheBridgeAdapter is
MixinWOOFi,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth) public MixinCurve(weth) {}
constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(false) {}
function _trade(
BridgeOrder memory order,
@ -106,6 +108,11 @@ contract AvalancheBridgeAdapter is
return (0, true);
}
boughtAmount = _tradeZeroExBridge(sellToken, buyToken, sellAmount, order.bridgeData);
} else if (protocolId == BridgeProtocols.AAVEV3) {
if (dryRun) {
return (0, true);
}
boughtAmount = _tradeAaveV3(sellToken, buyToken, sellAmount, order.bridgeData);
}
emit BridgeFill(order.source, sellToken, buyToken, sellAmount, boughtAmount);

View File

@ -58,4 +58,5 @@ library BridgeProtocols {
uint128 internal constant SOLIDLY = 29;
uint128 internal constant SYNTHETIX = 30;
uint128 internal constant WOOFI = 31;
uint128 internal constant AAVEV3 = 32;
}

View File

@ -22,6 +22,7 @@ pragma experimental ABIEncoderV2;
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinAaveV3.sol";
import "./mixins/MixinAaveV2.sol";
import "./mixins/MixinBalancerV2.sol";
import "./mixins/MixinBalancerV2Batch.sol";
@ -34,6 +35,7 @@ import "./mixins/MixinZeroExBridge.sol";
contract FantomBridgeAdapter is
AbstractBridgeAdapter(250, "Fantom"),
MixinAaveV3,
MixinAaveV2,
MixinBalancerV2,
MixinBalancerV2Batch,
@ -44,7 +46,7 @@ contract FantomBridgeAdapter is
MixinWOOFi,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth) public MixinCurve(weth) {}
constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(false) {}
function _trade(
BridgeOrder memory order,
@ -99,6 +101,11 @@ contract FantomBridgeAdapter is
return (0, true);
}
boughtAmount = _tradeZeroExBridge(sellToken, buyToken, sellAmount, order.bridgeData);
} else if (protocolId == BridgeProtocols.AAVEV3) {
if (dryRun) {
return (0, true);
}
boughtAmount = _tradeAaveV3(sellToken, buyToken, sellAmount, order.bridgeData);
}
emit BridgeFill(order.source, sellToken, buyToken, sellAmount, boughtAmount);

View File

@ -17,6 +17,7 @@ pragma experimental ABIEncoderV2;
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinAaveV3.sol";
import "./mixins/MixinBalancerV2.sol";
import "./mixins/MixinBalancerV2Batch.sol";
import "./mixins/MixinCurve.sol";
@ -29,6 +30,7 @@ import "./mixins/MixinZeroExBridge.sol";
contract OptimismBridgeAdapter is
AbstractBridgeAdapter(10, "Optimism"),
MixinAaveV3,
MixinBalancerV2,
MixinBalancerV2Batch,
MixinCurve,
@ -39,7 +41,7 @@ contract OptimismBridgeAdapter is
MixinSolidly,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth) public MixinCurve(weth) {}
constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(true) {}
function _trade(
BridgeOrder memory order,
@ -94,6 +96,11 @@ contract OptimismBridgeAdapter is
return (0, true);
}
boughtAmount = _tradeBalancerV2Batch(sellAmount, order.bridgeData);
} else if (protocolId == BridgeProtocols.AAVEV3) {
if (dryRun) {
return (0, true);
}
boughtAmount = _tradeAaveV3(sellToken, buyToken, sellAmount, order.bridgeData);
}
emit BridgeFill(order.source, sellToken, buyToken, sellAmount, boughtAmount);

View File

@ -22,6 +22,7 @@ pragma experimental ABIEncoderV2;
import "./AbstractBridgeAdapter.sol";
import "./BridgeProtocols.sol";
import "./mixins/MixinAaveV3.sol";
import "./mixins/MixinAaveV2.sol";
import "./mixins/MixinBalancerV2.sol";
import "./mixins/MixinBalancerV2Batch.sol";
@ -40,6 +41,7 @@ import "./mixins/MixinZeroExBridge.sol";
contract PolygonBridgeAdapter is
AbstractBridgeAdapter(137, "Polygon"),
MixinAaveV3,
MixinAaveV2,
MixinBalancerV2,
MixinBalancerV2Batch,
@ -56,7 +58,7 @@ contract PolygonBridgeAdapter is
MixinWOOFi,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth) public MixinCurve(weth) {}
constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(false) {}
function _trade(
BridgeOrder memory order,
@ -141,6 +143,11 @@ contract PolygonBridgeAdapter is
return (0, true);
}
boughtAmount = _tradeZeroExBridge(sellToken, buyToken, sellAmount, order.bridgeData);
} else if (protocolId == BridgeProtocols.AAVEV3) {
if (dryRun) {
return (0, true);
}
boughtAmount = _tradeAaveV3(sellToken, buyToken, sellAmount, order.bridgeData);
}
emit BridgeFill(order.source, sellToken, buyToken, sellAmount, boughtAmount);

View File

@ -0,0 +1,125 @@
// 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 V3 Pool interface
interface IPool {
/**
* @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User supplies 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @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 supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
/**
* @notice 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 The 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);
}
// Minimal Aave V3 L2Pool interface
interface IL2Pool {
/**
* @notice Calldata efficient wrapper of the supply function on behalf of the caller
* @param args Arguments for the supply function packed in one bytes32
* 96 bits 16 bits 128 bits 16 bits
* | 0-padding | referralCode | shortenedAmount | assetId |
* @dev the shortenedAmount is cast to 256 bits at decode time, if type(uint128).max the value will be expanded to
* type(uint256).max
* @dev assetId is the index of the asset in the reservesList.
*/
function supply(bytes32 args) external;
/**
* @notice Calldata efficient wrapper of the withdraw function, withdrawing to the caller
* @param args Arguments for the withdraw function packed in one bytes32
* 112 bits 128 bits 16 bits
* | 0-padding | shortenedAmount | assetId |
* @dev the shortenedAmount is cast to 256 bits at decode time, if type(uint128).max the value will be expanded to
* type(uint256).max
* @dev assetId is the index of the asset in the reservesList.
*/
function withdraw(bytes32 args) external;
}
contract MixinAaveV3 {
using LibERC20TokenV06 for IERC20TokenV06;
bool private immutable _isL2;
constructor(bool isL2) public {
_isL2 = isL2;
}
function _tradeAaveV3(
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
) internal returns (uint256) {
if (_isL2) {
(IL2Pool pool, address aToken, bytes32 l2Params) = abi.decode(bridgeData, (IL2Pool, address, bytes32));
sellToken.approveIfBelow(address(pool), sellAmount);
if (address(buyToken) == aToken) {
pool.supply(l2Params);
// 1:1 mapping token --> aToken and have the same number of decimals as the underlying token
return sellAmount;
} else if (address(sellToken) == aToken) {
pool.withdraw(l2Params);
return sellAmount;
}
revert("MixinAaveV3/UNSUPPORTED_TOKEN_PAIR");
}
(IPool pool, address aToken, ) = abi.decode(bridgeData, (IPool, address, bytes32));
sellToken.approveIfBelow(address(pool), sellAmount);
if (address(buyToken) == aToken) {
pool.supply(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 pool.withdraw(address(buyToken), sellAmount, address(this));
}
revert("MixinAaveV3/UNSUPPORTED_TOKEN_PAIR");
}
}

View File

@ -133,7 +133,7 @@
"wethTransformer": "0xe309d011cc6f189a3e8dcba85922715a019fed38",
"payTakerTransformer": "0xed8932ca083e1ef1960dea875a132926e6b242ab",
"affiliateFeeTransformer": "0xf79071e2f860d48a08fd7e091d4b126a1d757148",
"fillQuoteTransformer": "0x854a632299c4304992aa30f4f192308c86fd1e89",
"fillQuoteTransformer": "0xccb88bc39a49a83db492dc1701d8fd7b680f9015",
"positiveSlippageFeeTransformer": "0x8f5e7188f443a9a8dc180f4618fd23915043ea15"
}
},
@ -179,7 +179,7 @@
"wethTransformer": "0x9b8b52391071d71cd4ad1e61d7f273268fa34c6c",
"payTakerTransformer": "0xb9a4c32547bc3cdc2ee2fb13cc1a0717dac9888f",
"affiliateFeeTransformer": "0x105679f99d668001370b4621ad8648ac570c860f",
"fillQuoteTransformer": "0xcee9118bc14e1fe740c54c754b901629b322ee4f",
"fillQuoteTransformer": "0x40e9b95d4c389eb3e1f95b0ff1cc9d5e97d348dc",
"positiveSlippageFeeTransformer": "0xadbfdc58a24b6dbc16f21541800f43dd6e282250"
}
},
@ -202,7 +202,7 @@
"wethTransformer": "0x9b6aa8f26a92108e7d1f66373d757bb955112703",
"payTakerTransformer": "0x62d688337db92a916c7edbcc0f16c895510ab195",
"affiliateFeeTransformer": "0xb7da46e42472ecc7ae277e04a16c92bdd51a2db7",
"fillQuoteTransformer": "0x3a1e9825c9966daab30db241a7ee51a8dd7ad74f",
"fillQuoteTransformer": "0x28a4a63c74a7acd044c7edf4684232fb553baf66",
"positiveSlippageFeeTransformer": "0x42e30820804fc55d9cc03de613587947391550ff"
}
},
@ -248,7 +248,7 @@
"wethTransformer": "0x02ce7af6520e2862f961f5d7eda746642865179c",
"payTakerTransformer": "0xa6c3ca183a67fcb4299fb4199c12ca74874ca489",
"affiliateFeeTransformer": "0x3102aea537ecb6f164550b094663c82a8c53a972",
"fillQuoteTransformer": "0x845c75a791cceb1a451f4ca5778c011226dda95c",
"fillQuoteTransformer": "0x3f21d1ca2b1dd0744e8984f811d3dc251d2ff48d",
"positiveSlippageFeeTransformer": "0x9a4947d3fb77a7afc2c9cd6714bbae96dddde059"
}
},
@ -294,7 +294,7 @@
"wethTransformer": "0x10e968968f49dd66a5efeebbb2edcb9c49c4fc49",
"payTakerTransformer": "0xd81e65fc9bb7323bdbef8b2cdddd3b83fe41d630",
"affiliateFeeTransformer": "0x970e318b8f074c20bf0cee06970f01dc7a761e50",
"fillQuoteTransformer": "0x466b00a77662245c2cc7b093a7102a687afc16f3",
"fillQuoteTransformer": "0xaec6610c9069d6b7d604a5b0b3c1f6661489d0e1",
"positiveSlippageFeeTransformer": "0x20f935b037e8490d8027f2751f9452725eee01ad"
}
}

View File

@ -162,6 +162,7 @@ export enum BridgeProtocol {
Solidly,
Synthetix,
WOOFi,
AaveV3,
}
/**