smart-contract-vulnerabilities
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSKILL: Smart Contract Vulnerabilities — Expert Attack Playbook
SKILL:智能合约漏洞——专家攻击手册
AI LOAD INSTRUCTION: Expert smart contract audit techniques. Covers reentrancy (single, cross-function, cross-contract, read-only), integer overflow, access control, delegatecall, randomness manipulation, flash loans, signature replay, front-running/MEV, and CREATE2 exploitation. Base models miss subtle cross-contract reentrancy and storage layout collisions in proxy patterns.
AI加载说明:专业智能合约审计技术,涵盖重入(单函数、跨函数、跨合约、只读)、整数溢出、访问控制、delegatecall、随机数操纵、闪电贷、签名重放、抢先交易/MEV以及CREATE2漏洞利用。基础模型容易遗漏跨合约重入和代理模式中的存储布局冲突等细微问题。
0. RELATED ROUTING
0. 相关路由
- defi-attack-patterns when the vulnerability is part of a DeFi protocol exploit (flash loans, oracle manipulation, governance attacks)
- deserialization-insecure when the target is off-chain infrastructure deserializing blockchain data
- DeFi攻击模式 适用于漏洞属于DeFi协议利用的场景(闪电贷、预言机操纵、治理攻击)
- 不安全反序列化 适用于目标为反序列化区块链数据的链下基础设施场景
Advanced Reference
高级参考
Also load SOLIDITY_VULN_PATTERNS.md when you need:
- Side-by-side vulnerable vs fixed code patterns for each vulnerability class
- Gas optimization traps that introduce vulnerabilities
- Proxy pattern storage collision examples with slot calculations
如需以下内容,请同时加载SOLIDITY_VULN_PATTERNS.md:
- 各类漏洞对应的易受攻击代码与修复代码的对照模式
- 会引入漏洞的Gas优化陷阱
- 附带插槽计算的代理模式存储冲突示例
1. REENTRANCY
1. 重入
The most iconic smart contract vulnerability. External calls transfer execution control; if state is not updated before the call, the callee can re-enter.
最典型的智能合约漏洞。外部调用会转移执行控制权;如果调用前未更新状态,被调用方可以重新进入合约。
1.1 Classic Reentrancy (Single-Function)
1.1 经典重入(单函数)
Victim.withdraw()
├── checks balance[msg.sender] > 0 ✓
├── msg.sender.call{value: balance}("") ← external call
│ └── Attacker.receive()
│ └── Victim.withdraw() ← re-enters before state update
│ ├── checks balance[msg.sender] ← still > 0!
│ └── sends ETH again
└── balance[msg.sender] = 0 ← too lateVictim.withdraw()
├── checks balance[msg.sender] > 0 ✓
├── msg.sender.call{value: balance}("") ← external call
│ └── Attacker.receive()
│ └── Victim.withdraw() ← re-enters before state update
│ ├── checks balance[msg.sender] ← still > 0!
│ └── sends ETH again
└── balance[msg.sender] = 0 ← too late1.2 Cross-Function Reentrancy
1.2 跨函数重入
Two functions share state; attacker re-enters a different function during callback:
| Step | Execution | State |
|---|---|---|
| 1 | Call | balance still positive |
| 2 | Attacker fallback calls | balance used before reset |
| 3 | | attacker2 receives tokens |
| 4 | Original | damage done |
两个函数共享状态;攻击者在回调期间重新进入另一个函数:
| 步骤 | 执行过程 | 状态 |
|---|---|---|
| 1 | 调用 | 余额仍为正 |
| 2 | 攻击者 fallback 函数调用 | 余额在重置前被使用 |
| 3 | | attacker2收到代币 |
| 4 | 原始 | 损害已经造成 |
1.3 Cross-Contract Reentrancy
1.3 跨合约重入
Contract A calls Contract B, which calls back into Contract A (or Contract C that reads A's stale state). Especially dangerous in DeFi protocols where multiple contracts share state.
合约A调用合约B,合约B回调合约A(或者调用读取A过期状态的合约C)。在多合约共享状态的DeFi协议中风险极高。
1.4 Read-Only Reentrancy
1.4 只读重入
The re-entered function is a function used by a third-party contract for price calculation. No state modification in the victim, but the stale intermediate state misleads the reader.
viewReal-world: Curve pool read during callback → inflated price → profit on dependent lending protocol.
get_virtual_price()remove_liquidity()被重入的函数是第三方合约用于价格计算的函数。受害合约没有状态修改,但中间过期状态会误导读取方。
view真实案例:Curve池在回调期间被读取 → 价格被高估 → 依赖该池的借贷协议产生损失。
get_virtual_price()remove_liquidity()Mitigations
修复方案
| Pattern | Protection Level |
|---|---|
| Checks-Effects-Interactions (CEI) | Core defense; update state before external call |
| Mutex lock; prevents same-tx re-entry |
| Pull payment pattern | Eliminate external calls in state-changing functions |
| CEI + guard on all public functions | Defense-in-depth against cross-function |
| 模式 | 防护等级 |
|---|---|
| 检查-效果-交互(CEI) | 核心防御;外部调用前先更新状态 |
| 互斥锁;防止同一交易内重入 |
| 拉取支付模式 | 消除状态变更函数中的外部调用 |
| 所有公开函数同时使用CEI+防护锁 | 针对跨函数重入的纵深防御 |
2. INTEGER OVERFLOW / UNDERFLOW
2. 整数溢出/下溢
Pre-Solidity 0.8
Solidity 0.8之前版本
Arithmetic silently wraps: , .
uint8(255) + 1 == 0uint8(0) - 1 == 255| Attack | Example |
|---|---|
| Balance underflow | |
| Supply overflow | |
| Timelock bypass | |
算术运算会静默绕回:,。
uint8(255) + 1 == 0uint8(0) - 1 == 255| 攻击类型 | 示例 |
|---|---|
| 余额下溢 | 当amount大于余额时执行 |
| 供应溢出 | |
| 时间锁绕过 | |
Post-Solidity 0.8
Solidity 0.8及之后版本
Default checked arithmetic reverts on overflow. But blocks reintroduce risk:
unchecked{}solidity
unchecked {
// "gas optimization" — but if i can be influenced by user input, overflow returns
for (uint i = start; i < end; i++) { ... }
}默认开启算术检查,溢出时会回滚交易。但块会重新引入风险:
unchecked{}solidity
unchecked {
// 「Gas优化」——但如果i可被用户输入影响,溢出风险会重新出现
for (uint i = start; i < end; i++) { ... }
}SafeMath Bypass Scenarios
SafeMath绕过场景
- Casting: →
uint256truncation before SafeMath checkuint128 - Assembly blocks: /
mstorebypass Solidity-level checksadd - Intermediate multiplication overflow before division: where
(a * b) / coverflowsa * b
- 类型转换:SafeMath检查前将截断为
uint256uint128 - 汇编块:/
mstore等操作绕过Solidity层面检查add - 除法前的中间乘法溢出:中
(a * b) / c先溢出a * b
3. ACCESS CONTROL
3. 访问控制
tx.origin vs msg.sender
tx.origin vs msg.sender
| Property | | |
|---|---|---|
| Value | Immediate caller | EOA that initiated the tx |
| Safe for auth | Yes | No — phishing contract can inherit tx.origin |
Attack: trick owner into calling attacker contract → attacker contract calls victim with owner's .
tx.origin| 属性 | | |
|---|---|---|
| 值 | 直接调用方 | 发起交易的EOA地址 |
| 是否适合用于鉴权 | 是 | 否 — 钓鱼合约可以继承tx.origin |
攻击方式:诱导所有者调用攻击者合约 → 攻击者合约以所有者的调用受害合约。
tx.originCommon Patterns
常见问题
| Issue | Impact |
|---|---|
Missing | Anyone can call admin functions |
Unprotected | Anyone can destroy the contract, force-send ETH |
Unprotected | Attacker executes arbitrary code in victim's context |
| Default visibility (pre-0.6.0) | Functions default to |
| Missing zero-address checks | Ownership transferred to |
| 问题 | 影响 |
|---|---|
关键函数缺少 | 任何人都可以调用管理员函数 |
未受保护的 | 任何人都可以销毁合约,强制发送ETH |
未受保护的 | 攻击者可以在受害合约上下文中执行任意代码 |
| 默认可见性(0.6.0之前版本) | 函数默认为 |
| 缺少零地址检查 | 所有权被转移到 |
4. RANDOMNESS MANIPULATION
4. 随机数操纵
On-chain randomness sources are predictable to miners/validators:
| Source | Predictability |
|---|---|
| Miner has ~15s window to manipulate |
| Known to all at execution time |
| Always returns 0 (current block hash unknown) |
| Post-merge: known beacon chain value |
Commit-reveal bypass: If reveal phase doesn't enforce timeout or bond, attacker can choose not to reveal unfavorable outcomes (selective abort attack).
链上随机数来源对矿工/验证者是可预测的:
| 来源 | 可预测性 |
|---|---|
| 矿工有约15秒的操纵窗口 |
| 执行时对所有节点可见 |
| 永远返回0(当前区块哈希未知) |
| 合并后:已知的信标链值 |
提交-揭示方案绕过:如果揭示阶段没有强制超时或保证金,攻击者可以选择不揭示不利结果(选择性中止攻击)。
5. DELEGATECALL VULNERABILITIES
5. DELEGATECALL漏洞
delegatecalldelegatecallStorage Layout Collision
存储布局冲突
Proxy (storage): Implementation (code):
slot 0: owner slot 0: someVariable
slot 1: implementation slot 1: anotherVariableImplementation writes to (slot 0) → overwrites proxy's . Attacker calls implementation function that writes slot 0 → becomes proxy owner.
someVariableowner代理(存储): 实现合约(代码):
slot 0: owner slot 0: someVariable
slot 1: implementation slot 1: anotherVariable实现合约写入(插槽0)→ 覆盖代理的。攻击者调用实现合约中写入插槽0的函数 → 成为代理所有者。
someVariableownerFunction Selector Collision
函数选择器冲突
4-byte function selectors can collide. If proxy's selector collides with implementation's , calling on the proxy executes logic.
admin()transfer()admin()transfer()Tool: (Foundry) to enumerate selectors.
cast selectors <bytecode>4字节函数选择器可能发生冲突。如果代理的选择器与实现合约的冲突,调用代理的会执行逻辑。
admin()transfer()admin()transfer()工具:(Foundry)可枚举选择器。
cast selectors <bytecode>6. FRONT-RUNNING / MEV
6. 抢先交易/MEV
Transaction Ordering Manipulation
交易顺序操纵
Victim submits DEX swap tx (visible in mempool)
├── Front-runner: buy token before victim (raise price)
├── Victim tx executes at worse price
└── Back-runner: sell token after victim (profit from spread)
= Sandwich attack受害者提交DEX兑换交易(在内存池中可见)
├── 抢先交易者:在受害者交易前买入代币(推高价格)
├── 受害者交易以更差的价格执行
└── 后跑交易者:在受害者交易后卖出代币(赚取差价)
= 三明治攻击Protection Patterns
防护模式
| Defense | Mechanism |
|---|---|
| Commit-reveal | Hide transaction intent until reveal |
| Flashbots / private mempool | Submit tx directly to block builder |
| Slippage protection | Set |
| Time-lock | Delay execution to reduce predictability |
| 防御方案 | 机制 |
|---|---|
| 提交-揭示 | 直到揭示阶段才公开交易意图 |
| Flashbots/私有内存池 | 直接向区块构建者提交交易 |
| 滑点保护 | 设置 |
| 时间锁 | 延迟执行降低可预测性 |
7. SIGNATURE REPLAY
7. 签名重放
Missing Nonce
缺少Nonce
Reuse a valid signature to repeat the action (e.g., transfer) multiple times.
重复使用有效签名多次执行同一操作(例如转账)。
Cross-Chain Replay
跨链重放
Same contract deployed on multiple chains with same address → signature valid on all chains. Must include in signed message.
block.chainid同一合约在多条链上部署相同地址 → 签名在所有链上都有效。必须在签名消息中包含。
block.chainidEIP-712 Implementation Errors
EIP-712实现错误
| Error | Consequence |
|---|---|
Missing | Cross-chain replay |
| Domain separator cached at deploy | Breaks after hard fork changing chainId |
| Missing nonce in struct hash | Signature replay |
| Passes |
| 错误 | 后果 |
|---|---|
缺少带chainId的 | 跨链重放 |
| 部署时缓存域分隔符 | 硬分叉修改chainId后失效 |
| 结构体哈希中缺少nonce | 签名重放 |
无效签名时 | 通过 |
8. SELF-DESTRUCT & FORCE-SEND ETH
8. SELF-DESTRUCT与强制发送ETH
selfdestruct(recipient)receive()fallback()Breaks contracts that rely on for logic (e.g., ).
address(this).balancerequire(balance == expected)Post-EIP-6780 (Dencun): only sends ETH; code/storage deletion only if called in same tx as creation.
selfdestructselfdestruct(recipient)receive()fallback()会破坏依赖做逻辑判断的合约(例如)。
address(this).balancerequire(balance == expected)EIP-6780(Dencun升级)后:仅发送ETH;仅在与部署同交易中调用时才会删除代码/存储。
selfdestruct9. CREATE2 & DETERMINISTIC ADDRESS EXPLOITATION
9. CREATE2与确定性地址漏洞利用
CREATE2keccak256(0xff ++ deployer ++ salt ++ keccak256(initCode))| Attack | Method |
|---|---|
| Pre-fund exploitation | Predict address → send tokens/ETH before deployment → |
| Pre-approve exploitation | Predicted address gets token approvals → deploy malicious contract → drain approved tokens |
| Metamorphic contracts | |
CREATE2keccak256(0xff ++ deployer ++ salt ++ keccak256(initCode))| 攻击 | 方式 |
|---|---|
| 预注资漏洞利用 | 预测地址 → 部署前发送代币/ETH → 执行 |
| 预授权漏洞利用 | 预测地址获得代币授权 → 部署恶意合约 → 转走授权代币 |
| 变形合约 | |
10. FLASH LOAN ATTACK PATTERNS
10. 闪电贷攻击模式
Single transaction:
├── Borrow large amount (no collateral)
├── Manipulate state (price oracle, governance, etc.)
├── Extract profit from manipulated state
├── Repay loan + fee
└── Keep profitKey: entire sequence must succeed atomically or the whole tx reverts.
单交易流程:
├── 无抵押借入大额资金
├── 操纵状态(价格预言机、治理等)
├── 从被操纵的状态中提取利润
├── 偿还贷款+手续费
└── 剩余利润归攻击者所有关键:整个序列必须原子性成功,否则整个交易回滚。
11. SHORT ADDRESS ATTACK
11. 短地址攻击
EVM pads missing bytes in ABI-encoded calldata with zeros. If is called with a 19-byte address, the uint256 amount shifts left by 8 bits → multiplied by 256.
transfer(address, uint256)Mitigation: validate calldata length; modern Solidity compilers add checks.
EVM会将ABI编码调用数据中缺失的字节补零。如果调用时传入19字节地址,uint256金额会左移8位 → 放大256倍。
transfer(address, uint256)修复方案:验证调用数据长度;现代Solidity编译器已内置检查。
12. TOOLS
12. 工具
| Tool | Purpose | Usage |
|---|---|---|
| Slither | Static analysis, vulnerability detection | |
| Mythril | Symbolic execution, path exploration | |
| Echidna | Property-based fuzzing | Define invariants, fuzz for violations |
| Foundry (Forge) | Test framework, fuzzing, gas analysis | |
| Hardhat | Development, testing, deployment | |
| Certora | Formal verification | Write specs, prove/disprove properties |
| 4naly3er | Automated gas optimization + vuln report | CI integration |
| 工具 | 用途 | 用法 |
|---|---|---|
| Slither | 静态分析、漏洞检测 | 项目根目录执行 |
| Mythril | 符号执行、路径探索 | |
| Echidna | 基于属性的模糊测试 | 定义不变量,模糊测试验证是否被打破 |
| Foundry (Forge) | 测试框架、模糊测试、Gas分析 | |
| Hardhat | 开发、测试、部署 | |
| Certora | 形式化验证 | 编写规范,证明/证伪属性 |
| 4naly3er | 自动化Gas优化+漏洞报告 | CI集成 |
13. DECISION TREE
13. 决策树
Auditing a smart contract?
├── Is it a proxy pattern?
│ ├── Yes → Check storage layout collision (Section 5)
│ │ ├── Compare slot assignments between proxy and implementation
│ │ ├── Check for function selector collision
│ │ └── Verify initializer cannot be called twice
│ └── No → Continue
├── Does it make external calls?
│ ├── Yes → Check reentrancy (Section 1)
│ │ ├── State updated before call? → CEI pattern OK
│ │ ├── ReentrancyGuard present? → Check all entry points
│ │ ├── Cross-function state sharing? → Cross-function reentrancy risk
│ │ └── View functions read during callback? → Read-only reentrancy
│ └── No → Continue
├── Does it handle tokens/ETH?
│ ├── Yes → Check integer overflow (Section 2)
│ │ ├── Solidity < 0.8? → All arithmetic suspect
│ │ ├── unchecked{} blocks? → Verify no user-influenced values
│ │ └── Casting between uint sizes? → Truncation risk
│ └── Also check self-destruct force-send (Section 8)
├── Does it use signatures?
│ ├── Yes → Check replay (Section 7)
│ │ ├── Nonce included? → Verify incremented
│ │ ├── ChainId included? → Cross-chain safe
│ │ └── ecrecover result checked for address(0)? → OK
│ └── No → Continue
├── Does it use on-chain randomness?
│ ├── Yes → Predictable (Section 4)
│ │ └── Recommend Chainlink VRF or commit-reveal with bond
│ └── No → Continue
├── Does it interact with DeFi protocols?
│ ├── Yes → Load [defi-attack-patterns](../defi-attack-patterns/SKILL.md)
│ │ ├── Flash loan vectors
│ │ ├── Oracle manipulation
│ │ └── MEV exposure
│ └── No → Continue
├── Does it use CREATE2?
│ ├── Yes → Check deterministic address exploitation (Section 9)
│ └── No → Continue
└── Run automated tools (Section 12)
├── Slither for static analysis
├── Mythril for symbolic execution
└── Echidna for fuzzing invariants审计智能合约?
├── 是否是代理模式?
│ ├── 是 → 检查存储布局冲突(第5节)
│ │ ├── 对比代理和实现合约的插槽分配
│ │ ├── 检查函数选择器冲突
│ │ └── 验证初始化函数不能被重复调用
│ └── 否 → 继续
├── 是否有外部调用?
│ ├── 是 → 检查重入(第1节)
│ │ ├── 调用前是否更新状态? → CEI模式合规
│ │ ├── 是否有ReentrancyGuard? → 检查所有入口点
│ │ ├── 是否有跨函数状态共享? → 跨函数重入风险
│ │ └── 回调期间是否有view函数被读取? → 只读重入风险
│ └── 否 → 继续
├── 是否处理代币/ETH?
│ ├── 是 → 检查整数溢出(第2节)
│ │ ├── Solidity版本 < 0.8? → 所有算术运算都有风险
│ │ ├── 是否有unchecked{}块? → 确认没有用户可控值
│ │ └── 是否有uint类型之间的转换? → 截断风险
│ └── 同时检查self-destruct强制发送ETH(第8节)
├── 是否使用签名?
│ ├── 是 → 检查重放(第7节)
│ │ ├── 是否包含Nonce? → 验证会递增
│ │ ├── 是否包含ChainId? → 跨链安全
│ │ └── ecrecover结果是否检查非零地址? → 合规
│ └── 否 → 继续
├── 是否使用链上随机数?
│ ├── 是 → 可预测(第4节)
│ │ └── 推荐使用Chainlink VRF或带保证金的提交-揭示方案
│ └── 否 → 继续
├── 是否与DeFi协议交互?
│ ├── 是 → 加载[DeFi攻击模式](../defi-attack-patterns/SKILL.md)
│ │ ├── 闪电贷攻击向量
│ │ ├── 预言机操纵
│ │ └── MEV暴露风险
│ └── 否 → 继续
├── 是否使用CREATE2?
│ ├── 是 → 检查确定性地址漏洞利用(第9节)
│ └── 否 → 继续
└── 运行自动化工具(第12节)
├── Slither做静态分析
├── Mythril做符号执行
└── Echidna做不变量模糊测试