Solidity智能合约安全指南 solidity-security

本指南提供Solidity智能合约开发的核心安全模式与漏洞防范措施,涵盖重入攻击防护、访问控制、整数安全、预言机安全、闪电贷风险及Gas优化等关键领域。适用于以太坊智能合约开发者、安全审计员和区块链工程师,帮助构建安全可靠的DeFi、NFT及链上应用。关键词:Solidity安全,智能合约审计,重入攻击,访问控制,预言机,闪电贷,Gas优化,区块链安全。

智能合约 0 次安装 0 次浏览 更新于 2/23/2026

name: solidity-security description: Solidity安全模式与漏洞防范。在编写任何Solidity代码前、代码审查期间或部署前使用。涵盖重入攻击、访问控制、整数安全、预言机操纵、闪电贷和Gas优化。

Solidity 安全

重入攻击

CEI模式(检查-效果-交互)—— 不可协商

function withdraw(uint256 amount) external {
    // 检查
    require(balances[msg.sender] >= amount, InsufficientBalance());

    // 效果(在外部调用前更新状态)
    balances[msg.sender] -= amount;

    // 交互(最后进行外部调用)
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success, TransferFailed());
}

额外防护

  • 对于复杂函数,使用OpenZeppelin的ReentrancyGuard
  • 跨函数重入:保护多个函数间共享的状态
  • 只读重入:注意在回调期间读取陈旧状态的视图函数

访问控制

模式 适用场景
Ownable 单一管理员,简单合约
AccessControl(角色) 多角色,细粒度权限
多签(Safe) 高价值操作,主网
时间锁 治理,延迟执行
  • 切勿使用tx.origin进行授权——使用msg.sender
  • 在修饰器中检查msg.sender,而非函数体内(除非逻辑复杂)
  • 考虑两步所有权转移(Ownable2Step

整数安全

  • Solidity 0.8+ 内置溢出/下溢保护
  • 仅当溢出在数学上不可能时使用unchecked
  • 记录每个unchecked块安全的原因
  • 使用type(uint256).max而非魔数
  • 注意先除后乘的精度损失

抢先交易 / MEV

攻击 缓解措施
三明治攻击 滑点保护,截止时间参数
抢先交易 提交-揭示方案
MEV提取 使用Flashbots,私有内存池
预言机操纵 时间加权平均价格(TWAP),多数据源

预言机安全

  • 切勿使用单一DEX的现货价格——使用TWAP
  • Chainlink:检查updatedAt新鲜度,answeredInRound >= roundId
  • 优雅处理预言机停机(断路器)
  • 使用多预言机源并设置回退逻辑

委托调用风险

  • 代理与实现合约的存储布局必须匹配
  • 切勿对不受信任的地址进行delegatecall
  • 实现合约必须在构造函数中调用_disableInitializers()
  • 注意代理模式中的存储冲突

闪电贷攻击向量

  • 假设单笔交易可借入任意数量的代币
  • 不要在同一区块内依赖代币余额进行治理权重计算
  • 使用快照机制记录投票权
  • 对关键操作添加时间加权检查

存储冲突(代理)

  • 使用EIP-1967存储槽存储代理状态
  • 升级时切勿修改存储布局顺序——仅可追加
  • 使用/// @custom:storage-location进行命名空间存储(EIP-7201)
  • 升级前运行forge inspect验证存储布局

详细参考