关于 entry-point-analyzer
entry-point-analyzer 是面向智能合约审计人员的技能,用于梳理外部可调用且会改变状态的函数并分类其访问控制。它覆盖多种合约语言;Solidity 可使用 Slither,也可改为手动分析。
主要功能
- 01查找状态变更入口
- 02分类访问限制
- 03支持多种合约语言
- 04使用 Slither 或手动检查
- 05生成结构化 Markdown 报告
适用场景
- 01在审计开始时梳理攻击面
- 02审查合约特权操作
- 03追踪函数访问控制
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ trailofbits/ skills --skill entry-point-analyzer安装后在 Claude Code 中输入/entry-point-analyzer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlassets/trail-of-bits-mark.svgreferences/cosmwasm.mdmove-aptos.mdmove-sui.mdsolana.mdsolidity.mdton.mdvyper.md详细介绍
入口点分析器
系统地识别智能合约代码库中所有会改变状态的入口点,为安全审计提供指引。
在 Codex 中执行
使用可用的文件读取、搜索和 Shell 工具。引用的参考文件链接应相对于此 SKILL.md 解析,而不是相对于受审计的代码库。Slither 为可选工具;如果不可用或运行失败,请手动检查。将无法读取的源文件或参考文件报告为覆盖范围缺口。运行时权限取决于工作区。
适用场景
在以下情况下使用此技能:
- 开始智能合约安全审计,以梳理攻击面
- 需要查找入口点、外部函数或审计流程
- 分析代码库中的访问控制模式
- 识别特权操作和受角色限制的函数
- 了解哪些函数可以修改合约状态
不适用场景
以下情况不要使用此技能:
- 漏洞检测(使用 audit-context-building 或 domain-specific-audits)
- 编写漏洞利用 POC(使用 solidity-poc-builder)
- 代码质量或 Gas 优化分析
- 非智能合约代码库
- 分析只读函数(此技能不涵盖此类函数)
范围:仅限会改变状态的函数
此技能仅关注能够修改状态的函数。排除项:
| 语言 | 排除模式 |
|---|---|
| Solidity | view、pure 函数 |
| Vyper | @view、@pure 函数 |
| Solana | 不含 mut 账户引用的函数 |
| Move | 只读函数体;仅凭可见性无法确定可变性 |
| TON | get 方法(FunC)、只读接收器(Tact) |
| CosmWasm | query 入口点及其处理程序 |
即使没有 entry,也要纳入会改变状态的 Move public fun:Aptos 事务脚本和 Sui 可编程事务块都可以调用这些函数。必要时追踪被调用函数以确定状态影响,并将签名者、能力和对象所有权要求与可见性要求分开记录。
为什么排除只读函数? 它们无法直接导致资金损失或状态损坏。虽然它们可能泄露信息,但审计的主要重点是能够改变状态的函数。
工作流
- 检测语言 - 根据文件扩展名和语法识别合约语言
- 使用工具(如果可用) - 对于 Solidity,检查 Slither 是否可用,并使用它
- 定位合约 - 查找所有合约/模块文件(如指定目录筛选条件,则应用该条件)
- 提取入口点 - 解析每个文件,查找可从外部调用且会改变状态的函数
- 分类访问权限 - 按访问级别对函数进行分类
- 生成报告 - 输出结构化 Markdown 报告
Slither 集成(Solidity)
对于 Solidity 代码库,Slither 可以自动提取入口点。在手动分析之前:
1. 检查 Slither 是否可用
which slither
2. 如果检测到 Slither,则运行入口点打印器
slither . --print entry-points
这会输出一张表格,列出所有会改变状态的入口点,包括:
- 合约名称
- 函数名称
- 可见性
- 应用的修饰符
3. 将 Slither 输出作为基础
- 解析 Slither 输出表格,填充分析结果
- 通过手动检查交叉核对访问控制分类
- Slither 可能会遗漏某些模式(回调、动态访问控制),应通过手动审查补充
- 如果 Slither 运行失败(编译错误、不支持的功能),则改用手动分析
4. Slither 不可用时
如果 which slither 没有返回任何内容,请使用语言专属参考文件进行手动分析。
语言检测
| 扩展名 | 语言 | 参考文档 |
|---|---|---|
.sol | Solidity | references/solidity.md |
.vy | Vyper | references/vyper.md |
.rs + 包含 solana-program 的 Cargo.toml | Solana(Rust) | references/solana.md |
.move + 包含 edition 的 Move.toml | Move(Sui) | references/move-sui.md |
.move + 包含 Aptos 的 Move.toml | Move(Aptos) | references/move-aptos.md |
.fc、.func、.tact | TON(FunC/Tact) | references/ton.md |
.rs + 包含 cosmwasm-std 的 Cargo.toml | CosmWasm | references/cosmwasm.md |
在分析前,根据检测到的语言加载相应的参考文件。
访问权限分类
将每个会改变状态的入口点归入以下类别之一:
1. 公开(不受限制)
没有调用者身份或角色限制的函数。单独记录暂停标志等状态条件;这些条件不会使函数具备特权。
2. 受角色限制
仅限特定角色调用的函数。常见检测模式:
- 明确的角色名称:
admin、owner、governance、guardian、operator、manager、minter、pauser、keeper、relayer、lender、borrower - 角色检查模式:
onlyRole、hasRole、require(msg.sender == X)、assert_owner、#[access_control] - 角色含义不明确时,标记为 “受限(需要复核)”,并注明限制模式
3. 仅限合约调用(内部集成入口)
调用者限制经强制执行后,仅允许其他合约调用的函数。请引用实际检查,并说明获准调用者的身份或来源。回调名称、实现的接口或预期的集成关系都不构成访问控制。
- 未检查调用者的回调属于公开(不受限制)。
- 检查配置地址时,如果无法确定其身份,应标记为受限(需要复核);如果已确认该地址是集成合约,则使用仅限合约调用。
msg.sender != tx.origin可确定调用路径条件,但不能验证受信任协议的身份。记录该条件,但不要推断调用者可信。
输出格式
按以下结构生成 Markdown 报告:
# Entry Point Analysis: [Project Name]
**Analyzed**: [timestamp]
**Scope**: [directories analyzed or "full codebase"]
**Languages**: [detected languages]
**Focus**: State-changing functions only (view/pure excluded)
## Summary
| Category | Count |
|----------|-------|
| Public (Unrestricted) | X |
| Role-Restricted | X |
| Restricted (Review Required) | X |
| Contract-Only | X |
| **Total** | **X** |
---
## Public Entry Points (Unrestricted)
State-changing functions callable by anyone—prioritize for attack surface analysis.
| Function | File | Notes |
|----------|------|-------|
| `functionName(params)` | `path/to/file.sol:L42` | Brief note if relevant |
---
## Role-Restricted Entry Points
### Admin / Owner
| Function | File | Restriction |
|----------|------|-------------|
| `setFee(uint256)` | `Config.sol:L15` | `onlyOwner` |
### Governance
| Function | File | Restriction |
|----------|------|-------------|
### Guardian / Pauser
| Function | File | Restriction |
|----------|------|-------------|
### Other Roles
| Function | File | Restriction | Role |
|----------|------|-------------|------|
---
## Restricted (Review Required)
Functions with access control patterns that need manual verification.
| Function | File | Pattern | Why Review |
|----------|------|---------|------------|
| `execute(bytes)` | `Executor.sol:L88` | `require(trusted[msg.sender])` | Dynamic trust list |
---
## Contract-Only (Internal Integration Points)
Functions only callable by other contracts—useful for understanding trust boundaries.
| Function | File | Expected Caller |
|----------|------|-----------------|
| `onFlashLoan(...)` | `Vault.sol:L200` | Flash loan provider |
---
## Files Analyzed
- `path/to/file1.sol` (X state-changing entry points)
- `path/to/file2.sol` (X state-changing entry points)
筛选
用户指定目录筛选条件时:
- 仅分析该路径中的文件
- 在报告标题中注明筛选条件
- 示例:“仅分析
src/core/” → 范围 =src/core/
分析指南
- 全面分析:不要跳过文件。每个可从外部调用并会改变状态的函数都至关重要。
- 保守判断:无法确定访问级别时,应标记为需要复核,而不是错误分类。
- 跳过只读函数:排除
view、pure及等效的只读函数。 - 注明继承:如果函数的访问控制来自父合约,请注明。
- 跟踪修饰符:列出应用于每个函数的所有访问相关修饰符/装饰器。
- 识别模式:留意以下常见模式:
- 初始化函数(首次调用通常不受限制)
- 升级函数(高权限)
- 紧急/暂停函数(守护者级别)
- 费用/参数设置函数(管理员级别)
- 代币转账和授权(通常公开)
按协议类型划分的常见角色模式
| 协议类型 | 常见角色 |
|---|---|
| DEX | owner、feeManager、pairCreator |
| 借贷 | admin、guardian、liquidator、oracle |
| 治理 | proposer、executor、canceller、timelock |
| NFT | minter、admin、royaltyReceiver |
| 跨链桥 | relayer、guardian、validator、operator |
| 金库/收益 | strategist、keeper、harvester、manager |
应当摒弃的想当然
分析入口点时,请避免以下捷径:
- “这个函数看起来很常规” → 仍要对其分类;常规函数也可能具有非常规的访问控制
- “修饰符名称很明确” → 验证修饰符的实际实现
- “这显然仅限管理员使用” → 追踪实际限制;“显而易见”的假设会遗漏细微的绕过方式
- “我会跳过回调” → 回调定义了信任边界;务必将其纳入分析
- “它修改的状态不多” → 任何状态变更都可能遭到利用;纳入所有非 view 函数
错误处理
如果无法解析某个文件:
- 在报告的“分析警告”部分注明
- 继续处理其余文件
- 建议对无法解析的文件进行人工审查