Skip to content

feat(plugins): implement unchecked return value detection plugin (#16) - #99

Open
Salahalioui wants to merge 1 commit into
VeridionLabs:mainfrom
Salahalioui:feat/unchecked-return-plugin
Open

feat(plugins): implement unchecked return value detection plugin (#16)#99
Salahalioui wants to merge 1 commit into
VeridionLabs:mainfrom
Salahalioui:feat/unchecked-return-plugin

Conversation

@Salahalioui

Copy link
Copy Markdown

Closes #16

Summary of Changes

Implements the @veridion/plugin-unchecked-return scanner plugin to detect unchecked low-level Solidity calls (.call(), .send(), .delegatecall()) per SWC-104 guidelines, and registers it in scanner-core.

Architectural Design & Edge Case Handling

Rather than relying on naive regex matching that breaks across multi-line definitions or comments, the plugin uses a deterministic character scanner:

  • Masks single-line comments, multi-line comments, and string literals upfront while preserving original byte offsets and newline positions.
  • Tracks {} brace depth from declaration boundaries (function, constructor, modifier, receive, fallback) to guarantee strict function scope isolation. Checks in one function cannot leak or validate calls in another.
  • Differentiates direct condition evaluations (require(call), if (!call) revert(), return call) from statements where return values are captured via tuple (bool ok, ) = ... or variable declaration bool sent = ....
  • Verifies truthiness semantics in deferred assertions, rejecting negated checks (!ok), negative equality (ok == false), and equality against untrusted variables (ok == someFlag).
  • Excludes native address.transfer() calls because the EVM automatically reverts on failure and returns no boolean.

Implementation Details

  • plugins/unchecked-return/src/index.ts: Implements IRulePlugin, exposing AST-free lexer, scope boundary tracker, statement locator, and truthiness evaluator.
  • plugins/unchecked-return/src/index.test.ts: 66 unit tests covering positive detections, tuple omissions, single assignments, variable reassignments, external object lookalikes (verifier.assert(ok)), comments/strings masking, and multi-contract isolation.
  • packages/scanner-core/src/plugin-registry.ts: Registers UncheckedReturnPlugin in defaultPlugins and exports createDefaultRegistry().
  • packages/scanner-core/src/plugin-registry.test.ts: Integration tests verifying scanner registration and end-to-end detection.

Test & Verification Evidence

Run locally with:

pnpm --filter=@veridion/plugin-unchecked-return test
pnpm --filter=@veridion/scanner-core test
pnpm prettier --check "plugins/unchecked-return/**/*.{ts,js,json}" "packages/scanner-core/**/*.{ts,js,json}"

Output:

> @veridion/plugin-unchecked-return@0.1.0 test
> vitest run

 RUN  v1.6.1 .../veridion/plugins/unchecked-return

 ✓ src/index.test.ts  (66 tests) 32ms

 Test Files  1 passed (1)
      Tests  66 passed (66)

> @veridion/scanner-core@0.1.0 test
> vitest run

 RUN  v1.6.1 .../veridion/packages/scanner-core

 ✓ src/plugin-registry.test.ts  (8 tests) 14ms

 Test Files  1 passed (1)
      Tests  8 passed (8)

Checking formatting...
All matched files use Prettier code style!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scanner: Implement Unchecked Return Value detection plugin

1 participant