feat: Lido StETH deposit integration [TKR-90] (#260)

* feat: initial stab at the LidoSampler and the MixinLido

* feat: full integration of lido sampler and mixin

* fix: return pooled Ether amount not shares & properly unwrap WETH

* refactor: clean up Lido sampler and data passing

* fix: lower gas schedule for WETH to stETH deposits

* refactor: remove MixinLido unused ETH code path

* chore: add changelog entries

* fix: lower Lido gas schedule slightly

* fix: revert MixinLido on unsupported token pair

* fix: address review comments, improve early exit if wrong tokens

* fix: add contract addresses to Lido FQT
This commit is contained in:
Kim Persson
2021-06-22 11:25:47 +02:00
committed by GitHub
parent aba9db2be7
commit 7580719586
22 changed files with 318 additions and 4 deletions

View File

@@ -33,6 +33,7 @@ import "./mixins/MixinDodo.sol";
import "./mixins/MixinDodoV2.sol";
import "./mixins/MixinKyber.sol";
import "./mixins/MixinKyberDmm.sol";
import "./mixins/MixinLido.sol";
import "./mixins/MixinMakerPSM.sol";
import "./mixins/MixinMooniswap.sol";
import "./mixins/MixinMStable.sol";
@@ -57,6 +58,7 @@ contract BridgeAdapter is
MixinDodoV2,
MixinKyber,
MixinKyberDmm,
MixinLido,
MixinMakerPSM,
MixinMooniswap,
MixinMStable,
@@ -80,6 +82,7 @@ contract BridgeAdapter is
MixinDodo()
MixinDodoV2()
MixinKyber(weth)
MixinLido(weth)
MixinMakerPSM()
MixinMooniswap(weth)
MixinMStable()
@@ -235,6 +238,13 @@ contract BridgeAdapter is
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.LIDO) {
boughtAmount = _tradeLido(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else {
boughtAmount = _tradeZeroExBridge(
sellToken,

View File

@@ -48,4 +48,5 @@ library BridgeProtocols {
uint128 internal constant UNISWAPV3 = 18;
uint128 internal constant KYBERDMM = 19;
uint128 internal constant CURVEV2 = 20;
uint128 internal constant LIDO = 21;
}

View File

@@ -0,0 +1,70 @@
// 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";
/// @dev Minimal interface for minting StETH
interface ILido {
/// @dev Adds eth to the pool
/// @param _referral optional address for referrals
/// @return StETH Amount of shares generated
function submit(address _referral) external payable returns (uint256 StETH);
/// @dev Retrieve the current pooled ETH representation of the shares amount
/// @param _sharesAmount amount of shares
/// @return amount of pooled ETH represented by the shares amount
function getPooledEthByShares(uint256 _sharesAmount) external view returns (uint256);
}
contract MixinLido {
using LibERC20TokenV06 for IERC20TokenV06;
using LibERC20TokenV06 for IEtherTokenV06;
IEtherTokenV06 private immutable WETH;
constructor(IEtherTokenV06 weth)
public
{
WETH = weth;
}
function _tradeLido(
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
(ILido lido) = abi.decode(bridgeData, (ILido));
if (address(sellToken) == address(WETH) && address(buyToken) == address(lido)) {
WETH.withdraw(sellAmount);
boughtAmount = lido.getPooledEthByShares(lido.submit{ value: sellAmount}(address(0)));
} else {
revert("MixinLido/UNSUPPORTED_TOKEN_PAIR");
}
}
}