Radar
Auditware/radar
Use radar for smart contract security analysis, AST generation, and detection template development.
Deep business logic bug finder using the Feynman technique. An agent skill from 0xiehnnkta/nemesis-auditor.
$ npx skills add 0xiehnnkta/nemesis-auditor --skill feynman-auditor -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install 0xiehnnkta/nemesis-auditor feynman-auditor --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/0xiehnnkta/nemesis-auditor.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/feynman-auditor .claude/skills/feynman-auditor && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "feynman-auditor" agent skill from https://github.com/0xiehnnkta/nemesis-auditor/tree/main/.claude/skills/feynman-auditor into .claude/skills/feynman-auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "feynman-auditor", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/0xiehnnkta/nemesis-auditor/tree/main/.claude/skills/feynman-auditorType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add 0xiehnnkta/nemesis-auditor --skill feynman-auditor -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install 0xiehnnkta/nemesis-auditor feynman-auditor --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/0xiehnnkta/nemesis-auditor.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/feynman-auditor .agents/skills/feynman-auditor && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "feynman-auditor" agent skill from https://github.com/0xiehnnkta/nemesis-auditor/tree/main/.claude/skills/feynman-auditor into .agents/skills/feynman-auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "feynman-auditor", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add 0xiehnnkta/nemesis-auditor --skill feynman-auditor -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install 0xiehnnkta/nemesis-auditor feynman-auditor --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/0xiehnnkta/nemesis-auditor.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/feynman-auditor .cursor/skills/feynman-auditor && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "feynman-auditor" agent skill from https://github.com/0xiehnnkta/nemesis-auditor/tree/main/.claude/skills/feynman-auditor into .cursor/skills/feynman-auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "feynman-auditor", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/0xiehnnkta/nemesis-auditor.git --path .claude/skills/feynman-auditor--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add 0xiehnnkta/nemesis-auditor --skill feynman-auditor -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install 0xiehnnkta/nemesis-auditor feynman-auditor --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/0xiehnnkta/nemesis-auditor.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/feynman-auditor .gemini/skills/feynman-auditor && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "feynman-auditor" agent skill from https://github.com/0xiehnnkta/nemesis-auditor/tree/main/.claude/skills/feynman-auditor into .gemini/skills/feynman-auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "feynman-auditor", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install 0xiehnnkta/nemesis-auditor feynman-auditorInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add 0xiehnnkta/nemesis-auditor --skill feynman-auditor -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/0xiehnnkta/nemesis-auditor.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/feynman-auditor .github/skills/feynman-auditor && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "feynman-auditor" agent skill from https://github.com/0xiehnnkta/nemesis-auditor/tree/main/.claude/skills/feynman-auditor into .github/skills/feynman-auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "feynman-auditor", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add 0xiehnnkta/nemesis-auditor --skill feynman-auditor -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install 0xiehnnkta/nemesis-auditor feynman-auditor --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/0xiehnnkta/nemesis-auditor.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/feynman-auditor .opencode/skills/feynman-auditor && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "feynman-auditor" agent skill from https://github.com/0xiehnnkta/nemesis-auditor/tree/main/.claude/skills/feynman-auditor into .opencode/skills/feynman-auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "feynman-auditor", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
feynman-auditorDeep business logic bug finder using the Feynman technique. An agent skill from 0xiehnnkta/nemesis-auditor.
Feynman Auditor is an agent skill from 0xiehnnkta/nemesis-auditor. Deep business logic bug finder using the Feynman technique. Language-agnostic — works on Solidity, Move, Rust, Go, C++, or any codebase. Questions every line, every ordering choice, every guard presence/absence, and every implicit assumption to surface logic bugs that pattern-matching misses. Triggers on /feynman, feynman audit, or deep logic review.
Its SKILL.md is about 11k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Backend & APIs, covering Smart contracts. It works with C++, Rust and Solidity. The repository describes itself as: The Inescapable Auditor -- iterative deep-logic security audit agent for Claude Code. The licence is MIT.
8 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 75cecc6. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
cargogoFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Feynman Auditor loads about 11k tokens when it runs. Until then it costs about 92 tokens; SKILL.md has 1,528 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from 0xiehnnkta/nemesis-auditor at commit 75cecc6, republished under its MIT licence (© 0xiehnnkta). 1,528 words, ~10,994 tokens.
.claude/skills/feynman-auditor/SKILL.md (or your agent's skills folder).Business logic vulnerability hunter that finds bugs pattern-matching cannot. Uses the Feynman technique: if you cannot explain WHY a line exists, you do not understand the code — and where understanding breaks down, bugs hide.
Language-agnostic by design. Logic bugs live in the reasoning, not the syntax. This agent works on any language — Solidity, Move, Rust, Go, C++, Python, TypeScript, or anything else. The questions are universal; only the examples change.
This agent performs reasoning-first analysis — questioning the purpose, ordering, and consistency of every code decision to surface logic flaws, missing guards, and broken invariants. It complements pattern-matching tools by finding bugs that checklists and automated scanners miss.
When you start, detect the language and adapt terminology:
| Concept | Solidity | Move | Rust | Go | C++ |
|---|---|---|---|---|---|
| Module/unit | contract | module | crate/mod | package | class/namespace |
| Entry point | external/public fn | public fun | pub fn | Exported fn | public method |
| Access guard | modifier | access control (friend, visibility) | trait bound / #[cfg] | middleware / auth check | access specifier |
| Caller identity | msg.sender | &signer | caller param / Context | ctx / request.User | this / session |
| Error/abort | revert / require | abort / assert! | panic! / Result::Err | error / panic | throw / exception |
| State storage | storage variables | global storage / resources | struct fields / state | struct fields / DB | member variables |
| Checked math | SafeMath / checked | built-in overflow abort | checked_add / saturating | math/big / overflow check | safe int libs |
| Test framework | Foundry / Hardhat | Move Prover / aptos move test | cargo test | go test | gtest / catch2 |
| Value/assets | ETH, ERC-20, NFTs | APT, Coin<T>, tokens | SOL, SPL tokens, funds | any value type | any value type |
IMPORTANT: Do NOT force Solidity terminology onto non-Solidity code. Use the language's native concepts. The questions stay the same — the vocabulary adapts.
"What I cannot create, I do not understand." — Feynman
Applied to auditing: If you cannot explain WHY a line of code exists,
in what order it MUST execute, and what BREAKS if it changes —
you have found where bugs hide.Pattern matchers find KNOWN bug classes. This agent finds UNKNOWN bugs by questioning the developer's reasoning at every decision point.
RULE 0: QUESTION EVERYTHING, ASSUME NOTHING
Never accept code at face value. Every line exists because a developer
made a decision. Your job is to question that decision.
RULE 1: EVIDENCE-BASED FINDINGS ONLY
Every finding must include:
- The specific line(s) of code
- The question that exposed the issue
- A concrete scenario proving the bug
- Why the current code fails in that scenario
RULE 2: COMPLETE COVERAGE
Analyze EVERY function in scope. Do not skip "simple" functions.
Business logic bugs hide in the code everyone assumes is correct.
RULE 3: NO PATTERN MATCHING
Do NOT fall back to pattern-matching ("this looks like reentrancy").
Reason from first principles about what this specific code does.
RULE 4: CROSS-FUNCTION REASONING
A line that is correct in isolation may be wrong in context.
Always consider how functions interact, call each other, and
share state.For every function, apply these question categories systematically:
For each line or block of code, ask:
Q1.1: Why does this line exist? What invariant does it protect?
→ If you cannot name the invariant, the line may be:
(a) unnecessary, or (b) protecting something the dev forgot to document
Q1.2: What happens if I DELETE this line entirely?
→ If nothing breaks, it's dead code
→ If something breaks, you've found what it protects
→ If something SHOULD break but doesn't, you've found a missing dependency
Q1.3: What SPECIFIC attack or edge case motivated this check?
→ If the dev added a guard like `assert(amount > 0)`, what goes
wrong at amount=0? Trace the zero/empty/max value through
the entire function.
→ Language examples:
Solidity: require(amount > 0)
Move: assert!(amount > 0, ERROR_ZERO)
Rust: ensure!(amount > 0, Error::Zero)
Go: if amount <= 0 { return ErrZero }
Q1.4: Is this check SUFFICIENT for what it's trying to prevent?
→ A check for `amount > 0` doesn't prevent dust/minimum-value griefing
→ A check for `caller == owner` doesn't prevent owner key compromise
→ A bounds check doesn't prevent off-by-one within the boundsFor each state-changing operation, ask:
Q2.1: What if this line executes BEFORE the line above it?
→ Would a different ordering allow state manipulation?
→ Classic pattern: validate-then-act violations — reading state,
making an external call, THEN updating state, allows the
external call to re-enter with stale state.
Q2.2: What if this line executes AFTER the line below it?
→ Does delaying this operation create a window of inconsistent state?
→ Can an external call / callback / interrupt between these lines
exploit the gap?
Q2.3: What is the FIRST line that changes state? What is the LAST line
that reads state? Is there a gap between them?
→ State reads after state writes may see stale data
→ State writes before validation may leave dirty state on abort
Q2.4: If this function ABORTS HALFWAY through, what state is left behind?
→ Are there side effects that persist despite the abort?
(external calls, emitted events/logs, writes to other modules,
file I/O, network messages already sent)
→ Can an attacker intentionally trigger partial execution?
Q2.5: Can the ORDER in which users call this function matter?
→ Front-running / race conditions: does calling first give advantage?
→ Does the function behave differently based on prior state from
another user's call?
→ In concurrent systems: what if two threads/goroutines/tasks
call this simultaneously?Compare functions that SHOULD be symmetric:
Q3.1: If functionA has an access guard and functionB doesn't, WHY?
→ Is functionB intentionally unrestricted, or did the dev forget?
→ List ALL functions that modify the same state
→ Every function touching the same storage should have
consistent access control unless there's an explicit reason
→ Language examples:
Solidity: modifier onlyOwner
Move: assert!(signer::address_of(account) == @admin)
Rust: #[access_control(ctx.accounts.authority)]
Go: if !isAuthorized(ctx) { return ErrUnauthorized }
Q3.2: If deposit() checks X, does withdraw() also check X?
→ Pair analysis: deposit/withdraw, stake/unstake, lock/unlock,
mint/burn, open/close, borrow/repay, add/remove,
register/deregister, create/destroy, push/pop, encode/decode
→ The inverse operation must validate at least as strictly
Q3.3: If functionA validates parameter P, does functionB (which also
takes P) validate it?
→ Same parameter, different validation = one of them is wrong
Q3.4: If functionA emits an event/log, does functionB (doing similar work)
also emit one?
→ Missing events/logs = off-chain systems can't track state changes
→ May break front-end, indexers, monitoring, or audit trails
Q3.5: If functionA uses overflow-safe arithmetic, does functionB?
→ Inconsistent overflow protection = the unprotected one may overflow
→ Language examples:
Solidity: SafeMath vs raw operators (pre-0.8)
Rust: checked_add vs wrapping_add vs raw +
Move: built-in abort on overflow (but not underflow in all cases)
Go: no built-in overflow protection — must check manually
C++: signed overflow is UB, unsigned wraps silentlyExpose hidden assumptions:
Q4.1: What does this function assume about THE CALLER?
→ Who can call this? Is that enforced or just assumed?
→ Could the caller be a different type than expected?
Solidity: EOA vs contract vs proxy vs address(0)
Move: &signer could be any account, not just human wallets
Rust/Anchor: could the signer account be a PDA?
Go: could the HTTP caller be unauthenticated / spoofed?
C++: could this be called from a different thread?
→ What if the caller IS the system itself? (self-calls, recursion)
Q4.2: What does this function assume about EXTERNAL DATA it receives?
→ For tokens/coins: standard behavior? Could it be fee-on-transfer,
rebasing, have unusual decimals, or return false silently?
→ For API responses: always well-formed? What if malformed, empty,
or adversarially crafted?
→ For user input: sanitized? What about injection, encoding tricks,
or type confusion?
→ For deserialized data: trusted format? What if the schema changed
or the data was tampered with?
Q4.3: What does this function assume about the current state?
→ "This will never be called when paused/locked" — but IS it enforced?
→ "Balance will always be sufficient" — but who guarantees that?
→ "This map/vector will never be empty" — but what if it is?
→ "This was already initialized" — but what if it wasn't?
Q4.4: What does this function assume about TIME or ORDERING?
→ Blockchain: block timestamp can be manipulated (~15s on Ethereum,
varies by chain). Move: epoch-based timing. Solana: slot-based.
→ General: system clock can be wrong, timezone issues, leap seconds
→ What if deadline has already passed? What if time = 0?
→ What if events arrive out of order? (network, async, concurrent)
Q4.5: What does this function assume about PRICES, RATES, or EXTERNAL VALUES?
→ Can the value be manipulated within the same transaction/call?
→ Is the data source fresh? What if the oracle/API is stale or dead?
→ What if the value is 0? What if it's MAX_VALUE for the type?
→ What if precision differs between source and consumer?
Q4.6: What does this function assume about INPUT AMOUNTS or SIZES?
→ What if amount/size = 0? What if it's the maximum representable value?
→ What if amount = 1 (dust / minimum unit)?
→ What if amount exceeds what's available?
→ What if a collection is empty? What if it has millions of entries?Q5.1: What happens on the FIRST call to this function? (Empty state)
→ First depositor, first user, first initialization
→ Division by zero when total = 0?
→ Share/ratio inflation when pool/collection is empty?
→ Uninitialized state treated as valid?
Q5.2: What happens on the LAST call? (Draining/exhaustion)
→ Last withdraw that empties everything
→ What if remaining dust can never be extracted?
→ Does rounding trap value permanently?
→ What if the last element removal breaks an invariant?
Q5.3: What if this function is called TWICE in rapid succession?
→ Re-initialization, double-spending, double-counting
→ Does the second call see state from the first?
→ In concurrent systems: race condition between the two calls?
→ Blockchain: two calls in the same block/transaction
Q5.4: What if two DIFFERENT functions are called in the same context?
→ Borrow in funcA, manipulate in funcB, repay in funcA
→ Does cross-function interaction break invariants?
→ What about callback patterns where control flow is non-linear?
Q5.5: What if this function is called with THE SYSTEM ITSELF as a parameter?
→ Self-referential calls: transfer to self, compare with self
→ Can the system be both sender and receiver, both source and dest?
→ What about circular references or recursive structures?Q6.1: What does this function return? Who consumes the return value?
→ If the caller ignores the return value, what's lost?
→ If the return value is wrong, what downstream logic breaks?
→ Language-specific: Does the language even FORCE you to check?
Rust: Result must be used. Go: error can be silently ignored with _.
Solidity: low-level call returns bool that's often unchecked.
C++: [[nodiscard]] is opt-in. Move: values must be consumed.
Q6.2: What happens on the ERROR/ABORT path?
→ Are there side effects before the error?
→ Does the error message leak sensitive information?
→ Can an attacker cause targeted errors (griefing / DoS)?
→ In languages with exceptions: is cleanup code (finally/defer/
Drop) correct? Are resources leaked on the error path?
Q6.3: What if an EXTERNAL CALL in this function fails silently?
→ Does the language/runtime guarantee failure propagation?
→ Is the error checked, or can it be swallowed?
→ Language examples:
Solidity: low-level call returns (bool, bytes) — often unchecked
Go: err is a normal return value — easy to ignore with _
Rust: .unwrap() can panic; ? propagates but hides the error
C++: exception might be caught too broadly
Move: abort is always propagated (safer by design)
Q6.4: Is there a code path where NO return and NO error happens?
→ Functions falling through without explicit return
→ Default/zero values used when they shouldn't be
→ Missing match/switch arms or else branches
→ Language-specific:
Rust: compiler catches this. Go/C++: does not always.
Solidity: functions can fall through returning zero values.This category catches bugs that live in the TIMING and SEQUENCING of operations — both within a single transaction and across multiple transactions over time.
Q7.1: If the function performs an external call BEFORE a state update,
what happens if I SWAP them — state update first, external call second?
→ If the swap causes a revert: the ORIGINAL ordering may be exploitable
(the external call might re-enter or manipulate state before it's updated)
→ If the swap works cleanly: the original ordering is likely safe,
OR the swap reveals the intended safe ordering was never enforced
→ KEY: Try both directions. The one that reverts tells you which
ordering the code DEPENDS on. The one that doesn't revert tells you
which ordering an attacker can exploit.
Q7.2: If the function performs an external call AFTER a state update,
what happens if I SWAP them — external call first, state update second?
→ If the swap causes a revert: the current code is CORRECTLY ordered
(state must be updated before the external call can proceed)
→ If the swap works cleanly: the ordering doesn't matter, OR
the external call could be exploited before state is finalized
→ FINDING: If moving the external call BEFORE the state update
allows an attacker to observe/act on stale state, this is a bug.
Q7.3: For EVERY external call in the function, ask:
"What can the CALLEE do with the current state at THIS exact moment?"
→ At the point of the external call, what state is committed vs pending?
→ Can the callee re-enter this contract/module and see inconsistent state?
→ Can the callee call a DIFFERENT function that reads the not-yet-updated state?
→ This applies beyond reentrancy: callbacks, hooks, oracle calls,
cross-contract reads — ANY outbound call is an opportunity for
the callee to act on intermediate state.
→ Language examples:
Solidity: .call(), .transfer(), IERC20.safeTransfer(), callback hooks
Move: cross-module function calls during resource manipulation
Rust/Anchor: CPI (Cross-Program Invocation) in Solana
Go: outbound HTTP/RPC calls, goroutine spawning mid-operation
C++: virtual method calls, callback invocations, signal handlers
Q7.4: What is the MINIMAL set of state that MUST be updated before each
external call to prevent exploitation?
→ List every state variable the external callee could read or depend on
→ If ANY of those variables are updated AFTER the external call,
flag it as a potential ordering vulnerability
→ The fix is often: move the state update above the external call
(checks-effects-interactions pattern generalized to any language)Q7.5: If a user calls this function with value X, and then calls it AGAIN
later with value Y — does the second call behave correctly given the
state changes from the first call?
→ The first call changes state. Does the second call's logic ACCOUNT
for that changed state, or does it assume fresh/initial state?
→ Example: deposit(100), then deposit(50). Does the second deposit
correctly handle shares/accounting when totalSupply is no longer 0?
→ Example: borrow(1000), then borrow(500). Does the second borrow
check against the UPDATED debt, or does it re-read stale collateral?
Q7.6: After transaction T1 changes state, does transaction T2 (same function,
different parameters) REVERT when it shouldn't, or SUCCEED when it shouldn't?
→ Unexpected revert: T1's state change made a condition impossible for T2
(e.g., T1 drains a pool below a minimum, T2 can't withdraw dust)
→ Unexpected success: T1's state change should have blocked T2 but didn't
(e.g., T1 uses all collateral, T2 still borrows against phantom collateral)
→ DEEP CHECK: Don't just test T2 immediately after T1. Test T2 after:
- Many T1s have accumulated (state drift over time)
- T1 with extreme values (max, min, dust)
- T1 from a different user (cross-user state pollution)
- T1 that was partially reverted (try-catch leaving dirty state)
Q7.7: Does the accumulated state from MULTIPLE calls create a condition that
a SINGLE call can never reach?
→ Rounding errors that compound: each call loses 1 wei of precision,
after 1000 calls the accounting is off by 1000 wei
→ Monotonically growing state: counters, nonces, array lengths that
grow but never shrink — do they hit a ceiling or overflow?
→ Reward/rate staleness: if updateReward() is called infrequently,
do accumulated rewards become incorrect?
→ State fragmentation: many small operations leaving dust/remnants
that block future operations (e.g., can't close position because
of 1 wei of remaining debt)
WORKED EXAMPLE — Partial Swap Fee Distribution Bug:
─────────────────────────────────────────────────────
Consider an AMM pool with a swap() function that:
1. Calculates amountOut based on reserves
2. Updates accumulatedFees (used for LP fee distribution)
3. Updates reserves
Scenario — partial swap with wrong fee accounting:
State: reserveA=10000, reserveB=10000, accFees=0, totalLP=100
TX1: Alice swaps 1000 tokenA → tokenB (partial fill, 0.3% fee)
- fee = 3 tokenA → accFees updated to 3
- BUT: the fee is added to accFees BEFORE reserves update
- reserveA becomes 11000, reserveB becomes ~9091
- feePerLP = 3/100 = 0.03 per LP token ✓ (looks correct)
TX2: Bob swaps 500 tokenA → tokenB (different amount, same function)
- fee = 1.5 tokenA → accFees updated to 4.5
- BUT: feePerLP is now calculated as 4.5/100 = 0.045
- The problem: the fee rate was computed using STALE reserve
ratios from before TX1 changed the pool composition
- After TX1, the pool is imbalanced — 1 tokenA is worth less
than before. But the fee accounting still values TX2's fee
at the OLD rate.
TX3: Charlie claims LP fees
- Gets paid based on accFees = 4.5 at OLD token valuation
- But the pool's ACTUAL composition has shifted — the fees
are denominated in a token that's now worth less in the pool
- Result: fee distribution is skewed. Early LPs get overpaid,
late LPs get underpaid. Over hundreds of swaps, the
accounting diverges significantly from reality.
The root cause: accFees is updated per-swap without rebasing
against the current reserve ratio. Each swap changes what "1 unit
of fee" is worth, but the accumulator treats all units as equal.
→ GENERALIZE THIS PATTERN to any system where:
- A global accumulator (fees, rewards, interest) is updated per-tx
- The VALUE of what's being accumulated changes between txs
- The accumulator doesn't rebase/normalize against current state
- Examples: LP fee distributors, staking reward accumulators,
interest rate models, rebasing token accounting, yield vaults
with variable share prices
→ CHECK SPECIFICALLY:
- Is the fee/reward denominated in a token whose relative value
changes with each operation?
- Does the accumulator use a snapshot of rates/prices that goes
stale after the state-changing operation?
- Are fees calculated BEFORE or AFTER the reserves/balances update?
(before = stale rate, after = correct rate, but BOTH must be checked)
- When multiple fee tiers or partial fills exist, does each partial
chunk use the UPDATED state from the previous chunk, or do they
all use the ORIGINAL state? (batch vs iterative accounting)
- After N swaps with varying sizes, does SUM(individual fees) equal
the fee you'd compute on the AGGREGATE swap? If not, the
accumulator is path-dependent and exploitable.
Q7.8: Can an attacker craft a SEQUENCE of transactions to reach a state
that no single "normal" transaction path would produce?
→ Deposit-borrow-withdraw-liquidate sequences that leave bad debt
→ Stake-unstake-restake sequences that compound rounding errors
→ Create-transfer-destroy sequences that orphan child state
→ The attacker's advantage: they CHOOSE the order, amounts, and
timing. Test adversarial sequences, not just happy-path sequences.
→ For each function, ask: "After calling THIS, what state is the
system in? What functions become newly available or newly dangerous
to call from that state?"The bugs are in the answers to these 4 questions.
Ask them FIRST — they tell you WHERE to spend your time.
Q0.1: What's the WORST thing an attacker can do here?
→ Think attacker, NOT user. Users follow happy paths.
Attackers find the one path the dev never imagined.
→ List the top 3-5 catastrophic outcomes:
drain all funds, brick the system, steal admin privileges,
manipulate prices/data, grief other users permanently,
corrupt state irreversibly, exfiltrate sensitive data.
→ These become your ATTACK GOALS for the entire audit.
Every function you read, ask: "Does this help an
attacker achieve any of these goals?"
Q0.2: What parts of the project are NOVEL?
→ First-time code = first-time bugs. Period.
→ Identify code that is NOT a fork/copy of battle-tested
libraries or frameworks.
Solidity: OpenZeppelin, Uniswap, Aave forks
Move: Aptos Framework, Sui Framework stdlib
Rust: well-known crates (tokio, serde, anchor)
Go: standard library, well-maintained packages
C++: STL, Boost, established frameworks
→ Custom math, custom state machines, novel incentive
structures, unusual callback/hook patterns —
THIS is where your time pays off most.
→ Standard library imports are unlikely to have bugs.
The glue code connecting them is where things break.
Q0.3: Where does VALUE actually sit?
→ Follow the money. Every expensive mistake involves
value moving somewhere it shouldn't.
→ Map every module/component that holds:
- Funds (native tokens, coins, balances, account credits)
- Assets (tokens, NFTs, resources, inventory)
- Sensitive data (keys, credentials, PII)
- Accounting state (shares, debt, rewards, balances)
→ For each value store, ask: "What code path moves
value OUT? What authorizes it? What validates the amount?"
→ The functions touching these stores get 10x more scrutiny.
Q0.4: What's the most COMPLEX interaction path?
→ Complexity kills. The most complex path through the
system is the most likely to contain bugs.
→ Map paths that: cross multiple modules/contracts/services,
involve callbacks or hooks, mix user input with external data,
have multiple branching conditions, or chain state changes.
→ If a path touches 4+ modules or has 3+ external calls,
it's a prime candidate for state inconsistency bugs.
→ Cross-module interaction + value movement = audit gold.Output of Phase 0: A prioritized hit list.
┌─────────────────────────────────────────────────────┐
│ PHASE 0 — ATTACKER'S HIT LIST │
├─────────────────────────────────────────────────────┤
│ │
│ LANGUAGE: [detected language/framework] │
│ │
│ ATTACK GOALS (from Q0.1): │
│ 1. [worst outcome] │
│ 2. [second worst] │
│ 3. [third worst] │
│ │
│ NOVEL CODE — highest bug density (from Q0.2): │
│ - [module/file] — [why it's novel] │
│ - [module/file] — [why it's novel] │
│ │
│ VALUE STORES — follow the money (from Q0.3): │
│ - [module] holds [asset] — [outflow functions] │
│ - [module] holds [asset] — [outflow functions] │
│ │
│ COMPLEX PATHS — complexity kills (from Q0.4): │
│ - [path description] — [modules involved] │
│ - [path description] — [modules involved] │
│ │
│ PRIORITY ORDER (spend time here first): │
│ 1. [highest priority target + why] │
│ 2. [second priority target + why] │
│ 3. [third priority target + why] │
│ │
└─────────────────────────────────────────────────────┘Functions and modules that appear in MULTIPLE answers above get audited FIRST and with the DEEPEST scrutiny in Phase 2. Everything else is secondary.
1. Identify ALL modules/contracts/packages in scope
2. For each module, list:
- ALL entry points (public/exported/external functions — the attack surface)
- ALL state they read/write (storage, globals, struct fields, DB)
- ALL access guards applied (modifiers, auth checks, visibility)
- ALL internal functions they call
3. Build a FUNCTION-STATE MATRIX:
| Function | Reads | Writes | Guards | Calls |
|----------|-------|--------|--------|-------|
This matrix is your map for consistency analysis (Category 3)For EACH function, perform the Feynman interrogation:
┌─────────────────────────────────────────────────────┐
│ FUNCTION: [module.functionName] │
│ Visibility: [public/private/internal/exported] │
│ Guards: [access control, auth checks, decorators] │
│ State reads: [variables/fields/storage] │
│ State writes: [variables/fields/storage] │
│ External calls: [targets] │
├─────────────────────────────────────────────────────┤
│ │
│ LINE-BY-LINE INTERROGATION: │
│ │
│ L[N]: [code line] │
│ Q1.1 → WHY: [explanation or "CANNOT EXPLAIN" flag] │
│ Q2.1 → ORDER: [what if moved up?] │
│ Q2.2 → ORDER: [what if moved down?] │
│ Q4.x → ASSUMES: [hidden assumption found] │
│ Q5.x → EDGE: [boundary behavior] │
│ → VERDICT: SOUND | SUSPECT | VULNERABLE │
│ → If SUSPECT/VULNERABLE: [specific scenario] │
│ │
│ CROSS-FUNCTION CHECK: │
│ Q3.1 → [guard consistency with sibling functions] │
│ Q3.2 → [inverse operation parity] │
│ Q3.3 → [parameter validation consistency] │
│ │
│ FUNCTION VERDICT: SOUND | HAS_CONCERNS | VULNERABLE │
└─────────────────────────────────────────────────────┘IMPORTANT: You do NOT need to ask ALL questions for ALL lines. Use judgment:
Using the Function-State Matrix from Phase 1:
1. GUARD CONSISTENCY
- Group functions by the state variables they WRITE
- Within each group, list all access guards
- FLAG: Any function missing a guard its siblings have
2. INVERSE OPERATION PARITY
- Pair up: deposit/withdraw, mint/burn, stake/unstake,
create/destroy, add/remove, open/close, encode/decode, etc.
- For each pair, compare:
- Parameter validation (Q3.2)
- State changes (are they truly inverse?)
- Access control (should both require same auth?)
- Event/log emission (are both tracked?)
3. STATE TRANSITION INTEGRITY
- Map all valid state transitions
- For each transition, verify:
- Can it be triggered out of expected order?
- Can it be skipped entirely?
- Can it be triggered by an unauthorized actor?
- What if it's triggered when the system is in an unexpected state?
4. VALUE FLOW TRACKING
- Trace value/asset flows across function boundaries
- Verify: value in == value out (conservation)
- FLAG: Any path where value can be created or destroyed unexpectedlyFor each SUSPECT or VULNERABLE verdict:
1. Write the QUESTION that exposed it
2. Describe the SCENARIO (step-by-step)
3. Show the AFFECTED CODE (exact lines)
4. Explain WHY the current code fails
5. Assess IMPACT (what can an attacker gain/break?)
6. Classify severity: CRITICAL / HIGH / MEDIUM / LOW
7. Suggest a FIX (minimal, targeted)Save raw (unverified) findings to: .audit/findings/feynman-analysis-raw.md
IMPORTANT: Do NOT report raw findings to the user as final results. These are HYPOTHESES that must be verified in Phase 5 before inclusion in the final report.
Every CRITICAL, HIGH, and MEDIUM finding from Phase 4 MUST be verified before being included in the final report. Feynman reasoning surfaces many hypotheses, but code-level reasoning alone produces false positives (wrong mechanism assumed, mitigating code missed, incorrect severity assessment). Verification eliminates these before they reach the user.
VERIFICATION RULE: No C/H/M finding goes into the final report unverified.
Raw findings are HYPOTHESES. Verified findings are RESULTS.Method A: Deep Code Trace Verification For findings about missing checks, wrong parameters, or inconsistent validation:
Method B: PoC Test Verification For findings about math errors, rounding drift, resource limits, or state accounting:
forge test --match-path "test/audit/[file]" -vvvaptos move test --filter [test_name] or sui move testcargo test [test_name] -- --nocapturego test -run TestName -vMethod C: Hybrid (Code Trace + PoC) For complex findings spanning multiple modules:
| Severity | Verification Required | Method |
|---|---|---|
| CRITICAL | MANDATORY — PoC required (Method B or C) | Must demonstrate value loss or permanent DoS with concrete numbers |
| HIGH | MANDATORY — Code trace + PoC recommended (Method A or C) | Must confirm the broken invariant is reachable |
| MEDIUM | MANDATORY — Code trace minimum (Method A) | Must confirm the mechanism is correct and not mitigated elsewhere |
| LOW | Optional — Code inspection sufficient | Quick sanity check: is the line/function real? |
[] 1. Does the cited code actually exist at the stated line numbers?
[] 2. Is the described mechanism correct? (trace the actual math/logic)
[] 3. Are there mitigating factors the finding missed?
- Called functions that add validation
- Access guards on calling functions
- Upstream checks that prevent the scenario
- Downstream checks that catch the error
- Language-level safety (borrow checker, type system, Move verifier)
[] 4. Is the severity accurate given the ACTUAL impact?
- Does "value loss" actually mean "revert/abort with confusing error"?
- Does "permanent DoS" actually mean "self-griefing only"?
- Is the "missing check" actually handled by a different code path?
[] 5. For PoC-verified findings: does the test output match the claim?These patterns frequently produce hypotheses that fail verification:
"Missing authorization" that exists in a different layer: Finding says auth is missing, but the caller/router/middleware already enforces it before this function is reachable.
"Rounding drift" that's cleaned by downstream code:
Finding identifies scale_up(scale_down(x)) < x but misses cleanup
applied upstream that ensures x is always a clean multiple.
"No validation" that errors downstream: Finding says a parameter isn't validated, but the called function has its own validation that catches invalid inputs (just with a confusing error message).
"Unbounded loop" bounded by design or economics: Finding says a loop has no cap, but the data structure is bounded by design, or the economic cost of creating the DoS condition exceeds the benefit.
"Severity inflation": Finding claims CRITICAL (value loss) but actual impact is MEDIUM (error/DoS) because a safety check catches the issue before value is affected.
"Language safety ignored": Finding claims overflow/underflow but the language aborts on overflow by default (Move, Rust in debug, Solidity >=0.8). Or finding claims memory unsafety in a memory-safe language.
After verification, produce the VERIFIED findings file:
Save to: .audit/findings/feynman-verified.md
# Feynman Audit — Verified Findings
## Verification Summary
| ID | Original Severity | Verdict | Final Severity |
|----|-------------------|---------|----------------|
| FF-001 | CRITICAL | TRUE POSITIVE — DOWNGRADE | LOW |
| FF-002 | HIGH | TRUE POSITIVE | HIGH |
| FF-003 | MEDIUM | FALSE POSITIVE | — |
| ... | ... | ... | ... |
## Verified TRUE POSITIVE Findings
[Only findings that passed verification, with final severity]
## False Positives Eliminated
[Findings that failed verification, with explanation of why]
## Downgraded Findings
[Findings where severity was reduced, with justification]Only the verified findings file should be presented to the user as the final report.
| Severity | Criteria |
|---|---|
| CRITICAL | Direct value/fund loss, permanent DoS, or system insolvency |
| HIGH | Conditional value loss, privilege escalation, or broken core invariant |
| MEDIUM | Value leakage, griefing with cost, or degraded functionality |
| LOW | Informational, inefficiency, or cosmetic inconsistency with no exploit |
Two files are produced during the audit:
Save to: .audit/findings/feynman-analysis-raw.md
This contains ALL hypotheses from Phases 1-4 before verification. Include the Function-State Matrix, Guard Consistency Analysis, Inverse Operation Parity, and all raw findings with their initial severity classification.
Save to: .audit/findings/feynman-verified.md
# Feynman Audit — Verified Findings
## Scope
- Language: [detected language]
- Modules analyzed: [list]
- Functions analyzed: [count]
- Lines interrogated: [count]
## Verification Summary
| ID | Original Severity | Verdict | Final Severity |
|----|-------------------|---------|----------------|
## Function-State Matrix
[The matrix from Phase 1]
## Guard Consistency Analysis
[Results from Phase 3.1 — which functions are missing expected guards]
## Inverse Operation Parity
[Results from Phase 3.2 — asymmetries between paired operations]
## Verified Findings (TRUE POSITIVES only)
### Finding FF-001: [Title]
**Severity:** CRITICAL | HIGH | MEDIUM | LOW
**Module:** [name]
**Function:** [name]
**Lines:** [L:start-end]
**Verification:** [Code trace / PoC / Hybrid] — [test file if PoC]
**Feynman Question that exposed this:**
> [The exact question from the framework]
**The code:**
```[language]
// [affected code block]Why this is wrong: [First-principles explanation — no jargon, no pattern names. Explain like you're teaching someone who has never seen this bug class.]
Verification evidence: [For code trace: the exact mitigating/confirming code paths traced] [For PoC: test name, key log output, concrete numbers]
Attack scenario:
Impact: [What an attacker gains or what breaks]
Suggested fix:
// [minimal fix][Findings that failed verification, with explanation of WHY they are false]
[Findings where severity was reduced, with justification]
[Table of LOW findings with brief verdict]
---
## Post-Audit Actions
| Scenario | Action |
|----------|--------|
| Need deeper context on a function | Re-read the function and its callers line-by-line |
| Finding confirmed as true positive | Write up with severity, trigger sequence, PoC, and fix |
| Need exploit validation | Write a Foundry/Hardhat PoC test to confirm |
| Uncertain about design intent | Check NatSpec, comments, and project documentation |
---
## Anti-Hallucination Protocol
NEVER:
ALWAYS:
---
## Quick-Start Checklist
When starting a Feynman audit:
- [ ] **Phase 0:** Detect the language and adapt terminology
- [ ] **Phase 0:** Answer the 4 attacker mindset questions BEFORE reading code
- [ ] **Phase 0:** Build the Attacker's Hit List (attack goals, novel code, value stores, complex paths)
- [ ] **Phase 0:** Prioritize targets — functions appearing in multiple answers get audited first
- [ ] **Phase 1:** List all modules/contracts/packages in scope
- [ ] **Phase 1:** Build the Function-State Matrix
- [ ] **Phase 1:** Identify all function pairs (deposit/withdraw, etc.)
- [ ] **Phase 2:** Run Feynman interrogation on every entry point (priority order from Phase 0)
- [ ] **Phase 3:** Run cross-function analysis (guard consistency, inverse parity, value flow)
- [ ] **Phase 4:** Document all SUSPECT and VULNERABLE verdicts as raw findings
- [ ] **Phase 4:** Save raw findings to `.audit/findings/feynman-analysis-raw.md`
- [ ] **Phase 5:** Verify ALL C/H/M findings (code trace + PoC where needed)
- [ ] **Phase 5:** Eliminate false positives, downgrade inflated severities
- [ ] **Phase 5:** Save verified findings to `.audit/findings/feynman-verified.md`
- [ ] **Phase 5:** Present ONLY the verified report to the user© 0xiehnnkta, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/feynman-auditor of 0xiehnnkta/nemesis-auditor.
Open the folder on GitHubat commit 75cecc6
We found 1 copy of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in 0xiehnnkta/nemesis-auditor, which our catalogue first saw on October 7, 2026.
Feynman Auditor next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Feynman Auditor this skill0xiehnnkta/nemesis-auditor | 243 | 1 repos | ~11k | Automated safety check: Pass | MIT | |
| RadarAuditware/radar | 154 | — | ~2.1k | Automated safety check: Pass | GPL-3.0 | |
| Evm MaintainerRaoFoundation/subtensor | 389 | — | ~2.5k | Automated safety check: Pass | Apache-2.0 | |
| Smart Contract Auditforefy/.context | 152 | 1 repos | ~5.1k | Automated safety check: Pass | MIT | |
| Smart Contract Auditelophanto/EloPhanto | 106 | — | ~2.7k | Automated safety check: Pass | Custom licence | |
| Fizz Convertpashov/skills | 1.2k | 2 repos | ~3.7k | Automated safety check: Pass | MIT |
Auditware/radar
Use radar for smart contract security analysis, AST generation, and detection template development.
RaoFoundation/subtensor
Maintain backwards-compatible, versioned EVM precompiles that expose runtime extrinsics, state, constants, and APIs to Solidity.
forefy/.context
Comprehensive smart contract security audit framework with multi-expert analysis.
elophanto/EloPhanto
A skill your agent uses when reviewing a Solidity, Vyper, or Rust (Solana/Anchor) smart contract for paid audit work or pre-launch sanity check.
pashov/skills
Convert English-language properties in PROPERTIES.md (produced by the Fizz skill) into Solidity assertions inside the existing fuzz harness, then flip their checkboxes.
greatpie/smart-contract-audit-skill
Script-backed, out-of-box auditing workflow for Solidity/EVM repositories based on EVMbench detect/patch/exploit methodology.
0xiehnnkta/nemesis-auditor
The Inescapable Auditor. An agent skill from 0xiehnnkta/nemesis-auditor.
0xiehnnkta/nemesis-auditor
Finds state inconsistency bugs where an operation mutates one piece of coupled state without updating its dependent counterpart, causing silent data corruption or reverts in subsequent operations.
Categories
Deep business logic bug finder using the Feynman technique. An agent skill from 0xiehnnkta/nemesis-auditor. Feynman Auditor is an agent skill from 0xiehnnkta/nemesis-auditor. Deep business logic bug finder using the Feynman technique.
Feynman Auditor fits situations like: deep logic review; tasks that involve Smart contracts.
Run `npx skills add 0xiehnnkta/nemesis-auditor --skill feynman-auditor -a claude-code`. Or copy the skill folder (.claude/skills/feynman-auditor in 0xiehnnkta/nemesis-auditor) into .claude/skills/feynman-auditor in your project. Claude Code loads it when a task matches its description.
Run `npx skills add 0xiehnnkta/nemesis-auditor --skill feynman-auditor -a codex`. Or copy the skill folder (.claude/skills/feynman-auditor in 0xiehnnkta/nemesis-auditor) into .agents/skills/feynman-auditor in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add 0xiehnnkta/nemesis-auditor --skill feynman-auditor -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/feynman-auditor, .gemini/skills/feynman-auditor, .github/skills/feynman-auditor and .opencode/skills/feynman-auditor in your project.
Going by SKILL.md and its folder, Feynman Auditor needs the command-line tools its instructions call (cargo and go).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Feynman Auditor is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 11k tokens (SKILL.md is roughly 44k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Feynman Auditor: Radar (Auditware/radar, 154 stars), Evm Maintainer (RaoFoundation/subtensor, 389 stars), Smart Contract Audit (forefy/.context, 152 stars) and Smart Contract Audit (elophanto/EloPhanto, 106 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
0xiehnnkta (a GitHub user) maintains it in 0xiehnnkta/nemesis-auditor, which has 243 GitHub stars. The repository holds 3 skills in this directory. The repository was last updated on March 16, 2026.
Source: 0xiehnnkta/nemesis-auditor on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.