关于 solidity-security
为 Solidity 开发和审查提供安全规则与检查清单的技能,面向开发者及代码审查者。内容涵盖合约常见风险、密钥保护、测试要求,并说明可选的 Slither MCP 分析方式。
主要功能
- 01Solidity 安全编码规则
- 02私钥与环境文件保护
- 03访问控制和重入防护建议
- 04预审清单与测试要求
- 05Slither MCP 结果分析指引
适用场景
- 01编写或审查 Solidity 合约
- 02检查代币转账与权限控制
- 03准备合约审计前的检查
- 04通过 Slither MCP 查看结构化发现
MCP 相关
文档介绍了可选的 Slither MCP 集成,用于获取检测结果、合约元数据和函数源码;没有配置时可使用 Slither CLI 或检查清单。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ 0xlayerghost/ solidity-agent-kit --skill solidity-security安装后在 Claude Code 中输入/solidity-security确认已加载。
详细介绍
Solidity 安全标准
语言规则
- 始终使用用户所用的语言回复。 如果用户用中文提问,就用中文回复;如果用英文提问,就用英文回复。
私钥保护
- 在执行链上写入操作前,让开发者选择签名方式:
- Foundry Keystore(推荐): 使用
cast wallet import <NAME> --interactive导入,并使用--account <NAME>。 - 环境文件: 将
PRIVATE_KEY存储在.env中,使用source .env加载,并通过"$PRIVATE_KEY"引用;切勿将实际值直接粘贴到命令中。
- Foundry Keystore(推荐): 使用
- 切勿在日志、截图、对话或提交记录中泄露私钥
- 提供带占位值的
.env.example,供团队参考 - 将
.env添加到.gitignore中——每次提交前都使用git status验证 - 切勿读取或打印开发者的
.env;只提供由开发者运行的命令
安全决策规则
编写或审查 Solidity 代码时,应用以下规则:
| 情况 | 必须采取的操作 |
|---|---|
| 外部 ETH/代币转账 | 使用 ReentrancyGuard + 检查-生效-交互(CEI)模式 |
| ERC20 代币交互 | 使用 SafeERC20——调用 safeTransfer / safeTransferFrom,绝不使用原始 transfer / transferFrom |
| 仅限所有者的函数 | 继承 OZ 4.9.x 中的 Ownable2Step(优先)或 Ownable——Ownable2Step 可防止所有者意外丢失权限 |
| 多角色访问 | 使用 @openzeppelin/contracts/access/AccessControl.sol 中的 AccessControl |
| 代币授权 | 使用 SafeERC20 中的 safeIncreaseAllowance / safeDecreaseAllowance——绝不使用原始 approve |
| 需要价格数据 | 如果存在数据源,则使用 Chainlink AggregatorV3Interface;否则使用带最小流动性检查的 TWAP——绝不直接使用池子的现货价格 |
| 可升级合约 | 优先使用 UUPS(UUPSUpgradeable),而非 TransparentProxy;始终使用 Initializable |
| Solidity 版本 < 0.8.0 | 必须使用 SafeMath——但强烈建议升级到 0.8.20+ |
| 紧急情况 | 继承 Pausable,为面向用户的函数添加 whenNotPaused;保持管理/紧急函数不受暂停影响 |
| 白名单 / 空投 | 使用 MerkleProof 进行高效的 Gas 验证——绝不在链上存储完整地址列表 |
| 基于签名的身份验证 | 使用 ECDSA + EIP712——绝不自行实现签名验证 |
| 签名内容 | 签名必须绑定 chainId + nonce + msg.sender + deadline——防止重放和跨链复用 |
| 跨链桥 / 第三方依赖 | 审计所有继承的第三方合约代码——绝不假定依赖项是安全的 |
| 已弃用 / 遗留合约 | 永久 pause 或 selfdestruct 已弃用的合约——绝不让未使用的合约继续在链上可调用 |
| UUPS 升级模式 | _authorizeUpgrade 必须带有 onlyOwner;实现合约的构造函数调用 _disableInitializers();在 upgradeTo 上保留 onlyProxy — EVMbench/basin H-01 |
| 多合约信任边界 | Router/Registry 中继调用必须验证源合约授权;绝不在闪电贷回调中信任调用者身份 — EVMbench/noya H-08 |
| 计数器/ID + 外部调用 | 所有计数器递增和 ID 赋值都必须在外部调用前完成;ETH 退款必须最后执行 — EVMbench/phi H-06 |
重入保护
- 所有包含外部调用的合约:继承
ReentrancyGuard,并添加nonReentrant修饰符- 导入:
@openzeppelin/contracts/security/ReentrancyGuard.sol(OZ 4.9.x)
- 导入:
- 即使使用了
ReentrancyGuard,也始终应用 CEI 模式:- 检查——验证所有条件(
require) - 生效——更新状态变量
- 交互——最后执行外部调用
- 检查——验证所有条件(
输入验证
- 所有地址参数均拒绝
address(0) - 资金转账拒绝零金额
- 处理成对数组时,验证数组长度是否匹配
- 将数值输入限制在合理范围内(防止粉尘攻击和 Gas 消耗骚扰)
Gas 控制
- 部署命令必须包含
--gas-limit(建议不低于 3,000,000) - 使用
forge test --gas-report监控 Gas——每次 PR 前都要检查 - 在
foundry.toml中配置优化器:optimizer = true、optimizer_runs = 200 - 避免对动态数组进行无界循环——使用分页或拉取模式
审计前检查清单
提交代码以供审查或审计前,请确认:
访问与控制:
- 所有适用的 external/public 函数都使用
nonReentrant - 身份验证中未使用
tx.origin(请使用msg.sender) - 未对不受信任的地址使用
delegatecall - 所有者转移使用
Ownable2Step(而非Ownable),以防意外丢失所有权 - 含有面向用户函数的合约继承
Pausable,并实现pause()/unpause() - UUPS
_authorizeUpgrade带有onlyOwner修饰符 — EVMbench/basin H-01 - 实现合约的构造函数调用
_disableInitializers()— EVMbench/basin H-01 - Router/Registry 中继操作会验证源合约授权 — EVMbench/noya H-08
代币与资金安全:
- 所有 ERC20 交互都使用
SafeERC20(safeTransfer/safeTransferFrom) - 不使用原始的
token.transfer()或require(token.transfer())模式 - 代币授权使用
safeIncreaseAllowance,而非原始的approve - 检查所有
external call的返回值
代码质量:
- 每次状态变更都会发出事件
- 不使用硬编码地址——使用配置或构造函数参数
-
.env已加入.gitignore
预言机与价格(如适用):
- 价格数据来自 Chainlink feed 或 TWAP——绝不使用原始现货价格
- 预言机会检查最低流动性——若池储备过低则回滚
- 已设置价格偏差熔断机制
测试:
-
forge test通过且零失败 -
forge coverage显示安全关键路径具有足够的覆盖率 - 模糊测试覆盖算术边界情况(零、最大 uint、边界值)
安全验证命令
# Run all tests with gas report
forge test --gas-report
# Fuzz testing with higher runs for critical functions
forge test --fuzz-runs 10000
# Check test coverage
forge coverage
# Dry-run deployment to verify no runtime errors
forge script script/Deploy.s.sol --fork-url $RPC_URL -vvvv
# Static analysis (if slither installed locally)
slither src/
Slither MCP 集成(如可用)
配置了 slither MCP 时,优先使用它而非 CLI,以便进行结构化分析:
| 方式 | 使用场景 |
|---|---|
slither src/(CLI) | 快速本地扫描,输出原始终端结果 |
slither MCP get_detector_results | 提供结构化结果,支持按影响和置信度筛选,AI 可解析并分析发现的问题 |
slither MCP get_contract_metadata | 审查代码前了解合约结构 |
slither MCP get_function_source | 比 grep 更快地定位具体函数实现 |
建议:使用 AI Agent 时优先使用 slither MCP(结果结构化且可执行)。开发过程中进行快速本地检查时使用 CLI。
降级处理:如果 slither MCP 和 slither CLI 均不可用,请依赖上述审计前检查清单,并使用 forge test --fuzz-runs 10000 进行覆盖测试。
评论
支持 Markdown