@bradthomasbrown/evm-single-context 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/README.md +91 -0
  2. package/dist/lib.d.ts +26 -0
  3. package/dist/lib.d.ts.map +1 -0
  4. package/dist/lib.js +129 -0
  5. package/dist/machine.d.ts +40 -0
  6. package/dist/machine.d.ts.map +1 -0
  7. package/dist/machine.js +166 -0
  8. package/dist/opsets/9db704/opcodes/ADD.d.ts +8 -0
  9. package/dist/opsets/9db704/opcodes/ADD.d.ts.map +1 -0
  10. package/dist/opsets/9db704/opcodes/ADD.js +13 -0
  11. package/dist/opsets/9db704/opcodes/ADDRESS.d.ts +8 -0
  12. package/dist/opsets/9db704/opcodes/ADDRESS.d.ts.map +1 -0
  13. package/dist/opsets/9db704/opcodes/ADDRESS.js +11 -0
  14. package/dist/opsets/9db704/opcodes/AND.d.ts +8 -0
  15. package/dist/opsets/9db704/opcodes/AND.d.ts.map +1 -0
  16. package/dist/opsets/9db704/opcodes/AND.js +13 -0
  17. package/dist/opsets/9db704/opcodes/BYTE.d.ts +8 -0
  18. package/dist/opsets/9db704/opcodes/BYTE.d.ts.map +1 -0
  19. package/dist/opsets/9db704/opcodes/BYTE.js +13 -0
  20. package/dist/opsets/9db704/opcodes/CALLDATACOPY.d.ts +8 -0
  21. package/dist/opsets/9db704/opcodes/CALLDATACOPY.d.ts.map +1 -0
  22. package/dist/opsets/9db704/opcodes/CALLDATACOPY.js +14 -0
  23. package/dist/opsets/9db704/opcodes/CALLDATALOAD.d.ts +8 -0
  24. package/dist/opsets/9db704/opcodes/CALLDATALOAD.d.ts.map +1 -0
  25. package/dist/opsets/9db704/opcodes/CALLDATALOAD.js +17 -0
  26. package/dist/opsets/9db704/opcodes/CALLDATASIZE.d.ts +8 -0
  27. package/dist/opsets/9db704/opcodes/CALLDATASIZE.d.ts.map +1 -0
  28. package/dist/opsets/9db704/opcodes/CALLDATASIZE.js +11 -0
  29. package/dist/opsets/9db704/opcodes/CALLER.d.ts +8 -0
  30. package/dist/opsets/9db704/opcodes/CALLER.d.ts.map +1 -0
  31. package/dist/opsets/9db704/opcodes/CALLER.js +11 -0
  32. package/dist/opsets/9db704/opcodes/CALLVALUE.d.ts +8 -0
  33. package/dist/opsets/9db704/opcodes/CALLVALUE.d.ts.map +1 -0
  34. package/dist/opsets/9db704/opcodes/CALLVALUE.js +11 -0
  35. package/dist/opsets/9db704/opcodes/CHAINID.d.ts +8 -0
  36. package/dist/opsets/9db704/opcodes/CHAINID.d.ts.map +1 -0
  37. package/dist/opsets/9db704/opcodes/CHAINID.js +12 -0
  38. package/dist/opsets/9db704/opcodes/CODECOPY.d.ts +8 -0
  39. package/dist/opsets/9db704/opcodes/CODECOPY.d.ts.map +1 -0
  40. package/dist/opsets/9db704/opcodes/CODECOPY.js +13 -0
  41. package/dist/opsets/9db704/opcodes/CREATE.d.ts +8 -0
  42. package/dist/opsets/9db704/opcodes/CREATE.d.ts.map +1 -0
  43. package/dist/opsets/9db704/opcodes/CREATE.js +49 -0
  44. package/dist/opsets/9db704/opcodes/CREATE2.d.ts +8 -0
  45. package/dist/opsets/9db704/opcodes/CREATE2.d.ts.map +1 -0
  46. package/dist/opsets/9db704/opcodes/CREATE2.js +50 -0
  47. package/dist/opsets/9db704/opcodes/DIV.d.ts +8 -0
  48. package/dist/opsets/9db704/opcodes/DIV.d.ts.map +1 -0
  49. package/dist/opsets/9db704/opcodes/DIV.js +16 -0
  50. package/dist/opsets/9db704/opcodes/DUP.d.ts +8 -0
  51. package/dist/opsets/9db704/opcodes/DUP.d.ts.map +1 -0
  52. package/dist/opsets/9db704/opcodes/DUP.js +11 -0
  53. package/dist/opsets/9db704/opcodes/EQ.d.ts +8 -0
  54. package/dist/opsets/9db704/opcodes/EQ.d.ts.map +1 -0
  55. package/dist/opsets/9db704/opcodes/EQ.js +13 -0
  56. package/dist/opsets/9db704/opcodes/EXTCODECOPY.d.ts +8 -0
  57. package/dist/opsets/9db704/opcodes/EXTCODECOPY.d.ts.map +1 -0
  58. package/dist/opsets/9db704/opcodes/EXTCODECOPY.js +20 -0
  59. package/dist/opsets/9db704/opcodes/EXTCODESIZE.d.ts +8 -0
  60. package/dist/opsets/9db704/opcodes/EXTCODESIZE.d.ts.map +1 -0
  61. package/dist/opsets/9db704/opcodes/EXTCODESIZE.js +20 -0
  62. package/dist/opsets/9db704/opcodes/GAS.d.ts +8 -0
  63. package/dist/opsets/9db704/opcodes/GAS.d.ts.map +1 -0
  64. package/dist/opsets/9db704/opcodes/GAS.js +11 -0
  65. package/dist/opsets/9db704/opcodes/GT.d.ts +8 -0
  66. package/dist/opsets/9db704/opcodes/GT.d.ts.map +1 -0
  67. package/dist/opsets/9db704/opcodes/GT.js +13 -0
  68. package/dist/opsets/9db704/opcodes/ISZERO.d.ts +8 -0
  69. package/dist/opsets/9db704/opcodes/ISZERO.d.ts.map +1 -0
  70. package/dist/opsets/9db704/opcodes/ISZERO.js +13 -0
  71. package/dist/opsets/9db704/opcodes/JUMP.d.ts +8 -0
  72. package/dist/opsets/9db704/opcodes/JUMP.d.ts.map +1 -0
  73. package/dist/opsets/9db704/opcodes/JUMP.js +16 -0
  74. package/dist/opsets/9db704/opcodes/JUMPDEST.d.ts +8 -0
  75. package/dist/opsets/9db704/opcodes/JUMPDEST.d.ts.map +1 -0
  76. package/dist/opsets/9db704/opcodes/JUMPDEST.js +10 -0
  77. package/dist/opsets/9db704/opcodes/JUMPI.d.ts +8 -0
  78. package/dist/opsets/9db704/opcodes/JUMPI.d.ts.map +1 -0
  79. package/dist/opsets/9db704/opcodes/JUMPI.js +20 -0
  80. package/dist/opsets/9db704/opcodes/KECCAK256.d.ts +8 -0
  81. package/dist/opsets/9db704/opcodes/KECCAK256.d.ts.map +1 -0
  82. package/dist/opsets/9db704/opcodes/KECCAK256.js +14 -0
  83. package/dist/opsets/9db704/opcodes/LOG.d.ts +8 -0
  84. package/dist/opsets/9db704/opcodes/LOG.d.ts.map +1 -0
  85. package/dist/opsets/9db704/opcodes/LOG.js +14 -0
  86. package/dist/opsets/9db704/opcodes/LT.d.ts +8 -0
  87. package/dist/opsets/9db704/opcodes/LT.d.ts.map +1 -0
  88. package/dist/opsets/9db704/opcodes/LT.js +13 -0
  89. package/dist/opsets/9db704/opcodes/MLOAD.d.ts +8 -0
  90. package/dist/opsets/9db704/opcodes/MLOAD.d.ts.map +1 -0
  91. package/dist/opsets/9db704/opcodes/MLOAD.js +14 -0
  92. package/dist/opsets/9db704/opcodes/MSIZE.d.ts +8 -0
  93. package/dist/opsets/9db704/opcodes/MSIZE.d.ts.map +1 -0
  94. package/dist/opsets/9db704/opcodes/MSIZE.js +11 -0
  95. package/dist/opsets/9db704/opcodes/MSTORE.d.ts +8 -0
  96. package/dist/opsets/9db704/opcodes/MSTORE.d.ts.map +1 -0
  97. package/dist/opsets/9db704/opcodes/MSTORE.js +14 -0
  98. package/dist/opsets/9db704/opcodes/MSTORE8.d.ts +8 -0
  99. package/dist/opsets/9db704/opcodes/MSTORE8.d.ts.map +1 -0
  100. package/dist/opsets/9db704/opcodes/MSTORE8.js +14 -0
  101. package/dist/opsets/9db704/opcodes/MUL.d.ts +8 -0
  102. package/dist/opsets/9db704/opcodes/MUL.d.ts.map +1 -0
  103. package/dist/opsets/9db704/opcodes/MUL.js +13 -0
  104. package/dist/opsets/9db704/opcodes/NOT.d.ts +8 -0
  105. package/dist/opsets/9db704/opcodes/NOT.d.ts.map +1 -0
  106. package/dist/opsets/9db704/opcodes/NOT.js +13 -0
  107. package/dist/opsets/9db704/opcodes/OR.d.ts +8 -0
  108. package/dist/opsets/9db704/opcodes/OR.d.ts.map +1 -0
  109. package/dist/opsets/9db704/opcodes/OR.js +13 -0
  110. package/dist/opsets/9db704/opcodes/PC.d.ts +8 -0
  111. package/dist/opsets/9db704/opcodes/PC.d.ts.map +1 -0
  112. package/dist/opsets/9db704/opcodes/PC.js +11 -0
  113. package/dist/opsets/9db704/opcodes/POP.d.ts +8 -0
  114. package/dist/opsets/9db704/opcodes/POP.d.ts.map +1 -0
  115. package/dist/opsets/9db704/opcodes/POP.js +11 -0
  116. package/dist/opsets/9db704/opcodes/PUSH.d.ts +8 -0
  117. package/dist/opsets/9db704/opcodes/PUSH.d.ts.map +1 -0
  118. package/dist/opsets/9db704/opcodes/PUSH.js +11 -0
  119. package/dist/opsets/9db704/opcodes/RETURN.d.ts +8 -0
  120. package/dist/opsets/9db704/opcodes/RETURN.d.ts.map +1 -0
  121. package/dist/opsets/9db704/opcodes/RETURN.js +15 -0
  122. package/dist/opsets/9db704/opcodes/RETURNDATACOPY.d.ts +8 -0
  123. package/dist/opsets/9db704/opcodes/RETURNDATACOPY.d.ts.map +1 -0
  124. package/dist/opsets/9db704/opcodes/RETURNDATACOPY.js +13 -0
  125. package/dist/opsets/9db704/opcodes/RETURNDATASIZE.d.ts +8 -0
  126. package/dist/opsets/9db704/opcodes/RETURNDATASIZE.d.ts.map +1 -0
  127. package/dist/opsets/9db704/opcodes/RETURNDATASIZE.js +11 -0
  128. package/dist/opsets/9db704/opcodes/REVERT.d.ts +8 -0
  129. package/dist/opsets/9db704/opcodes/REVERT.d.ts.map +1 -0
  130. package/dist/opsets/9db704/opcodes/REVERT.js +15 -0
  131. package/dist/opsets/9db704/opcodes/SGT.d.ts +8 -0
  132. package/dist/opsets/9db704/opcodes/SGT.d.ts.map +1 -0
  133. package/dist/opsets/9db704/opcodes/SGT.js +15 -0
  134. package/dist/opsets/9db704/opcodes/SHL.d.ts +8 -0
  135. package/dist/opsets/9db704/opcodes/SHL.d.ts.map +1 -0
  136. package/dist/opsets/9db704/opcodes/SHL.js +13 -0
  137. package/dist/opsets/9db704/opcodes/SHR.d.ts +8 -0
  138. package/dist/opsets/9db704/opcodes/SHR.d.ts.map +1 -0
  139. package/dist/opsets/9db704/opcodes/SHR.js +13 -0
  140. package/dist/opsets/9db704/opcodes/SLOAD.d.ts +8 -0
  141. package/dist/opsets/9db704/opcodes/SLOAD.d.ts.map +1 -0
  142. package/dist/opsets/9db704/opcodes/SLOAD.js +21 -0
  143. package/dist/opsets/9db704/opcodes/SLT.d.ts +8 -0
  144. package/dist/opsets/9db704/opcodes/SLT.d.ts.map +1 -0
  145. package/dist/opsets/9db704/opcodes/SLT.js +15 -0
  146. package/dist/opsets/9db704/opcodes/SSTORE.d.ts +8 -0
  147. package/dist/opsets/9db704/opcodes/SSTORE.d.ts.map +1 -0
  148. package/dist/opsets/9db704/opcodes/SSTORE.js +50 -0
  149. package/dist/opsets/9db704/opcodes/STATICCALL.d.ts +8 -0
  150. package/dist/opsets/9db704/opcodes/STATICCALL.d.ts.map +1 -0
  151. package/dist/opsets/9db704/opcodes/STATICCALL.js +104 -0
  152. package/dist/opsets/9db704/opcodes/STOP.d.ts +8 -0
  153. package/dist/opsets/9db704/opcodes/STOP.d.ts.map +1 -0
  154. package/dist/opsets/9db704/opcodes/STOP.js +9 -0
  155. package/dist/opsets/9db704/opcodes/SUB.d.ts +8 -0
  156. package/dist/opsets/9db704/opcodes/SUB.d.ts.map +1 -0
  157. package/dist/opsets/9db704/opcodes/SUB.js +13 -0
  158. package/dist/opsets/9db704/opcodes/SWAP.d.ts +8 -0
  159. package/dist/opsets/9db704/opcodes/SWAP.d.ts.map +1 -0
  160. package/dist/opsets/9db704/opcodes/SWAP.js +15 -0
  161. package/dist/opsets/9db704/opcodes/TIMESTAMP.d.ts +8 -0
  162. package/dist/opsets/9db704/opcodes/TIMESTAMP.d.ts.map +1 -0
  163. package/dist/opsets/9db704/opcodes/TIMESTAMP.js +13 -0
  164. package/dist/opsets/9db704/opcodes/TLOAD.d.ts +8 -0
  165. package/dist/opsets/9db704/opcodes/TLOAD.d.ts.map +1 -0
  166. package/dist/opsets/9db704/opcodes/TLOAD.js +14 -0
  167. package/dist/opsets/9db704/opcodes/TSTORE.d.ts +8 -0
  168. package/dist/opsets/9db704/opcodes/TSTORE.d.ts.map +1 -0
  169. package/dist/opsets/9db704/opcodes/TSTORE.js +18 -0
  170. package/dist/opsets/9db704/opcodes/XOR.d.ts +8 -0
  171. package/dist/opsets/9db704/opcodes/XOR.d.ts.map +1 -0
  172. package/dist/opsets/9db704/opcodes/XOR.js +13 -0
  173. package/dist/opsets/9db704/opset.d.ts +53 -0
  174. package/dist/opsets/9db704/opset.d.ts.map +1 -0
  175. package/dist/opsets/9db704/opset.js +52 -0
  176. package/dist/types.d.ts +49 -0
  177. package/dist/types.d.ts.map +1 -0
  178. package/dist/types.js +1 -0
  179. package/package.json +26 -0
package/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # evm-single-context
2
+ This is an implementation of a "single-context machine" partial interpretation of an Ethereum Virtual Machine (EVM).
3
+ By "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.
4
+ This 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.
5
+
6
+ ## Why?
7
+ For 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.
8
+ `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.
9
+ Both require spinning up a node with an external application/binary and probably some form of container runtime.
10
+ The 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.
11
+ This 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.
12
+
13
+ ## Installation
14
+ ```sh
15
+ npm i @bradthomasbrown/evm-single-context
16
+ ```
17
+
18
+ ## Usage
19
+ ```js
20
+ import type { Context } from "@bradthomasbrown/evm-single-context/types";
21
+ import { EvmEntity } from "@bradthomasbrown/entity/evm";
22
+ import { createContext } from "@bradthomasbrown/evm-single-context/lib";
23
+ import { SingleContextMachine, traceObjects } from "@bradthomasbrown/evm-single-context";
24
+
25
+ // set up some test parameters
26
+ const parameters = {
27
+ from: "0x45c3bde5d2cc59a626bee55ac8e494cf128e866e",
28
+ gas: 217590n,
29
+ value: 111360000000000000n,
30
+ input: await Bun.file("testinput.hex").text(), // or any other way to set the input/data/calldata, which should appear as `0x<hex>...`
31
+ code: await Bun.file("testcode.hex").text(), // or any other way to set the code, which should appear as `0x<hex>...`
32
+ };
33
+
34
+ // assign a random address for a contract
35
+ const contract = EvmEntity.random();
36
+
37
+ // get the code as a uint8array
38
+ const code = parameters.code === null
39
+ ? Uint8Array.fromHex(parameters.input.slice(2)).buffer
40
+ : Uint8Array.fromHex(parameters.code.slice(2)).buffer;
41
+
42
+ // create state
43
+ const accounts:Context["states"][number]["accounts"] = new Map([ [contract.address, { nonce: 1n, balance: 0n, code }] ]);
44
+ const states:Context["states"] = [{ accounts, transientStorage: null, storage: null }];
45
+
46
+ // create a context
47
+ const context = createContext({
48
+ origin:parameters.from,
49
+ sender:parameters.from,
50
+ value:parameters.value,
51
+ to:contract.address,
52
+ gas:parameters.gas,
53
+ calldata:Uint8Array.fromHex(parameters.input.slice(2)).buffer,
54
+ code,
55
+ states
56
+ });
57
+
58
+ // do some initial context handling (more related to transactions, not single-contexts),
59
+ // like initial transaction cost and pre-warming precompile addresses
60
+ let g0_data = 0n;
61
+ if (context.calldata !== null)
62
+ for (const byte of new Uint8Array(context.calldata))
63
+ g0_data += byte === 0 ? 4n : 16n;
64
+ let g0_create = 0n;
65
+ if (context.to === null) {
66
+ const codeArray = new Uint8Array(context.calldata!);
67
+ g0_create += 32000n;
68
+ g0_create += 2n * BigInt((codeArray.byteLength + 0x1f & ~0x1f) >> 5);
69
+ }
70
+ const g0_transaction = 21000n;
71
+ const g0 = g0_data + g0_create + g0_transaction;
72
+ context.gas -= g0;
73
+ context.accountAccessSet.add(`0x${"1".padStart(40, '0')}`);
74
+
75
+ // create a single-context machine from this context, initialize and run it, then log trace objects
76
+ // should replicate go-ethereum's traces
77
+ const machine = new SingleContextMachine(context);
78
+ machine.initializeAndRun();
79
+ console.log(traceObjects);
80
+ /* ..., {
81
+ pc: 409,
82
+ op: "JUMP",
83
+ gas: 189836,
84
+ gasCost: 8,
85
+ depth: 1,
86
+ stack: [ "0x0", "0x19a", "0x36c", "0x13c" ],
87
+ memory: [ "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000",
88
+ "0000000000000000000000000000000000000000000000000000000000000080"
89
+ ],
90
+ }, ... */
91
+ ```
package/dist/lib.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { MapComponents, Context, PartialContext } from "./types.js";
2
+ import { keccak256 } from "@bradthomasbrown/keccak/keccak256";
3
+ declare function byteSliceToBigInt_be(bytes: Uint8Array, offset: number, size: number, permitOobZeroes: boolean): bigint;
4
+ declare function numberToHex(value: number | bigint, padding: number): string;
5
+ declare const F: {
6
+ p: bigint;
7
+ sqrt: (a: number | bigint) => bigint;
8
+ add(a: bigint | number, b: bigint | number): bigint;
9
+ multiply(a: bigint | number, b: bigint | number): bigint;
10
+ inverse(a: bigint | number): bigint;
11
+ subtract(a: bigint | number, b: bigint | number): bigint;
12
+ reciprocal(a: bigint | number): bigint;
13
+ divide(a: bigint | number, b: bigint | number): bigint;
14
+ power(b: bigint | number, e: bigint | number): bigint;
15
+ };
16
+ declare function pop(stack: Array<bigint>, count: number): bigint[];
17
+ declare function peek(stack: Array<bigint>, count: number): bigint[];
18
+ declare function copy(destinationBuffer: ArrayBuffer, sourceBuffer: null | ArrayBuffer, destinationOffset: number, sourceOffset: number, size: number, permitOobZeroes: boolean): void;
19
+ declare function memoryExpand(context: Context, size: number): void;
20
+ declare function getStateValue<I extends keyof Context["states"][number], M extends Context["states"][number][I], C extends MapComponents<NonNullable<M>>, K extends C["keyPath"], V extends C["value"]>(states: Context["states"], maxIndex: null | number, mapIdentifier: I, keyPath: K): null | V;
21
+ declare function createContext(partialContext: PartialContext): Context;
22
+ declare function deriveAddress(context: Context): string;
23
+ declare function deriveAddress2(sender: string, salt: bigint, code: ArrayBuffer): string;
24
+ declare function write(destination: ArrayBuffer, value: bigint, offset: number, size: number): void;
25
+ export { byteSliceToBigInt_be, numberToHex, F, keccak256, pop, peek, copy, memoryExpand, getStateValue, write, createContext, deriveAddress, deriveAddress2 };
26
+ //# sourceMappingURL=lib.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEzE,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAG9D,iBAAS,oBAAoB,CAAC,KAAK,EAAC,UAAU,EAAE,MAAM,EAAC,MAAM,EAAE,IAAI,EAAC,MAAM,EAAE,eAAe,EAAC,OAAO,UAOlG;AAED,iBAAS,WAAW,CAAC,KAAK,EAAC,MAAM,GAAC,MAAM,EAAE,OAAO,EAAC,MAAM,UAEvD;AAMD,QAAA,MAAM,CAAC;;;;;;;;;;CAAqB,CAAC;AAE7B,iBAAS,GAAG,CAAC,KAAK,EAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAC,MAAM,YAK7C;AAED,iBAAS,IAAI,CAAC,KAAK,EAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAC,MAAM,YAK9C;AAED,iBAAS,IAAI,CAAC,iBAAiB,EAAC,WAAW,EAAE,YAAY,EAAC,IAAI,GAAC,WAAW,EAAE,iBAAiB,EAAC,MAAM,EAAE,YAAY,EAAC,MAAM,EAAE,IAAI,EAAC,MAAM,EAAE,eAAe,EAAC,OAAO,QAa9J;AAED,iBAAS,YAAY,CAAC,OAAO,EAAC,OAAO,EAAE,IAAI,EAAC,MAAM,QAWjD;AAED,iBAAS,aAAa,CAClB,CAAC,SAAS,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EACzC,CAAC,SAAS,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EACtC,CAAC,SAAS,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EACvC,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,EACtB,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EACtB,MAAM,EAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAC,IAAI,GAAC,MAAM,EAAE,aAAa,EAAC,CAAC,EAAE,OAAO,EAAC,CAAC,GAAE,IAAI,GAAC,CAAC,CAenF;AAED,iBAAS,aAAa,CAAC,cAAc,EAAC,cAAc,GAAE,OAAO,CA0B5D;AAED,iBAAS,aAAa,CAAC,OAAO,EAAC,OAAO,UAIrC;AAED,iBAAS,cAAc,CAAC,MAAM,EAAC,MAAM,EAAE,IAAI,EAAC,MAAM,EAAE,IAAI,EAAC,WAAW,UAOnE;AAED,iBAAS,KAAK,CAAC,WAAW,EAAC,WAAW,EAAE,KAAK,EAAC,MAAM,EAAE,MAAM,EAAC,MAAM,EAAE,IAAI,EAAC,MAAM,QAI/E;AAED,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC"}
package/dist/lib.js ADDED
@@ -0,0 +1,129 @@
1
+ import { _7c3dda_ } from "@bradthomasbrown/finite-field";
2
+ import { keccak256 } from "@bradthomasbrown/keccak/keccak256";
3
+ import { encode } from "@bradthomasbrown/rlp";
4
+ function byteSliceToBigInt_be(bytes, offset, size, permitOobZeroes) {
5
+ if ((permitOobZeroes === false) && (offset + size > bytes.byteLength))
6
+ throw new Error("out of bounds", { cause: { bytes, offset, size } });
7
+ let value = 0n;
8
+ for (let i = offset; i < offset + size; i++)
9
+ value = (value << 8n) + (i >= bytes.byteLength ? 0n : BigInt(bytes[i]));
10
+ return value;
11
+ }
12
+ function numberToHex(value, padding) {
13
+ return value.toString(16).padStart(padding, '0');
14
+ }
15
+ // shouldn't use p3mod4 field implementation here, so we make our own field implementation
16
+ function sqrt() { throw new Error("sqrt unsupported"); return 0n; }
17
+ const FiniteField = _7c3dda_(sqrt);
18
+ const p = (1n << 256n);
19
+ const F = new FiniteField(p);
20
+ function pop(stack, count) {
21
+ const array = new Array(count);
22
+ for (let j = 0; j < count; j++)
23
+ array[j] = stack.pop();
24
+ return array;
25
+ }
26
+ function peek(stack, count) {
27
+ const array = new Array(count);
28
+ for (let j = 0; j < count; j++)
29
+ array[j] = stack.at(0 - (j + 1));
30
+ return array;
31
+ }
32
+ function copy(destinationBuffer, sourceBuffer, destinationOffset, sourceOffset, size, permitOobZeroes) {
33
+ if (size == 0)
34
+ return;
35
+ let sourceBytesAvailable = 0;
36
+ if (sourceBuffer !== null && sourceOffset < sourceBuffer.byteLength)
37
+ sourceBytesAvailable = Math.min(sourceBuffer.byteLength - sourceOffset, size);
38
+ const destinationArray = new Uint8Array(destinationBuffer);
39
+ if (sourceBytesAvailable > 0) {
40
+ const sourceArray = new Uint8Array(sourceBuffer.slice(sourceOffset, sourceOffset + sourceBytesAvailable));
41
+ destinationArray.set(sourceArray, destinationOffset);
42
+ }
43
+ const bytesRemaining = size - sourceBytesAvailable;
44
+ if (bytesRemaining == 0)
45
+ return;
46
+ if (permitOobZeroes === false)
47
+ throw new Error(`outOfBoundsCopy`, { cause: { destinationBuffer, sourceBuffer, destinationOffset, sourceOffset, size } });
48
+ destinationArray.fill(0, destinationOffset + sourceBytesAvailable, bytesRemaining);
49
+ }
50
+ function memoryExpand(context, size) {
51
+ if (size == 0)
52
+ return;
53
+ if (context.memory === null)
54
+ context.memory = new ArrayBuffer(1);
55
+ const memoryWords = (size + 0x1f) >> 5;
56
+ if (context.memoryWords >= memoryWords)
57
+ return;
58
+ const C_mem = 3n * BigInt(memoryWords) + BigInt(memoryWords) ** 2n / 512n;
59
+ context.gas -= C_mem - context.C_mem_prev;
60
+ context.memoryWords = memoryWords;
61
+ context.C_mem_prev = C_mem;
62
+ while (context.memory.byteLength < size)
63
+ context.memory = context.memory.transfer(context.memory.byteLength << 1);
64
+ }
65
+ function getStateValue(states, maxIndex, mapIdentifier, keyPath) {
66
+ let value = null;
67
+ l0: for (let i = Math.min(maxIndex ?? states.length - 1, states.length - 1); i >= 0; i--) {
68
+ let map = states[i][mapIdentifier];
69
+ if (map === null)
70
+ continue;
71
+ for (let j = 0; j < keyPath.length - 1; j++) {
72
+ if (map.has(keyPath[j]) === false)
73
+ continue l0;
74
+ map = map.get(keyPath[j]);
75
+ }
76
+ const lastKeyComponent = keyPath[keyPath.length - 1];
77
+ if (map.has(lastKeyComponent) === false)
78
+ continue;
79
+ value = map.get(lastKeyComponent);
80
+ break;
81
+ }
82
+ return value;
83
+ }
84
+ function createContext(partialContext) {
85
+ return {
86
+ origin: partialContext.origin,
87
+ sender: partialContext.sender,
88
+ to: partialContext.to ?? null,
89
+ address: partialContext.address ?? null,
90
+ value: partialContext.value ?? 0n,
91
+ pc: partialContext.pc ?? 0,
92
+ gas: partialContext.gas ?? 0n,
93
+ stack: partialContext.stack ?? [],
94
+ memory: partialContext.memory ?? null,
95
+ C_mem_prev: partialContext.C_mem_prev ?? 0n,
96
+ returndata: partialContext.returndata ?? null,
97
+ accountAccessSet: partialContext.accountAccessSet ?? new Set(),
98
+ storageAccessSet: partialContext.storageAccessSet ?? new Map(),
99
+ depth: partialContext.depth ?? 1,
100
+ calldata: partialContext.calldata ?? null,
101
+ subcontext: partialContext.subcontext ?? null,
102
+ blocked: partialContext.blocked ?? false,
103
+ reverted: partialContext.reverted ?? null,
104
+ states: partialContext.states ?? [{ accounts: null, transientStorage: null, storage: null }],
105
+ refund: partialContext.refund ?? 0n,
106
+ code: partialContext.code ?? null,
107
+ memoryWords: 0,
108
+ L: null
109
+ };
110
+ }
111
+ function deriveAddress(context) {
112
+ const account = getStateValue(context.states, null, "accounts", [context.sender]);
113
+ const addressBytes = Uint8Array.fromHex(context.sender.slice(2));
114
+ return `0x${keccak256(encode([addressBytes, account.nonce])).slice(12).toHex()}`;
115
+ }
116
+ function deriveAddress2(sender, salt, code) {
117
+ const bytes = new Uint8Array(1 + 20 + 32 + 32);
118
+ bytes[0] = 0xff;
119
+ bytes.set(Uint8Array.fromHex(sender.slice(2)), 1);
120
+ write(bytes.buffer, salt, 1 + 20, 0x20);
121
+ bytes.set(keccak256(new Uint8Array(code)), 1 + 20 + 0x20);
122
+ return `0x${keccak256(bytes).slice(12).toHex()}`;
123
+ }
124
+ function write(destination, value, offset, size) {
125
+ const array = new Uint8Array(destination);
126
+ for (let i = offset + size - 1; i >= offset; i--, value >>= 8n)
127
+ array[i] = Number(value & 0xffn);
128
+ }
129
+ export { byteSliceToBigInt_be, numberToHex, F, keccak256, pop, peek, copy, memoryExpand, getStateValue, write, createContext, deriveAddress, deriveAddress2 };
@@ -0,0 +1,40 @@
1
+ import type { Context } from "./types.js";
2
+ declare let traceHelper: {
3
+ instruction: null | number;
4
+ pc: null | number;
5
+ op: null | string;
6
+ gas: null | number;
7
+ depth: null | number;
8
+ stack: null | Array<string>;
9
+ returnData: null | string;
10
+ memoryWords: null | Array<string>;
11
+ storage: null | {
12
+ [key: string]: string;
13
+ };
14
+ stop: null | boolean;
15
+ };
16
+ declare function buildTraceObject(context: Context): {
17
+ pc: number;
18
+ op: string;
19
+ gas: number;
20
+ gasCost: number;
21
+ depth: number;
22
+ stack: Array<string>;
23
+ returnData?: string;
24
+ memory?: Array<string>;
25
+ storage?: {
26
+ [key: string]: string;
27
+ };
28
+ refund?: number;
29
+ };
30
+ declare const traceObjects: Array<ReturnType<typeof buildTraceObject>>;
31
+ declare const SingleContextMachine: new (context: Context) => {
32
+ context: Context;
33
+ continue(): boolean;
34
+ step(): void;
35
+ initialize(): void;
36
+ run(): void;
37
+ initializeAndRun(): void;
38
+ };
39
+ export { SingleContextMachine, traceObjects, traceHelper };
40
+ //# sourceMappingURL=machine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine.d.ts","sourceRoot":"","sources":["../src/machine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,YAAY,CAAC;AA2EpD,QAAA,IAAI,WAAW,EAAC;IACZ,WAAW,EAAC,IAAI,GAAC,MAAM,CAAC;IACxB,EAAE,EAAC,IAAI,GAAC,MAAM,CAAC;IACf,EAAE,EAAC,IAAI,GAAC,MAAM,CAAC;IACf,GAAG,EAAC,IAAI,GAAC,MAAM,CAAA;IACf,KAAK,EAAC,IAAI,GAAC,MAAM,CAAC;IAClB,KAAK,EAAC,IAAI,GAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzB,UAAU,EAAC,IAAI,GAAC,MAAM,CAAC;IACvB,WAAW,EAAC,IAAI,GAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,EAAC,IAAI,GAAC;QAAE,CAAC,GAAG,EAAC,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACtC,IAAI,EAAC,IAAI,GAAC,OAAO,CAAA;CACmH,CAAC;AAmDzI,iBAAS,gBAAgB,CAAC,OAAO,EAAC,OAAO;QAK9B,MAAM;QACN,MAAM;SACL,MAAM;aACF,MAAM;WACR,MAAM;WACN,KAAK,CAAC,MAAM,CAAC;iBACP,MAAM;aACV,KAAK,CAAC,MAAM,CAAC;cACZ;QAAE,CAAC,GAAG,EAAC,MAAM,GAAG,MAAM,CAAA;KAAE;aACzB,MAAM;EAcrB;AAED,QAAA,MAAM,YAAY,EAAC,KAAK,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAM,CAAA;AA6BlE,QAAA,MAAM,oBAAoB;;;;;;;CAOzB,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,166 @@
1
+ import { createMachine } from "@bradthomasbrown/machine/6873f5";
2
+ import { byteSliceToBigInt_be, numberToHex, peek, copy, getStateValue, deriveAddress } from "./lib.js";
3
+ import * as opset from "./opsets/9db704/opset.js";
4
+ function continuePredicate(context) {
5
+ // if revert is known (true or false, not null), don't continue
6
+ if (context.reverted !== null)
7
+ return false;
8
+ // if there is no code, don't continue
9
+ if (context.code === null)
10
+ return false;
11
+ // if the program counter is beyond the code length, don't continue
12
+ if (context.pc >= context.code.byteLength)
13
+ return false;
14
+ // if there is an incomplete subcontext, don't continue
15
+ if (context.subcontext !== null && context.subcontext.reverted === null)
16
+ return false;
17
+ // otherwise, continue
18
+ return true;
19
+ }
20
+ function parseInstruction(context) {
21
+ const codeArray = new Uint8Array(context.code);
22
+ const instruction = codeArray[context.pc];
23
+ // PUSH handling
24
+ if (instruction >= 0x5f && instruction < 0x80) {
25
+ const variant = instruction - 0x5f;
26
+ const width = variant + 1;
27
+ const literal = byteSliceToBigInt_be(codeArray, context.pc + 1, variant, true);
28
+ return [0x60, { variant, width, literal }];
29
+ }
30
+ // DUP handling
31
+ if (instruction >= 0x80 && instruction < 0x90) {
32
+ const variant = instruction - 0x80;
33
+ const width = 1;
34
+ const literal = null;
35
+ return [0x80, { variant, width, literal }];
36
+ }
37
+ // SWAP handling
38
+ if (instruction >= 0x90 && instruction < 0xa0) {
39
+ const variant = instruction - 0x90;
40
+ const width = 1;
41
+ const literal = null;
42
+ return [0x90, { variant, width, literal }];
43
+ }
44
+ // LOG handling
45
+ if (instruction >= 0xa0 && instruction < 0xa5) {
46
+ const variant = instruction - 0xa0;
47
+ const width = 1;
48
+ const literal = null;
49
+ return [0xa0, { variant, width, literal }];
50
+ }
51
+ // default handling
52
+ const variant = null;
53
+ const width = 1;
54
+ const literal = null;
55
+ return [instruction, { variant, width, literal }];
56
+ }
57
+ const debug = true;
58
+ const identifierToString = new Map();
59
+ for (const opcode of Object.values(opset))
60
+ identifierToString.set(opcode.identifier, (instruction) => opcode.instructionToString(instruction));
61
+ let traceHelper = { instruction: null, gas: null, pc: null, op: null, depth: null, stack: null, returnData: null, memoryWords: null, storage: null, stop: null };
62
+ // NOTE: the entirety of this is just debug-related as of now
63
+ function preExecute(context) {
64
+ if (debug === false)
65
+ return;
66
+ const instruction = new Uint8Array(context.code)[context.pc];
67
+ let identifier = instruction;
68
+ if (instruction >= 0x5f && instruction < 0x80)
69
+ identifier = 0x60; // PUSH
70
+ if (instruction >= 0x80 && instruction < 0x90)
71
+ identifier = 0x80; // DUP
72
+ if (instruction >= 0x90 && instruction < 0xa0)
73
+ identifier = 0x90; // SWAP
74
+ if (instruction >= 0xa0 && instruction < 0xa5)
75
+ identifier = 0xa0; // LOG
76
+ if (identifierToString.has(identifier) === false)
77
+ throw new Error(`missing identiferToString.get(${numberToHex(identifier, 2)})`);
78
+ traceHelper.instruction = instruction;
79
+ traceHelper.pc = context.pc;
80
+ traceHelper.op = identifierToString.get(identifier)(instruction);
81
+ traceHelper.gas = Number(context.gas);
82
+ traceHelper.depth = context.depth;
83
+ traceHelper.stack = context.stack.map(value => `0x${value.toString(16)}`);
84
+ if (context.subcontext !== null && context.subcontext.to !== null && context.subcontext.returndata !== null)
85
+ traceHelper.returnData = `0x${new Uint8Array(context.subcontext.returndata).toHex()}`;
86
+ else
87
+ traceHelper.returnData = null;
88
+ if (context.memory !== null) {
89
+ traceHelper.memoryWords = [];
90
+ for (let i = 0; i < context.memoryWords << 5; i += 0x20) {
91
+ const wordBytes = new ArrayBuffer(32);
92
+ copy(wordBytes, context.memory, 0, i, 0x20, true);
93
+ traceHelper.memoryWords.push(new Uint8Array(wordBytes).toHex());
94
+ }
95
+ }
96
+ if (instruction == 0x54) {
97
+ const [key] = peek(context.stack, 1);
98
+ const value = getStateValue(context.states, null, "storage", [context.address, key]) ?? 0n;
99
+ if (traceHelper.storage === null)
100
+ traceHelper.storage = {};
101
+ traceHelper.storage[numberToHex(key, 64)] = numberToHex(value, 64);
102
+ }
103
+ else if (instruction == 0x55) {
104
+ const [key, value] = peek(context.stack, 2);
105
+ if (traceHelper.storage === null)
106
+ traceHelper.storage = {};
107
+ traceHelper.storage[numberToHex(key, 64)] = numberToHex(value, 64);
108
+ }
109
+ traceHelper.stop = instruction == 0x00;
110
+ }
111
+ const dispatch = new Map();
112
+ for (const opcode of Object.values(opset))
113
+ dispatch.set(opcode.identifier, opcode.executor);
114
+ function getExecutor(identifier) {
115
+ if (dispatch.has(identifier))
116
+ return dispatch.get(identifier);
117
+ throw new Error(`no executor found for identifier ${numberToHex(identifier, 2)}`);
118
+ }
119
+ function buildTraceObject(context) {
120
+ let gasCost = null;
121
+ if ([0xf0, 0xf5].includes(traceHelper.instruction))
122
+ gasCost = traceHelper.gas - Number(context.gas) - Number(context.L);
123
+ else
124
+ gasCost = traceHelper.gas - Number(context.gas);
125
+ const traceObject = {
126
+ pc: traceHelper.pc,
127
+ op: traceHelper.op,
128
+ gas: traceHelper.gas,
129
+ gasCost,
130
+ depth: traceHelper.depth,
131
+ stack: traceHelper.stack
132
+ };
133
+ if (traceHelper.returnData !== null)
134
+ traceObject.returnData = traceHelper.returnData;
135
+ if (traceHelper.memoryWords !== null)
136
+ traceObject.memory = traceHelper.memoryWords;
137
+ if (traceHelper.op == "SLOAD" || traceHelper.op == "SSTORE")
138
+ traceObject.storage = traceHelper.storage;
139
+ if (context.refund != 0n)
140
+ traceObject.refund = Number(context.refund);
141
+ return traceObject;
142
+ }
143
+ const traceObjects = [];
144
+ function postExecute(context) {
145
+ if (debug === true)
146
+ traceObjects.push(buildTraceObject(context));
147
+ if (context.pc < context.code.byteLength)
148
+ return;
149
+ if (context.reverted !== null)
150
+ return;
151
+ // if program counter is past code and we haven't yet decided on reverted
152
+ // reverted is false
153
+ // this detects end of execution if no STOP, REVERT, RETURN, etc. was provided in code
154
+ context.reverted = false;
155
+ }
156
+ function initialize(context) {
157
+ if (context.address === null && context.to !== null)
158
+ context.address = context.to;
159
+ // for EoA deployments, address is null, but we'll need it in execution
160
+ if (context.address === null && context.to === null) {
161
+ context.address = deriveAddress(context);
162
+ context.code = context.calldata;
163
+ }
164
+ }
165
+ const SingleContextMachine = createMachine(continuePredicate, parseInstruction, preExecute, getExecutor, postExecute, initialize);
166
+ export { SingleContextMachine, traceObjects, traceHelper };
@@ -0,0 +1,8 @@
1
+ import type { Context } from "../../../types.js";
2
+ declare const _default: {
3
+ identifier: number;
4
+ executor(context: Context): void;
5
+ instructionToString(): string;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=ADD.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ADD.d.ts","sourceRoot":"","sources":["../../../../src/opsets/9db704/opcodes/ADD.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;;;sBAO5B,OAAO;;;AAJ5B,wBAeE"}
@@ -0,0 +1,13 @@
1
+ import { pop, F } from "../../../lib.js";
2
+ export default {
3
+ identifier: 0x01,
4
+ executor(context) {
5
+ const [a, b] = pop(context.stack, 2);
6
+ context.stack.push(F.add(a, b));
7
+ context.gas -= 3n;
8
+ context.pc++;
9
+ },
10
+ instructionToString() {
11
+ return "ADD";
12
+ }
13
+ };
@@ -0,0 +1,8 @@
1
+ import type { Context } from "../../../types.js";
2
+ declare const _default: {
3
+ identifier: number;
4
+ executor(context: Context): void;
5
+ instructionToString(): string;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=ADDRESS.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ADDRESS.d.ts","sourceRoot":"","sources":["../../../../src/opsets/9db704/opcodes/ADDRESS.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;;;sBAM5B,OAAO;;;AAJ5B,wBAcE"}
@@ -0,0 +1,11 @@
1
+ export default {
2
+ identifier: 0x30,
3
+ executor(context) {
4
+ context.stack.push(BigInt(context.address));
5
+ context.gas -= 2n;
6
+ context.pc++;
7
+ },
8
+ instructionToString() {
9
+ return "ADDRESS";
10
+ }
11
+ };
@@ -0,0 +1,8 @@
1
+ import type { Context } from "../../../types.js";
2
+ declare const _default: {
3
+ identifier: number;
4
+ executor(context: Context): void;
5
+ instructionToString(): string;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=AND.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AND.d.ts","sourceRoot":"","sources":["../../../../src/opsets/9db704/opcodes/AND.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;;;sBAO5B,OAAO;;;AAJ5B,wBAeE"}
@@ -0,0 +1,13 @@
1
+ import { pop } from "../../../lib.js";
2
+ export default {
3
+ identifier: 0x16,
4
+ executor(context) {
5
+ const [a, b] = pop(context.stack, 2);
6
+ context.stack.push(a & b);
7
+ context.gas -= 3n;
8
+ context.pc++;
9
+ },
10
+ instructionToString() {
11
+ return "AND";
12
+ }
13
+ };
@@ -0,0 +1,8 @@
1
+ import type { Context } from "../../../types.js";
2
+ declare const _default: {
3
+ identifier: number;
4
+ executor(context: Context): void;
5
+ instructionToString(): string;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=BYTE.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BYTE.d.ts","sourceRoot":"","sources":["../../../../src/opsets/9db704/opcodes/BYTE.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;;;sBAO5B,OAAO;;;AAJ5B,wBAeE"}
@@ -0,0 +1,13 @@
1
+ import { pop } from "../../../lib.js";
2
+ export default {
3
+ identifier: 0x1a,
4
+ executor(context) {
5
+ const [i, x] = pop(context.stack, 2);
6
+ context.stack.push(x >> (0x1fn - i << 3n) & 0xffn);
7
+ context.gas -= 3n;
8
+ context.pc++;
9
+ },
10
+ instructionToString() {
11
+ return "BYTE";
12
+ }
13
+ };
@@ -0,0 +1,8 @@
1
+ import type { Context } from "../../../types.js";
2
+ declare const _default: {
3
+ identifier: number;
4
+ executor(context: Context): void;
5
+ instructionToString(): string;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=CALLDATACOPY.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CALLDATACOPY.d.ts","sourceRoot":"","sources":["../../../../src/opsets/9db704/opcodes/CALLDATACOPY.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;;;sBAO5B,OAAO;;;AAJ5B,wBAgBE"}
@@ -0,0 +1,14 @@
1
+ import { pop, copy, memoryExpand } from "../../../lib.js";
2
+ export default {
3
+ identifier: 0x37,
4
+ executor(context) {
5
+ const [destOffset, offset, size] = pop(context.stack, 3);
6
+ context.gas -= 3n + 3n * (size + 0x1fn >> 5n);
7
+ memoryExpand(context, Number(destOffset) + Number(size));
8
+ copy(context.memory, context.calldata, Number(destOffset), Number(offset), Number(size), true);
9
+ context.pc++;
10
+ },
11
+ instructionToString() {
12
+ return "CALLDATACOPY";
13
+ }
14
+ };
@@ -0,0 +1,8 @@
1
+ import type { Context } from "../../../types.js";
2
+ declare const _default: {
3
+ identifier: number;
4
+ executor(context: Context): void;
5
+ instructionToString(): string;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=CALLDATALOAD.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CALLDATALOAD.d.ts","sourceRoot":"","sources":["../../../../src/opsets/9db704/opcodes/CALLDATALOAD.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;;;sBAO5B,OAAO;;;AAJ5B,wBAmBE"}
@@ -0,0 +1,17 @@
1
+ import { byteSliceToBigInt_be, pop } from "../../../lib.js";
2
+ export default {
3
+ identifier: 0x35,
4
+ executor(context) {
5
+ const [i] = pop(context.stack, 1);
6
+ context.gas -= 3n;
7
+ if (context.calldata === null) {
8
+ context.stack.push(0n);
9
+ return;
10
+ }
11
+ context.stack.push(byteSliceToBigInt_be(new Uint8Array(context.calldata), Number(i), 0x20, true));
12
+ context.pc++;
13
+ },
14
+ instructionToString() {
15
+ return "CALLDATALOAD";
16
+ }
17
+ };
@@ -0,0 +1,8 @@
1
+ import type { Context } from "../../../types.js";
2
+ declare const _default: {
3
+ identifier: number;
4
+ executor(context: Context): void;
5
+ instructionToString(): string;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=CALLDATASIZE.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CALLDATASIZE.d.ts","sourceRoot":"","sources":["../../../../src/opsets/9db704/opcodes/CALLDATASIZE.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;;;sBAM5B,OAAO;;;AAJ5B,wBAcE"}