-
Notifications
You must be signed in to change notification settings - Fork 4
/
WETHGateway.sol
189 lines (170 loc) · 6.64 KB
/
WETHGateway.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {IWETH} from './interfaces/IWETH.sol';
import {IWETHGateway} from './interfaces/IWETHGateway.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {IAToken} from '../interfaces/IAToken.sol';
import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol';
import {UserConfiguration} from '../protocol/libraries/configuration/UserConfiguration.sol';
import {Helpers} from '../protocol/libraries/helpers/Helpers.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
contract WETHGateway is IWETHGateway, Ownable {
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using UserConfiguration for DataTypes.UserConfigurationMap;
IWETH internal immutable WETH;
/**
* @dev Sets the WETH address and the LendingPoolAddressesProvider address. Infinite approves lending pool.
* @param weth Address of the Wrapped Ether contract
**/
constructor(address weth) public {
WETH = IWETH(weth);
}
function authorizeLendingPool(address lendingPool) external onlyOwner {
WETH.approve(lendingPool, uint256(-1));
}
/**
* @dev deposits WETH into the reserve, using native ETH. A corresponding amount of the overlying asset (aTokens)
* is minted.
* @param lendingPool address of the targeted underlying lending pool
* @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 lendingPool,
address onBehalfOf,
uint16 referralCode
) external payable override {
WETH.deposit{value: msg.value}();
ILendingPool(lendingPool).deposit(address(WETH), msg.value, onBehalfOf, referralCode);
}
/**
* @dev withdraws the WETH _reserves of msg.sender.
* @param lendingPool address of the targeted underlying lending pool
* @param amount amount of aWETH to withdraw and receive native ETH
* @param to address of the user who will receive native ETH
*/
function withdrawETH(
address lendingPool,
uint256 amount,
address to
) external override {
IAToken aWETH = IAToken(ILendingPool(lendingPool).getReserveData(address(WETH)).aTokenAddress);
uint256 userBalance = aWETH.balanceOf(msg.sender);
uint256 amountToWithdraw = amount;
// if amount is equal to uint(-1), the user wants to redeem everything
if (amount == type(uint256).max) {
amountToWithdraw = userBalance;
}
aWETH.transferFrom(msg.sender, address(this), amountToWithdraw);
ILendingPool(lendingPool).withdraw(address(WETH), amountToWithdraw, address(this));
WETH.withdraw(amountToWithdraw);
_safeTransferETH(to, amountToWithdraw);
}
/**
* @dev repays a borrow on the WETH reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified).
* @param lendingPool address of the targeted underlying lending pool
* @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
*/
function repayETH(
address lendingPool,
uint256 amount,
uint256 rateMode,
address onBehalfOf
) external payable override {
(uint256 stableDebt, uint256 variableDebt) =
Helpers.getUserCurrentDebtMemory(
onBehalfOf,
ILendingPool(lendingPool).getReserveData(address(WETH))
);
uint256 paybackAmount =
DataTypes.InterestRateMode(rateMode) == DataTypes.InterestRateMode.STABLE
? stableDebt
: variableDebt;
if (amount < paybackAmount) {
paybackAmount = amount;
}
require(msg.value >= paybackAmount, 'msg.value is less than repayment amount');
WETH.deposit{value: paybackAmount}();
ILendingPool(lendingPool).repay(address(WETH), msg.value, rateMode, onBehalfOf);
// refund remaining dust eth
if (msg.value > paybackAmount) _safeTransferETH(msg.sender, msg.value - paybackAmount);
}
/**
* @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 lendingPool address of the targeted underlying lending pool
* @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(
address lendingPool,
uint256 amount,
uint256 interesRateMode,
uint16 referralCode
) external override {
ILendingPool(lendingPool).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 {
(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
* 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 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
*/
fallback() external payable {
revert('Fallback not allowed');
}
}