Created
June 17, 2021 21:50
-
-
Save brianmcmichael/29577eb641a697eb8b5ccc963e3e73f3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.6.12; | |
interface VatAbstract { | |
function wards(address) external view returns (uint256); | |
function rely(address) external; | |
function deny(address) external; | |
function can(address, address) external view returns (uint256); | |
function hope(address) external; | |
function nope(address) external; | |
function ilks(bytes32) external view returns (uint256, uint256, uint256, uint256, uint256); | |
function urns(bytes32, address) external view returns (uint256, uint256); | |
function gem(bytes32, address) external view returns (uint256); | |
function dai(address) external view returns (uint256); | |
function sin(address) external view returns (uint256); | |
function debt() external view returns (uint256); | |
function vice() external view returns (uint256); | |
function Line() external view returns (uint256); | |
function live() external view returns (uint256); | |
function init(bytes32) external; | |
function file(bytes32, uint256) external; | |
function file(bytes32, bytes32, uint256) external; | |
function cage() external; | |
function slip(bytes32, address, int256) external; | |
function flux(bytes32, address, address, uint256) external; | |
function move(address, address, uint256) external; | |
function frob(bytes32, address, address, address, int256, int256) external; | |
function fork(bytes32, address, address, int256, int256) external; | |
function grab(bytes32, address, address, address, int256, int256) external; | |
function heal(uint256) external; | |
function suck(address, address, uint256) external; | |
function fold(bytes32, address, int256) external; | |
} | |
interface IERC20 { | |
function totalSupply() external view returns (uint256); | |
function balanceOf(address) external view returns (uint256); | |
function allowance(address, address) external view returns (uint256); | |
function approve(address, uint256) external returns (bool); | |
function transfer(address, uint256) external returns (bool); | |
function transferFrom(address, address, uint256) external returns (bool); | |
} | |
interface IERC3156FlashBorrower { | |
/** | |
* @dev Receive a flash loan. | |
* @param initiator The initiator of the loan. | |
* @param token The loan currency. | |
* @param amount The amount of tokens lent. | |
* @param fee The additional amount of tokens to repay. | |
* @param data Arbitrary data structure, intended to contain user-defined parameters. | |
* @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" | |
*/ | |
function onFlashLoan( | |
address initiator, | |
address token, | |
uint256 amount, | |
uint256 fee, | |
bytes calldata data | |
) external returns (bytes32); | |
} | |
interface IERC3156FlashLender { | |
/** | |
* @dev The amount of currency available to be lent. | |
* @param token The loan currency. | |
* @return The amount of `token` that can be borrowed. | |
*/ | |
function maxFlashLoan( | |
address token | |
) external view returns (uint256); | |
/** | |
* @dev The fee to be charged for a given loan. | |
* @param token The loan currency. | |
* @param amount The amount of tokens lent. | |
* @return The amount of `token` to be charged for the loan, on top of the returned principal. | |
*/ | |
function flashFee( | |
address token, | |
uint256 amount | |
) external view returns (uint256); | |
/** | |
* @dev Initiate a flash loan. | |
* @param receiver The receiver of the tokens in the loan, and the receiver of the callback. | |
* @param token The loan currency. | |
* @param amount The amount of tokens lent. | |
* @param data Arbitrary data structure, intended to contain user-defined parameters. | |
*/ | |
function flashLoan( | |
IERC3156FlashBorrower receiver, | |
address token, | |
uint256 amount, | |
bytes calldata data | |
) external returns (bool); | |
} | |
interface IVatDaiFlashBorrower { | |
/** | |
* @dev Receive a flash loan. | |
* @param initiator The initiator of the loan. | |
* @param amount The amount of tokens lent. [rad] | |
* @param fee The additional amount of tokens to repay. [rad] | |
* @param data Arbitrary data structure, intended to contain user-defined parameters. | |
* @return The keccak256 hash of "IVatDaiFlashLoanReceiver.onVatDaiFlashLoan" | |
*/ | |
function onVatDaiFlashLoan( | |
address initiator, | |
uint256 amount, | |
uint256 fee, | |
bytes calldata data | |
) external returns (bytes32); | |
} | |
interface IVatDaiFlashLender { | |
/** | |
* @dev Initiate a flash loan. | |
* @param receiver The receiver of the tokens in the loan, and the receiver of the callback. | |
* @param amount The amount of tokens lent. [rad] | |
* @param data Arbitrary data structure, intended to contain user-defined parameters. | |
*/ | |
function vatDaiFlashLoan( | |
IVatDaiFlashBorrower receiver, | |
uint256 amount, | |
bytes calldata data | |
) external returns (bool); | |
} | |
contract FlashBorrower is IVatDaiFlashBorrower { // 0x68C7b18c987e7Fea919e02894614fD4FA0d58B96 | |
enum Action {NORMAL, OTHER} | |
VatAbstract vat; | |
IVatDaiFlashLender lender; | |
constructor ( | |
VatAbstract vat_, // 0xbA987bDB501d131f766fEe8180Da5d81b34b69d9 | |
IVatDaiFlashLender lender_ // 0x5aA1323f61D679E52a90120DFDA2ed1A76E4475A | |
) public { | |
vat = vat_; | |
lender = lender_; | |
} | |
/// @dev Vat Dai Flash loan callback | |
function onVatDaiFlashLoan( | |
address initiator, | |
uint256 amount, | |
uint256 fee, | |
bytes calldata data | |
) external override returns (bytes32) { | |
require( | |
msg.sender == address(lender), | |
"FlashBorrower: Untrusted lender" | |
); | |
require( | |
initiator == address(this), | |
"FlashBorrower: Untrusted loan initiator" | |
); | |
(Action action) = abi.decode(data, (Action)); | |
if (action == Action.NORMAL) { | |
require(vat.dai(address(this)) >= amount); | |
// that's it, repay on 176 | |
} else if (action == Action.OTHER) { | |
// do another | |
} | |
// Repay the loan amount + fee | |
// Be sure not to overpay as there are no safety guards for this | |
vat.move(address(this), address(lender), amount + fee); | |
return keccak256("VatDaiFlashBorrower.onVatDaiFlashLoan"); | |
} | |
/// @dev Initiate a flash loan | |
function vatDaiFlashBorrow( | |
uint256 amount | |
) public { | |
bytes memory data = abi.encode(Action.NORMAL); | |
lender.vatDaiFlashLoan(this, amount, data); | |
} | |
} | |
/** | |
contract FlashBorrower is IERC3156FlashBorrower { | |
enum Action {NORMAL, OTHER} | |
IERC3156FlashLender lender; | |
constructor ( | |
IERC3156FlashLender lender_ // 0x5aA1323f61D679E52a90120DFDA2ed1A76E4475A | |
) public { | |
lender = lender_; | |
} | |
/// @dev ERC-3156 Flash loan callback | |
function onFlashLoan( | |
address initiator, | |
address token, | |
uint256 amount, | |
uint256 fee, | |
bytes calldata data | |
) external override returns (bytes32) { | |
require( | |
msg.sender == address(lender), | |
"FlashBorrower: Untrusted lender" | |
); | |
require( | |
initiator == address(this), | |
"FlashBorrower: Untrusted loan initiator" | |
); | |
(Action action) = abi.decode(data, (Action)); | |
if (action == Action.NORMAL) { | |
require(IERC20(token).balanceOf(address(this)) >= amount); | |
// make a profitable trade here | |
IERC20(token).transfer(initiator, amount + fee); | |
} else if (action == Action.OTHER) { | |
// do another | |
} | |
return keccak256("ERC3156FlashBorrower.onFlashLoan"); | |
} | |
/// @dev Initiate a flash loan | |
function flashBorrow( | |
address token, // Dai 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa | |
uint256 amount // wad | |
) public { | |
bytes memory data = abi.encode(Action.NORMAL); | |
uint256 _allowance = IERC20(token).allowance(address(this), address(lender)); | |
uint256 _fee = lender.flashFee(token, amount); | |
uint256 _repayment = amount + _fee; | |
IERC20(token).approve(address(lender), _allowance + _repayment); | |
lender.flashLoan(this, token, amount, data); | |
} | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment