Skip to content
Security
Skill

/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

BOOST
From plugin
quillshield-skills
12911 skills
Install
$ npx -y skills add quillai-network/quillshield_skills --skill reentrancy-pattern-analysis --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/reentrancy-pattern-analysis

Context preview

The summary Claude sees to decide when to auto-load this skill.

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

SKILL.md

reentrancy-pattern-analysis.SKILL.md
name: reentrancy-pattern-analysis
description: 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.

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.

// 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.

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.

// 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.

// 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.

// 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.send
Read more
Ships withquillshield-skills

AI agent skills for advanced smart contract security auditing. These skills teach AI agents (Claude, Cursor) the QuillShield methodology for detecting vulnerabilities that traditional static analysis tools miss.

Get the whole plugin

Other skills on quillshield-skills.