@morpho-org/evm-simulation 5.0.1 → 6.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.
- package/README.md +6 -4
- package/lib/cjs/errors.d.ts +17 -2
- package/lib/cjs/errors.js +19 -3
- package/lib/cjs/index.d.ts +2 -2
- package/lib/cjs/index.js +2 -1
- package/lib/cjs/params.d.ts +20 -1
- package/lib/cjs/requirements/requirements.js +2 -1
- package/lib/cjs/simulate/backends/eth-simulate-v1.d.ts +26 -34
- package/lib/cjs/simulate/backends/eth-simulate-v1.js +35 -74
- package/lib/cjs/simulate/backends/index.d.ts +1 -1
- package/lib/cjs/simulate/backends/index.js +1 -2
- package/lib/cjs/simulate/backends/parse-response.d.ts +1 -0
- package/lib/cjs/simulate/backends/parse-response.js +4 -2
- package/lib/cjs/simulate/backends/resolve-pinned-block.d.ts +6 -12
- package/lib/cjs/simulate/backends/resolve-pinned-block.js +3 -4
- package/lib/cjs/simulate/pipeline/bundles-retention.d.ts +3 -3
- package/lib/cjs/simulate/pipeline/bundles-retention.js +6 -6
- package/lib/cjs/simulate/pipeline/resolve-chain.d.ts +5 -1
- package/lib/cjs/simulate/pipeline/resolve-chain.js +12 -1
- package/lib/cjs/simulate/request/parse-request.d.ts +2 -1
- package/lib/cjs/simulate/request/parse-request.js +21 -0
- package/lib/cjs/simulate/run-simulation.js +9 -12
- package/lib/cjs/simulate/simulate.d.ts +30 -19
- package/lib/cjs/simulate/simulate.js +30 -19
- package/lib/cjs/types.d.ts +15 -0
- package/lib/esm/errors.d.ts +17 -2
- package/lib/esm/errors.js +17 -2
- package/lib/esm/index.d.ts +2 -2
- package/lib/esm/index.js +1 -1
- package/lib/esm/params.d.ts +20 -1
- package/lib/esm/requirements/requirements.js +2 -1
- package/lib/esm/simulate/backends/eth-simulate-v1.d.ts +26 -34
- package/lib/esm/simulate/backends/eth-simulate-v1.js +37 -75
- package/lib/esm/simulate/backends/index.d.ts +1 -1
- package/lib/esm/simulate/backends/index.js +1 -1
- package/lib/esm/simulate/backends/parse-response.d.ts +1 -0
- package/lib/esm/simulate/backends/parse-response.js +4 -2
- package/lib/esm/simulate/backends/resolve-pinned-block.d.ts +6 -12
- package/lib/esm/simulate/backends/resolve-pinned-block.js +3 -4
- package/lib/esm/simulate/pipeline/bundles-retention.d.ts +3 -3
- package/lib/esm/simulate/pipeline/bundles-retention.js +6 -6
- package/lib/esm/simulate/pipeline/resolve-chain.d.ts +5 -1
- package/lib/esm/simulate/pipeline/resolve-chain.js +13 -2
- package/lib/esm/simulate/request/parse-request.d.ts +2 -1
- package/lib/esm/simulate/request/parse-request.js +21 -0
- package/lib/esm/simulate/run-simulation.js +10 -13
- package/lib/esm/simulate/simulate.d.ts +30 -19
- package/lib/esm/simulate/simulate.js +30 -19
- package/lib/esm/types.d.ts +15 -0
- package/package.json +4 -4
|
@@ -4,11 +4,11 @@ import type { SimulationConfig } from "../types.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* Simulate a bundle of EVM transactions.
|
|
6
6
|
*
|
|
7
|
-
* Parses and normalizes the request → resolves
|
|
8
|
-
*
|
|
9
|
-
* and the execution → executes once through `eth_simulateV1` under
|
|
10
|
-
* timeout budget (simulation with in-block state reads → response
|
|
11
|
-
*
|
|
7
|
+
* Parses and normalizes the request → resolves a single pinned block (skipped
|
|
8
|
+
* when `params.block` is supplied) → resolves quoted-asset metadata → plans
|
|
9
|
+
* state reads and the execution → executes once through `eth_simulateV1` under
|
|
10
|
+
* the full timeout budget (simulation with in-block state reads → response
|
|
11
|
+
* parsing) → derives ERC20/WETH9 transfers and net asset changes from the
|
|
12
12
|
* user calls only → decodes quoted balances/positions → runs slippage checks
|
|
13
13
|
* → asserts no funds are retained by standalone `bundles` periphery contracts
|
|
14
14
|
* → returns the result. The caller reads whichever fields they need:
|
|
@@ -37,10 +37,13 @@ import type { SimulationConfig } from "../types.js";
|
|
|
37
37
|
* separating gas from economic effects. Monad nodes reject `false`, so Monad
|
|
38
38
|
* simulations send `true`; its simulated block charges no gas either way.
|
|
39
39
|
*
|
|
40
|
-
* @param config - Required per-chain `eth_simulateV1` URL, optional
|
|
41
|
-
*
|
|
40
|
+
* @param config - Required per-chain `eth_simulateV1` URL, optional per-chain
|
|
41
|
+
* `blockOverrides.gasLimit` and `parentHashCheck`, optional logger, and the
|
|
42
|
+
* overall timeout budget.
|
|
42
43
|
* @param params - Per-call simulation input.
|
|
43
|
-
* @param params.chainId - Chain id the bundle targets
|
|
44
|
+
* @param params.chainId - Chain id the bundle targets. Sent on every call inside
|
|
45
|
+
* `eth_simulateV1`, so nodes that check it reject a wrong-chain endpoint;
|
|
46
|
+
* there is no separate `eth_chainId` lookup.
|
|
44
47
|
* @param params.transactions - The bundle's transactions, in execution order.
|
|
45
48
|
* All must share the same `from`.
|
|
46
49
|
* @param params.mode - `"final"` (default) or `"preview"`.
|
|
@@ -50,9 +53,16 @@ import type { SimulationConfig } from "../types.js";
|
|
|
50
53
|
* than `"pending"`.
|
|
51
54
|
* Defaults to `latest` (`finalized` on Monad, whose `latest` block is not
|
|
52
55
|
* final), resolved exactly once.
|
|
56
|
+
* @param params.block - Optional caller-supplied state block (`number`,
|
|
57
|
+
* `hash`, `timestamp`). Skips the block lookup, so a simulation without
|
|
58
|
+
* asset metadata reads makes a single `eth_simulateV1` request. Cannot be
|
|
59
|
+
* combined with `blockNumber`.
|
|
53
60
|
* @throws {SimulationValidationError} for invalid input (mixed senders, bad
|
|
54
61
|
* addresses, empty transactions, malformed authorizations, final-mode
|
|
55
|
-
* authorizations, malformed limits, unknown fields, a `"pending"` block tag,
|
|
62
|
+
* authorizations, malformed limits, unknown fields, a `"pending"` block tag,
|
|
63
|
+
* a malformed `block` or one combined with `blockNumber`, a
|
|
64
|
+
* `blockOverrides.gasLimit` that is not a positive bigint, a `parentHashCheck`
|
|
65
|
+
* that is not a boolean, or share quotes for
|
|
56
66
|
* `blueSupplyCollateral` / `blueWithdrawCollateral`).
|
|
57
67
|
* @throws {ConsumerLimitViolationError} when a declared `limits` bound is
|
|
58
68
|
* violated by the observed effects.
|
|
@@ -66,20 +76,21 @@ import type { SimulationConfig } from "../types.js";
|
|
|
66
76
|
* @throws {InvalidSimulationResponseError} when the node response cannot be
|
|
67
77
|
* trusted (bad shape, call-count mismatch, block that is neither the pinned
|
|
68
78
|
* state block nor its immediate successor, a successor with a mismatched
|
|
69
|
-
* `parentHash
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
79
|
+
* `parentHash` (unless `parentHashCheck` is off; off by default on Stable,
|
|
80
|
+
* chain 988), a block timestamp earlier than the pinned block's, a
|
|
81
|
+
* malformed per-call result, or a quoted balance/position read whose
|
|
82
|
+
* non-empty return data cannot be decoded).
|
|
83
|
+
* @throws {InvalidChainIdError} when the node rejects the request `chainId`
|
|
84
|
+
* because the endpoint serves another chain (a subclass of
|
|
85
|
+
* `InvalidSimulationResponseError` sharing its `name`/`code`;
|
|
86
|
+
* `instanceof InvalidChainIdError` tells them apart). Never bypassable.
|
|
75
87
|
* @throws {BlacklistViolationError} when the simulation leaves value retained
|
|
76
88
|
* beyond the dust threshold by a `bundles` periphery contract
|
|
77
|
-
* (VaultExitBundlesV1, VaultBundlesV1, BlueBundlesV1,
|
|
89
|
+
* (VaultExitBundlesV1, VaultBundlesV1, BlueBundlesV1, MidnightBundlesV2).
|
|
78
90
|
* Never bypassable.
|
|
79
91
|
* @throws {ExternalServiceError} when the RPC is unavailable within the
|
|
80
|
-
* timeout budget or returns a malformed JSON-RPC envelope.
|
|
81
|
-
*
|
|
82
|
-
* `InvalidSimulationResponseError`.
|
|
92
|
+
* timeout budget or returns a malformed JSON-RPC envelope. A looked-up state
|
|
93
|
+
* block without number/hash is reported as `InvalidSimulationResponseError`.
|
|
83
94
|
* @returns A frozen {@link VerifiedSimulationResult} carrying the normalized
|
|
84
95
|
* `simulationTxs`, per-tx `calls` (aligned 1:1), parsed `transfers` (each
|
|
85
96
|
* stamped with `txIdx`), per-account net `assetChanges`, and per-operation
|
|
@@ -3,11 +3,11 @@ import { runSimulation } from "./run-simulation.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Simulate a bundle of EVM transactions.
|
|
5
5
|
*
|
|
6
|
-
* Parses and normalizes the request → resolves
|
|
7
|
-
*
|
|
8
|
-
* and the execution → executes once through `eth_simulateV1` under
|
|
9
|
-
* timeout budget (simulation with in-block state reads → response
|
|
10
|
-
*
|
|
6
|
+
* Parses and normalizes the request → resolves a single pinned block (skipped
|
|
7
|
+
* when `params.block` is supplied) → resolves quoted-asset metadata → plans
|
|
8
|
+
* state reads and the execution → executes once through `eth_simulateV1` under
|
|
9
|
+
* the full timeout budget (simulation with in-block state reads → response
|
|
10
|
+
* parsing) → derives ERC20/WETH9 transfers and net asset changes from the
|
|
11
11
|
* user calls only → decodes quoted balances/positions → runs slippage checks
|
|
12
12
|
* → asserts no funds are retained by standalone `bundles` periphery contracts
|
|
13
13
|
* → returns the result. The caller reads whichever fields they need:
|
|
@@ -36,10 +36,13 @@ import { runSimulation } from "./run-simulation.js";
|
|
|
36
36
|
* separating gas from economic effects. Monad nodes reject `false`, so Monad
|
|
37
37
|
* simulations send `true`; its simulated block charges no gas either way.
|
|
38
38
|
*
|
|
39
|
-
* @param config - Required per-chain `eth_simulateV1` URL, optional
|
|
40
|
-
*
|
|
39
|
+
* @param config - Required per-chain `eth_simulateV1` URL, optional per-chain
|
|
40
|
+
* `blockOverrides.gasLimit` and `parentHashCheck`, optional logger, and the
|
|
41
|
+
* overall timeout budget.
|
|
41
42
|
* @param params - Per-call simulation input.
|
|
42
|
-
* @param params.chainId - Chain id the bundle targets
|
|
43
|
+
* @param params.chainId - Chain id the bundle targets. Sent on every call inside
|
|
44
|
+
* `eth_simulateV1`, so nodes that check it reject a wrong-chain endpoint;
|
|
45
|
+
* there is no separate `eth_chainId` lookup.
|
|
43
46
|
* @param params.transactions - The bundle's transactions, in execution order.
|
|
44
47
|
* All must share the same `from`.
|
|
45
48
|
* @param params.mode - `"final"` (default) or `"preview"`.
|
|
@@ -49,9 +52,16 @@ import { runSimulation } from "./run-simulation.js";
|
|
|
49
52
|
* than `"pending"`.
|
|
50
53
|
* Defaults to `latest` (`finalized` on Monad, whose `latest` block is not
|
|
51
54
|
* final), resolved exactly once.
|
|
55
|
+
* @param params.block - Optional caller-supplied state block (`number`,
|
|
56
|
+
* `hash`, `timestamp`). Skips the block lookup, so a simulation without
|
|
57
|
+
* asset metadata reads makes a single `eth_simulateV1` request. Cannot be
|
|
58
|
+
* combined with `blockNumber`.
|
|
52
59
|
* @throws {SimulationValidationError} for invalid input (mixed senders, bad
|
|
53
60
|
* addresses, empty transactions, malformed authorizations, final-mode
|
|
54
|
-
* authorizations, malformed limits, unknown fields, a `"pending"` block tag,
|
|
61
|
+
* authorizations, malformed limits, unknown fields, a `"pending"` block tag,
|
|
62
|
+
* a malformed `block` or one combined with `blockNumber`, a
|
|
63
|
+
* `blockOverrides.gasLimit` that is not a positive bigint, a `parentHashCheck`
|
|
64
|
+
* that is not a boolean, or share quotes for
|
|
55
65
|
* `blueSupplyCollateral` / `blueWithdrawCollateral`).
|
|
56
66
|
* @throws {ConsumerLimitViolationError} when a declared `limits` bound is
|
|
57
67
|
* violated by the observed effects.
|
|
@@ -65,20 +75,21 @@ import { runSimulation } from "./run-simulation.js";
|
|
|
65
75
|
* @throws {InvalidSimulationResponseError} when the node response cannot be
|
|
66
76
|
* trusted (bad shape, call-count mismatch, block that is neither the pinned
|
|
67
77
|
* state block nor its immediate successor, a successor with a mismatched
|
|
68
|
-
* `parentHash
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
78
|
+
* `parentHash` (unless `parentHashCheck` is off; off by default on Stable,
|
|
79
|
+
* chain 988), a block timestamp earlier than the pinned block's, a
|
|
80
|
+
* malformed per-call result, or a quoted balance/position read whose
|
|
81
|
+
* non-empty return data cannot be decoded).
|
|
82
|
+
* @throws {InvalidChainIdError} when the node rejects the request `chainId`
|
|
83
|
+
* because the endpoint serves another chain (a subclass of
|
|
84
|
+
* `InvalidSimulationResponseError` sharing its `name`/`code`;
|
|
85
|
+
* `instanceof InvalidChainIdError` tells them apart). Never bypassable.
|
|
74
86
|
* @throws {BlacklistViolationError} when the simulation leaves value retained
|
|
75
87
|
* beyond the dust threshold by a `bundles` periphery contract
|
|
76
|
-
* (VaultExitBundlesV1, VaultBundlesV1, BlueBundlesV1,
|
|
88
|
+
* (VaultExitBundlesV1, VaultBundlesV1, BlueBundlesV1, MidnightBundlesV2).
|
|
77
89
|
* Never bypassable.
|
|
78
90
|
* @throws {ExternalServiceError} when the RPC is unavailable within the
|
|
79
|
-
* timeout budget or returns a malformed JSON-RPC envelope.
|
|
80
|
-
*
|
|
81
|
-
* `InvalidSimulationResponseError`.
|
|
91
|
+
* timeout budget or returns a malformed JSON-RPC envelope. A looked-up state
|
|
92
|
+
* block without number/hash is reported as `InvalidSimulationResponseError`.
|
|
82
93
|
* @returns A frozen {@link VerifiedSimulationResult} carrying the normalized
|
|
83
94
|
* `simulationTxs`, per-tx `calls` (aligned 1:1), parsed `transfers` (each
|
|
84
95
|
* stamped with `txIdx`), per-account net `assetChanges`, and per-operation
|
package/lib/esm/types.d.ts
CHANGED
|
@@ -3,6 +3,21 @@ import type { Address, Hex } from "viem";
|
|
|
3
3
|
export interface ChainSimulationConfig {
|
|
4
4
|
/** JSON-RPC URL supporting `eth_simulateV1`. Required for every configured chain. */
|
|
5
5
|
readonly simulateV1Url: string;
|
|
6
|
+
/**
|
|
7
|
+
* Block overrides forwarded to `eth_simulateV1` as the simulated block's
|
|
8
|
+
* `blockOverrides`. Omitted fields leave the node's defaults untouched.
|
|
9
|
+
*/
|
|
10
|
+
readonly blockOverrides?: {
|
|
11
|
+
/** Gas limit of the simulated block. Omitted: no gas limit override is sent. */
|
|
12
|
+
readonly gasLimit?: bigint;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Whether a simulated successor block's `parentHash` must equal the pinned
|
|
16
|
+
* state block hash. Block number and timestamp checks always run.
|
|
17
|
+
* Omitted: on everywhere except Stable (988), whose nodes report a
|
|
18
|
+
* `parentHash` that never matches the pinned block.
|
|
19
|
+
*/
|
|
20
|
+
readonly parentHashCheck?: boolean;
|
|
6
21
|
}
|
|
7
22
|
/**
|
|
8
23
|
* Top-level configuration for `simulate`.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morpho-org/evm-simulation",
|
|
3
3
|
"description": "EVM simulation engine for Morpho transactions.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "6.0.0",
|
|
5
5
|
"author": "Morpho Association <contact@morpho.org>",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"lib"
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@morpho-org/blue-sdk": "^
|
|
25
|
-
"@morpho-org/morpho-sdk": "^
|
|
26
|
-
"@morpho-org/morpho-ts": "^
|
|
24
|
+
"@morpho-org/blue-sdk": "^8.0.0",
|
|
25
|
+
"@morpho-org/morpho-sdk": "^7.0.0",
|
|
26
|
+
"@morpho-org/morpho-ts": "^4.0.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"viem": "^2.0.0"
|