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.
Maintainer Scope Upgrade
This issue is being expanded into a substantial, production-quality ChainProof enhancement. The implementation should be designed as maintainable platform work, not as a narrow proof of concept. A successful pull request must provide a cohesive user-facing capability, typed internal APIs, robust tests, documentation, and CI-safe behavior.
Expanded Objective
Implement CP-121 as a multi-hop, cross-contract reentrancy detector using resolved import and call-graph context. The feature should fit the existing monorepo architecture, reuse current scanner/report/CLI patterns where appropriate, and avoid introducing ad hoc subsystems that are difficult to test or maintain.
Required Implementation Depth
This issue is intentionally scoped to require more than 700 lines of meaningful implementation work. The line count expectation applies to purposeful source, tests, fixtures, and documentation that are necessary to deliver the feature. It must not be satisfied through generated output, lockfile churn, formatting-only changes, duplicated boilerplate, or artificial padding.
Expected work includes:
- Cross-contract call-chain traversal with bounded depth, cycle handling, state-finalization analysis, and reentrancy-guard recognition.
- 2-hop and 3-hop exploit fixtures plus guarded equivalents, with findings that report the complete actionable path.
- Integration with scanner configuration, Slither deduplication, documentation, and performance regression coverage.
- Public or internal types/interfaces where they clarify behavior and reduce future integration risk.
- Failure-mode handling for invalid input, missing configuration, unavailable optional dependencies, and degraded execution paths.
- Documentation updates that explain how maintainers and users should operate the new capability in local and CI environments.
Professional Quality Bar
The implementation must be production-ready and reviewable in isolation. Contributors should include clear separation between parsing, analysis, reporting, CLI/action integration, and persistence or provider code where those concerns apply. The code should follow existing ChainProof conventions, keep behavior deterministic in tests, and avoid coupling core analysis to network-only services unless explicitly optional and mocked.
Acceptance Criteria
- The delivered PR contains more than 700 meaningful lines of implementation across source, tests, fixtures, and docs, excluding generated files and lockfile-only changes.
- The feature is integrated into the relevant package entrypoints, CLI commands, report formats, GitHub Action behavior, or documentation as appropriate for this issue.
- Unit tests cover normal operation, edge cases, invalid inputs, and at least one realistic fixture or end-to-end workflow.
- Any optional external service, model provider, database, or platform integration has deterministic mocks or fallbacks so CI does not depend on secrets or network availability.
- User-facing output is documented and stable enough for downstream automation.
- Backward compatibility is preserved unless the PR explicitly documents a migration path and the maintainer approves it.
Mandatory CI and Merge Requirements
A PR resolving this issue must not be merged until all repository CI checks pass. At minimum, reviewers should verify the following from a clean checkout:
npm ci
npm run lint
npm run build --workspaces --if-present
npm run test:ci --workspace=packages/core
npm test --workspaces --if-present
npm run build --workspace=packages/core && npm run docs --workspace=packages/core
- Any package-specific tests, examples, validators, or integration checks introduced by the PR
If the PR adds a GitHub Action, report format, dashboard, persistence layer, or external integration, it must also include CI coverage or a documented local verification command for that path. Known warnings are acceptable only when they are documented and do not hide failures.
Review Expectations
Reviewers should reject PRs that only stub APIs, add superficial wrappers, omit tests for critical behavior, rely on live secrets in CI, or meet the line-count target through non-functional bulk changes. The preferred solution is a focused but complete vertical slice that leaves ChainProof more reliable, easier to operate, and easier to extend.
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.
Maintainer Scope Upgrade
This issue is being expanded into a substantial, production-quality ChainProof enhancement. The implementation should be designed as maintainable platform work, not as a narrow proof of concept. A successful pull request must provide a cohesive user-facing capability, typed internal APIs, robust tests, documentation, and CI-safe behavior.
Expanded Objective
Implement CP-121 as a multi-hop, cross-contract reentrancy detector using resolved import and call-graph context. The feature should fit the existing monorepo architecture, reuse current scanner/report/CLI patterns where appropriate, and avoid introducing ad hoc subsystems that are difficult to test or maintain.
Required Implementation Depth
This issue is intentionally scoped to require more than 700 lines of meaningful implementation work. The line count expectation applies to purposeful source, tests, fixtures, and documentation that are necessary to deliver the feature. It must not be satisfied through generated output, lockfile churn, formatting-only changes, duplicated boilerplate, or artificial padding.
Expected work includes:
Professional Quality Bar
The implementation must be production-ready and reviewable in isolation. Contributors should include clear separation between parsing, analysis, reporting, CLI/action integration, and persistence or provider code where those concerns apply. The code should follow existing ChainProof conventions, keep behavior deterministic in tests, and avoid coupling core analysis to network-only services unless explicitly optional and mocked.
Acceptance Criteria
Mandatory CI and Merge Requirements
A PR resolving this issue must not be merged until all repository CI checks pass. At minimum, reviewers should verify the following from a clean checkout:
npm cinpm run lintnpm run build --workspaces --if-presentnpm run test:ci --workspace=packages/corenpm test --workspaces --if-presentnpm run build --workspace=packages/core && npm run docs --workspace=packages/coreIf the PR adds a GitHub Action, report format, dashboard, persistence layer, or external integration, it must also include CI coverage or a documented local verification command for that path. Known warnings are acceptable only when they are documented and do not hide failures.
Review Expectations
Reviewers should reject PRs that only stub APIs, add superficial wrappers, omit tests for critical behavior, rely on live secrets in CI, or meet the line-count target through non-functional bulk changes. The preferred solution is a focused but complete vertical slice that leaves ChainProof more reliable, easier to operate, and easier to extend.