Skip to content

Commit 64a6972

Browse files
feat: added mainnet import with permit contract
1 parent 573c54e commit 64a6972

File tree

4 files changed

+729
-0
lines changed

4 files changed

+729
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
pragma experimental ABIEncoderV2;
4+
5+
contract Events {
6+
event LogAaveV3ImportWithPermit(
7+
address indexed user,
8+
address[] atokens,
9+
string[] supplyIds,
10+
string[] borrowIds,
11+
uint256[] flashLoanFees,
12+
uint256[] supplyAmts,
13+
uint256[] borrowAmts
14+
);
15+
event LogAaveV3ImportWithPermitAndCollateral(
16+
address indexed user,
17+
address[] atokens,
18+
string[] supplyIds,
19+
string[] borrowIds,
20+
uint256[] flashLoanFees,
21+
uint256[] supplyAmts,
22+
uint256[] borrowAmts,
23+
bool[] enableCollateral
24+
);
25+
}
Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
//SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
import { DSMath } from "../../../common/math.sol";
5+
import { Basic } from "../../../common/basic.sol";
6+
import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
7+
import { AaveInterface, AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol";
8+
import "./events.sol";
9+
import "./interface.sol";
10+
11+
abstract contract Helper is DSMath, Basic {
12+
/**
13+
* @dev Aave referal code
14+
*/
15+
uint16 internal constant referalCode = 3228;
16+
17+
/**
18+
* @dev Aave Lending Pool Provider
19+
*/
20+
AavePoolProviderInterface internal constant aaveProvider =
21+
AavePoolProviderInterface(0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e);
22+
23+
/**
24+
* @dev Aave Protocol Data Provider
25+
*/
26+
AaveDataProviderInterface internal constant aaveData =
27+
AaveDataProviderInterface(0x41393e5e337606dc3821075Af65AeE84D7688CBD);
28+
29+
function getIsColl(address token, address user)
30+
internal
31+
view
32+
returns (bool isCol)
33+
{
34+
(, , , , , , , , isCol) = aaveData.getUserReserveData(token, user);
35+
}
36+
37+
struct ImportData {
38+
address[] _supplyTokens;
39+
address[] _borrowTokens;
40+
ATokenInterface[] aTokens;
41+
uint256[] supplyAmts;
42+
uint256[] variableBorrowAmts;
43+
uint256[] variableBorrowAmtsWithFee;
44+
uint256[] stableBorrowAmts;
45+
uint256[] stableBorrowAmtsWithFee;
46+
uint256[] totalBorrowAmts;
47+
uint256[] totalBorrowAmtsWithFee;
48+
bool convertStable;
49+
}
50+
51+
struct ImportInputData {
52+
address[] supplyTokens;
53+
address[] borrowTokens;
54+
bool convertStable;
55+
uint256[] flashLoanFees;
56+
}
57+
58+
struct SignedPermits {
59+
uint8[] v;
60+
bytes32[] r;
61+
bytes32[] s;
62+
uint256[] expiry;
63+
}
64+
}
65+
66+
contract AaveHelpers is Helper {
67+
function getBorrowAmount(address _token, address userAccount)
68+
internal
69+
view
70+
returns (uint256 stableBorrow, uint256 variableBorrow)
71+
{
72+
(
73+
,
74+
address stableDebtTokenAddress,
75+
address variableDebtTokenAddress
76+
) = aaveData.getReserveTokensAddresses(_token);
77+
78+
stableBorrow = ATokenInterface(stableDebtTokenAddress).balanceOf(
79+
userAccount
80+
);
81+
variableBorrow = ATokenInterface(variableDebtTokenAddress).balanceOf(
82+
userAccount
83+
);
84+
}
85+
86+
function getBorrowAmounts(
87+
address userAccount,
88+
AaveInterface aave,
89+
ImportInputData memory inputData,
90+
ImportData memory data
91+
) internal returns (ImportData memory) {
92+
if (inputData.borrowTokens.length > 0) {
93+
data._borrowTokens = new address[](inputData.borrowTokens.length);
94+
data.variableBorrowAmts = new uint256[](
95+
inputData.borrowTokens.length
96+
);
97+
data.variableBorrowAmtsWithFee = new uint256[](
98+
inputData.borrowTokens.length
99+
);
100+
data.stableBorrowAmts = new uint256[](
101+
inputData.borrowTokens.length
102+
);
103+
data.stableBorrowAmtsWithFee = new uint256[](
104+
inputData.borrowTokens.length
105+
);
106+
data.totalBorrowAmts = new uint256[](inputData.borrowTokens.length);
107+
data.totalBorrowAmtsWithFee = new uint256[](
108+
inputData.borrowTokens.length
109+
);
110+
for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
111+
for (uint256 j = i; j < inputData.borrowTokens.length; j++) {
112+
if (j != i) {
113+
require(
114+
inputData.borrowTokens[i] !=
115+
inputData.borrowTokens[j],
116+
"token-repeated"
117+
);
118+
}
119+
}
120+
}
121+
for (uint256 i = 0; i < inputData.borrowTokens.length; i++) {
122+
address _token = inputData.borrowTokens[i] == ethAddr
123+
? wethAddr
124+
: inputData.borrowTokens[i];
125+
data._borrowTokens[i] = _token;
126+
127+
(
128+
data.stableBorrowAmts[i],
129+
data.variableBorrowAmts[i]
130+
) = getBorrowAmount(_token, userAccount);
131+
132+
if (data.variableBorrowAmts[i] != 0) {
133+
data.variableBorrowAmtsWithFee[i] = add(
134+
data.variableBorrowAmts[i],
135+
inputData.flashLoanFees[i]
136+
);
137+
data.stableBorrowAmtsWithFee[i] = data.stableBorrowAmts[i];
138+
} else {
139+
data.stableBorrowAmtsWithFee[i] = add(
140+
data.stableBorrowAmts[i],
141+
inputData.flashLoanFees[i]
142+
);
143+
}
144+
145+
data.totalBorrowAmts[i] = add(
146+
data.stableBorrowAmts[i],
147+
data.variableBorrowAmts[i]
148+
);
149+
data.totalBorrowAmtsWithFee[i] = add(
150+
data.stableBorrowAmtsWithFee[i],
151+
data.variableBorrowAmtsWithFee[i]
152+
);
153+
154+
if (data.totalBorrowAmts[i] > 0) {
155+
uint256 _amt = data.totalBorrowAmts[i];
156+
TokenInterface(_token).approve(address(aave), _amt);
157+
}
158+
}
159+
}
160+
return data;
161+
}
162+
163+
function getSupplyAmounts(
164+
address userAccount,
165+
ImportInputData memory inputData,
166+
ImportData memory data
167+
) internal view returns (ImportData memory) {
168+
data.supplyAmts = new uint256[](inputData.supplyTokens.length);
169+
data._supplyTokens = new address[](inputData.supplyTokens.length);
170+
data.aTokens = new ATokenInterface[](inputData.supplyTokens.length);
171+
172+
for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
173+
for (uint256 j = i; j < inputData.supplyTokens.length; j++) {
174+
if (j != i) {
175+
require(
176+
inputData.supplyTokens[i] != inputData.supplyTokens[j],
177+
"token-repeated"
178+
);
179+
}
180+
}
181+
}
182+
for (uint256 i = 0; i < inputData.supplyTokens.length; i++) {
183+
address _token = inputData.supplyTokens[i] == ethAddr
184+
? wethAddr
185+
: inputData.supplyTokens[i];
186+
(address _aToken, , ) = aaveData.getReserveTokensAddresses(_token);
187+
data._supplyTokens[i] = _token;
188+
data.aTokens[i] = ATokenInterface(_aToken);
189+
data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount);
190+
}
191+
192+
return data;
193+
}
194+
195+
function _paybackBehalfOne(
196+
AaveInterface aave,
197+
address token,
198+
uint256 amt,
199+
uint256 rateMode,
200+
address user
201+
) private {
202+
aave.repay(token, amt, rateMode, user);
203+
}
204+
205+
function _PaybackStable(
206+
uint256 _length,
207+
AaveInterface aave,
208+
address[] memory tokens,
209+
uint256[] memory amts,
210+
address user
211+
) internal {
212+
for (uint256 i = 0; i < _length; i++) {
213+
if (amts[i] > 0) {
214+
_paybackBehalfOne(aave, tokens[i], amts[i], 1, user);
215+
}
216+
}
217+
}
218+
219+
function _PaybackVariable(
220+
uint256 _length,
221+
AaveInterface aave,
222+
address[] memory tokens,
223+
uint256[] memory amts,
224+
address user
225+
) internal {
226+
for (uint256 i = 0; i < _length; i++) {
227+
if (amts[i] > 0) {
228+
_paybackBehalfOne(aave, tokens[i], amts[i], 2, user);
229+
}
230+
}
231+
}
232+
233+
function _PermitATokens(
234+
address userAccount,
235+
ATokenInterface[] memory aTokenContracts,
236+
address[] memory tokens,
237+
uint8[] memory v,
238+
bytes32[] memory r,
239+
bytes32[] memory s,
240+
uint256[] memory expiry
241+
) internal {
242+
for (uint256 i = 0; i < tokens.length; i++) {
243+
aTokenContracts[i].permit(
244+
userAccount,
245+
address(this),
246+
uint256(-1),
247+
expiry[i],
248+
v[i],
249+
r[i],
250+
s[i]
251+
);
252+
}
253+
}
254+
255+
function _TransferAtokens(
256+
uint256 _length,
257+
AaveInterface aave,
258+
ATokenInterface[] memory atokenContracts,
259+
uint256[] memory amts,
260+
address[] memory tokens,
261+
address userAccount
262+
) internal {
263+
for (uint256 i = 0; i < _length; i++) {
264+
if (amts[i] > 0) {
265+
uint256 _amt = amts[i];
266+
require(
267+
atokenContracts[i].transferFrom(
268+
userAccount,
269+
address(this),
270+
_amt
271+
),
272+
"allowance?"
273+
);
274+
275+
if (!getIsColl(tokens[i], address(this))) {
276+
aave.setUserUseReserveAsCollateral(tokens[i], true);
277+
}
278+
}
279+
}
280+
}
281+
282+
function _TransferAtokensWithCollateral(
283+
uint256 _length,
284+
AaveInterface aave,
285+
ATokenInterface[] memory atokenContracts,
286+
uint256[] memory amts,
287+
address[] memory tokens,
288+
bool[] memory colEnable,
289+
address userAccount
290+
) internal {
291+
for (uint256 i = 0; i < _length; i++) {
292+
if (amts[i] > 0) {
293+
uint256 _amt = amts[i];
294+
require(
295+
atokenContracts[i].transferFrom(
296+
userAccount,
297+
address(this),
298+
_amt
299+
),
300+
"allowance?"
301+
);
302+
303+
if (!getIsColl(tokens[i], address(this))) {
304+
aave.setUserUseReserveAsCollateral(tokens[i], colEnable[i]);
305+
}
306+
}
307+
}
308+
}
309+
310+
function _BorrowVariable(
311+
uint256 _length,
312+
AaveInterface aave,
313+
address[] memory tokens,
314+
uint256[] memory amts
315+
) internal {
316+
for (uint256 i = 0; i < _length; i++) {
317+
if (amts[i] > 0) {
318+
_borrowOne(aave, tokens[i], amts[i], 2);
319+
}
320+
}
321+
}
322+
323+
function _BorrowStable(
324+
uint256 _length,
325+
AaveInterface aave,
326+
address[] memory tokens,
327+
uint256[] memory amts
328+
) internal {
329+
for (uint256 i = 0; i < _length; i++) {
330+
if (amts[i] > 0) {
331+
_borrowOne(aave, tokens[i], amts[i], 1);
332+
}
333+
}
334+
}
335+
336+
function _borrowOne(
337+
AaveInterface aave,
338+
address token,
339+
uint256 amt,
340+
uint256 rateMode
341+
) private {
342+
aave.borrow(token, amt, rateMode, referalCode, address(this));
343+
}
344+
}

0 commit comments

Comments
 (0)