A map of the repository: directory layout, package responsibilities, and where each
concern lives. For how these pieces interact at runtime see
ARCHITECTURE.md.
web3_decoder_2/
├── README.md # Project overview + links to these docs
├── docs/ # This documentation set
├── settings.gradle # Gradle multi-project definition (root + :web3-decoder)
├── gradle/
│ ├── libs.versions.toml # Version catalog (Gradle-init leftover; see notes)
│ └── wrapper/ # Gradle 8.8 wrapper
├── gradlew / gradlew.bat # Gradle wrapper launchers
└── web3-decoder/ # The extension module
├── build.gradle # Dependencies, fat-jar packaging, test config
└── src/
├── main/
│ ├── java/com/nccgroup/web3decoder/
│ │ ├── Web3DecoderExtension.java # BurpExtension entry point
│ │ ├── Web3EditorTabProvider.java # Editor factory
│ │ ├── Web3RequestEditor.java # "Web3 Request" tab
│ │ ├── Web3ResponseEditor.java # "Web3 Response" tab
│ │ ├── Web3RequestContextDecoder.java # Headless decode orchestration
│ │ ├── RequestContextStore.java # Request→response context bridge
│ │ ├── abi/ # ABI resolution (chain-scoped chain)
│ │ ├── annotation/ # HTTP-handler history-row annotator
│ │ ├── decoder/ # Decode/encode core
│ │ ├── detection/ # Passive ABI detection (scan check, pool)
│ │ ├── proxies/ # Proxy detection
│ │ ├── persistence/ # Config + caches
│ │ ├── ui/ # Swing panels (Web3 suite tab)
│ │ │ └── editor/ # Custom JSON editor component
│ └── resources/
│ ├── chains.json # Default chain registry
│ └── builtin-abis/multicall3.json # Bundled Multicall3 ABI
└── test/
├── java/com/nccgroup/web3_decoder/... # JUnit 5 tests
└── resources/ # Sample ABIs + fixtures
The Gradle group is com.nccgroup.web3-decoder; runtime Java packages are under
com.nccgroup.web3decoder (production) and com.nccgroup.web3_decoder (tests).
graph LR
ROOT["web3decoder<br/>(entry + editors + orchestration)"]
ABI["web3decoder.abi<br/>(ABI resolution)"]
DEC["web3decoder.decoder<br/>(encode/decode core)"]
DET["web3decoder.detection<br/>(passive ABI detection + pool)"]
PROX["web3decoder.proxies<br/>(proxy detection)"]
PERS["web3decoder.persistence<br/>(config + caches)"]
UI["web3decoder.ui<br/>(suite-tab Swing panels)"]
ROOT --> DEC
ROOT --> ABI
ROOT --> DET
ROOT --> PROX
ROOT --> PERS
UI --> DEC
UI --> ABI
UI --> DET
UI --> PROX
UI --> PERS
DEC --> ABI
DEC --> DET
DEC --> PROX
ABI --> PERS
DET --> PERS
| File | Responsibility |
|---|
Web3DecoderExtension | BurpExtension entry point; registers editors + suite tab. |
Web3EditorTabProvider | Creates per-context request/response editor instances. |
Web3RequestEditor | Renders decoded calldata; re-encodes edited args on send. |
Web3ResponseEditor | Decodes JSON-RPC result; enriches multicall return data. |
Web3RequestContextDecoder | Headless decode of all eth_call items; populates the context store; resolves chain id. |
RequestContextStore | Static map bridging request decode → response decode, keyed by request + item. |
| File | Responsibility |
|---|
Web3DataDecoder | Per-call orchestration: proxy → ABI source → decode, with detected-pool and 4byte fallbacks. Tolerates a null AbiProvider for chain-agnostic decode. |
ABIInputDecoder | web3j-backed engine: selector hashing, type mapping, input/output decode, encode. Has a CLI main(). |
MulticallRecursiveDecoder | Detects/decodes the six Multicall3 aggregate variants recursively. |
| File | Responsibility |
|---|
IAbiProvider | Single-method interface: getAbi(address). |
AbiProvider | Composite: cache → builtin → explorer, with caching of explorer hits + lastAbiSource. |
CachedAbiProvider | Reads from the persistent CachedAbis store. |
BuiltinAbiProvider | Serves bundled ABIs (Multicall3 at its canonical address). |
EtherscanAbiProvider | Etherscan v2 multichain fetch with legacy /api fallback + support cache. |
FourByteSignatureProvider | 4byte selector lookup + synthetic-ABI generation. |
| File | Responsibility |
|---|
AbiDetectionScanCheck | Burp PassiveScanCheck registered as PER_REQUEST. Runs the pipeline on every audited response and raises a Solidity-ABI-detected audit issue per response that introduces a new ABI. |
AbiDetectionPipeline | Stateless facade: body → tokens → boundaries → normalize → validate → deduplicated list of DetectedAbi. |
AbiTokenScanner | Fixed-needle search over the body. Returns ascending byte offsets of candidate ABI internals. |
AbiBoundaryExtractor | String-aware, depth-tracking walk to the outermost enclosing [{...}] array of each hit. Computes the body's inString bitmap once and reuses it across all hits. |
AbiNormalizer | Jackson lenient parse with minified !0/!1 → true/false preprocessing, re-serialised as sorted-keys canonical JSON. |
AbiValidator | Type-vocabulary check, content fingerprint (SHA-256 of canonical JSON), and selector list extracted via AbiSelectorBuilder. |
AbiSelectorBuilder | Shared canonical-signature + 4-byte selector logic. Extracted from ABIInputDecoder so both decoder and validator reuse one implementation. |
DetectedAbi | Immutable value object: fingerprint, canonical JSON, selectors. Equality and hash are fingerprint-only. |
DetectedAbiStore | Project-scoped persistence over Burp PersistedObject (extensionData → detected_ABIs). Maintains an in-memory selector→fingerprint index, FIFO eviction at capacity, and exposes saveIfNew / findBySelector / snapshot / remove. |
| File | Responsibility |
|---|
IProxyDetector | Single-method interface: getImplementationAddress(address). |
ProxyDetector | Composite + shared cache; runs each detector in order. |
ERC1967ProxyDetector | Reads the EIP-1967 implementation storage slot. |
ZeppelinOSProxyDetector | Reads the legacy ZeppelinOS/OpenZeppelin slot. |
| File | Responsibility |
|---|
ExtensionConfig | Chain registry + API keys (Preferences), deprecated-chain migration, key resolution. |
ChainInfo | Jackson POJO: chainId, name, explorer, explorerAPIKey. |
CachedAbis | ABI cache over Burp PersistedObject, keyed chainId_address. |
| File | Responsibility |
|---|
Web3HistoryAnnotator | HttpHandler that annotates Burp's Proxy/HTTP history rows with the decoded Web3 function name (synchronously, before the handler returns). Also threads the shared DetectedAbiStore into the context decoder. |
AnnotationNoteBuilder | Builds the actual annotation string from a decoded request (multicall-aware). |
| File | Responsibility |
|---|
MainChainsPanel | 2×2 dashboard. The bottom-left slot is a JSplitPane of "Cached ABIs" + "Detected ABIs" when a detected pool is wired. |
ChainsListPanel | Chain CRUD table, per-chain + shared Etherscan API key management. |
CachedAbisListPanel | Cached-ABI list; add manually or fetch from explorer; remove. |
DetectedAbisListPanel | Detected-ABI list (fingerprint, function count, first-seen URL); open in editor; remove. |
AbiEditorPanel | View/edit/save a cached ABI (setAbi) or view a detected ABI read-only with a context header (setDetectedAbi). |
CalldataCodecPanel | Standalone decode/re-encode tool with optional RPC + proxy + multicall. |
| File | Responsibility |
|---|
Web3JsonEditor | Public reusable Swing JSON editor component; assembles gutter, text pane, and search bar. Used by both HTTP message tabs and the Calldata Codec. |
JsonStyleScanner | Pure-logic scanner; produces a list of StyleSpan (token ranges + StyleKind) from raw JSON text. |
JsonSearchEngine | Pure-logic search; finds all match ranges for a query string within the editor text. |
JsonValidator | Pure-logic validator; checks JSON well-formedness and reports the first error offset. |
BracketMatcher | Pure-logic matcher; locates the paired bracket for a given caret position; also defines StyleKind, StyleSpan, and Range value types. |
EditorTheme | Swing support; defines color constants (background, tokens, highlights) for the editor. |
LineNumberGutter | Swing support; JComponent painted alongside the text pane to show line numbers. |
SearchBar | Swing support; toolbar panel wiring together the search field, match navigation, and result count label. |
| Resource | Purpose |
|---|
resources/chains.json | Default chain registry (chainId → {name, explorer}); merged with user Preferences at load. All entries target the unified Etherscan v2 host api.etherscan.io. |
resources/builtin-abis/multicall3.json | Canonical Multicall3 ABI served by BuiltinAbiProvider for 0xca11bde0…ca11 on every chain. |
JUnit 5 + Mockito, under src/test/java/com/nccgroup/web3_decoder/:
| Test | Covers |
|---|
decoder/ABIInputDecoderTest | Core type encode/decode (scalars, arrays, tuples). |
decoder/ABIInputDecoderRealTransactionsTest | Decode against captured real-world calldata fixtures. |
decoder/NestedStructOutputDecodeTest | Nested struct/tuple output decoding. |
decoder/MulticallRecursiveDecoderTest | Multicall variant detection + recursive decode. |
decoder/Web3DataDecoderTest | Per-call strategy incl. proxy/detected/4byte fallbacks (mocked). |
abi/FourByteSignatureProviderTest | Selector lookup + synthetic ABI generation. |
detection/AbiTokenScannerTest / AbiBoundaryExtractorTest / AbiNormalizerTest / AbiValidatorTest | Per-stage unit tests for the passive detection pipeline. |
detection/AbiSelectorBuilderTest | Canonical signature / selector calculation. |
detection/AbiDetectionPipelineTest | Facade integration test, including a real-bundle excerpt fixture. |
detection/DetectedAbiStoreTest | Persistence + selector index + FIFO eviction + restart-reload semantics. |
detection/AbiDetectionScanCheckTest | Scan check happy path, dedup contract, audit-issue detail format. |
RequestContextStoreTest | Context store keying/retrieval semantics. |
Fixtures live in src/test/resources/ (sample contract ABIs, decoder edge cases,
captured real-transaction cases, and a trimmed minified-bundle excerpt for ABI
detection at abi-detection/hive-auth-svelte-excerpt.js).
gradle/libs.versions.toml is a gradle init leftover (declares guava and a
junit-jupiter alias) and is not referenced by build.gradle, which pins
versions directly. Treat the catalog as vestigial.
Main-Class is ABIInputDecoder — the packaged jar doubles as a small CLI for
decoding/encoding from an ABI file (see TECH_STACK.md).
- Jackson and BouncyCastle are not declared directly; they arrive transitively through
org.web3j:core.