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.
- package/LICENSE +21 -0
- package/README.md +228 -0
- package/contracts/TxSimulator.sol +305 -0
- package/dist/constants.d.ts +15 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +15 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors.d.ts +35 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +39 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated/txSimulatorBytecode.d.ts +2 -0
- package/dist/generated/txSimulatorBytecode.d.ts.map +1 -0
- package/dist/generated/txSimulatorBytecode.js +3 -0
- package/dist/generated/txSimulatorBytecode.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/data.d.ts +8 -0
- package/dist/internal/data.d.ts.map +1 -0
- package/dist/internal/data.js +31 -0
- package/dist/internal/data.js.map +1 -0
- package/dist/internal/probes.d.ts +29 -0
- package/dist/internal/probes.d.ts.map +1 -0
- package/dist/internal/probes.js +159 -0
- package/dist/internal/probes.js.map +1 -0
- package/dist/internal/requirements.d.ts +5 -0
- package/dist/internal/requirements.d.ts.map +1 -0
- package/dist/internal/requirements.js +173 -0
- package/dist/internal/requirements.js.map +1 -0
- package/dist/internal/rpc.d.ts +36 -0
- package/dist/internal/rpc.d.ts.map +1 -0
- package/dist/internal/rpc.js +124 -0
- package/dist/internal/rpc.js.map +1 -0
- package/dist/internal/simulator.d.ts +33 -0
- package/dist/internal/simulator.d.ts.map +1 -0
- package/dist/internal/simulator.js +199 -0
- package/dist/internal/simulator.js.map +1 -0
- package/dist/internal/slots.d.ts +7 -0
- package/dist/internal/slots.d.ts.map +1 -0
- package/dist/internal/slots.js +129 -0
- package/dist/internal/slots.js.map +1 -0
- package/dist/txSimulator.d.ts +83 -0
- package/dist/txSimulator.d.ts.map +1 -0
- package/dist/txSimulator.js +75 -0
- package/dist/txSimulator.js.map +1 -0
- package/dist/types.d.ts +214 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +82 -0
- package/src/constants.ts +15 -0
- package/src/errors.ts +45 -0
- package/src/generated/txSimulatorBytecode.ts +5 -0
- package/src/index.ts +34 -0
- package/src/internal/data.ts +36 -0
- package/src/internal/probes.ts +221 -0
- package/src/internal/requirements.ts +240 -0
- package/src/internal/rpc.ts +207 -0
- package/src/internal/simulator.ts +306 -0
- package/src/internal/slots.ts +211 -0
- package/src/txSimulator.ts +176 -0
- package/src/types.ts +240 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import type { Abi, Address, BlockTag, Hex, PublicClient } from "viem";
|
|
2
|
+
|
|
3
|
+
/** One transaction-like call to execute during a simulation batch. */
|
|
4
|
+
export type SimulatedCall = {
|
|
5
|
+
/** Target contract or recipient address. */
|
|
6
|
+
to: Address;
|
|
7
|
+
/** ABI-encoded calldata. Use `"0x"` for a plain native transfer. */
|
|
8
|
+
data: Hex;
|
|
9
|
+
/** Native value to send with this call; omitted means zero. */
|
|
10
|
+
value?: bigint;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/** Structured event emitted before and after each RPC call when debug logging is enabled. */
|
|
14
|
+
export type SimulationDebugEvent = {
|
|
15
|
+
/** Lifecycle phase for the RPC operation. */
|
|
16
|
+
phase: "start" | "success" | "error";
|
|
17
|
+
/** RPC method being issued. */
|
|
18
|
+
method: "eth_call" | "eth_createAccessList";
|
|
19
|
+
/** Stable step name used by tests and consumers to count RPCs. */
|
|
20
|
+
step: string;
|
|
21
|
+
/** Step-specific metadata, intentionally small and non-sensitive. */
|
|
22
|
+
details?: Record<string, unknown>;
|
|
23
|
+
/** Elapsed RPC time in milliseconds, present on success/error phases. */
|
|
24
|
+
durationMs?: number;
|
|
25
|
+
/** Human-readable error summary, present on error phases. */
|
|
26
|
+
error?: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** Callback form for receiving structured simulation debug events. */
|
|
30
|
+
export type SimulationDebugLogger = (event: SimulationDebugEvent) => void;
|
|
31
|
+
|
|
32
|
+
/** Debug option: `true` logs to the console, a callback receives structured events. */
|
|
33
|
+
export type SimulationDebug = boolean | SimulationDebugLogger;
|
|
34
|
+
|
|
35
|
+
/** Shared per-call options for block selection, gas budget, and debug events. */
|
|
36
|
+
type SimulationOptions = {
|
|
37
|
+
/** Historical block number to simulate against; if both block options are set, this wins. */
|
|
38
|
+
blockNumber?: bigint;
|
|
39
|
+
/** Block tag to simulate against when `blockNumber` is not set. */
|
|
40
|
+
blockTag?: BlockTag;
|
|
41
|
+
/** Gas budget for simulation RPC calls. Defaults to `DEFAULT_SIMULATION_GAS_LIMIT`. */
|
|
42
|
+
gas?: bigint;
|
|
43
|
+
/** Enables console logging or structured debug events for simulator RPC calls. */
|
|
44
|
+
debug?: SimulationDebug;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Storage-slot override: the unit that flows from preparation methods into
|
|
49
|
+
* `simulate({ tokenSlotOverrides })`.
|
|
50
|
+
*/
|
|
51
|
+
export type TokenSlotOverride = {
|
|
52
|
+
/** Token contract whose storage should be overridden. */
|
|
53
|
+
token: Address;
|
|
54
|
+
/** Storage slot to write. Usually prepared by `prepareBalanceOverrides` or `prepareAllowanceOverrides`. */
|
|
55
|
+
slot: Hex;
|
|
56
|
+
/** Value written to the slot. Must be below uint256 max. */
|
|
57
|
+
amount: bigint;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** Verified ERC-20 allowance mapping slot for one token, owner, and spender. */
|
|
61
|
+
export type AllowanceSlot = TokenSlotOverride & {
|
|
62
|
+
spender: Address;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/** Token/spender pair whose allowance override should be prepared or reported unresolved. */
|
|
66
|
+
export type AllowanceSlotPair = {
|
|
67
|
+
token: Address;
|
|
68
|
+
spender: Address;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/** Prepared balance storage overrides. */
|
|
72
|
+
export type PreparedBalanceOverrides = {
|
|
73
|
+
/** Verified slots that can be passed to `simulate` as `tokenSlotOverrides`. */
|
|
74
|
+
slots: TokenSlotOverride[];
|
|
75
|
+
/**
|
|
76
|
+
* Tokens the simulator could not `deal` in the Foundry sense: no storage slot could be
|
|
77
|
+
* sentinel-verified for writing hypothetical balances. Deltas for real holdings still come from
|
|
78
|
+
* `balanceOf`, including rebasing tokens.
|
|
79
|
+
*/
|
|
80
|
+
unresolved: Address[];
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/** Prepared allowance storage overrides. */
|
|
84
|
+
export type PreparedAllowanceOverrides = {
|
|
85
|
+
/** Verified slots that can be passed to `simulate` as `tokenSlotOverrides`. */
|
|
86
|
+
slots: AllowanceSlot[];
|
|
87
|
+
/** Pairs the simulator could not `deal` as allowances because no slot was sentinel-verified. */
|
|
88
|
+
unresolved: AllowanceSlotPair[];
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/** ABI-decoded revert error, present when revertData matches supplied error definitions or a built-in Error/Panic. */
|
|
92
|
+
export type RevertError = {
|
|
93
|
+
name: string;
|
|
94
|
+
args: readonly unknown[];
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/** Arguments for `TxSimulator.simulate`. */
|
|
98
|
+
export type SimulateArgs = SimulationOptions & {
|
|
99
|
+
/** Account being simulated; the ghost simulator bytecode is injected at this address. */
|
|
100
|
+
from: Address;
|
|
101
|
+
/** One call or an ERC-5792-style sequential batch. Must contain at least one call. */
|
|
102
|
+
calls: readonly SimulatedCall[];
|
|
103
|
+
/** Storage-slot overrides applied before simulating. Usually from override preparation. */
|
|
104
|
+
tokenSlotOverrides?: readonly TokenSlotOverride[];
|
|
105
|
+
/** Additional error definitions for decoding this call's reverts; merged after the bound errorAbi. */
|
|
106
|
+
errorAbi?: Abi;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/** Arguments for `TxSimulator.prepareBalanceOverrides`. */
|
|
110
|
+
export type PrepareBalanceOverridesArgs = SimulationOptions & {
|
|
111
|
+
/** Account whose token balance overrides should be prepared. */
|
|
112
|
+
from: Address;
|
|
113
|
+
/** Tokens to prepare ERC-20-style balance overrides for. */
|
|
114
|
+
tokens: readonly Address[];
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/** Arguments for `TxSimulator.prepareAllowanceOverrides`. */
|
|
118
|
+
export type PrepareAllowanceOverridesArgs = SimulationOptions & {
|
|
119
|
+
/** Account whose allowance overrides should be prepared. */
|
|
120
|
+
from: Address;
|
|
121
|
+
/** Token/spender allowance pairs to prepare overrides for. */
|
|
122
|
+
pairs: readonly AllowanceSlotPair[];
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/** Arguments for `TxSimulator.estimateAssetRequirements`. */
|
|
126
|
+
export type EstimateAssetRequirementsArgs = SimulationOptions & {
|
|
127
|
+
/** Account whose balance and approval needs should be estimated. */
|
|
128
|
+
from: Address;
|
|
129
|
+
/** One call or an ERC-5792-style sequential batch. Must contain at least one call. */
|
|
130
|
+
calls: readonly SimulatedCall[];
|
|
131
|
+
/** Additional error definitions for decoding this call's reverts; merged after the bound errorAbi. */
|
|
132
|
+
errorAbi?: Abi;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/** Configuration for `TxSimulator.create`. */
|
|
136
|
+
export type TxSimulatorConfig = {
|
|
137
|
+
client: PublicClient;
|
|
138
|
+
/** Default gas budget for all calls; per-call `gas` wins. */
|
|
139
|
+
gas?: bigint;
|
|
140
|
+
/** Default debug setting for all calls; per-call `debug` wins. */
|
|
141
|
+
debug?: SimulationDebug;
|
|
142
|
+
/** Error definitions used to decode custom-error reverts; merged with per-call errorAbi. */
|
|
143
|
+
errorAbi?: Abi;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/** Estimated minimum token balance needed under forged state. */
|
|
147
|
+
export type RequiredBalance = {
|
|
148
|
+
token: Address;
|
|
149
|
+
amount: bigint;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/** Estimated minimum total allowance needed under forged state. */
|
|
153
|
+
export type RequiredAllowance = {
|
|
154
|
+
token: Address;
|
|
155
|
+
spender: Address;
|
|
156
|
+
amount: bigint;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
type EstimatedAssetRequirementsBase = {
|
|
160
|
+
/** Maximum cumulative native outflow across call boundaries. */
|
|
161
|
+
native: bigint;
|
|
162
|
+
/** Minimum token balances needed to execute the observed path. */
|
|
163
|
+
balances: RequiredBalance[];
|
|
164
|
+
/** Minimum allowances needed before the batch, excluding allowances set inside the batch. */
|
|
165
|
+
allowances: RequiredAllowance[];
|
|
166
|
+
/** Verified slots prepared along the way; pass to `simulate` as `tokenSlotOverrides`. */
|
|
167
|
+
slots: TokenSlotOverride[];
|
|
168
|
+
/** Values the estimator could not verify or could not trust. */
|
|
169
|
+
unresolved: {
|
|
170
|
+
/**
|
|
171
|
+
* Tokens the estimator could not `deal` in the Foundry sense: no balance slot could be
|
|
172
|
+
* sentinel-verified for writing hypothetical balances. Real-holding deltas are unaffected.
|
|
173
|
+
*/
|
|
174
|
+
balanceSlots: Address[];
|
|
175
|
+
/** Token/spender pairs the estimator could not `deal` as allowances. */
|
|
176
|
+
allowanceSlots: AllowanceSlotPair[];
|
|
177
|
+
/** Token/spender pairs measured but discarded as unreliable, usually because they exceeded gross outflow. */
|
|
178
|
+
allowances: AllowanceSlotPair[];
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/** Successful asset-requirement estimate. */
|
|
183
|
+
export type EstimatedAssetRequirementsSuccess = EstimatedAssetRequirementsBase & {
|
|
184
|
+
status: "success";
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/** Asset-requirement estimate that still observed a transaction revert after forging available state. */
|
|
188
|
+
export type EstimatedAssetRequirementsReverted = EstimatedAssetRequirementsBase & {
|
|
189
|
+
status: "reverted";
|
|
190
|
+
/** Raw EVM revert data from the failing simulated call. */
|
|
191
|
+
revertData: Hex;
|
|
192
|
+
/** Human-readable decoded revert; present when revertData decodes via supplied error definitions or as built-in Error/Panic. */
|
|
193
|
+
revertReason?: string;
|
|
194
|
+
/** Decoded error when revertData matches supplied error definitions or built-in Error/Panic. */
|
|
195
|
+
revertError?: RevertError;
|
|
196
|
+
/** First 4 bytes of revertData; present whenever revertData carries a selector. */
|
|
197
|
+
revertSelector?: Hex;
|
|
198
|
+
/** Zero-based index of the call that reverted. */
|
|
199
|
+
failingCallIndex: number;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/** Asset-requirement estimate result; check `status` before reading revert fields. */
|
|
203
|
+
export type EstimatedAssetRequirements =
|
|
204
|
+
| EstimatedAssetRequirementsSuccess
|
|
205
|
+
| EstimatedAssetRequirementsReverted;
|
|
206
|
+
|
|
207
|
+
/** Raw balance delta for native ETH or an ERC-20-style `balanceOf(address)` asset. */
|
|
208
|
+
export type AssetBalanceDelta = {
|
|
209
|
+
/** `"native"` for ETH, otherwise the token contract address. */
|
|
210
|
+
asset: "native" | Address;
|
|
211
|
+
/** Signed raw-unit balance change for `from`; negative means the account lost assets. */
|
|
212
|
+
delta: bigint;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/** Successful simulation result. */
|
|
216
|
+
export type SimulationSuccess = {
|
|
217
|
+
status: "success";
|
|
218
|
+
/** Non-zero raw balance deltas observed during the simulated execution. */
|
|
219
|
+
assetBalanceDeltas: AssetBalanceDelta[];
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
/** Simulation result for a transaction revert; infrastructure failures throw typed errors instead. */
|
|
223
|
+
export type SimulationReverted = {
|
|
224
|
+
status: "reverted";
|
|
225
|
+
/** Non-zero raw balance deltas observed before the failing call. */
|
|
226
|
+
assetBalanceDeltas: AssetBalanceDelta[];
|
|
227
|
+
/** Raw EVM revert data from the failing simulated call. */
|
|
228
|
+
revertData: Hex;
|
|
229
|
+
/** Human-readable decoded revert; present when revertData decodes via supplied error definitions or as built-in Error/Panic. */
|
|
230
|
+
revertReason?: string;
|
|
231
|
+
/** Decoded error when revertData matches supplied error definitions or built-in Error/Panic. */
|
|
232
|
+
revertError?: RevertError;
|
|
233
|
+
/** First 4 bytes of revertData; present whenever revertData carries a selector. */
|
|
234
|
+
revertSelector?: Hex;
|
|
235
|
+
/** Zero-based index of the call that reverted. */
|
|
236
|
+
failingCallIndex: number;
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
/** Simulation result; transaction reverts are data, while RPC/infrastructure failures throw. */
|
|
240
|
+
export type SimulationResult = SimulationSuccess | SimulationReverted;
|