Transient Storage Vulns in Solidity
字数 1847 2025-08-29 08:30:12

Solidity Transient Storage 漏洞分析与实战教学

1. Transient Storage 概述

1.1 基本概念

Transient Storage 是 Solidity 0.8.24 版本引入的新特性,通过 EIP-1153 提案实现。它提供了:

  • 第四种数据存储位置(区别于 memory、storage、calldata)
  • 键值对存储方式
  • 仅在同一个交易中有效,交易结束时自动清零
  • 比常规 storage 更低的 gas 消耗

1.2 技术实现

Solidity 通过两个新的字节码支持 Transient Storage:

  • TSTORE - 存储数据
  • TLOAD - 加载数据

在 Solidity 0.8.28 版本中,进一步引入了 transient 关键字,使开发者无需使用汇编即可方便地使用 Transient Storage。

2. Transient Storage 的安全风险

2.1 跨交易不可组合性

Transient Storage 只在单个交易内保持状态,这会导致跨交易调用时出现非预期行为。

示例问题

// 使用 Transient Storage 的乘法器
function setMultiplier(uint x) { /* 使用 TSTORE 存储 */ }
function multiply(uint y) returns (uint) { /* 使用 TLOAD 读取并计算 */ }

连续三个交易:

  1. setMultiplier(42)
  2. multiply(1) → 返回 42
  3. multiply(2) → 返回 0(非预期的 84)

2.2 恶意组合复用风险

在同一交易内,Transient Storage 变量会跨函数调用保持,可能导致:

  1. 变量被多次重复利用
  2. 外部调用后变量状态被恶意操控

官方建议

建议在智能合约调用结束时完全清除 Transient Storage 变量,以避免此类问题,并简化复杂交易中合约行为的分析。

3. 实战案例:RemedyCTF 2025 tokemak

3.1 题目概述

目标:耗尽 LFGStaker 合约中的初始资产

合约功能

  • 用户质押 autoETH(类似 LP token)到 LFGStaker 合约
  • 用户获得收益
  • 提供 deposit 和 redeem 功能

3.2 漏洞分析路径

  1. 检查资产转换精度

    • 确认 deposit/redeem 中 assets 和 shares 的转换是否存在精度套利
    • 本例中无套利机会
  2. 分析 totalAssets()

    • 调用 autoETH.previewRedeem()
    • 该函数内部有复杂调用链,最终会:
      1. 检查闲置资金
      2. 不足时从流动性池(DestVault)取出
      3. 将取出的代币交换为所需资产
      4. 返回给用户并销毁 LP token
  3. 关键漏洞点

    • 交换步骤允许用户指定任意汇率的池子
    • 影响 totalAssets() 返回值
    • 使用 Transient Storage 决定是否使用用户指定池子

3.3 攻击步骤

  1. 初始资金获取

    • 使用闪电贷(如 Aave 或 dYdX)借入大量资金
  2. Transient Storage 操控

    • 通过 AutopilotRouter.redeemWithRoutes() 设置 customRoutes
    • 该函数会:
      • initTransientSwap 设置路由
      • 调用 vault.redeem(vault 为用户控制)
      • exitTransientSwap 清除状态
    • 攻击方法:
      • 传入自定义 vault 合约
      • vault.redeem 中执行攻击代码
      • 此时 Transient Storage 变量仍有效
  3. 套利执行

    • 通过恶意池子操纵资产估值
    • 调整 deposit/redeem 参数进行多轮套利

4. 防御建议

  1. Transient Storage 使用规范

    • 始终在函数结束时清除 Transient 变量
    • 避免在设置 Transient 变量后调用外部合约
  2. 安全模式

    function operation() external {
        // 设置 Transient 变量
        transientVar = x;
    
        // 执行操作
        _internalOperation();
    
        // 清除 Transient 变量
        delete transientVar;
    }
    
    function _internalOperation() internal {
        // 不包含外部调用
        // ...
    }
    
  3. 合约设计建议

    • 限制用户传入的合约地址权限
    • 对关键操作添加重入保护
    • 对 Transient Storage 的使用进行严格审计

5. 总结

Transient Storage 为 Solidity 提供了高效的临时存储方案,但也引入了新的安全考虑:

  1. 必须理解其生命周期(单交易有效)
  2. 警惕跨函数调用的状态保持
  3. 特别注意外部调用时的状态操控风险
  4. 遵循"设置-使用-清除"的最佳实践

通过 tokemak 案例可以看出,即使是简单的存储功能,在组合调用和外部合约交互的复杂场景下,也可能导致严重的安全漏洞。开发者需要全面理解这些新特性的行为特性,才能编写出安全的智能合约。

Solidity Transient Storage 漏洞分析与实战教学 1. Transient Storage 概述 1.1 基本概念 Transient Storage 是 Solidity 0.8.24 版本引入的新特性,通过 EIP-1153 提案实现。它提供了: 第四种数据存储位置(区别于 memory、storage、calldata) 键值对存储方式 仅在同一个交易中有效,交易结束时自动清零 比常规 storage 更低的 gas 消耗 1.2 技术实现 Solidity 通过两个新的字节码支持 Transient Storage: TSTORE - 存储数据 TLOAD - 加载数据 在 Solidity 0.8.28 版本中,进一步引入了 transient 关键字,使开发者无需使用汇编即可方便地使用 Transient Storage。 2. Transient Storage 的安全风险 2.1 跨交易不可组合性 Transient Storage 只在单个交易内保持状态,这会导致跨交易调用时出现非预期行为。 示例问题 : 连续三个交易: setMultiplier(42) multiply(1) → 返回 42 multiply(2) → 返回 0(非预期的 84) 2.2 恶意组合复用风险 在同一交易内,Transient Storage 变量会跨函数调用保持,可能导致: 变量被多次重复利用 外部调用后变量状态被恶意操控 官方建议 : 建议在智能合约调用结束时完全清除 Transient Storage 变量,以避免此类问题,并简化复杂交易中合约行为的分析。 3. 实战案例:RemedyCTF 2025 tokemak 3.1 题目概述 目标 :耗尽 LFGStaker 合约中的初始资产 合约功能 : 用户质押 autoETH(类似 LP token)到 LFGStaker 合约 用户获得收益 提供 deposit 和 redeem 功能 3.2 漏洞分析路径 检查资产转换精度 : 确认 deposit/redeem 中 assets 和 shares 的转换是否存在精度套利 本例中无套利机会 分析 totalAssets() : 调用 autoETH.previewRedeem() 该函数内部有复杂调用链,最终会: 检查闲置资金 不足时从流动性池(DestVault)取出 将取出的代币交换为所需资产 返回给用户并销毁 LP token 关键漏洞点 : 交换步骤允许用户指定任意汇率的池子 影响 totalAssets() 返回值 使用 Transient Storage 决定是否使用用户指定池子 3.3 攻击步骤 初始资金获取 : 使用闪电贷(如 Aave 或 dYdX)借入大量资金 Transient Storage 操控 : 通过 AutopilotRouter.redeemWithRoutes() 设置 customRoutes 该函数会: initTransientSwap 设置路由 调用 vault.redeem (vault 为用户控制) exitTransientSwap 清除状态 攻击方法: 传入自定义 vault 合约 在 vault.redeem 中执行攻击代码 此时 Transient Storage 变量仍有效 套利执行 : 通过恶意池子操纵资产估值 调整 deposit/redeem 参数进行多轮套利 4. 防御建议 Transient Storage 使用规范 : 始终在函数结束时清除 Transient 变量 避免在设置 Transient 变量后调用外部合约 安全模式 : 合约设计建议 : 限制用户传入的合约地址权限 对关键操作添加重入保护 对 Transient Storage 的使用进行严格审计 5. 总结 Transient Storage 为 Solidity 提供了高效的临时存储方案,但也引入了新的安全考虑: 必须理解其生命周期(单交易有效) 警惕跨函数调用的状态保持 特别注意外部调用时的状态操控风险 遵循"设置-使用-清除"的最佳实践 通过 tokemak 案例可以看出,即使是简单的存储功能,在组合调用和外部合约交互的复杂场景下,也可能导致严重的安全漏洞。开发者需要全面理解这些新特性的行为特性,才能编写出安全的智能合约。