Problem Statement
ChainProof's existing reentrancy detectors (CP-107, swc107-reentrancy-v2.ts) analyze external-call-before-state-update patterns within a single function/contract. The multi-file import-graph and call-graph resolution built for the "Multi-file contract analysis with inheritance and import graph resolution" work gives ChainProof the infrastructure to see across contract boundaries, but no rule currently uses it to detect cross-contract reentrancy: the case where Contract A calls into Contract B, which calls back into Contract A (directly, or via a third Contract C), re-entering a function whose state hasn't been finalized yet. This is precisely the pattern behind several real-world exploits in vault/strategy architectures and is invisible to single-function analysis.
Proposed Solution
Implement a new detector, CP-121 (multi-hop cross-contract reentrancy), built on top of the existing rules/call-graph.ts infrastructure:
- Traverse the resolved call graph across the full set of scanned and imported contracts to find call chains of length two or more (
A.f() → B.g() → A.h(), or longer) where the re-entered contract (A) has unfinalized state changes pending between the initial external call and the point of re-entry.
- Distinguish chains that are protected by a consistent reentrancy guard (e.g., a
nonReentrant-style modifier applied across the whole chain, or checks-effects-interactions correctly applied at every hop) from genuinely exploitable chains.
- Support a configurable traversal depth (default 3 hops) with a hard cap to keep analysis time bounded on large protocols, and short-circuit cycles that don't involve unfinalized state.
- Findings must reference the full call chain (each contract/function/line in the path), not just the terminal re-entrant call, so the report is actionable.
- Integrate with the existing severity model (
critical, given this class of bug is typically fund-draining) and with the Slither merge/deduplication logic so a Slither-detected same-chain finding doesn't produce a duplicate.
Technical Scope
- New
packages/core/src/rules/cp121-cross-contract-reentrancy.ts implementing the traversal and detection logic against the existing CallGraph type from rules/call-graph.ts.
- Extend
rules/rule-context.ts if needed so the rule has access to the full multi-file call graph, not just the current file's AST.
- Register the rule in
scanner.ts and add it to the vulnerability rules table in the README.
- New fixture contracts under
examples/contracts/ demonstrating a 2-hop and a 3-hop exploitable cross-contract reentrancy, plus a correctly guarded (non-vulnerable) equivalent for false-positive testing.
- Unit tests covering: direct 2-hop reentrancy, 3-hop reentrancy through an intermediate contract, correctly guarded chains producing no finding, and a depth-limited case that should not be flagged beyond the configured maximum hops.
Acceptance Criteria
- Detects the 2-hop and 3-hop fixture exploits with the full call chain reported in the finding.
- Does not flag the guarded fixture (zero false positives on that case).
- Analysis time on the existing
examples/ fixture set stays within the current scan performance budget (no more than a small, documented constant-factor slowdown).
- The new rule appears in the README's Vulnerability Rules table with its SWC cross-reference where applicable.
Estimated Scope
Approximately 700 lines of new TypeScript across the rule, fixtures, and tests.
Problem Statement
ChainProof's existing reentrancy detectors (
CP-107,swc107-reentrancy-v2.ts) analyze external-call-before-state-update patterns within a single function/contract. The multi-file import-graph and call-graph resolution built for the "Multi-file contract analysis with inheritance and import graph resolution" work gives ChainProof the infrastructure to see across contract boundaries, but no rule currently uses it to detect cross-contract reentrancy: the case where Contract A calls into Contract B, which calls back into Contract A (directly, or via a third Contract C), re-entering a function whose state hasn't been finalized yet. This is precisely the pattern behind several real-world exploits in vault/strategy architectures and is invisible to single-function analysis.Proposed Solution
Implement a new detector,
CP-121(multi-hop cross-contract reentrancy), built on top of the existingrules/call-graph.tsinfrastructure:A.f() → B.g() → A.h(), or longer) where the re-entered contract (A) has unfinalized state changes pending between the initial external call and the point of re-entry.nonReentrant-style modifier applied across the whole chain, or checks-effects-interactions correctly applied at every hop) from genuinely exploitable chains.critical, given this class of bug is typically fund-draining) and with the Slither merge/deduplication logic so a Slither-detected same-chain finding doesn't produce a duplicate.Technical Scope
packages/core/src/rules/cp121-cross-contract-reentrancy.tsimplementing the traversal and detection logic against the existingCallGraphtype fromrules/call-graph.ts.rules/rule-context.tsif needed so the rule has access to the full multi-file call graph, not just the current file's AST.scanner.tsand add it to the vulnerability rules table in the README.examples/contracts/demonstrating a 2-hop and a 3-hop exploitable cross-contract reentrancy, plus a correctly guarded (non-vulnerable) equivalent for false-positive testing.Acceptance Criteria
examples/fixture set stays within the current scan performance budget (no more than a small, documented constant-factor slowdown).Estimated Scope
Approximately 700 lines of new TypeScript across the rule, fixtures, and tests.