深入理解闪电贷攻击的底层逻辑
2023-03-29 06:57
Whaler 捕鲸船
2023-03-29 06:57
订阅此专栏
收藏此文章
深入到闪电贷的源代码,理解什么是闪电贷和闪电贷攻击。


分享嘉宾:Frog,Numen 区块链安全研究员

整理:小胡

编辑:辰一 


我们在上一期文章中,主要介绍了针对领先 DeFi 借贷协议 Euler Finance 的闪电贷攻击。在本期文章中,我们会更进一步,深入到闪电贷的源代码,理解什么是闪电贷和闪电贷攻击。


01 TL; DR


正如我们上一期文章(「暴雷」启示录:Euler Finance 被攻击前因后果复现),闪电贷有如下关键词:


1. 不需要抵押资金的贷款


2. 放贷、使用资金和还贷「同时」进行


因此利用无需抵押的大额资金,黑客可以:


1. 操纵价格,砸盘或拉盘


2. 成倍地放大已有漏洞


02 什么是闪电贷


闪电贷(Flash loan)是一种去中心化金融(DeFi)的创新产品,它允许用户在不提供任何抵押的情况下,借用协议池中的任意数量的资产,只要在同一笔交易(一个区块)中归还本金和利息。闪电贷的优势在于,它可以让用户利用市场上的套利机会,实现低成本、高收益的操作。闪电贷的风险在于,如果用户无法在规定时间内还款,那么交易会被撤销,用户将损失交易费用和利息。


1 常见的闪电贷平台


提到闪电贷,你可能会立刻联想到 Aave,这家公司是闪电贷的发明者和领导者。由于闪电贷的资金本身有低风险的特性,较高的需求立刻涌现了一大批闪电贷平台。提供闪电贷服务的头部平台还有:


- Uniswap: 一个去中心化的交易平台,提供闪电贷服务。用户可以通过 Uniswap 借用任何支持的代币,并在同一笔交易中进行兑换、做市、套利等操作。


- Compound:一个开源的借贷协议,支持多种数字资产的借贷和借款,提供闪电贷服务。用户可以通过 Compound 借用任何可用的资产,并在同一笔交易中进行还款、抵押、借款等操作。


- MakerDAO:一个去中心化的稳定币平台,支持 DAI 稳定币的发行和交易,提供闪电贷服务。用户可以通过 MakerDAO 借用 DAI,并在同一笔交易中进行还款、兑换、偿还清算罚金等操作。


- dYdX:一个去中心化交易所,提供闪电贷服务和开放式借贷市场。用户可以通过 dYdX 借用任何可用的资产,并在同一笔交易中进行还款、交易、杠杆等操作。


除此之外,常见的还有 Nuo、Fulcrum、bZx、DeFi Money Market、ETHLend 等。


这些闪电贷平台在功能上都提供了无抵押、即时借贷的服务,细节上的差异更多的是体现在平台的安全性、用户体验和手续费上。


2 Uniswap 闪电贷


Uniswap 是 DeFi 中最受欢迎的去中心化交易所之一。一般用户接触到 Uniswap 的途径是网页界面。比如下图展示了 ETH-DAI 的兑换。我们称两个代币之间的兑换为一个交易对。



但除了使用网站进行交互,我们还可以直接调用智能合约交互。当你想在他们的平台上购买 token 时:


  • 首先需要发送 token 用于支付
  • 然后调用一个 swap() 的函数,它将发送你刚刚购买的 token。


Uniswap V2 版有一个新的功能,叫做 Flashswap,是 Uniswap 对闪电贷的称呼。这一功能是集成在常规的 swap() 函数中的。


一个常见的闪电贷操作逻辑有四步,必须在同一个区块中完成:


1. 发送交易请求,并上传智能合约


2. 向协议发送代币


3. 上传的智能合约使用代币交互


4. 归还代币给协议



因为 Uniswap 的 swap() 函数模式是先转账再进行校验,所以第二步可以先将需要的代币借出后,第三步调用自己合约中的 uniswapV2Call() 函数进行其它操作,完成后第四步再将借的代币归还,完成闪电贷服务。


在代码中,红框部分就是用户预先部署的合约。要想在同一个区块中完成上面的所有操作,用户要将如何使用借出的资金用合约预先定义好,毕竟手工操作的速度没有代码执行快。



而在红框上方的两行中,我们看到有两个转账函数。如注释所言,这是「乐观的转账」──即不校验是否支付就先转账。在最后的部分中,调用完用户合约之后,swap() 函数才会慢悠悠地 require 支付金额。


而无论是否使用闪电贷服务,Uniswap 都会对每笔交易收取高达 0.3% 的手续费。


3 AAVE 闪电贷


总体而言,AAVE 的 LendingPool 合约中的 Flashloan 函数提供了类似的闪电贷功能。通过调用 Flashloan 函数,传入借贷的金额和代币类型借贷地址等参数。执行过程中将代币转给传入的接收地址后会调用传入地址的 executeOperation 函数,这时可以在 executeOperation 函数完成其它操作。



AAVE 和 Uniswap 有一点点不同之处在于还款的流程。AAVE 闪电贷的还款,是需要借贷者向 LendingPool 合约授权,在完成闪电贷过程后,由 AAVE 合约将借用的钱和手续费从借款地址中转回。而在 Uniswap 中,是由用户调用 safeTransfer 进行手动转账。



这样可以保证更高的成功率,但相应的可能有一定的合约漏洞风险。


03 闪电贷攻击


关于闪电贷攻击的讨论是不断的。有人说闪电贷攻击严格来讲名不副实,因为并没有利用闪电贷的漏洞,而是利用大额的资金提前发现了已有的漏洞。比如利用闪电贷低成本的大额资金,可以:


1. 利用闪电贷大的资金量操纵价格,一些项目中价格获取逻辑存在问题。


2. 一些项目在抵押或其它过程中会产生瞬时奖励,利用闪电贷获得大额奖励。


3. 项目中存在其它的逻辑漏洞,利用闪电贷大的资金量放大套利空间。


我们先从案例进行分析,然后再讨论哪些漏洞容易被闪电贷攻击。


1 DFX 攻击事件


简单来讲,针对 DFX 的攻击分为三步:


1. 从 UniswapV3 完成对 USDC 和 XIDR 的闪电贷。



2. 从 DFX 的合约中调用 flash 函数借贷到 UCDC 和 XIDR 后又去调用了 deposit 函数进行了抵押,抵押时可以看到又将黑客借出的钱抵押回了 DFX 合约。



3. 因为用户抵押时将代币又转回到了 DFX 的合约导致借款前后的余额验证通过,不用再归还借出的闪电贷,但是黑客有抵押操作,此时便可以调用提取函数,提取抵押后离场。



2 常见漏洞分析


让我们来盘点一下下面代码都有哪些漏洞。


1. 通过代币数量获取价格:



这段代码直接读取了去中心化交易所 pair 合约中的代币数量,将两者之商作为代币的价格。对于缺乏代码审计经验的人来说,这样写乍一看似乎没有什么问题。但是如果考虑到 Uniswap 支持闪电贷这一事实,事情就变得有趣了起来。


如果没有闪电贷,两种代币的数量一定是一个减少另一个就增加。但是有了闪电贷,很有可能发生的局面是一个代币减少,而另一种代币没有增加。如果闪电贷的数额不大,两种情况下的差额不大。但如果借出了巨额闪电贷,这个价差将会被立刻拉大,形成巨大套利空间。


这样的漏洞对于没有代码审计经验的人来说很难发现,需要在安全领域有较长时间的深耕和积累,才能形成一套成熟的代码审计体系。


2. 发放奖励:



在这段代码中,合约会根据抵押量的大小,立刻将奖励返还给用户地址。这里的问题我们已经提到过了,也是比较好想到。如果奖励发放没有延迟,闪电贷的钱在合约中质押了仅仅一瞬间就能获得奖励,这样无疑是一个巨大的套利漏洞。


3 防范措施


在 DeFi 还没有成熟的时间段内,闪电贷攻击仍将持续不断,成为悬在人们头上的一把达摩克利斯之剑。不同的闪电贷攻击影响的范围也不同,有的可能导致某个看起来毫不相干的 DeFi 协议暴雷,有的可能波及众多用户。我们能做好的就是做好防范措施,静待 DeFi 不断成熟:


1. 质押挖矿功能和借贷合约做分离,不要将用户抵押的代币转移到借贷合约或者记录变量做运算。


2. 借贷时添加特殊重入锁,借贷时不允许抵押。


3. 项目在价格获取时采用多数据源的形式,数据对比后减小价格误差。


4. 移除流动性时应当先销毁 LP,再进行其它调用。


5. 奖励的产生尽量采用隔区块或者时间差的形式,可以有效避免闪电贷攻击。


6. 项目逻辑问题是导致黑客利用闪电贷放大套利最常见得情况。因此,项目在上线前要做好安全审计和测试,保证项目安全性。

相关Wiki

【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。

在 App 打开
空投
rwa
稳定币
wct
hyperliquid
uniswap
initia
fo
以太坊
om
crv
香港