译文出自:登链翻译计划 [1]
译者:翻译小组 [2]
校对:Tiny 熊 [3]
概述
Aave,以前称为 ETHLender,现在是 DeFi 领域的前沿应用。Aave 是该领域中第一个提出闪电贷 [4] 概念的人。在闪电贷之前,你必须用一个超额抵押的资产来借贷另一个资产。例如,如果我想借一个 DAI ),我将不得不存入另一个超过该价值的加密货币。换句话说,你必须有钱才能借到钱。闪电贷打破了这种想法。他们为一个新的贷款系统打开了大门,并且做到了这一点,允许用户在不提供任何东西作为抵押的情况下借款。
在本教程中,你将了解到闪电贷 [5] 是如何实现的,以及如何自己实现执行一笔闪电贷。
关于 Aave
摘自 Aave 官网 [6]:Aave 是一个去中心化的非托管流动性市场协议,用户可以作为存款人或借款人参与。储户向市场提供流动性,以赚取被动收入,而借款人能够以过度抵押(永久)或不足抵押(单块流动性)的方式借款。
这个定义完全正确的,但如果你不熟悉 DeFi 行业的行话,你可能并不理解它的含义。你可以把 Aave 看成是一个去中心化的伪银行。Aave 没有一个验证所有交易的中央银行,而是利用智能合约,以自动化的方式完成所有这些工作。存款人将他们的代币放入 Aave,并开始为他们的存款赚取利息。另一方面,借款人会做相反的事情。他们从 Aave 中取出钱,并开始对所借的金额计息。不过他们必须超额抵押 [7] 才能借到钱。
对于那些不想把钱存入 Aave,而只想借钱的人来说,还有一种方法。这就是我们前面提到的闪电贷。
关于闪电贷(Flash Loan)
之前提到的闪电贷是一种在区块链上借入资产的新方式。最初由 Aave 实现,其他趋势性的 DeFi 协议,如 dYdX[8] 迅速跟进,增加了这个新功能。所有以太坊交易的一个特性,使闪电贷成为可能。而这个关键特性就是 原子性 #:~:text= 一个原子交易就是,直接拒绝整个系列。)。
一个交易的操作系列是不可分割和不可消减的,它就是原子的。简单来说就是:要么_所有执行_,要么_什么都没有_发生。没有中间状态 ! 闪电贷利用原子性,允许用户在不提交抵押品的情况下先进行借款。首先,每当你在闪电贷中借入一项资产时,你必须支付贷款金额的 0.09% 的费用。其次,你必须在借贷的同一交易中偿还贷款。虽然这种能力很好,但它的用途却有些局限。闪电贷主要用于资产间套利 [9]。
Remix 设置
为了简单起见,我们将使用 Remix IDE[10]。Remix 是一个基于浏览器的 IDE。也被称为集成开发环境。Remix 具有编写、调试、部署和操作以太坊智能合约 [11] 的能力。浏览器中加载 Remix 后,你会看到这个菜单:
pasted image 0
这里不会对 IDE 进行深入的研究(你可以阅读跟我学 Solidity :开发环境 [12]),因为本教程的重点是闪电贷。不过,你需要了解一下上图的四个部分:主面板、侧边面板、图标面板和终端面板。
在我们开始编写智能合约之前,我们要下载一个浏览器插件,现在最流行的是 MetaMask[13],使我们能够与以太坊区块链对接。
MetaMask 安装
如何安装 MetaMask:
-
你将开始从网站 https://metamask.io/ 上下载扩展程序。
-
点击你新安装的扩展程序,并同意条款和条件。
-
创建一个安全的密码!
-
备份助记词,它应该物理存在,不应该保存在你的电脑上的任何地方。
如果上述四个步骤都完成了,你就可以开始编写你的第一个智能合约了 !
智能合约
智能合约允许我们通过执行确定性的程序来读写区块链的数据。我们使用一种名为 Solidity[14] 的编程语言编写以太坊智能合约。Solidity 文件以 .sol 扩展名结尾。
欢迎订阅全面掌握 Solidity 智能合约开发 [15]
你可以在第一次启动 Remix 时删除工作区中可能存在的任何文件。然后创建几个文件:
- FlashLoan.sol
2. FlashLoanReceiverBase.sol
-
ILendingPoolAddressesProvider.sol
-
IFlashLoanReceiver.sol
-
ILendingPool.sol
-
Withdrawable.sol
下面的代码片断是 FlashLoan.sol. 的实现。
这个闪电贷将借入 1 DAI )。
pragma solidity ^0.6.6; import "./FlashLoanReceiverBase.sol"; import "./ILendingPoolAddressesProvider.sol"; import "./ILendingPool.sol"; contract FlashloanV1 is FlashLoanReceiverBaseV1 { constructor(address_addressProvider) FlashLoanReceiverBaseV1(_addressProvider) public{} /** Flash loan 1000000000000000000 wei (1 ether) worth of `_asset` */ function flashloan(address_asset) public onlyOwner { bytes memory data = ""; uint amount = 1 ether; ILendingPoolV1 lendingPool = ILendingPoolV1(addressesProvider.getLendingPool()); lendingPool.flashLoan(address(this),_asset, amount, data); } /** This function is called after your contract has received the flash loaned amount */ function executeOperation( address_reserve, uint256_amount, uint256_fee, bytes calldata_params ) external override { require(_amount <= getBalanceInternal(address(this),_reserve), "Invalid balance, was the flashLoan successful?"); // // Your logic goes here. // !! Ensure that *this contract* has enough of `_reserve` funds to payback the `_fee` !! // uint totalDebt =_amount.add(_fee); transferFundsBackToPoolInternal(_reserve, totalDebt); } }
总而言之,我们首先要导入执行闪电贷所需的依赖。其中一些依赖关系被称为抽象合约 [16])。一个抽象合约至少有个函数没有实现。你可以把它想象成一个房子的图纸。一个建筑商使用这个图纸来建造房子。然而,在我们的比喻中,图纸是一个抽象合约,你是建造者,而房子是派生合约。
在我们的案例中,闪电贷合约使用的是一个名为 FlashLoanReceiverBaseV1 的抽象合约,它提供了必要的实现细节,如闪电贷的偿还。
现在来逐行解读代码:
1 首先,我们必须定义 solidity 编译器的版本。在这个例子中,它是 0.6.6。
2-4 为智能合约导入依赖项 #6 FlashLoanV1 合约是继承自 FlashLoanReceiverBaseV1 合约。
8 传递了 Aave 的一个借贷池提供者的地址。在这个例子中,我们提供的是 DAI 借贷池的地址。
13 定义了一个叫做 flashLoan 的函数。参数是想要闪电贷的资产地址。在这种情况下,该资产是 DAI。
14 由于这里不需要任何闪电贷的数据,所以我们传递一个空字符串。
15. 定义我们想要借出的 DAI 的数量(以 10^18 的 Wei 为单位)。
16. 通过 Aave 提供的 ILendingPoolV1 初始化 LendingPool 接口,这样我们就可以调用 flashLoan 函数。#17. 最后,调用 flashLoan 函数。该函数需要 4 个主要参数。首先,传递将接收贷款的地址。在我们的例子中,它是当前合约。其次,我们传递资产的地址。在我们的例子中,它是 Kovan 网络中 DAI 的地址。第三,传递资产的数量,在我们的案例中,它是 1 个 ether 单位(或 10^18 的
wei
单位)的数量。第四,传递额外的空数据。
24-31. 接下来第二个函数 executeOperation。这就是我们利用闪电贷的地方。它在 flashLoan 函数成功执行后被内部调用。它需要 4 个主要参数,分别是:
1). 必须偿还贷款的储备资产地址。2). 资产的数额 3). 协议书所收取的费用 4). 额外的参数,由函数内部使用。
33. 检查我们是否收到了适当的贷款金额,否则它将抛出一个错误信息。
34. 在这里,可以根据你自己的使用场景,定制自己的实现逻辑(例如去 DEX 中套利)。
40. 我们通过使用 SafeMaths 库提供的 add 函数,将费用和贷款金额加在一起。
41. 最后,把总的债务或贷款金额还给贷款人。
部署合约
- 首先,打开你的 MetaMask,将你的网络设置为
Kovan 测试网络
。
Kovan 测试网络
- 使用这个 gist 代码来定义 flashloan 智能合约的依赖关系。点击每个链接并将代码粘贴到你之前创建的相应的 Solidity 文件中:a. ILendingPool[17]b. IFlashLoanReceiver[18]c. ILendingPoolAddressesProvider[19]d. FlashLoanReceiverBase[20]e. Withdrawable[21]
Solidity 文件
- 切换到
Solidity Compiler
标签。将编译器设置为 0.6.6 并点击compile FlashLoan.sol
。
-
你应该看到一些警告,但没有错误信息。
-
现在,我们已经准备好将合约部署到 Kovan 网络。切换到
Deploy & Run Transctions
标签。把部署环境(ENVIRONMENT),从 JavaScript VM 改为 Injected Web3。这应该会打开 MetaMask 询问你的权限。
部署环境
- 确保合约选择的是 FlashLoan.sol。在部署按钮旁边的文本字段中提供 LendingPool 的地址。在我们的例子中,它将是 0x506B0B2CF20FAA8f38a4E2B524EE43e1f4458Cc5 。然后点击
Deploy(部署)
,它应该会打开 MetaMask。
注意 。所有已部署的合约地址列表可在这里 [22] 找到。在那里,你可以找到 Aave 支持的各种借贷池的地址。虽然每个代币的地址都不同,但程序是相同的。
- 点击
确认 (Confirm)
。这样做后,你应该看到 MetaMask 发出的成功通知。之后侧边栏应该有一个 “已部署的合约(Deployed Contracts)”。
为闪电贷准备资金
在新的
已部署合约
标签下,可以复制已部署合约的地址。我们稍后会回到这一步;与此同时,我们需要给闪电贷合约添加一些 DAI。这是因为闪电贷需要合约中的资金才能成功执行。为此,你可以跳转到水龙头 [23] 链接,获得一些 DAI 代币(请确保连接到右上角有小
K
的
Aave v2 市场
)。点击 Faucet,粘贴你的 MetaMask 钱包地址,然后等待确认。
获得确认后,我们将把 DAI 代币添加到 MetaMask 中。为此,打开你的 MetaMask。点击底部的
Add Token
。在
代币合约地址(Token Contract Address)
栏输入 0xF795577d9AC8bD7D90Ee22b6C1703490b6512FD。这是 Kovan 的 DAI 的合约地址。点击
下一步
后,它应该显示你先前从水龙头(Faucet)得到的 DAI。
img
接下来,点击 DAI 代币。点击
发送
,它应该打开一个类似于下图的窗口:
输入我们的闪电贷的合约地址,之前已经复制了该地址。输入我们要发送的金额。在我们的案例中,发送 10DAI。然后点击
下一步
。点击
确认
! 你现在已经成功地给你的闪电贷合约发送了 10DAI。
执行闪电贷
回到 Remix,在部署的闪电贷合约下,还有一个
flashloan
函数。这个函数需要一个我们想使用的资产的合约地址。在我们的例子中,它是 Kovan 测试网的 DAI 合约,是 0xF795577d9AC8bD7D90Ee22b6C1703490b6512FD。正确填写该字段后,你现在可以点击
交易(transact)
按钮,如下图所示:
点击按钮后,MetaMask 会弹出交易确认。确认交易后,你应该收到一条成功信息。在 Remix 的终端,你应该看到一个 URL。点击后会跳转到 Etherscan。
remix
在
代币转移(Tokens Transferred)
下,你应该看到三个不同的转账:
红色的箭头强调了从 LendingPool 转移 1 个 DAI 到我们的合约。橙色的箭头表示将 1 个 DAI 连同费用一起返还给 Landing pool。蓝色的箭头表示产生利息的 DAI。
小结
我们成功地编写了闪电贷的智能合约, 它能够从资金池中借入 DAI,支付闪电贷费用,然后在一次交易中偿还所借金额。不需要没有任何抵押物就借到了钱 !
本翻译由 CellETF[24] 赞助支持。
来源:How to Make a Flash Loan using Aave[25]
参考资料
[1]
登链翻译计划 : https://github.com/lbc-team/Pioneer
[2]
翻译小组 : https://learnblockchain.cn/people/412
[3]
Tiny 熊 : https://learnblockchain.cn/people/15
[4]
闪电贷 : https://aave.com/flash-loans/
[5]
闪电贷 : https://learnblockchain.cn/tags/%E9%97%AA%E7%94%B5%E8%B4%B7
[6]
Aave 官网 : https://aave.com/
[7]
超额抵押 : https://www.oxfordreference.com/view/10.1093/oi/authority.20110803100257900
[8]
dYdX: https://dydx.exchange/
[9]
资产间套利 : https://en.wikipedia.org/wiki/Arbitrage
[10]
Remix IDE: https://remix.ethereum.org/
[11]
以太坊智能合约 : https://ethereum.org/en/developers/docs/smart-contracts/
[12]
跟我学 Solidity :开发环境 : https://learnblockchain.cn/article/1755
[13]
MetaMask: https://metamask.io/
[14]
Solidity: https://learnblockchain.cn/docs/solidity/
[15]
全面掌握 Solidity 智能合约开发 : https://learnblockchain.cn/column/1
[16]
抽象合约 : https://learnblockchain.cn/docs/solidity/contracts.html#abstract-contract
[17]
ILendingPool: https://gist.github.com/akp111/e254b2b5b98aa5a79f3f8dc501dfaedb#file-ilendingpool-sol
[18]
IFlashLoanReceiver: https://gist.github.com/akp111/e254b2b5b98aa5a79f3f8dc501dfaedb#file-iflashloanreceiver-sol
[19]
ILendingPoolAddressesProvider: https://gist.github.com/akp111/e254b2b5b98aa5a79f3f8dc501dfaedb#file-ilendingpooladdressesprovider-sol
[20]
FlashLoanReceiverBase: https://gist.github.com/akp111/e254b2b5b98aa5a79f3f8dc501dfaedb#file-flashloanreceiverbase-sol
[21]
Withdrawable: https://gist.github.com/akp111/e254b2b5b98aa5a79f3f8dc501dfaedb#file-withdrawable-sol
[22]
这里 : https://docs.aave.com/developers/v/1.0/deployed-contracts/deployed-contract-instances
[23]
水龙头 : https://testnet.aave.com/faucet/DAI
[24]
CellETF: https://celletf.io/?utm_souce=learnblockchain
[25]
How to Make a Flash Loan using Aave: https://www.quicknode.com/guides/defi/how-to-make-a-flash-loan-using-aave