Skip to content

AUDIT.md — sun audit: Aderyn with Controlled TVM Degradation

Living reference for internal/audit and the sun audit command. Tier-1 authority is docs/ARCHITECTURE.md §5.8.


1. The pinned binary

sun audit runs Cyfrin Aderyn, managed exactly like solc (ARCHITECTURE §1.5): version pinned in sail.toml, downloaded on demand into <SAIL_HOME>/bin/aderyn-<version>, and never executed without a SHA-256 match. The release ships .tar.xz archives; the digest pinned per platform is that of the extracted binary, verified before the file ever becomes executable and re-verified on every run (compiler.EnsureManaged, the generalized solc manager).

[aderyn]
version = "0.6.8"

[aderyn.checksums]
"darwin/arm64" = "8cb4f272…"
"darwin/amd64" = "a3f47a3d…"
"linux/arm64"  = "77303383…"
"linux/amd64"  = "a268d616…"

Windows: upstream publishes no Windows asset — sun audit on Windows reports exactly that (no pinned aderyn binary for windows/amd64: upstream (Cyfrin/aderyn) publishes no Windows asset) instead of failing obscurely. SAIL_ADERYN_URL overrides the download URL (mirrors/air-gapped setups); the checksum requirement is unaffected.

2. Per-file execution and degradation

Aderyn is executed once per src/**/*.sol file (aderyn . -i <file> -o <tmp>.json). A file it cannot parse — TVM syntax such as trcToken, msg.tokenvalue or the Stake 2.0 APIs — makes that invocation print a Compilation Error and write no report (observed v0.6.8 behavior, which exits 0 either way); sun audit degrades that file to a SKIPPED (TVM syntax) row and the rest of the project is analyzed normally. Any other per-file failure is reported as that file's error — the set is never aborted.

3. The TVM post-filter — visible, never silent

Findings from detectors whose premises are EVM-specific are suppressed with a recorded reason, kept in the report, and rendered collapsed:

Detector Reason
push-zero-opcode The TVM ships Shanghai's PUSH0 (schedule-enabled); the missing-opcode warning targets other chains.
selfdestruct Aderyn models EIP-6780 Ethereum semantics; the TVM implements TIP-6780 with TRON-specific eligibility rules.

--show-suppressed lists them inline with their reasons. Suppressed findings never count toward --fail-on.

Every output ends with the fixed limitations section:

static analysis with EVM semantics; TVM divergences (energy model, TVM-specific opcodes, TIP-6780 selfdestruct, 0x41 CREATE2) are not modeled

4. Output formats

  • Terminal: SEVERITY · FILE:LINE · RULE · DESCRIPTION, grouped high → low, followed by SKIPPED/ERROR rows, the counts line, and the limitations.
  • --json (global flag): stable structured dump (files, findings with suppression flags, counts, limitations) for CI.
  • --report <path.md>: passthrough of Aderyn's native markdown report — one extra whole-project run with the skipped files excluded (-x).
  • --fail-on <low|medium|high>: exit ≠ 0 when any unsuppressed finding reaches the threshold. Aderyn v0.6 reports only high/low, so medium behaves like high. Default: report and exit 0 — the failure policy belongs to CI, not the tool (§5.8).

5. Testing

Hermetic (make check and make e2e): a fake aderyn shell script reproduces the observed v0.6.8 contract — per-file JSON, markdown passthrough, and the Compilation-Error-without-report degradation signal — via the SAIL_ADERYN_BIN override, so no download ever happens in the gates. The managed-download path (tar.xz extraction, checksum refusal, atomic install) is covered by internal/compiler/binmgr_test.go against an in-process HTTP server. The real-binary flow was validated manually on Nile's scaffold project (v0.6.8: 5 low findings on Counter.sol, 1 suppressed).