Entry Point Analyzer
Trail of BitsOfficialPublished by Trail of Bits
- Skill
- Review and audit
- Security
- CC-BY-SA-4.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The Entry Point Analyzer is a specialized tool for smart contract security auditors. It systematically scans a codebase to identify all externally callable functions that modify contract state, while explicitly excluding read-only (view/pure) functions. By mapping these entry points and classifying them by their access control requirements—such as public, admin, or role-restricted—it provides a structured foundation for attack surface analysis and security auditing across multiple blockchain ecosystems including Solidity, Vyper, Solana, Move, TON, and CosmWasm.
What it does
- Detects state-changing entry points in various smart contract languages.
- Categorizes functions by access level: Public, Role-Restricted, or Contract-Only.
- Generates a structured markdown report summarizing the contract's attack surface.
- Integrates with Slither for automated analysis in Solidity projects.
- Identifies common access control patterns like admin, owner, and capability-based checks.
- Provides a clear inventory of privileged operations and potential integration points.
When to use it
- At the start of a smart contract security audit to map the attack surface.
- When you need to identify all functions capable of modifying contract state.
- When analyzing access control patterns and identifying privileged operations.
- When you need to understand trust boundaries and contract-to-contract interactions.
Advantages
- Reduces manual effort by automating the discovery of state-changing functions.
- Standardizes the audit process across different blockchain languages.
- Helps prioritize audit focus by highlighting public versus restricted entry points.
- Provides a consistent output format for audit documentation.
- Reduces the risk of missing critical privileged functions during an audit.
Usage examples
- “Analyze the entry points in this Solidity project.”
- The agent will scan the codebase, run Slither if available, and produce a markdown report listing all state-changing functions categorized by their access control modifiers.
- “Find all admin-restricted functions in this Move module.”
- The agent will parse the Move files, identify functions with signer or capability checks, and generate a report specifically highlighting the admin-restricted entry points.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/trailofbits/entry-point-analyzer/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip entry-point-analyzer.zip -d .agents/skills
Documentation by Trail of Bits
Entry Point Analyzer
Systematically identify all state-changing entry points in a smart contract codebase to guide security audits.
Execution in Codex
Use the available file-reading, search, and shell tools. Resolve bundled reference links relative to this SKILL.md, not the audited repository. Slither is optional; use manual inspection if it is unavailable or fails. Report unreadable source or reference files as coverage gaps. Runtime permissions come from the workspace.
When to Use
Use this skill when:
Starting a smart contract security audit to map the attack surface
Asked to find entry points, external functions, or audit flows
Analyzing access control patterns across a codebase
Identifying privileged operations and role-restricted functions
Building an understanding of which functions can modify contract state
When NOT to Use
Do NOT use this skill for:
Vulnerability detection (use audit-context-building or domain-specific-audits)
Writing exploit POCs (use solidity-poc-builder)
Code quality or gas optimization analysis
Non-smart-contract codebases
Analyzing read-only functions (this skill excludes them)
Scope: State-Changing Functions Only
This skill focuses exclusively on functions that can modify state. Excluded:
| Language | Excluded Patterns |
|---|---|
| Solidity | view, pure functions |
| Vyper | @view, @pure functions |
| Solana | Functions without mut account references |
| Move | Read-only function bodies; visibility alone does not establish mutability |
| TON | get methods (FunC), read-only receivers (Tact) |
| CosmWasm | query entry point and its handlers |
Include state-changing Move public fun even without entry: Aptos transaction
scripts and Sui programmable transaction blocks can reach them. Trace callees when
needed to determine state effects, and record signer, capability, and object
ownership requirements separately from visibility.
Why exclude read-only functions? They cannot directly cause loss of funds or state corruption. While they may leak information, the primary audit focus is on functions that can change state.
Workflow
Detect Language - Identify contract language(s) from file extensions and syntax
Use Tooling (if available) - For Solidity, check if Slither is available and use it
Locate Contracts - Find all contract/module files (apply directory filter if specified)
Extract Entry Points - Parse each file for externally callable, state-changing functions
Classify Access - Categorize each function by access level
Generate Report - Output structured markdown report
Slither Integration (Solidity)
For Solidity codebases, Slither can automatically extract entry points. Before manual analysis:
1. Check if Slither is Available
which slither2. If Slither is Detected, Run Entry Points Printer
slither . --print entry-pointsThis outputs a table of all state-changing entry points with:
Contract name
Function name
Visibility
Modifiers applied
3. Use Slither Output as Foundation
Parse the Slither output table to populate your analysis
Cross-reference with manual inspection for access control classification
Slither may miss some patterns (callbacks, dynamic access control)—supplement with manual review
If Slither fails (compilation errors, unsupported features), fall back to manual analysis
4. When Slither is NOT Available
If which slither returns nothing, proceed with manual analysis using the language-specific reference files.
Language Detection
| Extension | Language | Reference |
|---|---|---|
.sol | Solidity | references/solidity.md |
.vy | Vyper | references/vyper.md |
.rs + Cargo.toml with solana-program | Solana (Rust) | references/solana.md |
.move + Move.toml with edition | Move (Sui) | references/move-sui.md |
.move + Move.toml with Aptos | Move (Aptos) | references/move-aptos.md |
.fc, .func, .tact | TON (FunC/Tact) | references/ton.md |
.rs + Cargo.toml with cosmwasm-std | CosmWasm | references/cosmwasm.md |
Load the appropriate reference file(s) based on detected language before analysis.
Access Classification
Classify each state-changing entry point into one of these categories:
1. Public (Unrestricted)
Functions with no caller-identity or role restriction. Record state conditions such as pause flags separately; they do not make a function privileged.
2. Role-Restricted
Functions limited to specific roles. Common patterns to detect:
Explicit role names:
admin,owner,governance,guardian,operator,manager,minter,pauser,keeper,relayer,lender,borrowerRole-checking patterns:
onlyRole,hasRole,require(msg.sender == X),assert_owner,#[access_control]When role is ambiguous, flag as "Restricted (review required)" with the restriction pattern noted
3. Contract-Only (Internal Integration Points)
Functions whose enforced caller restrictions limit them to other contracts. Cite the actual check and the identity or provenance of the permitted caller. A callback name, implemented interface, or intended integration is not access control.
A callback without caller checks is Public (Unrestricted).
A check against a configured address is Restricted (Review Required) if its identity is unresolved; use Contract-Only when that address is established as the integration contract.
msg.sender != tx.originestablishes a call-path condition, not authentication of a trusted protocol. Record that condition without inferring a trusted caller.
Output Format
Generate a markdown report with this structure:
# 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)Filtering
When user specifies a directory filter:
Only analyze files within that path
Note the filter in the report header
Example: "Analyze only
src/core/" → scope =src/core/
Analysis Guidelines
Be thorough: Don't skip files. Every state-changing externally callable function matters.
Be conservative: When uncertain about access level, flag for review rather than miscategorize.
Skip read-only: Exclude
view,pure, and equivalent read-only functions.Note inheritance: If a function's access control comes from a parent contract, note this.
Track modifiers: List all access-related modifiers/decorators applied to each function.
Identify patterns: Look for common patterns like:
Initializer functions (often unrestricted on first call)
Upgrade functions (high-privilege)
Emergency/pause functions (guardian-level)
Fee/parameter setters (admin-level)
Token transfers and approvals (often public)
Common Role Patterns by Protocol Type
| Protocol Type | Common Roles |
|---|---|
| DEX | owner, feeManager, pairCreator |
| Lending | admin, guardian, liquidator, oracle |
| Governance | proposer, executor, canceller, timelock |
| NFT | minter, admin, royaltyReceiver |
| Bridge | relayer, guardian, validator, operator |
| Vault/Yield | strategist, keeper, harvester, manager |
Rationalizations to Reject
When analyzing entry points, reject these shortcuts:
"This function looks standard" → Still classify it; standard functions can have non-standard access control
"The modifier name is clear" → Verify the modifier's actual implementation
"This is obviously admin-only" → Trace the actual restriction; "obvious" assumptions miss subtle bypasses
"I'll skip the callbacks" → Callbacks define trust boundaries; always include them
"It doesn't modify much state" → Any state change can be exploited; include all non-view functions
Error Handling
If a file cannot be parsed:
Note it in the report under "Analysis Warnings"
Continue with remaining files
Suggest manual review for unparsable files
Files
- ATTRIBUTION.mdAdded by AutoGineer954 B
- LICENSELicence file added by AutoGineer19.7 KiB
- SKILL.md10.4 KiB
- agents/openai.yaml238 B
- assets/trail-of-bits-mark.svg3.0 KiB
- references/cosmwasm.md5.3 KiB
- references/move-aptos.md3.9 KiB
- references/move-sui.md3.4 KiB
- references/solana.md4.7 KiB
- references/solidity.md5.6 KiB
- references/ton.md4.9 KiB
- references/vyper.md4.2 KiB
references/ton.md
TON Entry Point Detection (FunC/Tact)
Entry Point Identification (State-Changing Only)
Focus on message handlers that modify state. Exclude read-only patterns:
getmethods in FunC (pure getters)Receivers that only return data without state changes
FunC Entry Points
;; Main entry point - receives all external messages
() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {
;; Dispatch based on op code
int op = in_msg_body~load_uint(32);
if (op == op::transfer) { handle_transfer(); }
}
;; External messages (from outside blockchain)
() recv_external(slice in_msg) impure {
;; Usually for wallet operations
}
;; Tick-tock for special contracts
() run_ticktock(cell full_state, int is_tock) impure {
}Tact Entry Points
contract MyContract {
// Receivers are entry points
receive(msg: Transfer) {
// Handle Transfer message
}
receive("increment") {
// Handle text message
}
// External receiver
external(msg: Deploy) {
// Handle external message
}
// Bounce handler
bounced(src: bounced<Transfer>) {
// Handle bounced message
}
}Entry Point Types
| Pattern | Include? | Notes |
|---|---|---|
recv_internal | Yes | All internal messages (state-changing) |
recv_external | Yes | External (off-chain) messages |
receive(MsgType) | Yes | Tact message handler |
external(MsgType) | Yes | Tact external handler |
bounced(...) | Yes | Bounce handler |
get methods (FunC) | No | EXCLUDE - read-only getters |
get fun (Tact) | No | EXCLUDE - read-only getters |
| Helper functions | No | Internal only |
Access Control Patterns
FunC Access Control
;; Owner check
() check_owner() impure inline {
throw_unless(401, equal_slices(sender_address, owner_address));
}
;; Admin check via stored address
() require_admin() impure inline {
var ds = get_data().begin_parse();
slice admin = ds~load_msg_addr();
throw_unless(403, equal_slices(sender_address, admin));
}Tact Access Control
contract Owned {
owner: Address;
receive(msg: AdminAction) {
require(sender() == self.owner, "Not owner");
// ...
}
// Using traits
receive(msg: Transfer) {
self.requireOwner(); // From Ownable trait
// ...
}
}Op Code Dispatch Pattern (FunC)
() recv_internal(...) impure {
int op = in_msg_body~load_uint(32);
;; Public operations
if (op == op::transfer) { return handle_transfer(); }
if (op == op::swap) { return handle_swap(); }
;; Admin operations
if (op == op::set_fee) {
check_owner();
return handle_set_fee();
}
}Access Control Classification
| Pattern | Classification |
|---|---|
equal_slices(sender, owner) | Owner |
equal_slices(sender, admin) | Admin |
require(sender() == self.owner) | Owner |
self.requireOwner() | Owner |
throw_unless(X, equal_slices(...)) | Check error code context |
| No sender check for op code | Public (Unrestricted) |
Contract-Only Detection
Callback Patterns
;; Jetton transfer notification
() on_jetton_transfer(...) impure {
;; Should verify sender is jetton wallet
}
;; NFT callbacks
() on_nft_transfer(...) impure {
}Contract Verification
;; Verify caller is expected contract
() verify_caller(slice expected) impure inline {
throw_unless(402, equal_slices(sender_address, expected));
}Extraction Strategy
FunC
Parse
.fc/.funcfilesFind
recv_internalandrecv_externalfunctionsExtract op code dispatch table:
Map op codes to handler functions
Check each handler for owner/admin checks
Classify:
Op codes with no access check → Public
Op codes with
check_owner/similar → Role-basedCallbacks → Contract-Only
Tact
Parse
.tactfilesFind
contractdeclarationsExtract all
receive,external,bouncedhandlersSkip
get fundeclarations (read-only getters)
Check handler body for:
require(sender() == self.X)→ Role-basedself.requireOwner()→ OwnerNo sender validation → Public (Unrestricted)
TON-Specific Considerations
Message-Based: All interactions are via messages with op codes
Workchains: Check if contract operates on specific workchain
Bounced Messages: Handle bounced messages appropriately
Gas Management:
accept_message()in FunC accepts gas paymentState Init: Initial deployment may set owner/admin
Common Gotchas
Op Code Collisions: Different contracts may use same op codes
Proxy Patterns: Some contracts forward messages
Wallet Contracts: Special access control for wallet operations
Masterchain: Some operations require masterchain deployment
Query ID: Track request/response with query_id
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Trail of Bits
- Publisher
- Trail of Bits (Official)
- Source
- trailofbits/skills · plugins/entry-point-analyzer/skills/entry-point-analyzer · commit e4dd0bb
- Licence
- Creative Commons Attribution-ShareAlike 4.0 International (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Trail of Bits.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download entry-point-analyzer.zip