Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
RPC Assistant

智能合约安全最佳实践:开发者检查清单

摘要

了解Solidity开发者必备的智能合约安全最佳实践,包括重入保护、访问控制和安全的数学运算。了解可靠RPC端点等基础设施选择如何支持安全部署和监控。

智能合约安全决策检查清单

在部署任何智能合约之前,请验证以下六项安全控制措施:

  • 使用重入保护(例如OpenZeppelin的ReentrancyGuard)。
  • 应用检查-效果-交互模式。
  • 使用msg.sender进行身份验证,而不是tx.origin。
  • 使用显式的可见性修饰符(public、private、internal、external)。
  • 使用Solidity 0.8+的内置检查或较旧版本的SafeMath来处理整数溢出。
  • 在公共测试网上使用可靠的RPC端点(例如,通过OnFinality等提供商的Sepolia)进行测试,以模拟真实条件。

常见智能合约漏洞

智能合约执行链上逻辑,部署后不可变。这种不可变性使得安全性至关重要。下表列出了最常见的漏洞及其缓解措施。

漏洞缓解措施重要性
重入攻击使用重入保护以及检查-效果-交互模式防止攻击者递归调用提款函数以耗尽资金
访问控制实施基于角色的访问控制(例如OpenZeppelin AccessControl)确保只有授权角色才能执行特权函数
整数溢出/下溢使用Solidity 0.8+(内置检查)或SafeMath库防止数学错误导致铸造无限代币或窃取资金
未检查的外部调用验证call / delegatecall的返回值避免在调用实际回退时误以为成功
时间戳依赖避免在关键逻辑中使用block.timestamp矿工可以在小窗口内操纵时间戳,破坏基于时间的条件
抢先交易使用提交-揭示方案或时间锁保护用户免受看到待处理交易并利用价格差异的影响

Solidity安全最佳实践

1. 使用重入保护

重入发生在合约在更新自身状态之前对外部不可信合约进行外部调用时。攻击者的回退函数可以重新进入原始函数并耗尽资金。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract SecureVault is ReentrancyGuard {
    mapping(address => uint256) public balances;

    function withdraw(uint256 _amount) external nonReentrant {
        require(balances[msg.sender] >= _amount, "余额不足");
        balances[msg.sender] -= _amount;
        (bool success, ) = msg.sender.call{value: _amount}("");
        require(success, "转账失败");
    }
}

nonReentrant修饰符防止嵌套调用。始终在外部调用之前更新状态(检查-效果-交互)。

2. 使用msg.sender而不是tx.origin

tx.origin返回发起交易的初始外部账户。如果恶意合约通过攻击者的账户调用你的合约,tx.origin将是攻击者,这可以绕过身份验证。

// 错误:使用tx.origin进行授权
function withdraw() public {
    require(tx.origin == owner, "不是所有者");
    // ...
}

// 正确:使用msg.sender
function withdraw() external {
    require(msg.sender == owner, "不是所有者");
    // ...
}

始终使用msg.sender进行直接身份验证。

3. 正确使用可见性修饰符

显式声明函数和状态变量的可见性。公共函数和变量可从外部访问;对于仅从合约外部调用的函数,使用external以节省gas。将内部函数标记为internal,私有函数标记为private。

contract VisibilityExample {
    uint256 private secretNumber; // 仅此合约
    string public name; // 任何人都可读取

    function doSomething() external { /* ... */ }
    function _helper() internal { /* ... */ } // 仅派生合约
}

4. 避免对不可信合约使用delegatecall

delegatecall在调用者的上下文中执行另一个合约的代码。恶意实现可以修改存储或耗尽资金。如果必须使用代理,请遵循既定模式,如OpenZeppelin的透明代理或UUPS代理。

// 风险:委托给任意地址
function execute(address _impl, bytes memory _data) public {
    (bool success, ) = _impl.delegatecall(_data);
    require(success);
}

5. 对于Solidity <0.8.0,使用SafeMath

如果你使用较旧的Solidity版本,始终使用OpenZeppelin的SafeMath库来防止算术溢出。自Solidity 0.8.0起,溢出检查已内置。

6. 使用OpenZeppelin进行访问控制

不要硬编码所有者地址,而是使用基于角色的系统。

import "@openzeppelin/contracts/access/AccessControl.sol";

contract MyToken is AccessControl {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

    function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
        _mint(to, amount);
    }
}

使用可靠RPC进行测试和监控

安全并非止于部署。持续监控链上交易和合约交互至关重要。可靠的RPC提供商为你提供:

  • 高可用性端点,用于实时监控事件。
  • 访问存档数据,对可疑交易进行历史分析。
  • 低延迟连接,快速检测漏洞利用。

使用像OnFinality这样的专用节点服务,可以让你的自动监控脚本在关键事件期间无需担心速率限制即可查询链。查看我们的支持的网络和RPC定价以规划你的基础设施。

使用Trace API进行安全分析

为了检测重入或恶意delegatecall,你可以使用debug_traceTransaction API(以太坊)逐步检查交易的执行。这需要一个启用了追踪的存档节点。

curl -X POST <RPC_ENDPOINT> -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "method": "debug_traceTransaction",
  "params": ["0x...txhash"],
  "id": 1
}'

在确定平台之前,确保你的RPC提供商支持存档和追踪方法。

安全工具与审计

在部署之前,运行自动静态分析工具:

  • Slither:检测常见漏洞并生成函数图。
  • Mythril:符号执行引擎,检查安全漏洞。
  • Echidna:基于属性的模糊测试工具。
  • Surya:可视化合约控制流。

此外,考虑聘请专业审计公司如ConsenSys Diligence或Trail of Bits进行审计。结合自动扫描和手动审查以实现全面覆盖。

关键要点

  1. 始终使用重入保护,并遵循检查-效果-交互模式。
  2. 选择Solidity 0.8+或SafeMath以防止整数溢出。
  3. 使用msg.sender进行身份验证,并使用显式可见性修饰符。
  4. 避免对不可信合约使用delegatecall;谨慎使用代理模式。
  5. 使用可靠RPC端点在测试网上进行全面测试。
  6. 使用高可用性RPC基础设施监控生产合约。

常见问题

问:如何选择用于安全监控的RPC提供商? 答:寻找提供存档数据、追踪API和WebSocket支持的提供商。根据你的监控频率评估其正常运行时间SLA和速率限制。比较选项。

问:我应该为我的智能合约使用私有RPC端点吗? 答:对于生产监控和敏感数据提取,专用RPC端点可降低速率限制风险并确保一致性能。公共端点适用于轻量测试。

问:我可以依赖Solidity内置的溢出检查吗? 答:自Solidity 0.8.0起,溢出检查默认启用。对于旧版本,你必须使用SafeMath或unchecked块(如果你确定操作不会溢出)。

问:测试重入的最佳方法是什么? 答:使用模拟递归调用的模拟合约进行单元测试。Foundry等工具允许你用Solidity编写此类测试。同时,使用Slither的reentrancy检测器运行静态分析。

RPC 知识库

相关 RPC 内容

网络 RPCBittensor

Bittensor 挖矿教程:如何保持矿工注册并在线?

Bittensor 挖矿不是算力挖矿。矿工在子网内运行模型或服务,在 Subtensor 链上注册热键,当验证者对其响应评分良好时获得排放。本教程将引导您完成实际路径:选择子网、设置钱包、注册、运行矿工,并保持链连接稳定。 最常见的故障点不是模型,而是连接性。注册、权重设置和元图同步都依赖于可靠的 ...

网络 RPCAvalanche

Polygon 网络 RPC:端点、链设置和调试

了解如何通过 RPC 连接到 Polygon 网络,包括 OnFinality 官方公共端点、链设置和常见故障排除步骤。本指南涵盖 JSON-RPC 方法、WebSocket 支持,以及如何为您的 dApp 选择公共、共享和专用 RPC 基础设施。...

网络 RPCAvalanche

Sonic 网络 RPC:链设置、端点和提供商选择

Sonic 是一个高性能的 EVM 兼容 Layer-1 区块链,具有亚秒级最终性。本页涵盖官方 Sonic 网络 RPC 设置、如何连接您的钱包或 dApp,以及如何评估用于生产环境的 RPC 提供商。我们还解释了何时选择托管或专用的 Sonic RPC 端点是正确的选择。...

网络 RPCxx network

什么是 xx network,开发者如何与之交互?

xx network 是一个抗量子、注重隐私的区块链,具有去中心化的混合网络(mixnet)。它基于 Substrate 链,并为开发者提供 RPC 端点。本文解释了该网络的架构、如何通过 RPC 连接,以及在选择基础设施以在 xx 上构建时需要考虑的事项。...

RPC 提供商选择Solana

如何选择Solana WebSocket基础设施提供商

Solana WebSocket基础设施支持实时账户订阅、交易监控和订单簿流。选择合适的提供商取决于你的工作负载:公共端点适合原型开发,但生产应用需要具有稳定连接和低延迟的托管或专用节点。本指南比较了提供商类型,并为你提供了实用的评估框架。...

RPC 提供商选择Base

哪些 RPC 提供商支持 Base RPC?

Base 是一个基于 OP Stack 构建的以太坊 Layer 2 网络,许多 RPC 提供商都为其提供端点。本文介绍了在选择 Base RPC 提供商时需要注意的事项,包括端点类型、可靠性和定价,并列出了值得考虑的几家主要提供商。...

永远不用担心基础设施

OnFinality 消除了 DevOps 的繁重工作,让您能够更聪明、更快地构建。

开始