solidity-security
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSolidity Security Standards
Solidity安全标准
Language Rule
语言规则
- Always respond in the same language the user is using. If the user asks in Chinese, respond in Chinese. If in English, respond in English.
- 始终使用用户使用的语言进行响应。如果用户用中文提问,就用中文回复;如果用英文,就用英文回复。
Private Key Protection
私钥保护
- Store private keys in , load via
.env— never pass keys as CLI argumentssource .env - Never expose private keys in logs, screenshots, conversations, or commits
- Provide with placeholder values for team reference
.env.example - Add to
.env— verify with.gitignorebefore every commitgit status
- 将私钥存储在文件中,通过
.env加载——绝不要将密钥作为CLI参数传递source .env - 绝不要在日志、截图、对话或提交记录中暴露私钥
- 提供带有占位符值的供团队参考
.env.example - 将添加到
.env中——每次提交前用.gitignore确认git status
Security Decision Rules
安全决策规则
When writing or reviewing Solidity code, apply these rules:
| Situation | Required Action |
|---|---|
| External ETH/token transfer | Use |
| ERC20 token interaction | Use |
| Owner-only function | Inherit |
| Multi-role access | Use |
| Token approval | Use |
| Price data needed | Use Chainlink |
| Upgradeable contract | Prefer UUPS ( |
| Solidity version < 0.8.0 | Must use |
| Emergency scenario | Inherit |
| Whitelist / airdrop | Use |
| Signature-based auth | Use |
| Signature content | Signature must bind |
| Cross-chain bridge / third-party dependency | Audit all inherited third-party contract code — never assume dependencies are safe |
| Deprecated / legacy contracts | Permanently |
| UUPS upgrade pattern | |
| Multi-contract trust boundary | Router/Registry relay calls must verify source contract authorization; never trust caller identity inside flash loan callbacks — EVMbench/noya H-08 |
| Counter/ID + external call | All counter increments and ID assignments must complete before external calls; ETH refunds must be last — EVMbench/phi H-06 |
编写或审核Solidity代码时,请遵循以下规则:
| 场景 | 要求操作 |
|---|---|
| 外部ETH/代币转账 | 使用 |
| ERC20代币交互 | 使用 |
| 仅所有者可调用函数 | 继承OpenZeppelin(OZ)4.9.x版本的 |
| 多角色访问控制 | 使用 |
| 代币授权 | 使用 |
| 需要价格数据 | 若存在Chainlink预言机则使用 |
| 可升级合约 | 优先选择UUPS( |
| Solidity版本 < 0.8.0 | 必须使用 |
| 紧急场景 | 继承 |
| 白名单/空投 | 使用 |
| 基于签名的认证 | 使用 |
| 签名内容 | 签名必须绑定 |
| 跨链桥/第三方依赖 | 审计所有继承的第三方合约代码——绝不要假设依赖是安全的 |
| 已废弃/遗留合约 | 永久 |
| UUPS升级模式 | |
| 多合约信任边界 | 路由/注册中心的中继调用必须验证源合约的授权;在闪电贷回调中绝不要信任调用者身份——参考EVMbench/noya H-08 |
| 计数器/ID + 外部调用 | 所有计数器递增和ID分配必须在外部调用前完成;ETH退款必须放在最后——参考EVMbench/phi H-06 |
Reentrancy Protection
重入防护
- All contracts with external calls: inherit , add
ReentrancyGuardmodifiernonReentrant- Import: (OZ 4.9.x)
@openzeppelin/contracts/security/ReentrancyGuard.sol
- Import:
- Always apply CEI pattern even with :
ReentrancyGuard- Checks — validate all conditions ()
require - Effects — update state variables
- Interactions — external calls last
- Checks — validate all conditions (
- 所有包含外部调用的合约:继承,添加
ReentrancyGuard修饰器nonReentrant- 导入路径:(OZ 4.9.x版本)
@openzeppelin/contracts/security/ReentrancyGuard.sol
- 导入路径:
- 即使使用,也始终遵循CEI模式:
ReentrancyGuard- 检查——验证所有条件(使用)
require - 状态变更——更新状态变量
- 交互——最后执行外部调用
- 检查——验证所有条件(使用
Input Validation
输入验证
- Reject for all address parameters
address(0) - Reject zero amounts for fund transfers
- Validate array lengths match when processing paired arrays
- Bound numeric inputs to reasonable ranges (prevent dust attacks, gas griefing)
- 拒绝所有地址参数为的情况
address(0) - 拒绝资金转账金额为0的情况
- 处理配对数组时验证数组长度匹配
- 对数值输入设置合理范围(防止粉尘攻击、Gas消耗攻击)
Gas Control
Gas控制
- Deployment commands must include (recommended >= 3,000,000)
--gas-limit - Monitor gas with — review before every PR
forge test --gas-report - Configure optimizer in :
foundry.toml,optimizer = trueoptimizer_runs = 200 - Avoid unbounded loops over dynamic arrays — use pagination or pull patterns
- 部署命令必须包含(推荐值≥3,000,000)
--gas-limit - 使用监控Gas消耗——每个PR提交前都要检查
forge test --gas-report - 在中配置优化器:
foundry.toml,optimizer = trueoptimizer_runs = 200 - 避免对动态数组进行无界循环——使用分页或拉取模式
Pre-Audit Checklist
审计前检查清单
Before submitting code for review or audit, verify:
Access & Control:
- All external/public functions have where applicable
nonReentrant - No used for authentication (use
tx.origin)msg.sender - No to untrusted addresses
delegatecall - Owner transfer uses (not
Ownable2Step) to prevent accidental lossOwnable - Contracts with user-facing functions inherit with
Pausable/pause()unpause() - UUPS has
_authorizeUpgrademodifier — EVMbench/basin H-01onlyOwner - Implementation constructor calls — EVMbench/basin H-01
_disableInitializers() - Router/Registry relay operations verify source contract authorization — EVMbench/noya H-08
Token & Fund Safety:
- All ERC20 interactions use (
SafeERC20/safeTransfer)safeTransferFrom - No raw or
token.transfer()patternsrequire(token.transfer()) - Token approvals use , not raw
safeIncreaseAllowanceapprove - All return values checked
external call
Code Quality:
- Events emitted for every state change
- No hardcoded addresses — use config or constructor params
- is in
.env.gitignore
Oracle & Price (if applicable):
- Price data sourced from Chainlink feed or TWAP — never raw spot price
- Oracle has minimum liquidity check — revert if pool reserves too low
- Price deviation circuit breaker in place
Testing:
- passes with zero failures
forge test - shows adequate coverage on security-critical paths
forge coverage - Fuzz tests cover arithmetic edge cases (zero, max uint, boundary values)
在提交代码进行评审或审计前,请验证以下内容:
访问与控制:
- 所有外部/公共函数在适用时都带有修饰器
nonReentrant - 未使用进行身份认证(使用
tx.origin)msg.sender - 未向不可信地址发起
delegatecall - 所有者权限转移使用(而非
Ownable2Step)以防止意外丢失权限Ownable - 带有面向用户函数的合约继承并实现
Pausable/pause()unpause() - UUPS的带有
_authorizeUpgrade修饰器——参考EVMbench/basin H-01onlyOwner - 实现合约的构造函数调用——参考EVMbench/basin H-01
_disableInitializers() - 路由/注册中心的中继操作验证源合约的授权——参考EVMbench/noya H-08
代币与资金安全:
- 所有ERC20交互都使用(
SafeERC20/safeTransfer)safeTransferFrom - 未使用原生或
token.transfer()模式require(token.transfer()) - 代币授权使用,而非原生
safeIncreaseAllowanceapprove - 所有的返回值都已检查
external call
代码质量:
- 每次状态变更都触发了事件
- 没有硬编码地址——使用配置或构造函数参数
- 已添加到
.env中.gitignore
预言机与价格(若适用):
- 价格数据来自Chainlink预言机或TWAP——绝不要使用原生现货价格
- 预言机带有最低流动性检查——若池储备过低则回滚
- 已设置价格偏差断路器
测试:
- 执行通过,无失败用例
forge test - 显示安全关键路径有足够的覆盖率
forge coverage - 模糊测试覆盖了算术边缘情况(零值、最大uint、边界值)
Security Verification Commands
安全验证命令
bash
undefinedbash
undefinedRun all tests with gas report
运行所有测试并生成Gas报告
forge test --gas-report
forge test --gas-report
Fuzz testing with higher runs for critical functions
对关键函数进行更高次数的模糊测试
forge test --fuzz-runs 10000
forge test --fuzz-runs 10000
Check test coverage
检查测试覆盖率
forge coverage
forge coverage
Dry-run deployment to verify no runtime errors
预部署以验证无运行时错误
forge script script/Deploy.s.sol --fork-url $RPC_URL -vvvv
forge script script/Deploy.s.sol --fork-url $RPC_URL -vvvv
Static analysis (if slither installed locally)
静态分析(若本地已安装slither)
slither src/
undefinedslither src/
undefinedSlither MCP Integration (if available)
Slither MCP集成(若可用)
When MCP is configured, prefer it over the CLI for structured analysis:
slither| Approach | When to Use |
|---|---|
| Quick local scan, raw terminal output |
slither MCP | Structured results with impact/confidence filtering, AI can parse and reason about findings |
slither MCP | Understanding contract structure before reviewing code |
slither MCP | Locating exact function implementations faster than grep |
Recommended: Use slither MCP when working with AI agents (results are structured and actionable). Use CLI for quick local checks during development.
Graceful degradation: If neither slither MCP nor slither CLI is available, rely on the Pre-Audit Checklist above and for coverage.
forge test --fuzz-runs 10000当配置了 MCP时,优先使用它而非CLI进行结构化分析:
slither| 方式 | 使用场景 |
|---|---|
| 快速本地扫描,原生终端输出 |
slither MCP | 带有影响度/置信度筛选的结构化结果,AI可解析并处理发现的问题 |
slither MCP | 在评审代码前了解合约结构 |
slither MCP | 比grep更快定位具体函数实现 |
推荐:与AI Agent协作时使用slither MCP(结果结构化且可执行)。开发过程中使用CLI进行快速本地检查。
降级方案:若slither MCP和CLI都不可用,则依赖上述审计前检查清单和来保证覆盖率。
forge test --fuzz-runs 10000