/execution-client-hardening
L1 trigger - audits execution engine (EVM interpreter, WASM, SVM) for memory corruption, gas mispricing (EXTCODESIZE class), opcode semantics, and VM invariant breaks.
$ npx -y skills add PlamenTSV/plamen --skill execution-client-hardening --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/execution-client-hardening
Context preview
The summary Claude sees to decide when to auto-load this skill.
L1 trigger - audits execution engine (EVM interpreter, WASM, SVM) for memory corruption, gas mispricing (EXTCODESIZE class), opcode semantics, and VM invariant breaks.
SKILL.md
execution-client-hardening.SKILL.mdname: "execution-client-hardening"
description: "L1 trigger - audits execution engine (EVM interpreter, WASM, SVM) for memory corruption, gas mispricing (EXTCODESIZE class), opcode semantics, and VM invariant breaks."
Injectable Skill: Execution Client Hardening
> **L1 trigger**: `L1_PATTERN=true` AND (`core/vm/` OR `revm` OR `interpreter` OR `opcodes.go` OR `evm-exec` OR `svm/` OR `move-vm` OR `wasmi` detected in recon subsystem map) > **Inject Into**: `depth-state-trace` or `depth-external` > **Language**: Go, Rust, occasionally C++ > **Finding prefix**: `[EX-N]` > **Status**: v0.1 draft, Round 4 exemplars pending
Orchestrator Decomposition Guide
- Sections 1, 2: depth-state-trace (VM state transitions)
- Sections 3, 4: depth-edge-case (opcode semantics)
- Section 5: depth-external (gas metering)
- Section 6: depth-consensus-invariant (cross-client consistency)
When This Skill Activates
Recon identifies a VM / execution engine. Covered VMs: EVM (all execution clients), SVM (Solana), Move VM (Aptos, Sui), WASM runtimes (NEAR, Polkadot), custom VMs. Client-vs-client divergence in VM behavior is Critical — historically several Ethereum consensus splits were VM implementation bugs.
1. Opcode Coverage Mapping
Enumerate every opcode / instruction the VM supports. For EVM, consult the latest Yellow Paper + EIPs. For others, the spec document.
| Opcode | Gas cost | Stack delta | State touched | Notes | |---|---|---|---|---|
This mapping grounds later checks. A new client must implement every opcode; a fork client must not accidentally remove or reprice any opcode.
Tag: `[OPCODE-COVERAGE:{missing-or-extra}]`
2. Gas / Resource Metering
Every operation must be priced to cover its real cost. Historical bugs: Ethereum Shanghai attacks (2016) — EXTCODESIZE was too cheap relative to disk I/O.
Patterns to check
- **Disk-touching opcodes**: SLOAD, SSTORE, EXTCODESIZE, EXTCODECOPY, EXTCODEHASH, BALANCE. Gas cost must reflect the (possibly cold) storage fetch.
- **Recursive opcodes**: CALL, DELEGATECALL, CALLCODE, STATICCALL. Gas forwarding (63/64 rule) correctness.
- **Memory-expanding opcodes**: MLOAD, MSTORE, RETURNDATACOPY, MCOPY. Memory expansion gas must be computed before the access.
- **Hashing**: KECCAK256 cost proportional to input size.
- **Log emission**: LOG0-LOG4 cost proportional to data size.
Warm/cold access (EIP-2929)
- Access list enforcement: first touch is cold (more expensive), subsequent warm
- Is the access list correctly reset per transaction?
- On reverted subcalls, does the access list roll back correctly?
Tag: `[GAS-MISPRICE:{opcode}:{actual-cost}:{charged-cost}]`
3. Opcode Semantics
For each opcode, the semantics must match the spec exactly. Common drift points:
3a. SELFDESTRUCT
- Pre-Cancun: destroys contract, transfers balance
- Post-Cancun (EIP-6780): only transfers balance if called in same tx as creation
- Bug class: incorrect balance accounting (see Optimism OVM_ETH exemplar)
3b. CREATE / CREATE2
- Address calculation: CREATE = hash(sender, nonce); CREATE2 = hash(0xff, sender, salt, init_code_hash)
- Collision handling: what happens if the computed address already has code/balance/nonce?
- Init code size limit (EIP-3860)
3c. RETURNDATACOPY
- Out-of-bounds access must revert (EIP-211)
- Returns empty buffer if no return data (not panic)
3d. PUSH0 (EIP-3855)
- Valid only post-Shanghai. Pre-Shanghai must be invalid.
3e. TLOAD / TSTORE (EIP-1153)
- Transient storage; resets per transaction
- Interaction with reverts
3f. MCOPY (EIP-5656)
- Memory copy, post-Cancun
3g. BLOBHASH / BLOBBASEFEE (EIP-4844)
- Blob-related
Tag: `[OPCODE-SEM:{opcode}:{drift}]`
4. Precompiles
Precompiles are native implementations of common functions at fixed addresses.
Check per precompile
- Is the precompile address correct? (e.g., 0x01 ECRECOVER, 0x02 SHA256, ...)
- Is the gas cost formula correct? Many precompiles have length-dependent gas.
- Is the input validated? Precompile panics crash the client.
- **Context-dependent inputs** (like Moonbeam's precompile-delegatecall bug): does the precompile care whether it's invoked via CALL vs DELEGATECALL? If yes, is it enforced?
Tag: `[PRECOMPILE:{address}:{issue}]`
5. Memory Safety
For Go clients, memory safety is largely on the runtime. For Rust clients (reth, revm), `unsafe` blocks in the VM are a bug source.
**Check**:
- Every `unsafe` in the interpreter hot path
- Every raw pointer manipulation
- Every length-based slicing — off-by-one crashes the VM
Interaction with `rust-unsafe-audit` skill.
5b. Interned/Compacted Identity Coherence
**Trigger**: The code assigns a compact numeric index or handle to a named entity (a type, account, resource, module, or similar) — typically to avoid storing the full name/key repeatedly — and one or more OTHER structures cache data derived from that entity, keyed by the compact index rather than by the entity's original identity. Common in interning tables, symbol/type caches, and any "intern this name once, refer to it by a small integer afterward" optimization (for example, a Move VM-style loader that interns module/type identities into a numeric table).
**Why this is structurally distinct from §8's cache lifecycle set-cover**: §8 concerns a SINGLE bounded cache whose OWN entries go stale or grow unbounded. This section concerns MULTIPLE structures that share one index/ handle space, where one structure can be reset/compacted while a SIBLING structure — keyed by the same index space — is not, so a recycled index silently points a stale consumer at a different entity's data. This is an asymmetric-invalidation bug across coupled structures, not a single eviction policy gap, and set-cover on one structure's legs will not catch it.
**Methodology**:
1. **Enumerate every structure keyed by the index/handle space** — not just the primary interning map. Grep for the index type's name (e.g. a `TypeIndex`,
Read more
name: "execution-client-hardening" description: "L1 trigger - audits execution engine (EVM interpreter, WASM, SVM) for memory corruption, gas mispricing (EXTCODESIZE class), opcode semantics, and VM invariant breaks."
Injectable Skill: Execution Client Hardening
> **L1 trigger**: `L1_PATTERN=true` AND (`core/vm/` OR `revm` OR `interpreter` OR `opcodes.go` OR `evm-exec` OR `svm/` OR `move-vm` OR `wasmi` detected in recon subsystem map) > **Inject Into**: `depth-state-trace` or `depth-external` > **Language**: Go, Rust, occasionally C++ > **Finding prefix**: `[EX-N]` > **Status**: v0.1 draft, Round 4 exemplars pending
Orchestrator Decomposition Guide
- Sections 1, 2: depth-state-trace (VM state transitions)
- Sections 3, 4: depth-edge-case (opcode semantics)
- Section 5: depth-external (gas metering)
- Section 6: depth-consensus-invariant (cross-client consistency)
When This Skill Activates
Recon identifies a VM / execution engine. Covered VMs: EVM (all execution clients), SVM (Solana), Move VM (Aptos, Sui), WASM runtimes (NEAR, Polkadot), custom VMs. Client-vs-client divergence in VM behavior is Critical — historically several Ethereum consensus splits were VM implementation bugs.
1. Opcode Coverage Mapping
Enumerate every opcode / instruction the VM supports. For EVM, consult the latest Yellow Paper + EIPs. For others, the spec document.
| Opcode | Gas cost | Stack delta | State touched | Notes | |---|---|---|---|---|
This mapping grounds later checks. A new client must implement every opcode; a fork client must not accidentally remove or reprice any opcode.
Tag: `[OPCODE-COVERAGE:{missing-or-extra}]`
2. Gas / Resource Metering
Every operation must be priced to cover its real cost. Historical bugs: Ethereum Shanghai attacks (2016) — EXTCODESIZE was too cheap relative to disk I/O.
Patterns to check
- **Disk-touching opcodes**: SLOAD, SSTORE, EXTCODESIZE, EXTCODECOPY, EXTCODEHASH, BALANCE. Gas cost must reflect the (possibly cold) storage fetch.
- **Recursive opcodes**: CALL, DELEGATECALL, CALLCODE, STATICCALL. Gas forwarding (63/64 rule) correctness.
- **Memory-expanding opcodes**: MLOAD, MSTORE, RETURNDATACOPY, MCOPY. Memory expansion gas must be computed before the access.
- **Hashing**: KECCAK256 cost proportional to input size.
- **Log emission**: LOG0-LOG4 cost proportional to data size.
Warm/cold access (EIP-2929)
- Access list enforcement: first touch is cold (more expensive), subsequent warm
- Is the access list correctly reset per transaction?
- On reverted subcalls, does the access list roll back correctly?
Tag: `[GAS-MISPRICE:{opcode}:{actual-cost}:{charged-cost}]`
3. Opcode Semantics
For each opcode, the semantics must match the spec exactly. Common drift points:
3a. SELFDESTRUCT
- Pre-Cancun: destroys contract, transfers balance
- Post-Cancun (EIP-6780): only transfers balance if called in same tx as creation
- Bug class: incorrect balance accounting (see Optimism OVM_ETH exemplar)
3b. CREATE / CREATE2
- Address calculation: CREATE = hash(sender, nonce); CREATE2 = hash(0xff, sender, salt, init_code_hash)
- Collision handling: what happens if the computed address already has code/balance/nonce?
- Init code size limit (EIP-3860)
3c. RETURNDATACOPY
- Out-of-bounds access must revert (EIP-211)
- Returns empty buffer if no return data (not panic)
3d. PUSH0 (EIP-3855)
- Valid only post-Shanghai. Pre-Shanghai must be invalid.
3e. TLOAD / TSTORE (EIP-1153)
- Transient storage; resets per transaction
- Interaction with reverts
3f. MCOPY (EIP-5656)
- Memory copy, post-Cancun
3g. BLOBHASH / BLOBBASEFEE (EIP-4844)
- Blob-related
Tag: `[OPCODE-SEM:{opcode}:{drift}]`
4. Precompiles
Precompiles are native implementations of common functions at fixed addresses.
Check per precompile
- Is the precompile address correct? (e.g., 0x01 ECRECOVER, 0x02 SHA256, ...)
- Is the gas cost formula correct? Many precompiles have length-dependent gas.
- Is the input validated? Precompile panics crash the client.
- **Context-dependent inputs** (like Moonbeam's precompile-delegatecall bug): does the precompile care whether it's invoked via CALL vs DELEGATECALL? If yes, is it enforced?
Tag: `[PRECOMPILE:{address}:{issue}]`
5. Memory Safety
For Go clients, memory safety is largely on the runtime. For Rust clients (reth, revm), `unsafe` blocks in the VM are a bug source.
**Check**:
- Every `unsafe` in the interpreter hot path
- Every raw pointer manipulation
- Every length-based slicing — off-by-one crashes the VM
Interaction with `rust-unsafe-audit` skill.
5b. Interned/Compacted Identity Coherence
**Trigger**: The code assigns a compact numeric index or handle to a named entity (a type, account, resource, module, or similar) — typically to avoid storing the full name/key repeatedly — and one or more OTHER structures cache data derived from that entity, keyed by the compact index rather than by the entity's original identity. Common in interning tables, symbol/type caches, and any "intern this name once, refer to it by a small integer afterward" optimization (for example, a Move VM-style loader that interns module/type identities into a numeric table).
**Why this is structurally distinct from §8's cache lifecycle set-cover**: §8 concerns a SINGLE bounded cache whose OWN entries go stale or grow unbounded. This section concerns MULTIPLE structures that share one index/ handle space, where one structure can be reset/compacted while a SIBLING structure — keyed by the same index space — is not, so a recycled index silently points a stale consumer at a different entity's data. This is an asymmetric-invalidation bug across coupled structures, not a single eviction policy gap, and set-cover on one structure's legs will not catch it.
**Methodology**:
1. **Enumerate every structure keyed by the index/handle space** — not just the primary interning map. Grep for the index type's name (e.g. a `TypeIndex`,
Autonomous Web3 security auditor for Claude Code and OpenAI Codex CLI. Orchestrates 18-100 AI agents across 40+ phases to produce audit reports with verified PoC exploits — for smart contracts and L1 node-client infrastructure.
Repo: PlamenTSV/plamen
Other skills on plamen.
- /ability-analysis
Trigger Pattern Always (Aptos Move) - foundational security check - Inject Into Breadth agents, depth agents
Open skill - /bit-shift-safety
Trigger Pattern Always (Aptos Move) - Move VM aborts on shift = bit width - Inject Into Breadth agents, depth-edge-case
Open skill - /centralization-risk
Trigger Protocol has privileged roles (admin, operator, governance, resource account owner) - Covers Single points of failure, privilege escalation, external governance dependen...
Open skill - /cross-chain-timing
Trigger Pattern wormhole|layerzero|ccip|bridge|cross_chain|vaa|guardian|emitter|relay|remote_chain|payload|nonce.sequence - Inject Into Breadth agents, depth-external
Open skill - /dependency-audit
Trigger EXTERNAL_LIB flag detected (protocol uses third-party Move dependencies) - Used by Breadth agents, depth-external
Open skill - /economic-design-audit
Trigger Pattern MONETARY_PARAMETER flag (required) - Inject Into Breadth agents (merged via M4 hierarchy)
Open skill

