-
Notifications
You must be signed in to change notification settings - Fork 161
/
FlashLoanPool.sol
74 lines (68 loc) · 2.38 KB
/
FlashLoanPool.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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
// Minimal ERC20 interface.
interface IERC20 {
function balanceOf(address owner) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
}
// Interface implemented by a flash loan borrower contract.
interface IBorrower {
function onFlashLoan(
// Who called `flashLoan()`.
address operator,
// Token borrowed.
IERC20 token,
// Amount of tokens borrowed.
uint256 amount,
// Extra tokens (on top of `amount`) to return as the loan fee.
uint256 fee,
// Arbitrary data passed into `flashLoan()`.
bytes calldata data
) external;
}
// A simple flash loan protocol with a single depositor/withdrawer (OWNER).
contract FlashLoanPool {
uint16 public constant FEE_BPS = 0.001e4; // 0.1% fee.
address public immutable OWNER;
constructor(address owner) { OWNER = owner; }
// Perform a flash loan.
function flashLoan(
// Token to borrow.
IERC20 token,
// How much to borrow.
uint256 borrowAmount,
// Address of the borrower (handler) contract.
IBorrower borrower,
// Arbitrary data to pass to borrower contract.
bytes calldata data
)
external
{
// Snapshot our token balance before the transfer.
uint256 balanceBefore = token.balanceOf(address(this));
require(balanceBefore >= borrowAmount, 'too much');
// Compute the fee, rounded up.
uint256 fee = (FEE_BPS * borrowAmount + 1e4-1) / 1e4;
// Transfer tokens to the borrower contract.
token.transfer(address(borrower), borrowAmount);
// Let the borrower do its thing.
borrower.onFlashLoan(
msg.sender,
token,
borrowAmount,
fee,
data
);
// Check that all the tokens were returned + fee.
uint256 balanceAfter = token.balanceOf(address(this));
require(balanceAfter >= balanceBefore + fee, 'not repaid');
}
// Withdraw tokens from this contract to the contract owner.
function withdraw(IERC20 token, uint256 amount)
external
{
require(msg.sender == OWNER, 'not owner');
token.transfer(msg.sender, amount);
}
}