Overview
This is the final report and close-out for SEBI (Stylus Execution Boundary Inspector), submitted under the Arbitrum One Developer Tooling Program (Stylus 3.0).
The idea behind SEBI is pretty simple: when you’re building a Stylus contract, there’s currently no lightweight way to check whether your compiled WASM artifact has execution-boundary issues before you deploy. Things like unbounded memory growth, dynamic dispatch via indirect calls, or loop structures that can lead to unpredictable execution are basically invisible until you’re either running on-chain or going through a full audit. SEBI fills that gap by doing a static, fully offline inspection of the compiled artifact and telling you what it finds — deterministically, without touching chain state.
All three milestones are done. Everything is publicly accessible at this repo https://github.com/Qeyphen/sebi.
Delivered Scope vs. Proposal
| Milestone | Scope | Status | Grant Amount |
|---|---|---|---|
| M1 – Core Static Analysis Engine | WASM parsing, signal extraction, rule evaluation, classification, CLI | $7,875 | |
| M2 – Reporting, CI Integration & Real-World Validation | JSON schema, human-readable output, GitHub Actions CI, OpenZeppelin validation | $2,100 | |
| M3 – Final Report & Close-Out | Written summary, limitations, lessons learned | $1,125 | |
| Total | $11,100 |
What Was Built
SEBI is a Rust workspace with two crates: sebi-core (the analysis library) and sebi-cli (the command-line tool). You point it at a .wasm file, and it gives you back a structured report telling you what it found and how it classified the artifact.
What it does:
-
Parses WASM binaries offline and inspects all relevant sections (memory, imports, exports, functions)
-
Scans every function body for three key instruction-level signals:
memory.grow,call_indirect, andloop -
Extracts 16+ structured signals across artifact, module, memory, and instruction categories
-
Evaluates those signals against a 5-rule explainable catalog and outputs a
SAFE / RISK / HIGH_RISKverdict -
Produces byte-for-byte identical JSON output across repeated runs — no timestamps, sorted arrays, stable hashing
-
Returns CI-ready exit codes:
0 = SAFE,1 = RISK,2 = HIGH_RISK
The test suite has 127 passing tests across unit, integration, and CLI categories.
Execution-Boundary Signals & Rule Behavior
Signals extracted per artifact:
| Category | Signals |
|---|---|
| Artifact | size_bytes, SHA-256 hash |
| Module | function_count, section_count |
| Memory | memory_count, min_pages, max_pages, has_max |
| Instructions | has_memory_grow, memory_grow_count, has_call_indirect, call_indirect_count, has_loop, loop_count |
| Imports/Exports | import_count, export_count, detailed inventories |
Rule catalog (v0.1.0):
| Rule ID | Description | Severity | Trigger |
|---|---|---|---|
| R-MEM-01 | Missing declared memory maximum | MED | has_max == false |
| R-MEM-02 | Runtime memory growth detected | HIGH | has_memory_grow == true |
| R-SIZE-01 | Large WASM artifact | MED | size_bytes > 200,000 |
| R-LOOP-01 | Loop constructs detected | MED | has_loop == true |
| R-CALL-01 | Dynamic dispatch detected | HIGH | has_call_indirect == true |
Classification:
-
SAFE— nothing triggered -
RISK— at least one MED rule, no HIGH -
HIGH_RISK— at least one HIGH rule
Real-World Validation
To make sure SEBI actually works against real production contracts and not just hand-crafted test fixtures, I ran it against the full OpenZeppelin Rust Contracts for Stylus repository — 64 compiled WASM artifacts in total.
The results were pretty informative:
-
All 64 contracts triggered R-MEM-01. This is expected — the Stylus toolchain doesn’t set a WASM memory maximum by default, so every artifact will hit this rule. It’s a toolchain-level structural property, not something individual developers are doing wrong.
-
32 contracts (debug builds) came back
HIGH_RISK, triggering R-MEM-02, R-CALL-01, and R-LOOP-01. Debug builds retain more complex instruction patterns that the optimizer strips out. -
32 contracts (release builds) came back
RISKwith only R-MEM-01. The Rust compiler eliminates dynamic dispatch, memory growth, and loop constructs in optimized output, which is exactly what you’d expect.
This was a useful sanity check. SEBI correctly differentiates between debug and release profiles, runs fully offline, and behaves consistently across the full contract set.
CI Integration
There’s a complete GitHub Actions workflow at examples/sebi-ci.yml. It auto-discovers all cdylib crates in your workspace, compiles them to WASM, runs SEBI on each one, embeds the git commit SHA for traceability, and fails the job if anything comes back RISK or HIGH_RISK. Flagged contracts surface as ::error annotations in the PR UI, and all JSON reports are uploaded as CI artifacts regardless of outcome.
Getting it into a project is just:
mkdir -p .github/workflows
cp examples/sebi-ci.yml .github/workflows/sebi.yml
No RPC, no chain access, no configuration needed.
Limitations and Non-Goals
Worth being upfront about what SEBI is and isn’t:
-
It doesn’t execute WASM or estimate gas. It’s purely structural — it looks at what instructions and sections are present, not what they do at runtime.
-
A
HIGH_RISKresult doesn’t mean a contract is broken. It means structural patterns with execution-boundary implications were found. Whether that’s actually a problem depends on the contract’s intent. SEBI surfaces the signal; a developer or auditor still has to interpret it. -
R-MEM-01 will fire on essentially every Stylus contract right now because the toolchain doesn’t emit a memory maximum by default. That’s expected behavior and not something SEBI can work around — it’s a property of how Stylus compiles today.
-
Multi-memory and component model artifacts aren’t fully analyzed. SEBI handles standard WASM MVP modules. If it encounters something outside that, it emits a warning but won’t produce a complete analysis.
-
Rule thresholds are conservative and MVP-grade. The 200 KB threshold for R-SIZE-01 was chosen to be permissive enough to avoid false positives on real contracts while still flagging genuinely large artifacts. It may need tuning as the ecosystem grows.
Deliverables Index
| Deliverable | Location |
|---|---|
| Core analysis library | crates/sebi-core/ |
| CLI binary | crates/sebi-cli/ |
| JSON report schema | docs/SCHEMA.md |
| Rule catalog | docs/RULES.md |
| User documentation | README.md |
| WAT/WASM test fixtures | crates/sebi-core/tests/fixtures/ |
| CLI WASM fixtures | crates/sebi-cli/fixtures/ |
| CI integration example | examples/sebi-ci.yml |
| Test suite (127 tests) | cargo test --workspace |
Closing
SEBI does what it set out to do: give Stylus developers a fast, offline way to see execution-boundary properties in their compiled contracts before deployment. It’s not a security auditor and it’s not a substitute for review — but it fills a real gap in the current tooling landscape by making these structural signals visible early, in CI, without any chain dependency.
Thanks to the Arbitrum Foundation and DAO for supporting this. The project is open, documented, and ready for anyone in the ecosystem to use or build on.
SEBI — Stylus Execution Boundary Inspector | Grant Close-Out | April 2026