Reentrancy Pattern Analysis logo

Reentrancy Pattern Analysis

Organization
quillai-network
reentrancy-pattern-analysis

Systematically detects all reentrancy vulnerability variants in smart contracts — classic, cross-function, cross-contract, and read-only reentrancy. Builds call graphs, verifies CEI (Checks-Effects-Interactions) pattern compliance, traces state changes relative to external calls, and identifies callback vectors through ERC-777/ERC-1155 hooks. Use when auditing contracts that make external calls, transfer ETH or tokens, interact with callback-enabled standards, or have complex multi-contract architectures.

Overview

Publisherquillai-network
Repositoryquillshield_skills
Skill namereentrancy-pattern-analysis
Stars
131
Forks
28
Bundled files
2
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 2 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by quillai-network on GitHub. Read the source before you install it.

Installation

Install the Reentrancy Pattern Analysis AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/quillai-network/quillshield_skills/tree/main/plugins/reentrancy-pattern-analysis/skills/reentrancy-pattern-analysis
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/quillai-network/quillshield_skills.git /tmp/quillshield_skills
mkdir -p .claude/skills
cp -r /tmp/quillshield_skills/plugins/reentrancy-pattern-analysis/skills/reentrancy-pattern-analysis .claude/skills/reentrancy-pattern-analysis
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Reentrancy Pattern Analysis in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Reentrancy Pattern Analysis on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Reentrancy Pattern Analysis is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Reentrancy Pattern Analysis

Systematically detect all variants of reentrancy vulnerabilities by mapping the relationship between external calls and state changes across the entire contract system.

When to Use

  • Auditing any contract that makes external calls (ETH transfers, token interactions, cross-contract calls)
  • Reviewing contracts integrating with callback-enabled token standards (ERC-777, ERC-1155)
  • Analyzing DeFi protocols with multi-contract architectures
  • Verifying reentrancy guard coverage across all entry points
  • When traditional tools only check for classic reentrancy but miss cross-function or read-only variants

When NOT to Use

  • Pure state variable analysis without external calls (use state-invariant-detection)
  • Access control consistency checking (use semantic-guard-analysis)
  • Full multi-dimensional audit (use behavioral-state-analysis, which orchestrates this skill)

Core Concept: The CEI Invariant

Checks-Effects-Interactions (CEI) is the fundamental safety pattern:

1. CHECKS   — Validate all conditions (require statements, access control)
2. EFFECTS  — Update all state variables
3. INTERACTIONS — Make external calls (ETH transfers, token calls, cross-contract)

Any function that performs INTERACTIONS before completing all EFFECTS is potentially vulnerable to reentrancy.

The Five Reentrancy Variants

Variant 1: Classic Single-Function Reentrancy

The original and most well-known pattern. A function makes an external call before updating its own state, allowing the callee to re-enter the same function.

solidity
// VULNERABLE
function withdraw(uint256 amount) public {
    require(balances[msg.sender] >= amount);
    (bool success, ) = msg.sender.call{value: amount}(""); // INTERACTION before EFFECT
    require(success);
    balances[msg.sender] -= amount; // State update AFTER external call
}

Detection: Find functions where state writes to variables used in require checks occur AFTER external calls.

Variant 2: Cross-Function Reentrancy

Two or more functions share state, and an attacker re-enters through a DIFFERENT function than the one making the external call.

solidity
function withdraw(uint256 amount) public {
    require(balances[msg.sender] >= amount);
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success);
    balances[msg.sender] -= amount;
}

// Attacker re-enters HERE during withdraw's external call
function transfer(address to, uint256 amount) public {
    require(balances[msg.sender] >= amount);
    balances[msg.sender] -= amount;
    balances[to] += amount;
}

Detection: For each external call in function F, check if any OTHER public function reads/writes the same state variables that F modifies after the call.

Variant 3: Cross-Contract Reentrancy

The re-entry occurs through a different contract that shares state or trust relationships with the vulnerable contract.

solidity
// Contract A
function withdrawFromVault() public {
    uint256 shares = vault.balanceOf(msg.sender);
    vault.burn(msg.sender, shares);
    // External call — attacker can re-enter Contract B
    (bool success, ) = msg.sender.call{value: shares * pricePerShare}("");
    require(success);
}

// Contract B (attacker re-enters here)
function borrow() public {
    uint256 collateral = vault.balanceOf(msg.sender); // Reads stale state!
    // Shares not yet burned, so collateral appears inflated
    uint256 loanAmount = collateral * maxLTV;
    token.transfer(msg.sender, loanAmount);
}

Detection: Map all cross-contract dependencies. For each external call, identify which other contracts read the state that should have been updated.

Variant 4: Read-Only Reentrancy

A view/pure function returns stale state during a reentrancy callback. No state is modified during re-entry — the attacker exploits the READING of inconsistent state by a third-party contract.

solidity
// Pool contract
function removeLiquidity() external {
    uint256 shares = balances[msg.sender];
    // Burns LP tokens (updates internal accounting)
    _burn(msg.sender, shares);
    // External call BEFORE updating reserves
    (bool success, ) = msg.sender.call{value: ethAmount}("");
    // Reserves updated AFTER the call
    totalReserves -= ethAmount;
}

// This view function returns stale data during the callback
function getRate() public view returns (uint256) {
    return totalReserves / totalSupply(); // totalReserves not yet updated!
}

// Third-party contract reads the inflated rate
function priceOracle() external view returns (uint256) {
    return pool.getRate(); // Returns wrong value during reentrancy
}

Detection: For each external call, identify view functions that read state variables modified AFTER the call. Check if any external protocol depends on those view functions.

Variant 5: ERC-777 / ERC-1155 Callback Reentrancy

Token standards with built-in callback hooks that execute arbitrary code on the receiver during transfers.

solidity
// ERC-777: tokensReceived() hook called on recipient
// ERC-1155: onERC1155Received() hook called on recipient
// ERC-721: onERC721Received() hook called on recipient

function deposit(uint256 amount) public {
    token.transferFrom(msg.sender, address(this), amount); // Triggers callback!
    // If token is ERC-777, msg.sender's tokensReceived() runs HERE
    balances[msg.sender] += amount; // State update after callback
}

Detection: Identify all token transfer/transferFrom/safeTransfer calls. Check if the token could be ERC-777/ERC-1155/ERC-721. Verify state updates happen before the transfer.

Three-Phase Detection Architecture

Phase 1: Call Graph Construction

Build a complete map of all external interactions.

For each function, extract:

Function: withdraw()
├── External Calls:
│   ├── msg.sender.call{value: amount}("") at line 45
│   ├── token.transfer(user, amount) at line 48
│   └── oracle.getPrice() at line 42
├── State Writes:
│   ├── balances[msg.sender] -= amount at line 50
│   └── totalWithdrawn += amount at line 51
├── State Reads (in requires):
│   └── balances[msg.sender] at line 41
└── Modifiers:
    └── nonReentrant: NO

Call Classification:

Call TypeReentrancy RiskExamples
ETH transfer via callHIGHaddr.call{value: x}("")
Token transfer/transferFromMEDIUM-HIGHERC-777 hooks, ERC-1155 callbacks
safeTransferFrom (NFT)MEDIUMERC-721 onERC721Received callback
Cross-contract function callMEDIUMotherContract.doSomething()
staticcall / view callsLOWCannot modify state but can trigger read-only reentrancy in callers
delegatecallHIGHExecutes in caller's context

Phase 2: CEI Violation Detection

For each function with external calls, verify CEI ordering.

Algorithm:

For each function F with external calls:
  1. E = set of all state variables written by F
  2. C = set of all state variables read in require/if checks
  3. I = position of each external call in F
  4. For each external call at position P:
     a. W_after = state writes that occur AFTER position P
     b. If W_after ∩ (E ∪ C) ≠ ∅:
        → CEI VIOLATION: state modified after external call
     c. Classify violation:
        - W_after ∩ C ≠ ∅ → Classic reentrancy (check variable modified after call)
        - W_after ∩ E ≠ ∅ → State inconsistency window

Cross-Function Extension:

For each external call in function F at position P:
  W_before = state variables NOT yet updated at position P
  For each OTHER public function G:
    R_G = state variables read by G
    W_G = state variables written by G
    If R_G ∩ W_before ≠ ∅ OR W_G ∩ W_before ≠ ∅:
      → CROSS-FUNCTION REENTRANCY: G can be called during F's external call
         with inconsistent state

Phase 3: Guard Coverage Verification

Check that reentrancy protections are correctly applied.

Guard Types:

GuardCoverageLimitations
nonReentrant modifier (OpenZeppelin)Single contract, all functions with modifierDoes not protect cross-contract reentrancy
CEI pattern compliancePer-functionMust be verified for every function individually
transfer() / send() (2300 gas)Limits callback gasNOT safe — EIP-1884 changed gas costs; don't rely on this
Pull payment patternEliminates external calls from state changesRequires architectural change

Verification:

For each function F with CEI violations:
  1. Check if F has nonReentrant modifier → Mitigated (single-contract only)
  2. Check if ALL functions sharing state also have nonReentrant → Mitigated (cross-function)
  3. Check if cross-contract consumers are protected → Requires manual review
  4. If no guard → VULNERABLE

Workflow

Task Progress:
- [ ] Step 1: Identify all external calls in every function (ETH transfers, token calls, cross-contract)
- [ ] Step 2: Build call graph with state read/write positions relative to each call
- [ ] Step 3: Detect CEI violations (state writes after external calls)
- [ ] Step 4: Detect cross-function reentrancy (shared state across functions)
- [ ] Step 5: Detect callback vectors (ERC-777, ERC-1155, ERC-721 token interactions)
- [ ] Step 6: Detect read-only reentrancy (view functions reading stale state)
- [ ] Step 7: Verify guard coverage (nonReentrant, CEI compliance, pull patterns)
- [ ] Step 8: Score findings and generate report

Output Format

markdown
## Reentrancy Analysis Report

### Finding: [Title]

**Function:** `functionName()` at `Contract.sol:L42`
**Variant:** [Classic | Cross-Function | Cross-Contract | Read-Only | Callback]
**Severity:** [CRITICAL | HIGH | MEDIUM]
**Guard Status:** [Unguarded | Partially Guarded | Guarded]

**CEI Violation:**
  - External call at line [X]: `[call expression]`
  - State write AFTER call at line [Y]: `[state variable] = [expression]`

**Re-Entry Path:**
  1. Attacker calls `functionName()`
  2. External call triggers callback to attacker contract
  3. Attacker re-enters via `[re-entry function]`
  4. State variable `[name]` still has pre-update value
  5. [Exploit consequence]

**Impact:**
[Funds drained, state corrupted, price manipulated, etc.]

**Recommendation:**
[Specific fix — reorder state updates, add nonReentrant, use pull pattern]

Severity Classification

VariantState ModifiedFunds at RiskSeverity
Classic — ETH drainYesYesCRITICAL
Cross-function — balance manipulationYesYesCRITICAL
Cross-contract — oracle/price manipulationIndirectlyYesHIGH
Read-only — stale price in third-partyNo (view only)PossiblyHIGH
Callback — ERC-777 deposit inflationYesPossiblyHIGH
Any variant with nonReentrant on targetMitigatedNoLOW/INFO

Advanced Detection: Transitive Reentrancy

Trace reentrancy through multiple contract hops:

Contract A calls Contract B
Contract B calls Contract C
Contract C calls back to Contract A (or reads A's stale state)

Detection: Build transitive call graph across all contracts in scope.
For each call chain A → B → ... → X:
  If X can call back to any contract in the chain → TRANSITIVE REENTRANCY

Quick Detection Checklist

When analyzing a contract, immediately check:

  • Does any function make an external call (ETH transfer, token transfer, cross-contract) BEFORE completing all state updates?
  • Are there multiple public functions that modify the same state variables, where at least one makes an external call?
  • Does the contract interact with ERC-777, ERC-1155, or ERC-721 tokens (callback hooks)?
  • Do view functions read state that is only partially updated during an external call?
  • Is nonReentrant applied to ALL functions that share state with a function making external calls, not just the calling function itself?
  • Does the contract rely on transfer() or send() for reentrancy protection? (Unsafe assumption)

For detailed variant taxonomy, see {baseDir}/references/reentrancy-variants.md. For real-world case studies, see {baseDir}/references/case-studies.md.

Rationalizations to Reject

  • "We use transfer() so reentrancy is impossible" → EIP-1884 changed gas costs; transfer is no longer considered safe
  • "The function has nonReentrant" → Check cross-function and cross-contract paths; one modifier doesn't protect everything
  • "It's just a view function" → Read-only reentrancy can manipulate prices and oracles in third-party contracts
  • "We only interact with standard ERC20 tokens" → ERC-777 is backward-compatible with ERC20; token type may change
  • "The external call is to a trusted contract" → Trust boundaries shift; verify the actual code path through all intermediaries
  • "State is updated right after the call" → "Right after" is too late; the call already happened

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Reentrancy Pattern Analysis AI skill do?

Systematically detects all reentrancy vulnerability variants in smart contracts — classic, cross-function, cross-contract, and read-only reentrancy. Builds call graphs, verifies CEI (Checks-Effects-Interactions) pattern compliance, traces state changes relative to external calls, and identifies callback vectors through ERC-777/ERC-1155 hooks. Use when auditing contracts that make external calls, transfer ETH or tokens, interact with callback-enabled standards, or have complex multi-contract architectures.

Why use Reentrancy Pattern Analysis on TypingMind?

Because you install it once and use it with any model. Reentrancy Pattern Analysis is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Reentrancy Pattern Analysis in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/quillai-network/quillshield_skills/tree/main/plugins/reentrancy-pattern-analysis/skills/reentrancy-pattern-analysis. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Reentrancy Pattern Analysis?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Reentrancy Pattern Analysis?

As many as you like. As long as a model supports skills, you can use Reentrancy Pattern Analysis with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Reentrancy Pattern Analysis AI skill free?

Yes. It is published on GitHub by quillai-network under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇