viem-tx-sim 0.1.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 (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +228 -0
  3. package/contracts/TxSimulator.sol +305 -0
  4. package/dist/constants.d.ts +15 -0
  5. package/dist/constants.d.ts.map +1 -0
  6. package/dist/constants.js +15 -0
  7. package/dist/constants.js.map +1 -0
  8. package/dist/errors.d.ts +35 -0
  9. package/dist/errors.d.ts.map +1 -0
  10. package/dist/errors.js +39 -0
  11. package/dist/errors.js.map +1 -0
  12. package/dist/generated/txSimulatorBytecode.d.ts +2 -0
  13. package/dist/generated/txSimulatorBytecode.d.ts.map +1 -0
  14. package/dist/generated/txSimulatorBytecode.js +3 -0
  15. package/dist/generated/txSimulatorBytecode.js.map +1 -0
  16. package/dist/index.d.ts +5 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +4 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/internal/data.d.ts +8 -0
  21. package/dist/internal/data.d.ts.map +1 -0
  22. package/dist/internal/data.js +31 -0
  23. package/dist/internal/data.js.map +1 -0
  24. package/dist/internal/probes.d.ts +29 -0
  25. package/dist/internal/probes.d.ts.map +1 -0
  26. package/dist/internal/probes.js +159 -0
  27. package/dist/internal/probes.js.map +1 -0
  28. package/dist/internal/requirements.d.ts +5 -0
  29. package/dist/internal/requirements.d.ts.map +1 -0
  30. package/dist/internal/requirements.js +173 -0
  31. package/dist/internal/requirements.js.map +1 -0
  32. package/dist/internal/rpc.d.ts +36 -0
  33. package/dist/internal/rpc.d.ts.map +1 -0
  34. package/dist/internal/rpc.js +124 -0
  35. package/dist/internal/rpc.js.map +1 -0
  36. package/dist/internal/simulator.d.ts +33 -0
  37. package/dist/internal/simulator.d.ts.map +1 -0
  38. package/dist/internal/simulator.js +199 -0
  39. package/dist/internal/simulator.js.map +1 -0
  40. package/dist/internal/slots.d.ts +7 -0
  41. package/dist/internal/slots.d.ts.map +1 -0
  42. package/dist/internal/slots.js +129 -0
  43. package/dist/internal/slots.js.map +1 -0
  44. package/dist/txSimulator.d.ts +83 -0
  45. package/dist/txSimulator.d.ts.map +1 -0
  46. package/dist/txSimulator.js +75 -0
  47. package/dist/txSimulator.js.map +1 -0
  48. package/dist/types.d.ts +214 -0
  49. package/dist/types.d.ts.map +1 -0
  50. package/dist/types.js +2 -0
  51. package/dist/types.js.map +1 -0
  52. package/package.json +82 -0
  53. package/src/constants.ts +15 -0
  54. package/src/errors.ts +45 -0
  55. package/src/generated/txSimulatorBytecode.ts +5 -0
  56. package/src/index.ts +34 -0
  57. package/src/internal/data.ts +36 -0
  58. package/src/internal/probes.ts +221 -0
  59. package/src/internal/requirements.ts +240 -0
  60. package/src/internal/rpc.ts +207 -0
  61. package/src/internal/simulator.ts +306 -0
  62. package/src/internal/slots.ts +211 -0
  63. package/src/txSimulator.ts +176 -0
  64. package/src/types.ts +240 -0
@@ -0,0 +1,75 @@
1
+ import { DEFAULT_SIMULATION_GAS_LIMIT } from "./constants.js";
2
+ import { InvalidSimulationInputError } from "./errors.js";
3
+ import { estimateAssetRequirements } from "./internal/requirements.js";
4
+ import { blockOptionsSpread } from "./internal/rpc.js";
5
+ import { discoverCandidateAddresses, runSimulator } from "./internal/simulator.js";
6
+ import { prepareAllowanceOverrides, prepareBalanceOverrides } from "./internal/slots.js";
7
+ /** Factory for {@link TxSimulator} instances bound to one viem public client. */
8
+ export const TxSimulator = {
9
+ /**
10
+ * Creates a simulator with optional default gas and debug settings.
11
+ *
12
+ * `gas` defaults to `DEFAULT_SIMULATION_GAS_LIMIT`; `debug` may be `true` for console logging or a
13
+ * callback for structured events. Per-call `gas` and `debug` take precedence over these defaults.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const sim = TxSimulator.create({ client, debug: true });
18
+ * const result = await sim.simulate({ from, calls });
19
+ * ```
20
+ */
21
+ create(bound) {
22
+ const defaults = (args) => {
23
+ const gas = args.gas ?? bound.gas ?? DEFAULT_SIMULATION_GAS_LIMIT;
24
+ const debug = args.debug ?? bound.debug;
25
+ return {
26
+ gas,
27
+ ...(debug !== undefined ? { debug } : {}),
28
+ };
29
+ };
30
+ const revertDefaults = (args) => {
31
+ const errorAbi = [...(bound.errorAbi ?? []), ...(args.errorAbi ?? [])];
32
+ return {
33
+ ...defaults(args),
34
+ ...(errorAbi.length > 0 ? { errorAbi } : {}),
35
+ };
36
+ };
37
+ return {
38
+ simulate: (args) => runSimulate({ ...args, ...revertDefaults(args), client: bound.client }),
39
+ prepareBalanceOverrides: (args) => prepareBalanceOverrides({ ...args, ...defaults(args), client: bound.client }),
40
+ prepareAllowanceOverrides: (args) => prepareAllowanceOverrides({ ...args, ...defaults(args), client: bound.client }),
41
+ estimateAssetRequirements: (args) => estimateAssetRequirements({ ...args, ...revertDefaults(args), client: bound.client }),
42
+ };
43
+ },
44
+ };
45
+ async function runSimulate(args) {
46
+ if (args.calls.length === 0) {
47
+ throw new InvalidSimulationInputError("simulate requires at least one call.");
48
+ }
49
+ const calls = args.calls.map((call) => ({
50
+ to: call.to,
51
+ data: call.data,
52
+ value: call.value ?? 0n,
53
+ }));
54
+ const candidateAddresses = await discoverCandidateAddresses({
55
+ client: args.client,
56
+ from: args.from,
57
+ calls,
58
+ ...blockOptionsSpread(args),
59
+ gas: args.gas,
60
+ ...(args.debug !== undefined ? { debug: args.debug } : {}),
61
+ });
62
+ const tokenSlotOverrides = args.tokenSlotOverrides ?? [];
63
+ return runSimulator({
64
+ client: args.client,
65
+ from: args.from,
66
+ calls,
67
+ candidates: [...candidateAddresses, ...tokenSlotOverrides.map((slot) => slot.token)],
68
+ tokenSlotOverrides,
69
+ debug: args.debug,
70
+ ...blockOptionsSpread(args),
71
+ gas: args.gas,
72
+ ...(args.errorAbi !== undefined ? { errorAbi: args.errorAbi } : {}),
73
+ });
74
+ }
75
+ //# sourceMappingURL=txSimulator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"txSimulator.js","sourceRoot":"","sources":["../src/txSimulator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,214 @@
1
+ import type { Abi, Address, BlockTag, Hex, PublicClient } from "viem";
2
+ /** One transaction-like call to execute during a simulation batch. */
3
+ export type SimulatedCall = {
4
+ /** Target contract or recipient address. */
5
+ to: Address;
6
+ /** ABI-encoded calldata. Use `"0x"` for a plain native transfer. */
7
+ data: Hex;
8
+ /** Native value to send with this call; omitted means zero. */
9
+ value?: bigint;
10
+ };
11
+ /** Structured event emitted before and after each RPC call when debug logging is enabled. */
12
+ export type SimulationDebugEvent = {
13
+ /** Lifecycle phase for the RPC operation. */
14
+ phase: "start" | "success" | "error";
15
+ /** RPC method being issued. */
16
+ method: "eth_call" | "eth_createAccessList";
17
+ /** Stable step name used by tests and consumers to count RPCs. */
18
+ step: string;
19
+ /** Step-specific metadata, intentionally small and non-sensitive. */
20
+ details?: Record<string, unknown>;
21
+ /** Elapsed RPC time in milliseconds, present on success/error phases. */
22
+ durationMs?: number;
23
+ /** Human-readable error summary, present on error phases. */
24
+ error?: string;
25
+ };
26
+ /** Callback form for receiving structured simulation debug events. */
27
+ export type SimulationDebugLogger = (event: SimulationDebugEvent) => void;
28
+ /** Debug option: `true` logs to the console, a callback receives structured events. */
29
+ export type SimulationDebug = boolean | SimulationDebugLogger;
30
+ /** Shared per-call options for block selection, gas budget, and debug events. */
31
+ type SimulationOptions = {
32
+ /** Historical block number to simulate against; if both block options are set, this wins. */
33
+ blockNumber?: bigint;
34
+ /** Block tag to simulate against when `blockNumber` is not set. */
35
+ blockTag?: BlockTag;
36
+ /** Gas budget for simulation RPC calls. Defaults to `DEFAULT_SIMULATION_GAS_LIMIT`. */
37
+ gas?: bigint;
38
+ /** Enables console logging or structured debug events for simulator RPC calls. */
39
+ debug?: SimulationDebug;
40
+ };
41
+ /**
42
+ * Storage-slot override: the unit that flows from preparation methods into
43
+ * `simulate({ tokenSlotOverrides })`.
44
+ */
45
+ export type TokenSlotOverride = {
46
+ /** Token contract whose storage should be overridden. */
47
+ token: Address;
48
+ /** Storage slot to write. Usually prepared by `prepareBalanceOverrides` or `prepareAllowanceOverrides`. */
49
+ slot: Hex;
50
+ /** Value written to the slot. Must be below uint256 max. */
51
+ amount: bigint;
52
+ };
53
+ /** Verified ERC-20 allowance mapping slot for one token, owner, and spender. */
54
+ export type AllowanceSlot = TokenSlotOverride & {
55
+ spender: Address;
56
+ };
57
+ /** Token/spender pair whose allowance override should be prepared or reported unresolved. */
58
+ export type AllowanceSlotPair = {
59
+ token: Address;
60
+ spender: Address;
61
+ };
62
+ /** Prepared balance storage overrides. */
63
+ export type PreparedBalanceOverrides = {
64
+ /** Verified slots that can be passed to `simulate` as `tokenSlotOverrides`. */
65
+ slots: TokenSlotOverride[];
66
+ /**
67
+ * Tokens the simulator could not `deal` in the Foundry sense: no storage slot could be
68
+ * sentinel-verified for writing hypothetical balances. Deltas for real holdings still come from
69
+ * `balanceOf`, including rebasing tokens.
70
+ */
71
+ unresolved: Address[];
72
+ };
73
+ /** Prepared allowance storage overrides. */
74
+ export type PreparedAllowanceOverrides = {
75
+ /** Verified slots that can be passed to `simulate` as `tokenSlotOverrides`. */
76
+ slots: AllowanceSlot[];
77
+ /** Pairs the simulator could not `deal` as allowances because no slot was sentinel-verified. */
78
+ unresolved: AllowanceSlotPair[];
79
+ };
80
+ /** ABI-decoded revert error, present when revertData matches supplied error definitions or a built-in Error/Panic. */
81
+ export type RevertError = {
82
+ name: string;
83
+ args: readonly unknown[];
84
+ };
85
+ /** Arguments for `TxSimulator.simulate`. */
86
+ export type SimulateArgs = SimulationOptions & {
87
+ /** Account being simulated; the ghost simulator bytecode is injected at this address. */
88
+ from: Address;
89
+ /** One call or an ERC-5792-style sequential batch. Must contain at least one call. */
90
+ calls: readonly SimulatedCall[];
91
+ /** Storage-slot overrides applied before simulating. Usually from override preparation. */
92
+ tokenSlotOverrides?: readonly TokenSlotOverride[];
93
+ /** Additional error definitions for decoding this call's reverts; merged after the bound errorAbi. */
94
+ errorAbi?: Abi;
95
+ };
96
+ /** Arguments for `TxSimulator.prepareBalanceOverrides`. */
97
+ export type PrepareBalanceOverridesArgs = SimulationOptions & {
98
+ /** Account whose token balance overrides should be prepared. */
99
+ from: Address;
100
+ /** Tokens to prepare ERC-20-style balance overrides for. */
101
+ tokens: readonly Address[];
102
+ };
103
+ /** Arguments for `TxSimulator.prepareAllowanceOverrides`. */
104
+ export type PrepareAllowanceOverridesArgs = SimulationOptions & {
105
+ /** Account whose allowance overrides should be prepared. */
106
+ from: Address;
107
+ /** Token/spender allowance pairs to prepare overrides for. */
108
+ pairs: readonly AllowanceSlotPair[];
109
+ };
110
+ /** Arguments for `TxSimulator.estimateAssetRequirements`. */
111
+ export type EstimateAssetRequirementsArgs = SimulationOptions & {
112
+ /** Account whose balance and approval needs should be estimated. */
113
+ from: Address;
114
+ /** One call or an ERC-5792-style sequential batch. Must contain at least one call. */
115
+ calls: readonly SimulatedCall[];
116
+ /** Additional error definitions for decoding this call's reverts; merged after the bound errorAbi. */
117
+ errorAbi?: Abi;
118
+ };
119
+ /** Configuration for `TxSimulator.create`. */
120
+ export type TxSimulatorConfig = {
121
+ client: PublicClient;
122
+ /** Default gas budget for all calls; per-call `gas` wins. */
123
+ gas?: bigint;
124
+ /** Default debug setting for all calls; per-call `debug` wins. */
125
+ debug?: SimulationDebug;
126
+ /** Error definitions used to decode custom-error reverts; merged with per-call errorAbi. */
127
+ errorAbi?: Abi;
128
+ };
129
+ /** Estimated minimum token balance needed under forged state. */
130
+ export type RequiredBalance = {
131
+ token: Address;
132
+ amount: bigint;
133
+ };
134
+ /** Estimated minimum total allowance needed under forged state. */
135
+ export type RequiredAllowance = {
136
+ token: Address;
137
+ spender: Address;
138
+ amount: bigint;
139
+ };
140
+ type EstimatedAssetRequirementsBase = {
141
+ /** Maximum cumulative native outflow across call boundaries. */
142
+ native: bigint;
143
+ /** Minimum token balances needed to execute the observed path. */
144
+ balances: RequiredBalance[];
145
+ /** Minimum allowances needed before the batch, excluding allowances set inside the batch. */
146
+ allowances: RequiredAllowance[];
147
+ /** Verified slots prepared along the way; pass to `simulate` as `tokenSlotOverrides`. */
148
+ slots: TokenSlotOverride[];
149
+ /** Values the estimator could not verify or could not trust. */
150
+ unresolved: {
151
+ /**
152
+ * Tokens the estimator could not `deal` in the Foundry sense: no balance slot could be
153
+ * sentinel-verified for writing hypothetical balances. Real-holding deltas are unaffected.
154
+ */
155
+ balanceSlots: Address[];
156
+ /** Token/spender pairs the estimator could not `deal` as allowances. */
157
+ allowanceSlots: AllowanceSlotPair[];
158
+ /** Token/spender pairs measured but discarded as unreliable, usually because they exceeded gross outflow. */
159
+ allowances: AllowanceSlotPair[];
160
+ };
161
+ };
162
+ /** Successful asset-requirement estimate. */
163
+ export type EstimatedAssetRequirementsSuccess = EstimatedAssetRequirementsBase & {
164
+ status: "success";
165
+ };
166
+ /** Asset-requirement estimate that still observed a transaction revert after forging available state. */
167
+ export type EstimatedAssetRequirementsReverted = EstimatedAssetRequirementsBase & {
168
+ status: "reverted";
169
+ /** Raw EVM revert data from the failing simulated call. */
170
+ revertData: Hex;
171
+ /** Human-readable decoded revert; present when revertData decodes via supplied error definitions or as built-in Error/Panic. */
172
+ revertReason?: string;
173
+ /** Decoded error when revertData matches supplied error definitions or built-in Error/Panic. */
174
+ revertError?: RevertError;
175
+ /** First 4 bytes of revertData; present whenever revertData carries a selector. */
176
+ revertSelector?: Hex;
177
+ /** Zero-based index of the call that reverted. */
178
+ failingCallIndex: number;
179
+ };
180
+ /** Asset-requirement estimate result; check `status` before reading revert fields. */
181
+ export type EstimatedAssetRequirements = EstimatedAssetRequirementsSuccess | EstimatedAssetRequirementsReverted;
182
+ /** Raw balance delta for native ETH or an ERC-20-style `balanceOf(address)` asset. */
183
+ export type AssetBalanceDelta = {
184
+ /** `"native"` for ETH, otherwise the token contract address. */
185
+ asset: "native" | Address;
186
+ /** Signed raw-unit balance change for `from`; negative means the account lost assets. */
187
+ delta: bigint;
188
+ };
189
+ /** Successful simulation result. */
190
+ export type SimulationSuccess = {
191
+ status: "success";
192
+ /** Non-zero raw balance deltas observed during the simulated execution. */
193
+ assetBalanceDeltas: AssetBalanceDelta[];
194
+ };
195
+ /** Simulation result for a transaction revert; infrastructure failures throw typed errors instead. */
196
+ export type SimulationReverted = {
197
+ status: "reverted";
198
+ /** Non-zero raw balance deltas observed before the failing call. */
199
+ assetBalanceDeltas: AssetBalanceDelta[];
200
+ /** Raw EVM revert data from the failing simulated call. */
201
+ revertData: Hex;
202
+ /** Human-readable decoded revert; present when revertData decodes via supplied error definitions or as built-in Error/Panic. */
203
+ revertReason?: string;
204
+ /** Decoded error when revertData matches supplied error definitions or built-in Error/Panic. */
205
+ revertError?: RevertError;
206
+ /** First 4 bytes of revertData; present whenever revertData carries a selector. */
207
+ revertSelector?: Hex;
208
+ /** Zero-based index of the call that reverted. */
209
+ failingCallIndex: number;
210
+ };
211
+ /** Simulation result; transaction reverts are data, while RPC/infrastructure failures throw. */
212
+ export type SimulationResult = SimulationSuccess | SimulationReverted;
213
+ export {};
214
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "viem-tx-sim",
3
+ "version": "0.1.0",
4
+ "description": "RPC-only transaction simulation helpers for viem applications.",
5
+ "keywords": [
6
+ "eth_call",
7
+ "ethereum",
8
+ "simulation",
9
+ "state-override",
10
+ "transaction-preview",
11
+ "viem",
12
+ "wallet"
13
+ ],
14
+ "homepage": "https://github.com/frontier159/viem-tx-sim#readme",
15
+ "bugs": {
16
+ "url": "https://github.com/frontier159/viem-tx-sim/issues"
17
+ },
18
+ "license": "MIT",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/frontier159/viem-tx-sim.git"
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "src",
26
+ "contracts/TxSimulator.sol"
27
+ ],
28
+ "type": "module",
29
+ "sideEffects": false,
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "default": "./dist/index.js"
36
+ }
37
+ },
38
+ "scripts": {
39
+ "build": "pnpm build:contracts && pnpm build:ts",
40
+ "build:contracts": "forge build && node scripts/generate-txsim-bytecode.mjs",
41
+ "build:ts": "tsc -p tsconfig.build.json",
42
+ "changeset": "changeset",
43
+ "fmt": "oxfmt package.json .oxlintrc.json .oxfmtrc.json tsconfig.json tsconfig.build.json vitest.config.ts src test scripts",
44
+ "fmt:check": "oxfmt --check package.json .oxlintrc.json .oxfmtrc.json tsconfig.json tsconfig.build.json vitest.config.ts src test scripts",
45
+ "lint": "oxlint && oxfmt --check package.json .oxlintrc.json .oxfmtrc.json tsconfig.json tsconfig.build.json vitest.config.ts src test scripts",
46
+ "lint:fix": "oxlint --fix && oxfmt package.json .oxlintrc.json .oxfmtrc.json tsconfig.json tsconfig.build.json vitest.config.ts src test scripts",
47
+ "prepare": "pnpm build:ts",
48
+ "prepublishOnly": "pnpm build:ts",
49
+ "release": "pnpm verify && pnpm changeset publish",
50
+ "test": "pnpm build:contracts && vitest run",
51
+ "test:debug": "VIEM_TX_SIM_DEBUG_RPC=1 pnpm test",
52
+ "test:mainnet": "pnpm build:contracts && vitest run test/mainnet.test.ts",
53
+ "typecheck": "tsc -p tsconfig.json --noEmit",
54
+ "verify": "pnpm lint && pnpm typecheck && pnpm build && pnpm test"
55
+ },
56
+ "devDependencies": {
57
+ "@arethetypeswrong/cli": "^0.18.4",
58
+ "@changesets/changelog-github": "^0.7.0",
59
+ "@changesets/cli": "^2.31.0",
60
+ "@types/node": "^20.19.0",
61
+ "oxfmt": "^0.57.0",
62
+ "oxlint": "^1.72.0",
63
+ "typescript": "^5.5.4",
64
+ "viem": "^2.54.1",
65
+ "vitest": "^2.1.9"
66
+ },
67
+ "peerDependencies": {
68
+ "viem": "2.x"
69
+ },
70
+ "engines": {
71
+ "node": ">=20"
72
+ },
73
+ "packageManager": "pnpm@10.18.3",
74
+ "pnpm": {
75
+ "onlyBuiltDependencies": [
76
+ "esbuild"
77
+ ],
78
+ "overrides": {
79
+ "ws": ">=8.21.0"
80
+ }
81
+ }
82
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Default gas budget for simulator `eth_call` executions.
3
+ *
4
+ * The injected simulator changes gas accounting, so this is intentionally a generous execution
5
+ * budget rather than a gas estimate for the real transaction.
6
+ */
7
+ export const DEFAULT_SIMULATION_GAS_LIMIT = 16_000_000n;
8
+
9
+ /**
10
+ * Default forged token balance or allowance written by slot overrides.
11
+ *
12
+ * This is deliberately below `uint256.max`: standard ERC-20 implementations skip allowance
13
+ * decrements at exactly max allowance, which would hide required approvals during measurement.
14
+ */
15
+ export const OVERRIDE_TOKEN_AMOUNT = 10n ** 50n;
package/src/errors.ts ADDED
@@ -0,0 +1,45 @@
1
+ /** Base class for typed infrastructure and input errors thrown by viem-tx-sim. */
2
+ export class TxSimError extends Error {
3
+ override readonly name: string = "TxSimError";
4
+ }
5
+
6
+ /**
7
+ * Thrown when the RPC endpoint cannot run `eth_createAccessList` for a non-transaction-revert reason.
8
+ *
9
+ * Transaction execution reverts during access-list creation are normalized to an empty access list;
10
+ * this error means provider capability or infrastructure failure. Try another RPC endpoint that
11
+ * supports EIP-2930 access lists for historical/state-overridden calls.
12
+ */
13
+ export class AccessListUnsupportedError extends TxSimError {
14
+ override readonly name = "AccessListUnsupportedError";
15
+
16
+ constructor(message = "RPC endpoint does not support eth_createAccessList for this simulation.") {
17
+ super(message);
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Thrown when the RPC endpoint cannot execute `eth_call` with state overrides or returns bad output.
23
+ *
24
+ * This is usually a provider capability issue, including unsupported state overrides or simulator
25
+ * output that cannot be decoded. Retrying the same request generally will not help unless the RPC
26
+ * failure was transient; use a provider with state-override support.
27
+ */
28
+ export class StateOverrideUnsupportedError extends TxSimError {
29
+ override readonly name = "StateOverrideUnsupportedError";
30
+
31
+ constructor(
32
+ message = "RPC endpoint does not support eth_call state overrides for this simulation.",
33
+ ) {
34
+ super(message);
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Thrown for caller-side input bugs, such as an empty call batch.
40
+ *
41
+ * This is not an RPC/provider issue and should be fixed before retrying.
42
+ */
43
+ export class InvalidSimulationInputError extends TxSimError {
44
+ override readonly name = "InvalidSimulationInputError";
45
+ }
@@ -0,0 +1,5 @@
1
+ import type { Hex } from "viem";
2
+
3
+ // Generated by scripts/generate-txsim-bytecode.mjs.
4
+ export const txSimulatorRuntimeBytecode =
5
+ "0x60806040526004361061004c575f3560e01c8063150b7a02146100575780631626ba7e146100a0578063bc197c81146100bf578063cb8935e9146100ed578063f23a6e6114610119575f80fd5b3661005357005b5f80fd5b348015610062575f80fd5b506100826100713660046110ac565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020015b60405180910390f35b3480156100ab575f80fd5b506100826100ba366004611115565b610145565b3480156100ca575f80fd5b506100826100d936600461119c565b63bc197c8160e01b98975050505050505050565b3480156100f8575f80fd5b5061010c61010736600461124e565b610181565b60405161009791906113cb565b348015610124575f80fd5b506100826101333660046114b9565b63f23a6e6160e01b9695505050505050565b5f30610152858585610300565b6001600160a01b03161461016e576001600160e01b0319610177565b630b135d3f60e11b5b90505b9392505050565b6101d56040518061014001604052805f151581526020015f8152602001606081526020015f8152602001606081526020016060815260200160608152602001606081526020015f8152602001606081525090565b475f6101e18787610456565b90506101ee88600161153f565b6101f89085611552565b6001600160401b0381111561020f5761020f611569565b604051908082528060200260200182016040528015610238578160200160208202803683370190505b50610120840190815260408051608081018252838201518152602080850151908201529151908201525f90606081016102728b600161153f565b905290505f6102878b8b8b8b8b8b888b6106d5565b60408901919091526020880191909152901515865290506102a847856107cd565b8560600181815250506102c383606001518460800151610844565b6080860152808410156102d6575f6102e0565b6102e0818561157d565b6101008601526102f2898985886108e0565b505050509695505050505050565b5f60418290036103bb578235602084013560408501355f1a601b81101561032f5761032c601b82611590565b90505b8060ff16601b1415801561034757508060ff16601c14155b15610357575f935050505061017a565b604080515f81526020810180835289905260ff831691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa1580156103a7573d5f803e3d5ffd5b50505060206040510351935050505061017a565b604082900361044d57823560208401356001600160ff1b0381165f6103e560ff84901c601b61153f565b604080515f8152602081018083528b905260ff831691810191909152606081018690526080810184905290915060019060a0016020604051602081039080840390855afa158015610438573d5f803e3d5ffd5b5050506020604051035194505050505061017a565b505f9392505050565b6104876040518060a00160405280606081526020016060815260200160608152602001606081526020015f81525090565b816001600160401b0381111561049f5761049f611569565b6040519080825280602002602001820160405280156104c8578160200160208202803683370190505b508152816001600160401b038111156104e3576104e3611569565b60405190808252806020026020018201604052801561050c578160200160208202803683370190505b506020820152816001600160401b0381111561052a5761052a611569565b604051908082528060200260200182016040528015610553578160200160208202803683370190505b506040820152816001600160401b0381111561057157610571611569565b60405190808252806020026020018201604052801561059a578160200160208202803683370190505b5060608201525f5b828110156106ce575f806105dc8686858181106105c1576105c16115a9565b90506020020160208101906105d691906115bd565b30610b97565b9150915081156106c4576001846040015184815181106105fe576105fe6115a9565b60200260200101901515908115158152505080845f01518481518110610626576106266115a9565b6020026020010181815250508084602001518481518110610649576106496115a9565b602002602001018181525050858584818110610667576106676115a9565b905060200201602081019061067c91906115bd565b606085015160808601805190610691826115d6565b9052815181106106a3576106a36115a9565b60200260200101906001600160a01b031690816001600160a01b0316815250505b50506001016105a2565b5092915050565b60015f1960608386156106f7576106f7888888606001515f8a60400151610c6f565b5f5b8b8110156107bd575f8061072f8f8f85818110610718576107186115a9565b905060200281019061072a91906115ee565b610d2a565b9150915081610768575f96509194509092508390838915610761576107618b8b90508a60600151858c60400151610dac565b50506107bd565b4784811015610775578094505b6107888e8e8c5f01518d60200151610e4b565b8a156107af576107af8c8c8c606001518760016107a5919061153f565b8e60400151610c6f565b5050508060010190506106f9565b5098509850985098945050505050565b5f818310610808575f6107e0838561157d565b90506001600160ff1b03811115610801576001600160ff1b0391505061083e565b905061083e565b5f610813848461157d565b90506001600160ff1b0381111561083157600160ff1b91505061083e565b61083a8161160c565b9150505b92915050565b6060816001600160401b0381111561085e5761085e611569565b604051908082528060200260200182016040528015610887578160200160208202803683370190505b5090505f5b828110156106ce578381815181106108a6576108a66115a9565b60200260200101518282815181106108c0576108c06115a9565b6001600160a01b039092166020928302919091019091015260010161088c565b826001600160401b038111156108f8576108f8611569565b604051908082528060200260200182016040528015610921578160200160208202803683370190505b5060e08201525f836001600160401b0381111561094057610940611569565b604051908082528060200260200182016040528015610969578160200160208202803683370190505b5090505f846001600160401b0381111561098557610985611569565b6040519080825280602002602001820160405280156109ae578160200160208202803683370190505b5090505f805b86811015610b6c57856040015181815181106109d2576109d26115a9565b602002602001015115610b6457856020015181815181106109f5576109f56115a9565b6020026020010151865f01518281518110610a1257610a126115a9565b602002602001015110610a875785602001518181518110610a3557610a356115a9565b6020026020010151865f01518281518110610a5257610a526115a9565b6020026020010151610a64919061157d565b8560e001518281518110610a7a57610a7a6115a9565b6020026020010181815250505b5f80610a9e8a8a858181106105c1576105c16115a9565b9150915081610aae575050610b64565b5f610ad5828a5f01518681518110610ac857610ac86115a9565b60200260200101516107cd565b90508015610b60578a8a85818110610aef57610aef6115a9565b9050602002016020810190610b0491906115bd565b878681518110610b1657610b166115a9565b60200260200101906001600160a01b031690816001600160a01b03168152505080868681518110610b4957610b496115a9565b6020908102919091010152610b5d856115d6565b94505b5050505b6001016109b4565b50610b778382610844565b60a0850152610b868282610ee4565b8460c0018190525050505050505050565b604080516001600160a01b0383811660248084019190915283518084039091018152604490920183526020820180516001600160e01b03166370a0823160e01b17905291515f92839283928392881691610bf091611626565b5f60405180830381855afa9150503d805f8114610c28576040519150601f19603f3d011682016040523d82523d5f602084013e610c2d565b606091505b5091509150811580610c40575060208151105b15610c4c575050610c68565b81935080806020019051810190610c639190611637565b925050505b9250929050565b5f5b84811015610d22575f80610cd6888885818110610c9057610c906115a9565b610ca692602060409092020190810191506115bd565b308a8a87818110610cb957610cb96115a9565b9050604002016020016020810190610cd191906115bd565b610f73565b9150915081610ce5575f610ce7565b805b8486610cf38987611552565b610cfd919061153f565b81518110610d0d57610d0d6115a9565b60209081029190910101525050600101610c71565b505050505050565b5f6060610d3a60208401846115bd565b6001600160a01b03166020840135610d55604086018661164e565b604051610d63929190611690565b5f6040518083038185875af1925050503d805f8114610d9d576040519150601f19603f3d011682016040523d82523d5f602084013e610da2565b606091505b5091509150915091565b5f5b84811015610e44575f8284610dc38785611552565b610dcd919061153f565b81518110610ddd57610ddd6115a9565b602002602001015190505f846001610df5919061153f565b90505b85811015610e3a57818482610e0d8987611552565b610e17919061153f565b81518110610e2757610e276115a9565b6020908102919091010152600101610df8565b5050600101610dae565b5050505050565b5f5b83811015610e4457828181518110610e6757610e676115a9565b602002602001015115610edc575f80610e8b8787858181106105c1576105c16115a9565b91509150818015610eb45750838381518110610ea957610ea96115a9565b602002602001015181105b15610ed95780848481518110610ecc57610ecc6115a9565b6020026020010181815250505b50505b600101610e4d565b6060816001600160401b03811115610efe57610efe611569565b604051908082528060200260200182016040528015610f27578160200160208202803683370190505b5090505f5b828110156106ce57838181518110610f4657610f466115a9565b6020026020010151828281518110610f6057610f606115a9565b6020908102919091010152600101610f2c565b604080516001600160a01b03848116602483015283811660448084019190915283518084039091018152606490920183526020820180516001600160e01b0316636eb1769f60e11b17905291515f92839283928392891691610fd491611626565b5f60405180830381855afa9150503d805f811461100c576040519150601f19603f3d011682016040523d82523d5f602084013e611011565b606091505b5091509150811580611024575060208151105b1561103057505061104c565b819350808060200190518101906110479190611637565b925050505b935093915050565b80356001600160a01b038116811461106a575f80fd5b919050565b5f8083601f84011261107f575f80fd5b5081356001600160401b03811115611095575f80fd5b602083019150836020828501011115610c68575f80fd5b5f805f805f608086880312156110c0575f80fd5b6110c986611054565b94506110d760208701611054565b93506040860135925060608601356001600160401b038111156110f8575f80fd5b6111048882890161106f565b969995985093965092949392505050565b5f805f60408486031215611127575f80fd5b8335925060208401356001600160401b03811115611143575f80fd5b61114f8682870161106f565b9497909650939450505050565b5f8083601f84011261116c575f80fd5b5081356001600160401b03811115611182575f80fd5b6020830191508360208260051b8501011115610c68575f80fd5b5f805f805f805f8060a0898b0312156111b3575f80fd5b6111bc89611054565b97506111ca60208a01611054565b965060408901356001600160401b03808211156111e5575f80fd5b6111f18c838d0161115c565b909850965060608b0135915080821115611209575f80fd5b6112158c838d0161115c565b909650945060808b013591508082111561122d575f80fd5b5061123a8b828c0161106f565b999c989b5096995094979396929594505050565b5f805f805f8060608789031215611263575f80fd5b86356001600160401b0380821115611279575f80fd5b6112858a838b0161115c565b9098509650602089013591508082111561129d575f80fd5b6112a98a838b0161115c565b909650945060408901359150808211156112c1575f80fd5b818901915089601f8301126112d4575f80fd5b8135818111156112e2575f80fd5b8a60208260061b85010111156112f6575f80fd5b6020830194508093505050509295509295509295565b5f5b8381101561132657818101518382015260200161130e565b50505f910152565b5f815180845261134581602086016020860161130c565b601f01601f19169290920160200192915050565b5f815180845260208085019450602084015f5b838110156113915781516001600160a01b03168752958201959082019060010161136c565b509495945050505050565b5f815180845260208085019450602084015f5b83811015611391578151875295820195908201906001016113af565b602081526113de60208201835115159052565b602082015160408201525f604083015161014080606085015261140561016085018361132e565b9150606085015160808501526080850151601f19808685030160a087015261142d8483611359565b935060a08701519150808685030160c087015261144a8483611359565b935060c08701519150808685030160e0870152611467848361139c565b935060e08701519150610100818786030181880152611486858461139c565b908801516101208881019190915288015187820390920184880152935090506114af838261139c565b9695505050505050565b5f805f805f8060a087890312156114ce575f80fd5b6114d787611054565b95506114e560208801611054565b9450604087013593506060870135925060808701356001600160401b0381111561150d575f80fd5b61151989828a0161106f565b979a9699509497509295939492505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561083e5761083e61152b565b808202811582820484141761083e5761083e61152b565b634e487b7160e01b5f52604160045260245ffd5b8181038181111561083e5761083e61152b565b60ff818116838216019081111561083e5761083e61152b565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156115cd575f80fd5b61017a82611054565b5f600182016115e7576115e761152b565b5060010190565b5f8235605e19833603018112611602575f80fd5b9190910192915050565b5f600160ff1b82016116205761162061152b565b505f0390565b5f825161160281846020870161130c565b5f60208284031215611647575f80fd5b5051919050565b5f808335601e19843603018112611663575f80fd5b8301803591506001600160401b0382111561167c575f80fd5b602001915036819003821315610c68575f80fd5b818382375f910190815291905056fea2646970667358221220c9adb57984fec989769acf8df499b49fd3aadd781fd0b128ec026480393cb0a764736f6c63430008180033" as const satisfies Hex;
package/src/index.ts ADDED
@@ -0,0 +1,34 @@
1
+ export { DEFAULT_SIMULATION_GAS_LIMIT, OVERRIDE_TOKEN_AMOUNT } from "./constants.js";
2
+ export { TxSimulator } from "./txSimulator.js";
3
+ export {
4
+ AccessListUnsupportedError,
5
+ InvalidSimulationInputError,
6
+ StateOverrideUnsupportedError,
7
+ TxSimError,
8
+ } from "./errors.js";
9
+ export type {
10
+ AllowanceSlot,
11
+ PreparedAllowanceOverrides,
12
+ AllowanceSlotPair,
13
+ AssetBalanceDelta,
14
+ PreparedBalanceOverrides,
15
+ PrepareAllowanceOverridesArgs,
16
+ PrepareBalanceOverridesArgs,
17
+ EstimatedAssetRequirements,
18
+ EstimatedAssetRequirementsReverted,
19
+ EstimatedAssetRequirementsSuccess,
20
+ EstimateAssetRequirementsArgs,
21
+ SimulateArgs,
22
+ SimulatedCall,
23
+ SimulationDebug,
24
+ SimulationDebugEvent,
25
+ SimulationDebugLogger,
26
+ RequiredAllowance,
27
+ RequiredBalance,
28
+ RevertError,
29
+ SimulationReverted,
30
+ SimulationResult,
31
+ SimulationSuccess,
32
+ TokenSlotOverride,
33
+ TxSimulatorConfig,
34
+ } from "./types.js";
@@ -0,0 +1,36 @@
1
+ import type { Address, Hex } from "viem";
2
+ import { getAddress } from "viem";
3
+
4
+ export function normalizeAddress(address: Address): Address {
5
+ return getAddress(address);
6
+ }
7
+
8
+ export function addressKey(address: Address): string {
9
+ return address.toLowerCase();
10
+ }
11
+
12
+ export function uniqueAddresses(addresses: Iterable<Address>): Address[] {
13
+ const seen = new Map<string, Address>();
14
+ for (const address of addresses) {
15
+ const normalized = normalizeAddress(address);
16
+ seen.set(addressKey(normalized), normalized);
17
+ }
18
+ return [...seen.values()];
19
+ }
20
+
21
+ export const MAX_UINT256 = (1n << 256n) - 1n;
22
+
23
+ export function uint256Hex(value: bigint): Hex {
24
+ if (value < 0n || value > MAX_UINT256) {
25
+ throw new RangeError("Value cannot be encoded as uint256.");
26
+ }
27
+ return `0x${value.toString(16).padStart(64, "0")}` as Hex;
28
+ }
29
+
30
+ export function getCallData(result: unknown): Hex {
31
+ if (typeof result === "string") return result as Hex;
32
+ if (result && typeof result === "object" && "data" in result && typeof result.data === "string") {
33
+ return result.data as Hex;
34
+ }
35
+ return "0x";
36
+ }