{"_id":"@bradthomasbrown/evm-single-context","_rev":"3-2d577161554d21717fe3e6fd5df3aef3","name":"@bradthomasbrown/evm-single-context","dist-tags":{"latest":"1.1.1"},"versions":{"1.0.0":{"name":"@bradthomasbrown/evm-single-context","version":"1.0.0","author":{"name":"Brad Brown","email":"https://t.me/bradthomasbrown"},"_id":"@bradthomasbrown/evm-single-context@1.0.0","maintainers":[{"name":"bradthomasbrown","email":"bradthomasbrown@outlook.com"}],"dist":{"shasum":"9056b47c608350ef293e1006a52774e12f9dc788","tarball":"https://registry.npmjs.org/@bradthomasbrown/evm-single-context/-/evm-single-context-1.0.0.tgz","fileCount":179,"integrity":"sha512-9C55gmwNT9dx0T28tS9pPf26GziUZxLM2Sqmz1aubYl6lIqXaP9LYqxUMpD/GF01YzMa8LqSXYCZtaE97O5lXQ==","signatures":[{"sig":"MEYCIQDF2AUk1KhpK7NrLL1M+mr4OXv3QWlFKVSbwKowZub2ogIhAJDFeUPpH/N33WJI+SwwaS4z+ASG0d3K82h8Y1PT356y","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":92854},"type":"module","exports":{".":"./dist/machine.js","./lib":"./dist/lib.js","./types":"./dist/types.js","./opsets/9db704":"./dist/opsets/9db704/opset.js"},"gitHead":"5100bfd48a05af21f5544863ba2c10e6b35f93ef","_npmUser":{"name":"bradthomasbrown","email":"bradthomasbrown@outlook.com"},"_npmVersion":"10.9.2","description":"An implementation of a single-context ethereum virtual machine in JavaScript/TypeScript.","directories":{},"_nodeVersion":"22.16.0","dependencies":{"@bradthomasbrown/rlp":"^1.0.0","@bradthomasbrown/ecdsa":"^2.0.1","@bradthomasbrown/75bb14":"^1.0.0","@bradthomasbrown/900ef2":"^1.0.0","@bradthomasbrown/entity":"^1.0.1","@bradthomasbrown/keccak":"^1.0.1","@bradthomasbrown/machine":"^1.0.0","@bradthomasbrown/finite-field":"^2.0.5"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/evm-single-context_1.0.0_1767343024078_0.17731279898461016","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@bradthomasbrown/evm-single-context","version":"1.1.0","author":{"name":"Brad Brown","email":"https://t.me/bradthomasbrown"},"_id":"@bradthomasbrown/evm-single-context@1.1.0","maintainers":[{"name":"bradthomasbrown","email":"bradthomasbrown@outlook.com"}],"dist":{"shasum":"28651df1097017660cd5df7199b89fedfc03a094","tarball":"https://registry.npmjs.org/@bradthomasbrown/evm-single-context/-/evm-single-context-1.1.0.tgz","fileCount":233,"integrity":"sha512-UPFJc7w6UYeyZEZxsFUj941ECL/toOLwtW/uPU1Sg5fuP4OfqM2FoP95udkeNpmDtXq+wf61XxbzRLJZmPaW+g==","signatures":[{"sig":"MEQCIDQ1ilJd+kO7n1tKKrVnaG/G2wHVsau8MlxY/4JjhuT4AiB838Fwk4gY9+hYkFTd2QO3jHdDeMscEjDUcyuezbhTfA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":137255},"type":"module","exports":{".":"./dist/machine.js","./lib":"./dist/lib.js","./types":"./dist/types.js","./opsets/9db704":"./dist/opsets/9db704/opset.js"},"gitHead":"fe82f8d9b653e0d211d01222435f8d92cc15fc69","_npmUser":{"name":"bradthomasbrown","email":"bradthomasbrown@outlook.com"},"_npmVersion":"11.7.0","description":"An implementation of a single-context ethereum virtual machine in JavaScript/TypeScript.","directories":{},"_nodeVersion":"22.16.0","dependencies":{"@bradthomasbrown/rlp":"^1.0.0","@bradthomasbrown/sha":"^1.0.0","@bradthomasbrown/ecdsa":"^2.0.3","@bradthomasbrown/75bb14":"^1.0.1","@bradthomasbrown/keccak":"^1.0.2","@bradthomasbrown/machine":"^1.0.0","@bradthomasbrown/finite-field":"^2.0.6"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.3.6","@bradthomasbrown/900ef2":"^1.0.0","@bradthomasbrown/entity":"^1.0.2"},"_npmOperationalInternal":{"tmp":"tmp/evm-single-context_1.1.0_1768882947406_0.04496972999489368","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@bradthomasbrown/evm-single-context","description":"An implementation of a single-context ethereum virtual machine in JavaScript/TypeScript.","version":"1.1.1","author":{"name":"Brad Brown","email":"https://t.me/bradthomasbrown"},"type":"module","exports":{".":"./dist/machine.js","./lib":"./dist/lib.js","./types":"./dist/types.js","./opsets/9db704":"./dist/opsets/9db704/opset.js"},"dependencies":{"@bradthomasbrown/75bb14":"^1.0.1","@bradthomasbrown/ecdsa":"^2.0.3","@bradthomasbrown/finite-field":"^2.0.6","@bradthomasbrown/keccak":"^1.0.2","@bradthomasbrown/machine":"^1.0.0","@bradthomasbrown/rlp":"^1.0.0","@bradthomasbrown/sha":"^1.0.0"},"devDependencies":{"@bradthomasbrown/900ef2":"^1.0.0","@bradthomasbrown/entity":"^1.0.2","@types/bun":"^1.3.6"},"gitHead":"ed4cbe83584c4b1eb865e74264f8bbadffbd365e","_id":"@bradthomasbrown/evm-single-context@1.1.1","_nodeVersion":"22.16.0","_npmVersion":"11.7.0","dist":{"integrity":"sha512-z7eITtfNoCVbEmFODXkX4mGrIQ4vMvMj2gDYlEuN3pwLO5LBz09G6ZHxo8XN7pCIXpkPgY/osvzvREoSgVQ72w==","shasum":"4149014ceeed8fd27f0bbafd3f4f21911b083682","tarball":"https://registry.npmjs.org/@bradthomasbrown/evm-single-context/-/evm-single-context-1.1.1.tgz","fileCount":233,"unpackedSize":133923,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICKt+L5sXyToDLMPJReP+tRUnhChcy+/pG/Zwzm3YLEZAiBUoDS88Grc0isBFVwmDwm2XqXIyH5Vwa1nA92effMA8g=="}]},"_npmUser":{"name":"bradthomasbrown","email":"bradthomasbrown@outlook.com"},"directories":{},"maintainers":[{"name":"bradthomasbrown","email":"bradthomasbrown@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/evm-single-context_1.1.1_1768883295537_0.6391586579407091"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-02T08:37:03.984Z","modified":"2026-01-20T04:28:15.812Z","1.0.0":"2026-01-02T08:37:04.233Z","1.1.0":"2026-01-20T04:22:27.552Z","1.1.1":"2026-01-20T04:28:15.672Z"},"author":{"name":"Brad Brown","email":"https://t.me/bradthomasbrown"},"description":"An implementation of a single-context ethereum virtual machine in JavaScript/TypeScript.","maintainers":[{"name":"bradthomasbrown","email":"bradthomasbrown@outlook.com"}],"readme":"# evm-single-context\r\nThis is an implementation of a \"single-context machine\" partial interpretation of an Ethereum Virtual Machine (EVM). \r\nBy \"single-context machine\", we mean that an instance of one of these machines will run until the point where most EVM implementations would recurse into a new execution context, like on any CALL-type or CREATE-type opcode.\r\nThis kind of machine will be different in that instances will simply block when these opcodes are reached and will wait for a higher machine or coordinator to do what is necessary and then unblock the machine.\r\n\r\n## Why?\r\nFor local testing, we found quickly that Anvil has execution consensus divergences (bugs) with go-ethereum (`geth`). If we want to deploy a contract on Ethereum Mainnet, we should not use Anvil.\r\n`geth` itself is very inflexible and not friendly for local development work and testing. If you want to test handling chain reorganizations, this will end up being a lot of work. Anvil allows easy testing of this, but has the aformentioned bugs.\r\nBoth require spinning up a node with an external application/binary and probably some form of container runtime.\r\nThe official JS/TS implementation is just as inflexible since it is designed to closely mirror `geth` and contains a lot of complexity and bloat since it aims to be as close to full EVM functionality as possible.\r\nThis will be the first of a set of light, simple, and flexible implementations designed to be easy to work with and use for developing/testing/verification.\r\n\r\n## Installation\r\n```sh\r\nnpm i @bradthomasbrown/evm-single-context\r\n```\r\n\r\n## Usage\r\n```js\r\nimport type { Context } from \"@bradthomasbrown/evm-single-context/types\";\r\nimport { EvmEntity } from \"@bradthomasbrown/entity/evm\";\r\nimport { createContext } from \"@bradthomasbrown/evm-single-context/lib\";\r\nimport { SingleContextMachine, traceObjects } from \"@bradthomasbrown/evm-single-context\";\r\n\r\n// set up some test parameters\r\nconst parameters = {\r\n    from: \"0x45c3bde5d2cc59a626bee55ac8e494cf128e866e\",\r\n    gas: 217590n,\r\n    value: 111360000000000000n,\r\n    input: await Bun.file(\"testinput.hex\").text(), // or any other way to set the input/data/calldata, which should appear as `0x<hex>...`\r\n    code: await Bun.file(\"testcode.hex\").text(), // or any other way to set the code, which should appear as `0x<hex>...`\r\n};\r\n\r\n// assign a random address for a contract\r\nconst contract = EvmEntity.random();\r\n\r\n// get the code as a uint8array\r\nconst code = parameters.code === null\r\n    ? Uint8Array.fromHex(parameters.input.slice(2)).buffer\r\n    : Uint8Array.fromHex(parameters.code.slice(2)).buffer;\r\n\r\n// create state\r\nconst accounts:Context[\"states\"][number][\"accounts\"] = new Map([ [contract.address, { nonce: 1n, balance: 0n, code }] ]);\r\nconst states:Context[\"states\"] = [{ accounts, transientStorage: null, storage: null }];\r\n\r\n// create a context\r\nconst context = createContext({\r\n    origin:parameters.from,\r\n    sender:parameters.from,\r\n    value:parameters.value,\r\n    to:contract.address,\r\n    gas:parameters.gas,\r\n    calldata:Uint8Array.fromHex(parameters.input.slice(2)).buffer,\r\n    code,\r\n    states\r\n});\r\n\r\n// do some initial context handling (more related to transactions, not single-contexts),\r\n// like initial transaction cost and pre-warming precompile addresses\r\nlet g0_data = 0n;\r\nif (context.calldata !== null)\r\n    for (const byte of new Uint8Array(context.calldata))\r\n        g0_data += byte === 0 ? 4n : 16n;\r\nlet g0_create = 0n;\r\nif (context.to === null) {\r\n    const codeArray = new Uint8Array(context.calldata!);\r\n    g0_create += 32000n;\r\n    g0_create += 2n * BigInt((codeArray.byteLength + 0x1f & ~0x1f) >> 5);\r\n}\r\nconst g0_transaction = 21000n;\r\nconst g0 = g0_data + g0_create + g0_transaction;\r\ncontext.gas -= g0;\r\ncontext.accountAccessSet.add(`0x${\"1\".padStart(40, '0')}`);\r\n\r\n// create a single-context machine from this context, initialize and run it, then log trace objects\r\n// should replicate go-ethereum's traces\r\nconst machine = new SingleContextMachine(context);\r\nmachine.initializeAndRun();\r\nconsole.log(traceObjects);\r\n/* ..., {\r\n    pc: 409,\r\n    op: \"JUMP\",\r\n    gas: 189836,\r\n    gasCost: 8,\r\n    depth: 1,\r\n    stack: [ \"0x0\", \"0x19a\", \"0x36c\", \"0x13c\" ],\r\n    memory: [ \"0000000000000000000000000000000000000000000000000000000000000000\", \"0000000000000000000000000000000000000000000000000000000000000000\",\r\n        \"0000000000000000000000000000000000000000000000000000000000000080\"\r\n    ],\r\n}, ... */\r\n```","readmeFilename":"README.md"}