Execution Engine
Status: v0.1 —
simulateBytecode,runTransaction,runBlock, capability registry, provenance.
The mcp-execution-engine is a pure TypeScript library: stateless EthereumJS v10 simulations with no HTTP, MCP transport, or payments. The gateway (Step 3+) depends on it one-way.
Repository: feelyourprotocol/mcp-execution-engine (v0.1.0). Consumed by mcp-gateway via LocalTaskProcessor.
End-user tool semantics: Describe Capabilities, Run Bytecode, Run Transaction, Run Block, Coverage, Guarantees.
Design principles
- Query shapes, not library APIs — the MCP surface exposes generic verbs (
simulate,transaction,block,generate,probe); the engine returns structured results. - Fork = capability set —
(baseHardfork, eips[])à la carte; named forks (osakabaseline,amsterdampreview) are catalog capabilities (summary, advertised EIPs, shapes). - Provenance on every result — engine version, fork config, advertised or explicit EIP maturity metadata, stability rollup, human caveat.
- Boundaries — raw bytecode or impersonated transaction fields plus constructed prestate; no Solidity compile; no archive node; no multi-block historical backtesting.
See also Design Principles.
Public API (v0.1)
| Export | Role |
|---|---|
simulateBytecode(input) | Run bytecode under a fork config; optional opcode trace |
runTransaction(input) | Run a value-bearing transaction (paid gas, receipt logs) |
runBlock(input) | Run 1–8 txs as a lab block (header snapshot + per-tx receipts) |
describeCapabilities() | Registry snapshot — named fork capabilities + runnable EIP modules (opcodes, encoding, no demos) |
listEipModules() | Live EIP module list (source of the catalog) |
buildCommon(config) | Resolve (baseHardfork, eips[]) → EthereumJS Common |
Input / output
// SimulateBytecodeInput
{
bytecode: string
accounts?: { address: string; balance?: string; code?: string; storage?: { slot: string; value: string }[] }[]
fork?: { baseHardfork: string; eips?: number[] }
gasLimit?: string
trace?: boolean
}
// SimulateBytecodeResult — gasUsedScope: 'call-frame'
// Optional stateGasSpilled when Amsterdam spills EIP-8037 state gas into the frame.
// RunTransactionInput
{
from: string
to: string
value?: string
data?: string
code?: string
accounts?: { address: string; balance?: string; code?: string; storage?: { slot: string; value: string }[] }[]
fork?: { baseHardfork: string; eips?: number[] }
gasLimit?: string
}
// RunTransactionResult — gasUsedScope: 'transaction'
// gasUsed is paid tx gas. Amsterdam may include txRegularGas / txStateGas.
// RunBlockInput
{
transactions: { from: string; to: string; value?: string; data?: string; code?: string; gasLimit?: string }[]
header?: { slotNumber?: string; number?: string; timestamp?: string }
accounts?: { address: string; balance?: string; code?: string; storage?: { slot: string; value: string }[] }[]
fork?: { baseHardfork: string; eips?: number[] }
}
// RunBlockResult — gasUsedScope: 'block'
// header.gasUsed is the generated header field (Amsterdam may be the 8037 state-gas dimension).
// Paid gas / logs live on transactions[].Ceilings (guardrails)
| Limit | Value |
|---|---|
| Max gas limit | 30_000_000 |
| Default gas limit | 1_000_000 |
| Max bytecode size | 24_576 bytes |
| Max trace steps | 10_000 |
| Max transactions per lab block | 8 |
Registered capabilities (live)
| EIP | Nature | Runnable | Shapes |
|---|---|---|---|
| 8024 | new-capability | yes | simulate |
| 7843 | new-capability | yes | block |
| 7708 | new-capability | yes | transaction, simulate |
| 7883 | repricing | yes | simulate |
| 7951 | new-capability | yes | simulate |
| 8037 | new-exec-model | yes | transaction, simulate |
| 8038 | repricing | yes | simulate, transaction |
Only runnable modules appear in describeCapabilities().eips. Named forks appear in namedForks with advertised relatedEips. Wallet / receipt questions use transaction; opcode / precompile questions use simulate; header slot / multi-tx questions use block. A generic Amsterdam run uses the same verbs with empty eips[].
Amsterdam in EthereumJS v10 already bundles EIP-8024 and EIP-7843 — eips: [8024] / eips: [7843] are not pre/post toggles. Use osaka baseline vs amsterdam preview for those comparisons.
Development
See Quality.
Changelog
- v0.1.112026-09-16Named forks are catalog capabilities; generic-run provenance lists advertised modules.
- v0.1.92026-09-14Boundaries: isolated lab / constructed prestate; historical backtesting still out.
- v0.1.82026-09-14EIP-8038 state-access module; accounts[].storage seed; SSTORE via runTransaction.
- v0.1.72026-09-10EIP-7843 SLOTNUM module — runBlock header.slotNumber; catalog row live.
- v0.1.62026-09-10runBlock lab verb — header snapshot, per-tx receipts, optional slotNumber.
- v0.1.52026-09-08runTransaction (VM tx path); paid gas, 8037 dimensions, 7708 receipt logs.
- v0.1.42026-09-08Simulate result: gasUsedScope plus messageCall approxTxGasUsed (21000 + call-frame).
- v0.1.32026-08-27Osaka mainnet baseline fork; baselineForkId and EIP comparison pairs in probe.
- v0.1.22026-08-27Removed compareVariants — agents call simulateBytecode twice to diff.
- v0.1.12026-08-27EIP module catalog (8024 opcodes/encoding only); stub EIPs and demo scenarios removed.
- v0.1.02026-07-20Initial engine — simulateBytecode, registry, provenance, compareVariants composer, seed presets.