概要
フラッシュローンとは、借金と返済を瞬時に行うDeFiプロトコルです。借金と返済を1トランザクション内で行い、返済ができない場合はトランザクションがrevert(失敗)するため、貸し倒れリスクがありません。そのため無担保・無制限・低利息(AAVEの場合は0.09%)で利用することができます。
フラッシュローンは下図のプロセスで行われます。
-
Pool.sol
のflashLoanSimple
メソッドを呼び出す。 -
flashLoanSimple
はexecuteOperation
メソッドをコールバックしながら要求されたERC20トークンを送金する。 -
executeOperation
メソッド内で別のDeFiコントラクトを呼び出し、借りたトークンを使い利益を上げる。 - 借りた額と利息を返済する(自動)。
借金の返済はAAVEのコントラクトがERC20のtransferFrom
メソッドを使い自動的に行います。したがって、コールバック関数の終わりまでに借入額+利息の分をapprove
してやる必要があります。
実装
以下の通りに実装しました。デプロイ時にPool.solのアドレスをここから調べ指定します。
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;
import "https://github.com/aave/aave-v3-core/blob/master/contracts/interfaces/IPool.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract Flashloan is Ownable{
IPool Pool;
address PoolAddress;
constructor(address _PoolAddress) {
PoolAddress = _PoolAddress;
Pool = IPool(_PoolAddress);
}
function executeOperation(
address _asset,
uint256 _amount,
uint256 _premium,
address _initiator,
bytes calldata _params
) external returns (bool)
{
//
// Your logic goes here.
//
IERC20(_asset).approve(address(PoolAddress), _amount+_premium);
return true;
}
function flashloan(address _asset, uint _amount) public onlyOwner {
bytes memory data = "";
Pool.flashLoanSimple(address(this), _asset, _amount, data, 0);
}
function withdraw(address _asset) public onlyOwner{
IERC20 token = IERC20(_asset);
uint balance = token.balanceOf(address(this));
assert(token.transfer(msg.sender, balance));
}
}
利息を払う必要があるので、あらかじめこのコントラクトにいくらかERC20トークンをtransfer
しておきます。借りたいassetのコントラクトアドレスと、借りたい額を引数にflashloan
メソッドを実行します。実行後にトークンが余ったらwithdraw
メソッドで回収してください。
参考文献