说明
现实生活中,如果我们需要借款一般都是需要担保或者是抵押,而且这些贷款需要有很复杂的流程,包括对你的资质的审查,你的抵押物的价值的评估,你的个人的还款能力,你个人的的资产等等,如果现实生活中大家如果有买房或者是买车的经验的话,对这些都应该有深刻的体会。
除此之外,目前很多银行APP中也提供了闪电贷的服务。这些银行因为对于个人的征信记录非常的了解,所以很容易确定每个人的资质,省去了前面很多的评估工作,很方便的每个人的资质决定贷款金额。只需要在这些APP上面点击几个申请按钮,银行就会立马将钱打入导账上。
然而在Web3中却不是这样的。在Web3中的闪电贷有完全一套自己的逻辑:
- 不需要任何的抵押
- 借款和还款操作需要在一个交易内完成
- 只能通过合约的方式借款和和还款
- 还款时,需要还本金和利息。如果最终检测到还款金额不足本金和利息,整笔交易就会取消
下面以Uniswap V2版本(以下所有的Uniswap均代指Uniswap V2版本)为例来讲解和展示闪电贷的原理
闪电贷的实现原理
Uniswap中的闪电贷的逻辑是在Pair合约中的swap()函数中实现的。
1 | function swap( |
uniswap是通过swap函数来实现闪电贷的。如果data参数不为空,说明当前是进行闪电贷的操作,需要调用目标合约的uniswapV2Call方法。也就说如果我们需要实现闪电贷,必须通过合约的方式来实现,同时需要实现IUniswapV2Callee接口中的uniswapV2Call方法。
简单理解,其实IUniswapV2Callee(to)就是触发了借款合约的回调函数(回调函数必须是uniswapV2Call()方法)。
可以看到,因为所有的配对合约全部都实现了swap()函数,所以所有的pair合约都可以实现闪电贷。
uniswapV2Call是目标合约获取到闪电贷借款之后需要进行的操作,包括套利和最终的借款操作;
借贷合约和Pair合约之间的交互逻辑如下所示:
因为在pair合约中的代码在实现闪电贷的逻辑时,一定要回调借贷目标合约的uniswapV2Call()方法,所以如果要实现闪电贷,就必须通过合约与Pair合约交互的方式来实现。
闪电贷演示
下面以一个实际的例子来展示闪电贷具体的借贷合约和代码的编写。
例子是来源于DeFiLabs
1 | // SPDX-License-Identifier: UNLICENSED |
运行查看最终的结果:forge test --contracts ./src/test/Uniswapv2_flashswap.sol -vvv
1 | Running 1 test for src/test/Uniswapv2_flashswap.sol:ContractTest |
测试用例正常通过,说明我们测试的借贷合约的借款,计算手续费,还款的逻辑全部没有问题。
这就是一个简单的闪电贷的例子,当然根据实际的场景,可以在uniswapV2Call()方法中可以实现更为复杂的逻辑,包括但不限于各种套利等等。
实例分析
查看一个实际的闪电贷的调用栈理解具体的闪电贷的调用过程。0x04ebf4d6fefed12efb581f3d46db739fbe1832ae4d8a9ac746ed258beafd604a

上面就是一个简单的闪电贷的调用栈的分析。通过调用栈结合上面的原理分析,相信对闪电贷有很深入的理解。
总结
目前一般DEX都会有闪电贷的功能,功能的实现也基本大同小异。因为在Web3中的闪电贷完全不同于真实世界的特殊实现方式,也是DeFi项目繁荣的原因之一。然而闪电贷在繁荣DeFi项目的同时,也有很多的黑客利用闪电贷的功能对各种项目发动攻击,被攻击的DeFi项目不计其数,损失的金额也十分巨大。
作为一个Web3的从业人员,闪电贷是必须要了解和掌握的,但是我们也必须要对闪电贷有一个清晰的认识,闪电贷就是一把双刃剑。
参考
https://github.com/Fankouzu/flashloan
https://www.youtube.com/watch?v=NeVfZYBydDQ
https://www.bccnav.com/2022/08/05/7294/
https://www.bccnav.com/2022/08/05/7292/
https://www.bccnav.com/2022/08/05/7289/
https://www.youtube.com/watch?v=kDkehUi5MoU
https://www.youtube.com/watch?v=EItibs4sy8g