aave-protocol-v2/contracts/misc/WETHGateway.sol

185 lines
6.5 KiB
Solidity
Raw Normal View History

2020-10-28 14:41:31 +00:00
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
2020-10-28 14:41:31 +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';
import {IAToken} from '../tokenization/interfaces/IAToken.sol';
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
import {Helpers} from '../libraries/helpers/Helpers.sol';
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
2020-10-28 14:41:31 +00:00
contract WETHGateway is IWETHGateway, Ownable {
2020-10-28 14:41:31 +00:00
using ReserveConfiguration for ReserveConfiguration.Map;
using UserConfiguration for UserConfiguration.Map;
IWETH internal immutable WETH;
ILendingPool internal immutable POOL;
IAToken internal immutable aWETH;
2020-10-28 14:41:31 +00:00
/**
* @dev Sets the WETH address and the LendingPoolAddressesProvider address. Infinite approves lending pool.
* @param weth Address of the Wrapped Ether contract
* @param pool Address of the LendingPool contract
2020-10-28 14:41:31 +00:00
**/
constructor(address weth, address pool) public {
2020-11-03 12:45:54 +00:00
ILendingPool poolInstance = ILendingPool(pool);
WETH = IWETH(weth);
2020-11-03 12:45:54 +00:00
POOL = poolInstance;
aWETH = IAToken(poolInstance.getReserveData(weth).aTokenAddress);
IWETH(weth).approve(pool, 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.
* @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.
**/
function depositETH(address onBehalfOf, uint16 referralCode) external override payable {
2020-10-28 14:41:31 +00:00
WETH.deposit{value: msg.value}();
POOL.deposit(address(WETH), msg.value, onBehalfOf, referralCode);
2020-10-28 14:41:31 +00:00
}
/**
* @dev withdraws the WETH _reserves of msg.sender.
* @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
*/
function withdrawETH(uint256 amount, address to) external override {
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);
POOL.withdraw(address(WETH), amountToWithdraw, address(this));
2020-10-28 14:41:31 +00:00
WETH.withdraw(amountToWithdraw);
_safeTransferETH(to, amountToWithdraw);
2020-10-28 14:41:31 +00:00
}
/**
* @dev repays a borrow on the WETH reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified).
* @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(
uint256 amount,
uint256 rateMode,
address onBehalfOf
) external override payable {
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebtMemory(
2020-10-28 14:41:31 +00:00
onBehalfOf,
POOL.getReserveData(address(WETH))
2020-10-28 14:41:31 +00:00
);
uint256 paybackAmount = ReserveLogic.InterestRateMode(rateMode) ==
ReserveLogic.InterestRateMode.STABLE
? stableDebt
: variableDebt;
if (amount < paybackAmount) {
paybackAmount = amount;
}
require(msg.value >= paybackAmount, 'msg.value is less than repayment amount');
WETH.deposit{value: paybackAmount}();
POOL.repay(address(WETH), msg.value, rateMode, onBehalfOf);
2020-10-28 14:41:31 +00:00
// refund remaining dust eth
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`.
* @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(
uint256 amount,
uint256 interesRateMode,
uint16 referralCode
) external override {
POOL.borrow(address(WETH), amount, interesRateMode, referralCode, msg.sender);
WETH.withdraw(amount);
_safeTransferETH(msg.sender, amount);
}
/**
* @dev transfer ETH to an address, revert if it fails.
* @param to recipient of the transfer
* @param value the amount to send
*/
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');
}
/**
* @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.
* @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);
}
/**
* @dev Get aWETH address used by WETHGateway
*/
function getAWETHAddress() external view returns (address) {
return address(aWETH);
}
/**
* @dev Get LendingPool address used by WETHGateway
*/
function getLendingPoolAddress() external view returns (address) {
return address(POOL);
}
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 {
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
}
}