solidity-security

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Solidity 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
    .env
    , load via
    source .env
    — never pass keys as CLI arguments
  • Never expose private keys in logs, screenshots, conversations, or commits
  • Provide
    .env.example
    with placeholder values for team reference
  • Add
    .env
    to
    .gitignore
    — verify with
    git status
    before every commit
  • 将私钥存储在
    .env
    文件中,通过
    source .env
    加载——绝不要将密钥作为CLI参数传递
  • 绝不要在日志、截图、对话或提交记录中暴露私钥
  • 提供带有占位符值的
    .env.example
    供团队参考
  • .env
    添加到
    .gitignore
    中——每次提交前用
    git status
    确认

Security Decision Rules

安全决策规则

When writing or reviewing Solidity code, apply these rules:
SituationRequired Action
External ETH/token transferUse
ReentrancyGuard
+ Checks-Effects-Interactions (CEI) pattern
ERC20 token interactionUse
SafeERC20
— call
safeTransfer
/
safeTransferFrom
, never raw
transfer
/
transferFrom
Owner-only functionInherit
Ownable2Step
(preferred) or
Ownable
from OZ 4.9.x —
Ownable2Step
prevents accidental owner loss
Multi-role accessUse
AccessControl
from
@openzeppelin/contracts/access/AccessControl.sol
Token approvalUse
safeIncreaseAllowance
/
safeDecreaseAllowance
from
SafeERC20
— never raw
approve
Price data neededUse Chainlink
AggregatorV3Interface
if feed exists; otherwise TWAP with min-liquidity check — never use spot pool price directly
Upgradeable contractPrefer UUPS (
UUPSUpgradeable
) over TransparentProxy; always use
Initializable
Solidity version < 0.8.0Must use
SafeMath
— but strongly prefer upgrading to 0.8.20+
Emergency scenarioInherit
Pausable
, add
whenNotPaused
to user-facing functions; keep admin/emergency functions unpaused
Whitelist / airdropUse
MerkleProof
for gas-efficient verification — never store full address lists on-chain
Signature-based authUse
ECDSA
+
EIP712
— never roll custom signature verification
Signature contentSignature must bind
chainId
+
nonce
+
msg.sender
+
deadline
— prevent replay and cross-chain reuse
Cross-chain bridge / third-party dependencyAudit all inherited third-party contract code — never assume dependencies are safe
Deprecated / legacy contractsPermanently
pause
or
selfdestruct
deprecated contracts — never leave unused contracts callable on-chain
UUPS upgrade pattern
_authorizeUpgrade
must have
onlyOwner
; implementation constructor calls
_disableInitializers()
; retain
onlyProxy
on
upgradeTo
EVMbench/basin H-01
Multi-contract trust boundaryRouter/Registry relay calls must verify source contract authorization; never trust caller identity inside flash loan callbacks — EVMbench/noya H-08
Counter/ID + external callAll counter increments and ID assignments must complete before external calls; ETH refunds must be last — EVMbench/phi H-06
编写或审核Solidity代码时,请遵循以下规则:
场景要求操作
外部ETH/代币转账使用
ReentrancyGuard
+ 检查-状态变更-交互(CEI)模式
ERC20代币交互使用
SafeERC20
——调用
safeTransfer
/
safeTransferFrom
,绝不要使用原生
transfer
/
transferFrom
仅所有者可调用函数继承OpenZeppelin(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
多合约信任边界路由/注册中心的中继调用必须验证源合约的授权;在闪电贷回调中绝不要信任调用者身份——参考EVMbench/noya H-08
计数器/ID + 外部调用所有计数器递增和ID分配必须在外部调用前完成;ETH退款必须放在最后——参考EVMbench/phi H-06

Reentrancy Protection

重入防护

  • All contracts with external calls: inherit
    ReentrancyGuard
    , add
    nonReentrant
    modifier
    • Import:
      @openzeppelin/contracts/security/ReentrancyGuard.sol
      (OZ 4.9.x)
  • Always apply CEI pattern even with
    ReentrancyGuard
    :
    1. Checks — validate all conditions (
      require
      )
    2. Effects — update state variables
    3. Interactions — external calls last
  • 所有包含外部调用的合约:继承
    ReentrancyGuard
    ,添加
    nonReentrant
    修饰器
    • 导入路径:
      @openzeppelin/contracts/security/ReentrancyGuard.sol
      (OZ 4.9.x版本)
  • 即使使用
    ReentrancyGuard
    ,也始终遵循CEI模式:
    1. 检查——验证所有条件(使用
      require
    2. 状态变更——更新状态变量
    3. 交互——最后执行外部调用

Input Validation

输入验证

  • Reject
    address(0)
    for all address parameters
  • 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
    --gas-limit
    (recommended >= 3,000,000)
  • Monitor gas with
    forge test --gas-report
    — review before every PR
  • Configure optimizer in
    foundry.toml
    :
    optimizer = true
    ,
    optimizer_runs = 200
  • Avoid unbounded loops over dynamic arrays — use pagination or pull patterns
  • 部署命令必须包含
    --gas-limit
    (推荐值≥3,000,000)
  • 使用
    forge test --gas-report
    监控Gas消耗——每个PR提交前都要检查
  • foundry.toml
    中配置优化器:
    optimizer = true
    optimizer_runs = 200
  • 避免对动态数组进行无界循环——使用分页或拉取模式

Pre-Audit Checklist

审计前检查清单

Before submitting code for review or audit, verify:
Access & Control:
  • All external/public functions have
    nonReentrant
    where applicable
  • No
    tx.origin
    used for authentication (use
    msg.sender
    )
  • No
    delegatecall
    to untrusted addresses
  • Owner transfer uses
    Ownable2Step
    (not
    Ownable
    ) to prevent accidental loss
  • Contracts with user-facing functions inherit
    Pausable
    with
    pause()
    /
    unpause()
  • UUPS
    _authorizeUpgrade
    has
    onlyOwner
    modifier — EVMbench/basin H-01
  • Implementation constructor calls
    _disableInitializers()
    EVMbench/basin H-01
  • Router/Registry relay operations verify source contract authorization — EVMbench/noya H-08
Token & Fund Safety:
  • All ERC20 interactions use
    SafeERC20
    (
    safeTransfer
    /
    safeTransferFrom
    )
  • No raw
    token.transfer()
    or
    require(token.transfer())
    patterns
  • Token approvals use
    safeIncreaseAllowance
    , not raw
    approve
  • All
    external call
    return values checked
Code Quality:
  • Events emitted for every state change
  • No hardcoded addresses — use config or constructor params
  • .env
    is in
    .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:
  • forge test
    passes with zero failures
  • forge coverage
    shows adequate coverage on security-critical paths
  • Fuzz tests cover arithmetic edge cases (zero, max uint, boundary values)
在提交代码进行评审或审计前,请验证以下内容:
访问与控制:
  • 所有外部/公共函数在适用时都带有
    nonReentrant
    修饰器
  • 未使用
    tx.origin
    进行身份认证(使用
    msg.sender
  • 未向不可信地址发起
    delegatecall
  • 所有者权限转移使用
    Ownable2Step
    (而非
    Ownable
    )以防止意外丢失权限
  • 带有面向用户函数的合约继承
    Pausable
    并实现
    pause()
    /
    unpause()
  • UUPS的
    _authorizeUpgrade
    带有
    onlyOwner
    修饰器——参考EVMbench/basin H-01
  • 实现合约的构造函数调用
    _disableInitializers()
    ——参考EVMbench/basin H-01
  • 路由/注册中心的中继操作验证源合约的授权——参考EVMbench/noya H-08
代币与资金安全:
  • 所有ERC20交互都使用
    SafeERC20
    safeTransfer
    /
    safeTransferFrom
  • 未使用原生
    token.transfer()
    require(token.transfer())
    模式
  • 代币授权使用
    safeIncreaseAllowance
    ,而非原生
    approve
  • 所有
    external call
    的返回值都已检查
代码质量:
  • 每次状态变更都触发了事件
  • 没有硬编码地址——使用配置或构造函数参数
  • .env
    已添加到
    .gitignore
预言机与价格(若适用):
  • 价格数据来自Chainlink预言机或TWAP——绝不要使用原生现货价格
  • 预言机带有最低流动性检查——若池储备过低则回滚
  • 已设置价格偏差断路器
测试:
  • forge test
    执行通过,无失败用例
  • forge coverage
    显示安全关键路径有足够的覆盖率
  • 模糊测试覆盖了算术边缘情况(零值、最大uint、边界值)

Security Verification Commands

安全验证命令

bash
undefined
bash
undefined

Run 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/
undefined
slither src/
undefined

Slither MCP Integration (if available)

Slither MCP集成(若可用)

When
slither
MCP is configured, prefer it over the CLI for structured analysis:
ApproachWhen to Use
slither src/
(CLI)
Quick local scan, raw terminal output
slither MCP
get_detector_results
Structured results with impact/confidence filtering, AI can parse and reason about findings
slither MCP
get_contract_metadata
Understanding contract structure before reviewing code
slither MCP
get_function_source
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
forge test --fuzz-runs 10000
for coverage.
当配置了
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和CLI都不可用,则依赖上述审计前检查清单和
forge test --fuzz-runs 10000
来保证覆盖率。