2020-10-28 14:41:31 +00:00
|
|
|
// SPDX-License-Identifier: agpl-3.0
|
2020-11-20 10:45:20 +00:00
|
|
|
pragma solidity 0.6.12;
|
2020-10-28 17:06:24 +00:00
|
|
|
pragma experimental ABIEncoderV2;
|
2020-10-28 14:41:31 +00:00
|
|
|
|
2020-11-26 09:21:18 +00:00
|
|
|
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
|
|
|
|
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
2020-11-02 16:01:47 +00:00
|
|
|
import {IWETH} from './interfaces/IWETH.sol';
|
|
|
|
import {IWETHGateway} from './interfaces/IWETHGateway.sol';
|
2020-10-28 14:41:31 +00:00
|
|
|
import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
2020-11-26 09:21:18 +00:00
|
|
|
import {IAToken} from '../interfaces/IAToken.sol';
|
2020-11-23 10:28:57 +00:00
|
|
|
import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol';
|
|
|
|
import {UserConfiguration} from '../protocol/libraries/configuration/UserConfiguration.sol';
|
|
|
|
import {Helpers} from '../protocol/libraries/helpers/Helpers.sol';
|
2020-11-24 13:53:34 +00:00
|
|
|
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
|
2020-10-28 14:41:31 +00:00
|
|
|
|
2020-11-03 16:23:35 +00:00
|
|
|
contract WETHGateway is IWETHGateway, Ownable {
|
2020-11-24 15:17:27 +00:00
|
|
|
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
|
|
|
|
using UserConfiguration for DataTypes.UserConfigurationMap;
|
2020-10-28 14:41:31 +00:00
|
|
|
|
2020-11-03 16:23:35 +00:00
|
|
|
IWETH internal immutable WETH;
|
2020-10-28 14:41:31 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Sets the WETH address and the LendingPoolAddressesProvider address. Infinite approves lending pool.
|
2020-11-03 12:29:11 +00:00
|
|
|
* @param weth Address of the Wrapped Ether contract
|
2020-10-28 14:41:31 +00:00
|
|
|
**/
|
2021-02-22 11:30:26 +00:00
|
|
|
constructor(address weth) public {
|
2020-11-03 12:29:11 +00:00
|
|
|
WETH = IWETH(weth);
|
2021-02-22 11:30:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function authorizeLendingPool(address lendingPool) external onlyOwner {
|
|
|
|
WETH.approve(lendingPool, uint256(-1));
|
2020-10-28 14:41:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev deposits WETH into the reserve, using native ETH. A corresponding amount of the overlying asset (aTokens)
|
|
|
|
* is minted.
|
2021-02-22 12:23:52 +00:00
|
|
|
* @param lendingPool address of the targeted underlying lending pool
|
2020-10-28 14:41:31 +00:00
|
|
|
* @param onBehalfOf address of the user who will receive the aTokens representing the deposit
|
|
|
|
* @param referralCode integrators are assigned a referral code and can potentially receive rewards.
|
|
|
|
**/
|
2021-02-22 11:30:26 +00:00
|
|
|
function depositETH(
|
|
|
|
address lendingPool,
|
|
|
|
address onBehalfOf,
|
|
|
|
uint16 referralCode
|
|
|
|
) external payable override {
|
2020-10-28 14:41:31 +00:00
|
|
|
WETH.deposit{value: msg.value}();
|
2021-02-22 11:30:26 +00:00
|
|
|
ILendingPool(lendingPool).deposit(address(WETH), msg.value, onBehalfOf, referralCode);
|
2020-10-28 14:41:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev withdraws the WETH _reserves of msg.sender.
|
2021-02-22 12:23:52 +00:00
|
|
|
* @param lendingPool address of the targeted underlying lending pool
|
2020-11-03 12:29:11 +00:00
|
|
|
* @param amount amount of aWETH to withdraw and receive native ETH
|
|
|
|
* @param to address of the user who will receive native ETH
|
2020-10-28 14:41:31 +00:00
|
|
|
*/
|
2021-02-22 11:30:26 +00:00
|
|
|
function withdrawETH(
|
|
|
|
address lendingPool,
|
|
|
|
uint256 amount,
|
|
|
|
address to
|
|
|
|
) external override {
|
|
|
|
IAToken aWETH = IAToken(ILendingPool(lendingPool).getReserveData(address(WETH)).aTokenAddress);
|
2020-11-03 12:45:54 +00:00
|
|
|
uint256 userBalance = aWETH.balanceOf(msg.sender);
|
2020-10-28 14:41:31 +00:00
|
|
|
uint256 amountToWithdraw = amount;
|
|
|
|
|
|
|
|
// if amount is equal to uint(-1), the user wants to redeem everything
|
|
|
|
if (amount == type(uint256).max) {
|
|
|
|
amountToWithdraw = userBalance;
|
|
|
|
}
|
2020-11-03 12:45:54 +00:00
|
|
|
aWETH.transferFrom(msg.sender, address(this), amountToWithdraw);
|
2021-02-22 11:30:26 +00:00
|
|
|
ILendingPool(lendingPool).withdraw(address(WETH), amountToWithdraw, address(this));
|
2020-10-28 14:41:31 +00:00
|
|
|
WETH.withdraw(amountToWithdraw);
|
2020-11-03 16:23:35 +00:00
|
|
|
_safeTransferETH(to, amountToWithdraw);
|
2020-10-28 14:41:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-10-28 17:06:24 +00:00
|
|
|
* @dev repays a borrow on the WETH reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified).
|
2021-02-22 12:23:52 +00:00
|
|
|
* @param lendingPool address of the targeted underlying lending pool
|
2020-10-28 17:06:24 +00:00
|
|
|
* @param amount the amount to repay, or uint256(-1) if the user wants to repay everything
|
|
|
|
* @param rateMode the rate mode to repay
|
|
|
|
* @param onBehalfOf the address for which msg.sender is repaying
|
2020-10-28 14:41:31 +00:00
|
|
|
*/
|
|
|
|
function repayETH(
|
2021-02-22 11:30:26 +00:00
|
|
|
address lendingPool,
|
2020-10-28 14:41:31 +00:00
|
|
|
uint256 amount,
|
|
|
|
uint256 rateMode,
|
|
|
|
address onBehalfOf
|
2020-11-23 10:28:57 +00:00
|
|
|
) external payable override {
|
|
|
|
(uint256 stableDebt, uint256 variableDebt) =
|
2021-02-22 11:30:26 +00:00
|
|
|
Helpers.getUserCurrentDebtMemory(
|
|
|
|
onBehalfOf,
|
|
|
|
ILendingPool(lendingPool).getReserveData(address(WETH))
|
|
|
|
);
|
2020-10-28 14:41:31 +00:00
|
|
|
|
2020-11-23 10:28:57 +00:00
|
|
|
uint256 paybackAmount =
|
2020-11-24 13:53:34 +00:00
|
|
|
DataTypes.InterestRateMode(rateMode) == DataTypes.InterestRateMode.STABLE
|
2020-11-23 10:28:57 +00:00
|
|
|
? stableDebt
|
|
|
|
: variableDebt;
|
2020-10-28 14:41:31 +00:00
|
|
|
|
|
|
|
if (amount < paybackAmount) {
|
|
|
|
paybackAmount = amount;
|
|
|
|
}
|
|
|
|
require(msg.value >= paybackAmount, 'msg.value is less than repayment amount');
|
|
|
|
WETH.deposit{value: paybackAmount}();
|
2021-02-22 11:30:26 +00:00
|
|
|
ILendingPool(lendingPool).repay(address(WETH), msg.value, rateMode, onBehalfOf);
|
2020-10-28 14:41:31 +00:00
|
|
|
|
2020-10-28 17:06:24 +00:00
|
|
|
// refund remaining dust eth
|
2020-11-03 16:23:35 +00:00
|
|
|
if (msg.value > paybackAmount) _safeTransferETH(msg.sender, msg.value - paybackAmount);
|
2020-10-28 14:41:31 +00:00
|
|
|
}
|
|
|
|
|
2020-11-06 12:22:03 +00:00
|
|
|
/**
|
|
|
|
* @dev borrow WETH, unwraps to ETH and send both the ETH and DebtTokens to msg.sender, via `approveDelegation` and onBehalf argument in `LendingPool.borrow`.
|
2021-02-22 12:23:52 +00:00
|
|
|
* @param lendingPool address of the targeted underlying lending pool
|
2020-11-06 12:22:03 +00:00
|
|
|
* @param amount the amount of ETH to borrow
|
|
|
|
* @param interesRateMode the interest rate mode
|
|
|
|
* @param referralCode integrators are assigned a referral code and can potentially receive rewards
|
|
|
|
*/
|
|
|
|
function borrowETH(
|
2021-02-22 11:30:26 +00:00
|
|
|
address lendingPool,
|
2020-11-06 12:22:03 +00:00
|
|
|
uint256 amount,
|
|
|
|
uint256 interesRateMode,
|
|
|
|
uint16 referralCode
|
|
|
|
) external override {
|
2021-02-22 11:30:26 +00:00
|
|
|
ILendingPool(lendingPool).borrow(
|
|
|
|
address(WETH),
|
|
|
|
amount,
|
|
|
|
interesRateMode,
|
|
|
|
referralCode,
|
|
|
|
msg.sender
|
|
|
|
);
|
2020-11-06 12:22:03 +00:00
|
|
|
WETH.withdraw(amount);
|
|
|
|
_safeTransferETH(msg.sender, amount);
|
|
|
|
}
|
|
|
|
|
2020-10-28 17:06:24 +00:00
|
|
|
/**
|
|
|
|
* @dev transfer ETH to an address, revert if it fails.
|
|
|
|
* @param to recipient of the transfer
|
|
|
|
* @param value the amount to send
|
|
|
|
*/
|
2020-11-03 16:23:35 +00:00
|
|
|
function _safeTransferETH(address to, uint256 value) internal {
|
2020-10-28 14:41:31 +00:00
|
|
|
(bool success, ) = to.call{value: value}(new bytes(0));
|
|
|
|
require(success, 'ETH_TRANSFER_FAILED');
|
|
|
|
}
|
|
|
|
|
2020-11-03 16:23:35 +00:00
|
|
|
/**
|
|
|
|
* @dev transfer ERC20 from the utility contract, for ERC20 recovery in case of stuck tokens due
|
|
|
|
* direct transfers to the contract address.
|
|
|
|
* @param token token to transfer
|
|
|
|
* @param to recipient of the transfer
|
|
|
|
* @param amount amount to send
|
|
|
|
*/
|
|
|
|
function emergencyTokenTransfer(
|
|
|
|
address token,
|
|
|
|
address to,
|
|
|
|
uint256 amount
|
|
|
|
) external onlyOwner {
|
|
|
|
IERC20(token).transfer(to, amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev transfer native Ether from the utility contract, for native Ether recovery in case of stuck Ether
|
2020-11-03 19:47:36 +00:00
|
|
|
* due selfdestructs or transfer ether to pre-computated contract address before deployment.
|
2020-11-03 16:23:35 +00:00
|
|
|
* @param to recipient of the transfer
|
|
|
|
* @param amount amount to send
|
|
|
|
*/
|
|
|
|
function emergencyEtherTransfer(address to, uint256 amount) external onlyOwner {
|
|
|
|
_safeTransferETH(to, amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Get WETH address used by WETHGateway
|
|
|
|
*/
|
|
|
|
function getWETHAddress() external view returns (address) {
|
|
|
|
return address(WETH);
|
|
|
|
}
|
|
|
|
|
2020-10-28 14:41:31 +00:00
|
|
|
/**
|
|
|
|
* @dev Only WETH contract is allowed to transfer ETH here. Prevent other addresses to send Ether to this contract.
|
|
|
|
*/
|
|
|
|
receive() external payable {
|
2020-11-03 12:29:11 +00:00
|
|
|
require(msg.sender == address(WETH), 'Receive not allowed');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dev Revert fallback calls
|
|
|
|
*/
|
2020-11-03 12:51:10 +00:00
|
|
|
fallback() external payable {
|
2020-11-03 12:54:15 +00:00
|
|
|
revert('Fallback not allowed');
|
2020-10-28 14:41:31 +00:00
|
|
|
}
|
|
|
|
}
|