@morpho-org/evm-simulation 5.0.0 → 5.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/README.md +2 -2
- package/lib/cjs/params.d.ts +2 -1
- package/lib/cjs/simulate/backends/eth-simulate-v1.d.ts +13 -5
- package/lib/cjs/simulate/backends/eth-simulate-v1.js +16 -7
- 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/pipeline/resolve-chain.d.ts +5 -1
- package/lib/cjs/simulate/pipeline/resolve-chain.js +12 -1
- package/lib/cjs/simulate/run-simulation.js +8 -1
- package/lib/cjs/simulate/simulate.d.ts +11 -6
- package/lib/cjs/simulate/simulate.js +11 -6
- package/lib/cjs/types.d.ts +17 -1
- package/lib/esm/params.d.ts +2 -1
- package/lib/esm/simulate/backends/eth-simulate-v1.d.ts +13 -5
- package/lib/esm/simulate/backends/eth-simulate-v1.js +16 -7
- 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/pipeline/resolve-chain.d.ts +5 -1
- package/lib/esm/simulate/pipeline/resolve-chain.js +13 -2
- package/lib/esm/simulate/run-simulation.js +9 -2
- package/lib/esm/simulate/simulate.d.ts +11 -6
- package/lib/esm/simulate/simulate.js +11 -6
- package/lib/esm/types.d.ts +17 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -46,11 +46,11 @@ try {
|
|
|
46
46
|
}
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
Every chain entry requires `simulateV1Url`, pointing to a JSON-RPC endpoint that supports `eth_simulateV1`. Execution uses the full `timeoutMs` budget (default 5000 ms), with no retries or provider fallback. RPC failures, timeouts and reverts throw typed errors. The optional logger still reports parsing and retention warnings.
|
|
49
|
+
Every chain entry requires `simulateV1Url`, pointing to a JSON-RPC endpoint that supports `eth_simulateV1`. Requests send `validation: false` so gas is not charged. Monad (chain 143) is handled internally: its nodes reject `false`, so it sends `true` (its simulated block charges no gas either way), and it pins to the `finalized` block by default because its `latest` block is not final. On Monad, `gasUsed` reports the call's gas limit, not the gas consumed. Set `blockOverrides.gasLimit` on a chain entry to send that gas limit as the simulated block's `blockOverrides.gasLimit`; without it, no block override is sent. Set `parentHashCheck` on a chain entry to turn on or off the check that the simulated block's `parentHash` is the pinned block hash. It defaults to off on Stable (chain 988), whose nodes report a `parentHash` that never matches the pinned block, and on for every other chain. The block number, timestamp and reorg checks always apply. Execution uses the full `timeoutMs` budget (default 5000 ms), with no retries or provider fallback. RPC failures, timeouts and reverts throw typed errors. The optional logger still reports parsing and retention warnings.
|
|
50
50
|
|
|
51
51
|
Native-ETH movements are observed through `traceTransfers` logs on the simulated calls — no `stateOverrides` or helper contracts are injected.
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Upgrading from v4? See the [v4 → v5 migration guide](../../docs/migrations/evm-simulation-v4-to-v5.md) for the backend cutover.
|
|
54
54
|
|
|
55
55
|
### API surface
|
|
56
56
|
|
package/lib/cjs/params.d.ts
CHANGED
|
@@ -17,7 +17,8 @@ export interface SimulateParams {
|
|
|
17
17
|
readonly mode?: SimulationMode;
|
|
18
18
|
/** Pending wallet requests, in order. Preview only; rejected in final. */
|
|
19
19
|
readonly authorizations?: readonly SimulationAuthorization[];
|
|
20
|
-
/** Resolved once; defaults to "latest"
|
|
20
|
+
/** Resolved once; defaults to "latest" ("finalized" on Monad, whose
|
|
21
|
+
* "latest" block is not final). Only canonical (mined) blocks can be
|
|
21
22
|
* pinned; `pending` has no stable hash and is rejected at runtime. */
|
|
22
23
|
readonly blockNumber?: bigint | Exclude<BlockTag, "pending">;
|
|
23
24
|
/** Caller-selected quotes and percentage tolerances. Omitted limits are unchecked. */
|
|
@@ -26,9 +26,13 @@ export declare function assertEndpointChain(params: {
|
|
|
26
26
|
*
|
|
27
27
|
* 1. **`eth_simulateV1`** — one `blockStateCalls` entry carrying the planned
|
|
28
28
|
* calls with their per-call `from`, `traceTransfers: true` so the node
|
|
29
|
-
* synthesizes native-ETH moves as transfer logs, and
|
|
30
|
-
* `
|
|
31
|
-
*
|
|
29
|
+
* synthesizes native-ETH moves as transfer logs, and `validation: false`
|
|
30
|
+
* (`true` on Monad, whose nodes reject `false` and charge no gas in the
|
|
31
|
+
* simulated block). Validation-off means gas is not charged, which is how
|
|
32
|
+
* gas is separated from economic effects. When `blockGasLimit` is set,
|
|
33
|
+
* it is sent as the block's `blockOverrides.gasLimit`; otherwise no block
|
|
34
|
+
* override is sent.
|
|
35
|
+
* **No balance override is
|
|
32
36
|
* applied** — `value` transfers are funded by the sender's real native
|
|
33
37
|
* balance.
|
|
34
38
|
* 2. **Response validation** — the response is parsed before the reorg
|
|
@@ -45,8 +49,9 @@ export declare function assertEndpointChain(params: {
|
|
|
45
49
|
* The endpoint must support `eth_simulateV1` with per-call `from`; there is
|
|
46
50
|
* no fallback backend.
|
|
47
51
|
*
|
|
48
|
-
* @param params - Shared simulation client, execution plan,
|
|
49
|
-
* state block
|
|
52
|
+
* @param params - Shared simulation client, execution plan, already-pinned
|
|
53
|
+
* state block, the `validation` flag to send, the optional simulated
|
|
54
|
+
* block gas limit, and whether to check the successor `parentHash`.
|
|
50
55
|
* @returns Deep-frozen {@link SimulationExecution} — per-transaction call
|
|
51
56
|
* results and the resolved {@link ExecutionBlock}.
|
|
52
57
|
* @throws {ExternalServiceError} For transport failures, timeouts,
|
|
@@ -66,5 +71,8 @@ export declare function executePlan(params: {
|
|
|
66
71
|
client: Client & Pick<PublicClient, "getBlock">;
|
|
67
72
|
plan: ExecutionPlan;
|
|
68
73
|
stateBlock: PinnedBlock;
|
|
74
|
+
validation: boolean;
|
|
75
|
+
blockGasLimit?: bigint | undefined;
|
|
76
|
+
parentHashCheck: boolean;
|
|
69
77
|
}): Promise<SimulationExecution>;
|
|
70
78
|
export {};
|
|
@@ -89,9 +89,13 @@ async function assertEndpointChain(params) {
|
|
|
89
89
|
*
|
|
90
90
|
* 1. **`eth_simulateV1`** — one `blockStateCalls` entry carrying the planned
|
|
91
91
|
* calls with their per-call `from`, `traceTransfers: true` so the node
|
|
92
|
-
* synthesizes native-ETH moves as transfer logs, and
|
|
93
|
-
* `
|
|
94
|
-
*
|
|
92
|
+
* synthesizes native-ETH moves as transfer logs, and `validation: false`
|
|
93
|
+
* (`true` on Monad, whose nodes reject `false` and charge no gas in the
|
|
94
|
+
* simulated block). Validation-off means gas is not charged, which is how
|
|
95
|
+
* gas is separated from economic effects. When `blockGasLimit` is set,
|
|
96
|
+
* it is sent as the block's `blockOverrides.gasLimit`; otherwise no block
|
|
97
|
+
* override is sent.
|
|
98
|
+
* **No balance override is
|
|
95
99
|
* applied** — `value` transfers are funded by the sender's real native
|
|
96
100
|
* balance.
|
|
97
101
|
* 2. **Response validation** — the response is parsed before the reorg
|
|
@@ -108,8 +112,9 @@ async function assertEndpointChain(params) {
|
|
|
108
112
|
* The endpoint must support `eth_simulateV1` with per-call `from`; there is
|
|
109
113
|
* no fallback backend.
|
|
110
114
|
*
|
|
111
|
-
* @param params - Shared simulation client, execution plan,
|
|
112
|
-
* state block
|
|
115
|
+
* @param params - Shared simulation client, execution plan, already-pinned
|
|
116
|
+
* state block, the `validation` flag to send, the optional simulated
|
|
117
|
+
* block gas limit, and whether to check the successor `parentHash`.
|
|
113
118
|
* @returns Deep-frozen {@link SimulationExecution} — per-transaction call
|
|
114
119
|
* results and the resolved {@link ExecutionBlock}.
|
|
115
120
|
* @throws {ExternalServiceError} For transport failures, timeouts,
|
|
@@ -126,13 +131,16 @@ async function assertEndpointChain(params) {
|
|
|
126
131
|
* @internal
|
|
127
132
|
*/
|
|
128
133
|
async function executePlan(params) {
|
|
129
|
-
const { client, plan, stateBlock } = params;
|
|
134
|
+
const { client, plan, stateBlock, validation, blockGasLimit, parentHashCheck, } = params;
|
|
130
135
|
const response = await (0, exports.rpc)("eth_simulateV1", () => client.request({
|
|
131
136
|
method: "eth_simulateV1",
|
|
132
137
|
params: [
|
|
133
138
|
{
|
|
134
139
|
blockStateCalls: [
|
|
135
140
|
{
|
|
141
|
+
...(blockGasLimit !== undefined && {
|
|
142
|
+
blockOverrides: { gasLimit: (0, viem_1.numberToHex)(blockGasLimit) },
|
|
143
|
+
}),
|
|
136
144
|
calls: plan.calls.map((call) => ({
|
|
137
145
|
from: call.transaction.from,
|
|
138
146
|
to: call.transaction.to,
|
|
@@ -142,7 +150,7 @@ async function executePlan(params) {
|
|
|
142
150
|
},
|
|
143
151
|
],
|
|
144
152
|
traceTransfers: true,
|
|
145
|
-
validation
|
|
153
|
+
validation,
|
|
146
154
|
},
|
|
147
155
|
(0, viem_1.numberToHex)(stateBlock.number),
|
|
148
156
|
],
|
|
@@ -158,6 +166,7 @@ async function executePlan(params) {
|
|
|
158
166
|
stateBlockNumber: stateBlock.number,
|
|
159
167
|
stateBlockHash: stateBlock.hash,
|
|
160
168
|
stateBlockTimestamp: stateBlock.timestamp,
|
|
169
|
+
parentHashCheck,
|
|
161
170
|
});
|
|
162
171
|
// Reorg window: the pinned state block must still carry the same hash
|
|
163
172
|
// after simulation, or the result may describe a different chain tip.
|
|
@@ -57,8 +57,10 @@ function parseSimulationResponse(params) {
|
|
|
57
57
|
}
|
|
58
58
|
// Anvil re-hashes the pinned block, so only the geth-style successor can be
|
|
59
59
|
// pinned by hash: it must report a parentHash (geth always does) equal to
|
|
60
|
-
// the pinned state block hash.
|
|
61
|
-
|
|
60
|
+
// the pinned state block hash. With `parentHashCheck` off (Stable by
|
|
61
|
+
// default) the block number, timestamp and reorg checks still apply.
|
|
62
|
+
if (params.parentHashCheck &&
|
|
63
|
+
blockNumber === params.stateBlockNumber + 1n &&
|
|
62
64
|
block.parentHash !== params.stateBlockHash) {
|
|
63
65
|
throw new errors_js_1.InvalidSimulationResponseError(`eth_simulateV1 reported block ${blockNumber} whose parent ${String(block.parentHash)} is not the pinned state block hash ${params.stateBlockHash}; the node did not simulate on top of the pinned block.`, { context: errorContext });
|
|
64
66
|
}
|
|
@@ -4,6 +4,10 @@ import type { ChainSimulationConfig, SimulationConfig } from "../../types.js";
|
|
|
4
4
|
*
|
|
5
5
|
* Looks up the per-chain `ChainSimulationConfig`. Throws `UnsupportedChainError`
|
|
6
6
|
* when the chain is absent from the map or has no `simulateV1Url` (defensive —
|
|
7
|
-
* the type already requires it at construction).
|
|
7
|
+
* the type already requires it at construction). Throws
|
|
8
|
+
* `SimulationValidationError` when `blockOverrides.gasLimit` is set but is
|
|
9
|
+
* not a positive bigint, or `parentHashCheck` is set but is not a boolean, so a
|
|
10
|
+
* misconfiguration never surfaces as a bypassable
|
|
11
|
+
* `ExternalServiceError`.
|
|
8
12
|
*/
|
|
9
13
|
export declare function resolveChain(config: SimulationConfig, chainId: number): ChainSimulationConfig;
|
|
@@ -7,11 +7,22 @@ const errors_js_1 = require("../../errors.js");
|
|
|
7
7
|
*
|
|
8
8
|
* Looks up the per-chain `ChainSimulationConfig`. Throws `UnsupportedChainError`
|
|
9
9
|
* when the chain is absent from the map or has no `simulateV1Url` (defensive —
|
|
10
|
-
* the type already requires it at construction).
|
|
10
|
+
* the type already requires it at construction). Throws
|
|
11
|
+
* `SimulationValidationError` when `blockOverrides.gasLimit` is set but is
|
|
12
|
+
* not a positive bigint, or `parentHashCheck` is set but is not a boolean, so a
|
|
13
|
+
* misconfiguration never surfaces as a bypassable
|
|
14
|
+
* `ExternalServiceError`.
|
|
11
15
|
*/
|
|
12
16
|
function resolveChain(config, chainId) {
|
|
13
17
|
const entry = config.chains.get(chainId);
|
|
14
18
|
if (!entry?.simulateV1Url)
|
|
15
19
|
throw new errors_js_1.UnsupportedChainError(chainId);
|
|
20
|
+
const gasLimit = entry.blockOverrides?.gasLimit;
|
|
21
|
+
if (gasLimit !== undefined &&
|
|
22
|
+
(typeof gasLimit !== "bigint" || gasLimit <= 0n))
|
|
23
|
+
throw new errors_js_1.SimulationValidationError(`Chain ${chainId} blockOverrides.gasLimit must be a positive bigint, got "${String(gasLimit)}" (${typeof gasLimit}). Pass a bigint greater than 0n or omit gasLimit.`, ["blockOverrides.gasLimit: must be a positive bigint"]);
|
|
24
|
+
const parentHashCheck = entry.parentHashCheck;
|
|
25
|
+
if (parentHashCheck !== undefined && typeof parentHashCheck !== "boolean")
|
|
26
|
+
throw new errors_js_1.SimulationValidationError(`Chain ${chainId} parentHashCheck must be a boolean, got "${String(parentHashCheck)}" (${typeof parentHashCheck}). Pass true or false, or omit parentHashCheck.`, ["parentHashCheck: must be a boolean"]);
|
|
16
27
|
return entry;
|
|
17
28
|
}
|
|
@@ -51,9 +51,13 @@ async function runSimulation(params) {
|
|
|
51
51
|
mode: request.mode,
|
|
52
52
|
blockNumber: typeof request.blockNumber === "bigint" ? request.blockNumber : undefined,
|
|
53
53
|
});
|
|
54
|
+
// Monad nodes reject `validation: false` and charge no gas in the simulated
|
|
55
|
+
// block either way. Its `latest` block is not final: simulating at its number
|
|
56
|
+
// runs on another parent, so default to `finalized`.
|
|
57
|
+
const monad = request.chainId === blue_sdk_1.ChainId.MonadMainnet;
|
|
54
58
|
const pinnedBlock = await (0, resolve_pinned_block_js_1.resolvePinnedBlock)({
|
|
55
59
|
client,
|
|
56
|
-
blockNumber: request.blockNumber,
|
|
60
|
+
blockNumber: request.blockNumber ?? (monad ? "finalized" : undefined),
|
|
57
61
|
signal,
|
|
58
62
|
});
|
|
59
63
|
// With no calldata decoding, the caller's declared `limits.operations`
|
|
@@ -86,6 +90,9 @@ async function runSimulation(params) {
|
|
|
86
90
|
client,
|
|
87
91
|
plan,
|
|
88
92
|
stateBlock: pinnedBlock,
|
|
93
|
+
validation: monad,
|
|
94
|
+
blockGasLimit: chain.blockOverrides?.gasLimit,
|
|
95
|
+
parentHashCheck: chain.parentHashCheck ?? request.chainId !== blue_sdk_1.ChainId.StableMainnet,
|
|
89
96
|
});
|
|
90
97
|
const userCalls = execution.calls
|
|
91
98
|
.filter((call) => call.planned.type === "transaction")
|
|
@@ -34,10 +34,12 @@ import type { SimulationConfig } from "../types.js";
|
|
|
34
34
|
* **Funding.** `value` transfers are funded by the sender's real native
|
|
35
35
|
* balance — no balance inflation — so under-funded bundles revert exactly as
|
|
36
36
|
* they would on-chain. `validation: false` keeps gas from being charged,
|
|
37
|
-
* separating gas from economic effects.
|
|
37
|
+
* separating gas from economic effects. Monad nodes reject `false`, so Monad
|
|
38
|
+
* simulations send `true`; its simulated block charges no gas either way.
|
|
38
39
|
*
|
|
39
|
-
* @param config - Required per-chain `eth_simulateV1` URL, optional
|
|
40
|
-
*
|
|
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.
|
|
41
43
|
* @param params - Per-call simulation input.
|
|
42
44
|
* @param params.chainId - Chain id the bundle targets; must match the endpoint.
|
|
43
45
|
* @param params.transactions - The bundle's transactions, in execution order.
|
|
@@ -47,10 +49,13 @@ import type { SimulationConfig } from "../types.js";
|
|
|
47
49
|
* @param params.limits - Optional quotes and percentage tolerances; unquoted amounts require no reads.
|
|
48
50
|
* @param params.blockNumber - Optional pinned block number or `BlockTag` other
|
|
49
51
|
* than `"pending"`.
|
|
50
|
-
* Defaults to `latest
|
|
52
|
+
* Defaults to `latest` (`finalized` on Monad, whose `latest` block is not
|
|
53
|
+
* final), resolved exactly once.
|
|
51
54
|
* @throws {SimulationValidationError} for invalid input (mixed senders, bad
|
|
52
55
|
* addresses, empty transactions, malformed authorizations, final-mode
|
|
53
|
-
* authorizations, malformed limits, unknown fields, a `"pending"` block tag,
|
|
56
|
+
* authorizations, malformed limits, unknown fields, a `"pending"` block tag, a
|
|
57
|
+
* `blockOverrides.gasLimit` that is not a positive bigint, a `parentHashCheck`
|
|
58
|
+
* that is not a boolean, or share quotes for
|
|
54
59
|
* `blueSupplyCollateral` / `blueWithdrawCollateral`).
|
|
55
60
|
* @throws {ConsumerLimitViolationError} when a declared `limits` bound is
|
|
56
61
|
* violated by the observed effects.
|
|
@@ -64,7 +69,7 @@ import type { SimulationConfig } from "../types.js";
|
|
|
64
69
|
* @throws {InvalidSimulationResponseError} when the node response cannot be
|
|
65
70
|
* trusted (bad shape, call-count mismatch, block that is neither the pinned
|
|
66
71
|
* state block nor its immediate successor, a successor with a mismatched
|
|
67
|
-
* `parentHash
|
|
72
|
+
* `parentHash` (unless `parentHashCheck` is off; off by default on Stable, chain 988), a block timestamp earlier than the pinned block's, a
|
|
68
73
|
* malformed per-call result, a quoted balance/position read whose non-empty
|
|
69
74
|
* return data cannot be decoded, a state-block hash that changed or a pinned
|
|
70
75
|
* block that vanished mid-flight, or an
|
|
@@ -36,10 +36,12 @@ const run_simulation_js_1 = require("./run-simulation.js");
|
|
|
36
36
|
* **Funding.** `value` transfers are funded by the sender's real native
|
|
37
37
|
* balance — no balance inflation — so under-funded bundles revert exactly as
|
|
38
38
|
* they would on-chain. `validation: false` keeps gas from being charged,
|
|
39
|
-
* separating gas from economic effects.
|
|
39
|
+
* separating gas from economic effects. Monad nodes reject `false`, so Monad
|
|
40
|
+
* simulations send `true`; its simulated block charges no gas either way.
|
|
40
41
|
*
|
|
41
|
-
* @param config - Required per-chain `eth_simulateV1` URL, optional
|
|
42
|
-
*
|
|
42
|
+
* @param config - Required per-chain `eth_simulateV1` URL, optional per-chain
|
|
43
|
+
* `blockOverrides.gasLimit` and `parentHashCheck`, optional logger, and the
|
|
44
|
+
* overall timeout budget.
|
|
43
45
|
* @param params - Per-call simulation input.
|
|
44
46
|
* @param params.chainId - Chain id the bundle targets; must match the endpoint.
|
|
45
47
|
* @param params.transactions - The bundle's transactions, in execution order.
|
|
@@ -49,10 +51,13 @@ const run_simulation_js_1 = require("./run-simulation.js");
|
|
|
49
51
|
* @param params.limits - Optional quotes and percentage tolerances; unquoted amounts require no reads.
|
|
50
52
|
* @param params.blockNumber - Optional pinned block number or `BlockTag` other
|
|
51
53
|
* than `"pending"`.
|
|
52
|
-
* Defaults to `latest
|
|
54
|
+
* Defaults to `latest` (`finalized` on Monad, whose `latest` block is not
|
|
55
|
+
* final), resolved exactly once.
|
|
53
56
|
* @throws {SimulationValidationError} for invalid input (mixed senders, bad
|
|
54
57
|
* addresses, empty transactions, malformed authorizations, final-mode
|
|
55
|
-
* authorizations, malformed limits, unknown fields, a `"pending"` block tag,
|
|
58
|
+
* authorizations, malformed limits, unknown fields, a `"pending"` block tag, a
|
|
59
|
+
* `blockOverrides.gasLimit` that is not a positive bigint, a `parentHashCheck`
|
|
60
|
+
* that is not a boolean, or share quotes for
|
|
56
61
|
* `blueSupplyCollateral` / `blueWithdrawCollateral`).
|
|
57
62
|
* @throws {ConsumerLimitViolationError} when a declared `limits` bound is
|
|
58
63
|
* violated by the observed effects.
|
|
@@ -66,7 +71,7 @@ const run_simulation_js_1 = require("./run-simulation.js");
|
|
|
66
71
|
* @throws {InvalidSimulationResponseError} when the node response cannot be
|
|
67
72
|
* trusted (bad shape, call-count mismatch, block that is neither the pinned
|
|
68
73
|
* state block nor its immediate successor, a successor with a mismatched
|
|
69
|
-
* `parentHash
|
|
74
|
+
* `parentHash` (unless `parentHashCheck` is off; off by default on Stable, chain 988), a block timestamp earlier than the pinned block's, a
|
|
70
75
|
* malformed per-call result, a quoted balance/position read whose non-empty
|
|
71
76
|
* return data cannot be decoded, a state-block hash that changed or a pinned
|
|
72
77
|
* block that vanished mid-flight, or an
|
package/lib/cjs/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, timestamp and reorg 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`.
|
|
@@ -145,7 +160,8 @@ export interface SimulationCall {
|
|
|
145
160
|
* Gas consumed by this call's root frame, not a safe gas limit. This is
|
|
146
161
|
* post-refund consumption and does not account for EIP-150's 63/64 rule in
|
|
147
162
|
* nested calls, so consumers deriving a limit must add their own headroom,
|
|
148
|
-
* larger than headroom derived from `eth_estimateGas`.
|
|
163
|
+
* larger than headroom derived from `eth_estimateGas`. On Monad it reports the
|
|
164
|
+
* call's gas limit (150M by default) instead of gas consumed.
|
|
149
165
|
*/
|
|
150
166
|
readonly gasUsed: bigint;
|
|
151
167
|
}
|
package/lib/esm/params.d.ts
CHANGED
|
@@ -17,7 +17,8 @@ export interface SimulateParams {
|
|
|
17
17
|
readonly mode?: SimulationMode;
|
|
18
18
|
/** Pending wallet requests, in order. Preview only; rejected in final. */
|
|
19
19
|
readonly authorizations?: readonly SimulationAuthorization[];
|
|
20
|
-
/** Resolved once; defaults to "latest"
|
|
20
|
+
/** Resolved once; defaults to "latest" ("finalized" on Monad, whose
|
|
21
|
+
* "latest" block is not final). Only canonical (mined) blocks can be
|
|
21
22
|
* pinned; `pending` has no stable hash and is rejected at runtime. */
|
|
22
23
|
readonly blockNumber?: bigint | Exclude<BlockTag, "pending">;
|
|
23
24
|
/** Caller-selected quotes and percentage tolerances. Omitted limits are unchecked. */
|
|
@@ -26,9 +26,13 @@ export declare function assertEndpointChain(params: {
|
|
|
26
26
|
*
|
|
27
27
|
* 1. **`eth_simulateV1`** — one `blockStateCalls` entry carrying the planned
|
|
28
28
|
* calls with their per-call `from`, `traceTransfers: true` so the node
|
|
29
|
-
* synthesizes native-ETH moves as transfer logs, and
|
|
30
|
-
* `
|
|
31
|
-
*
|
|
29
|
+
* synthesizes native-ETH moves as transfer logs, and `validation: false`
|
|
30
|
+
* (`true` on Monad, whose nodes reject `false` and charge no gas in the
|
|
31
|
+
* simulated block). Validation-off means gas is not charged, which is how
|
|
32
|
+
* gas is separated from economic effects. When `blockGasLimit` is set,
|
|
33
|
+
* it is sent as the block's `blockOverrides.gasLimit`; otherwise no block
|
|
34
|
+
* override is sent.
|
|
35
|
+
* **No balance override is
|
|
32
36
|
* applied** — `value` transfers are funded by the sender's real native
|
|
33
37
|
* balance.
|
|
34
38
|
* 2. **Response validation** — the response is parsed before the reorg
|
|
@@ -45,8 +49,9 @@ export declare function assertEndpointChain(params: {
|
|
|
45
49
|
* The endpoint must support `eth_simulateV1` with per-call `from`; there is
|
|
46
50
|
* no fallback backend.
|
|
47
51
|
*
|
|
48
|
-
* @param params - Shared simulation client, execution plan,
|
|
49
|
-
* state block
|
|
52
|
+
* @param params - Shared simulation client, execution plan, already-pinned
|
|
53
|
+
* state block, the `validation` flag to send, the optional simulated
|
|
54
|
+
* block gas limit, and whether to check the successor `parentHash`.
|
|
50
55
|
* @returns Deep-frozen {@link SimulationExecution} — per-transaction call
|
|
51
56
|
* results and the resolved {@link ExecutionBlock}.
|
|
52
57
|
* @throws {ExternalServiceError} For transport failures, timeouts,
|
|
@@ -66,5 +71,8 @@ export declare function executePlan(params: {
|
|
|
66
71
|
client: Client & Pick<PublicClient, "getBlock">;
|
|
67
72
|
plan: ExecutionPlan;
|
|
68
73
|
stateBlock: PinnedBlock;
|
|
74
|
+
validation: boolean;
|
|
75
|
+
blockGasLimit?: bigint | undefined;
|
|
76
|
+
parentHashCheck: boolean;
|
|
69
77
|
}): Promise<SimulationExecution>;
|
|
70
78
|
export {};
|
|
@@ -83,9 +83,13 @@ export async function assertEndpointChain(params) {
|
|
|
83
83
|
*
|
|
84
84
|
* 1. **`eth_simulateV1`** — one `blockStateCalls` entry carrying the planned
|
|
85
85
|
* calls with their per-call `from`, `traceTransfers: true` so the node
|
|
86
|
-
* synthesizes native-ETH moves as transfer logs, and
|
|
87
|
-
* `
|
|
88
|
-
*
|
|
86
|
+
* synthesizes native-ETH moves as transfer logs, and `validation: false`
|
|
87
|
+
* (`true` on Monad, whose nodes reject `false` and charge no gas in the
|
|
88
|
+
* simulated block). Validation-off means gas is not charged, which is how
|
|
89
|
+
* gas is separated from economic effects. When `blockGasLimit` is set,
|
|
90
|
+
* it is sent as the block's `blockOverrides.gasLimit`; otherwise no block
|
|
91
|
+
* override is sent.
|
|
92
|
+
* **No balance override is
|
|
89
93
|
* applied** — `value` transfers are funded by the sender's real native
|
|
90
94
|
* balance.
|
|
91
95
|
* 2. **Response validation** — the response is parsed before the reorg
|
|
@@ -102,8 +106,9 @@ export async function assertEndpointChain(params) {
|
|
|
102
106
|
* The endpoint must support `eth_simulateV1` with per-call `from`; there is
|
|
103
107
|
* no fallback backend.
|
|
104
108
|
*
|
|
105
|
-
* @param params - Shared simulation client, execution plan,
|
|
106
|
-
* state block
|
|
109
|
+
* @param params - Shared simulation client, execution plan, already-pinned
|
|
110
|
+
* state block, the `validation` flag to send, the optional simulated
|
|
111
|
+
* block gas limit, and whether to check the successor `parentHash`.
|
|
107
112
|
* @returns Deep-frozen {@link SimulationExecution} — per-transaction call
|
|
108
113
|
* results and the resolved {@link ExecutionBlock}.
|
|
109
114
|
* @throws {ExternalServiceError} For transport failures, timeouts,
|
|
@@ -120,13 +125,16 @@ export async function assertEndpointChain(params) {
|
|
|
120
125
|
* @internal
|
|
121
126
|
*/
|
|
122
127
|
export async function executePlan(params) {
|
|
123
|
-
const { client, plan, stateBlock } = params;
|
|
128
|
+
const { client, plan, stateBlock, validation, blockGasLimit, parentHashCheck, } = params;
|
|
124
129
|
const response = await rpc("eth_simulateV1", () => client.request({
|
|
125
130
|
method: "eth_simulateV1",
|
|
126
131
|
params: [
|
|
127
132
|
{
|
|
128
133
|
blockStateCalls: [
|
|
129
134
|
{
|
|
135
|
+
...(blockGasLimit !== undefined && {
|
|
136
|
+
blockOverrides: { gasLimit: numberToHex(blockGasLimit) },
|
|
137
|
+
}),
|
|
130
138
|
calls: plan.calls.map((call) => ({
|
|
131
139
|
from: call.transaction.from,
|
|
132
140
|
to: call.transaction.to,
|
|
@@ -136,7 +144,7 @@ export async function executePlan(params) {
|
|
|
136
144
|
},
|
|
137
145
|
],
|
|
138
146
|
traceTransfers: true,
|
|
139
|
-
validation
|
|
147
|
+
validation,
|
|
140
148
|
},
|
|
141
149
|
numberToHex(stateBlock.number),
|
|
142
150
|
],
|
|
@@ -152,6 +160,7 @@ export async function executePlan(params) {
|
|
|
152
160
|
stateBlockNumber: stateBlock.number,
|
|
153
161
|
stateBlockHash: stateBlock.hash,
|
|
154
162
|
stateBlockTimestamp: stateBlock.timestamp,
|
|
163
|
+
parentHashCheck,
|
|
155
164
|
});
|
|
156
165
|
// Reorg window: the pinned state block must still carry the same hash
|
|
157
166
|
// after simulation, or the result may describe a different chain tip.
|
|
@@ -54,8 +54,10 @@ export function parseSimulationResponse(params) {
|
|
|
54
54
|
}
|
|
55
55
|
// Anvil re-hashes the pinned block, so only the geth-style successor can be
|
|
56
56
|
// pinned by hash: it must report a parentHash (geth always does) equal to
|
|
57
|
-
// the pinned state block hash.
|
|
58
|
-
|
|
57
|
+
// the pinned state block hash. With `parentHashCheck` off (Stable by
|
|
58
|
+
// default) the block number, timestamp and reorg checks still apply.
|
|
59
|
+
if (params.parentHashCheck &&
|
|
60
|
+
blockNumber === params.stateBlockNumber + 1n &&
|
|
59
61
|
block.parentHash !== params.stateBlockHash) {
|
|
60
62
|
throw new InvalidSimulationResponseError(`eth_simulateV1 reported block ${blockNumber} whose parent ${String(block.parentHash)} is not the pinned state block hash ${params.stateBlockHash}; the node did not simulate on top of the pinned block.`, { context: errorContext });
|
|
61
63
|
}
|
|
@@ -4,6 +4,10 @@ import type { ChainSimulationConfig, SimulationConfig } from "../../types.js";
|
|
|
4
4
|
*
|
|
5
5
|
* Looks up the per-chain `ChainSimulationConfig`. Throws `UnsupportedChainError`
|
|
6
6
|
* when the chain is absent from the map or has no `simulateV1Url` (defensive —
|
|
7
|
-
* the type already requires it at construction).
|
|
7
|
+
* the type already requires it at construction). Throws
|
|
8
|
+
* `SimulationValidationError` when `blockOverrides.gasLimit` is set but is
|
|
9
|
+
* not a positive bigint, or `parentHashCheck` is set but is not a boolean, so a
|
|
10
|
+
* misconfiguration never surfaces as a bypassable
|
|
11
|
+
* `ExternalServiceError`.
|
|
8
12
|
*/
|
|
9
13
|
export declare function resolveChain(config: SimulationConfig, chainId: number): ChainSimulationConfig;
|
|
@@ -1,14 +1,25 @@
|
|
|
1
|
-
import { UnsupportedChainError } from "../../errors.js";
|
|
1
|
+
import { SimulationValidationError, UnsupportedChainError, } from "../../errors.js";
|
|
2
2
|
/**
|
|
3
3
|
* Stage 2 of the simulate() pipeline.
|
|
4
4
|
*
|
|
5
5
|
* Looks up the per-chain `ChainSimulationConfig`. Throws `UnsupportedChainError`
|
|
6
6
|
* when the chain is absent from the map or has no `simulateV1Url` (defensive —
|
|
7
|
-
* the type already requires it at construction).
|
|
7
|
+
* the type already requires it at construction). Throws
|
|
8
|
+
* `SimulationValidationError` when `blockOverrides.gasLimit` is set but is
|
|
9
|
+
* not a positive bigint, or `parentHashCheck` is set but is not a boolean, so a
|
|
10
|
+
* misconfiguration never surfaces as a bypassable
|
|
11
|
+
* `ExternalServiceError`.
|
|
8
12
|
*/
|
|
9
13
|
export function resolveChain(config, chainId) {
|
|
10
14
|
const entry = config.chains.get(chainId);
|
|
11
15
|
if (!entry?.simulateV1Url)
|
|
12
16
|
throw new UnsupportedChainError(chainId);
|
|
17
|
+
const gasLimit = entry.blockOverrides?.gasLimit;
|
|
18
|
+
if (gasLimit !== undefined &&
|
|
19
|
+
(typeof gasLimit !== "bigint" || gasLimit <= 0n))
|
|
20
|
+
throw new SimulationValidationError(`Chain ${chainId} blockOverrides.gasLimit must be a positive bigint, got "${String(gasLimit)}" (${typeof gasLimit}). Pass a bigint greater than 0n or omit gasLimit.`, ["blockOverrides.gasLimit: must be a positive bigint"]);
|
|
21
|
+
const parentHashCheck = entry.parentHashCheck;
|
|
22
|
+
if (parentHashCheck !== undefined && typeof parentHashCheck !== "boolean")
|
|
23
|
+
throw new SimulationValidationError(`Chain ${chainId} parentHashCheck must be a boolean, got "${String(parentHashCheck)}" (${typeof parentHashCheck}). Pass true or false, or omit parentHashCheck.`, ["parentHashCheck: must be a boolean"]);
|
|
13
24
|
return entry;
|
|
14
25
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getChainAddresses, UnsupportedChainIdError, } from "@morpho-org/blue-sdk";
|
|
1
|
+
import { ChainId, getChainAddresses, UnsupportedChainIdError, } from "@morpho-org/blue-sdk";
|
|
2
2
|
import { _try } from "@morpho-org/morpho-ts";
|
|
3
3
|
import { zeroAddress } from "viem";
|
|
4
4
|
import { InvalidSimulationResponseError, UnsupportedChainError, } from "../errors.js";
|
|
@@ -48,9 +48,13 @@ export async function runSimulation(params) {
|
|
|
48
48
|
mode: request.mode,
|
|
49
49
|
blockNumber: typeof request.blockNumber === "bigint" ? request.blockNumber : undefined,
|
|
50
50
|
});
|
|
51
|
+
// Monad nodes reject `validation: false` and charge no gas in the simulated
|
|
52
|
+
// block either way. Its `latest` block is not final: simulating at its number
|
|
53
|
+
// runs on another parent, so default to `finalized`.
|
|
54
|
+
const monad = request.chainId === ChainId.MonadMainnet;
|
|
51
55
|
const pinnedBlock = await resolvePinnedBlock({
|
|
52
56
|
client,
|
|
53
|
-
blockNumber: request.blockNumber,
|
|
57
|
+
blockNumber: request.blockNumber ?? (monad ? "finalized" : undefined),
|
|
54
58
|
signal,
|
|
55
59
|
});
|
|
56
60
|
// With no calldata decoding, the caller's declared `limits.operations`
|
|
@@ -83,6 +87,9 @@ export async function runSimulation(params) {
|
|
|
83
87
|
client,
|
|
84
88
|
plan,
|
|
85
89
|
stateBlock: pinnedBlock,
|
|
90
|
+
validation: monad,
|
|
91
|
+
blockGasLimit: chain.blockOverrides?.gasLimit,
|
|
92
|
+
parentHashCheck: chain.parentHashCheck ?? request.chainId !== ChainId.StableMainnet,
|
|
86
93
|
});
|
|
87
94
|
const userCalls = execution.calls
|
|
88
95
|
.filter((call) => call.planned.type === "transaction")
|
|
@@ -34,10 +34,12 @@ import type { SimulationConfig } from "../types.js";
|
|
|
34
34
|
* **Funding.** `value` transfers are funded by the sender's real native
|
|
35
35
|
* balance — no balance inflation — so under-funded bundles revert exactly as
|
|
36
36
|
* they would on-chain. `validation: false` keeps gas from being charged,
|
|
37
|
-
* separating gas from economic effects.
|
|
37
|
+
* separating gas from economic effects. Monad nodes reject `false`, so Monad
|
|
38
|
+
* simulations send `true`; its simulated block charges no gas either way.
|
|
38
39
|
*
|
|
39
|
-
* @param config - Required per-chain `eth_simulateV1` URL, optional
|
|
40
|
-
*
|
|
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.
|
|
41
43
|
* @param params - Per-call simulation input.
|
|
42
44
|
* @param params.chainId - Chain id the bundle targets; must match the endpoint.
|
|
43
45
|
* @param params.transactions - The bundle's transactions, in execution order.
|
|
@@ -47,10 +49,13 @@ import type { SimulationConfig } from "../types.js";
|
|
|
47
49
|
* @param params.limits - Optional quotes and percentage tolerances; unquoted amounts require no reads.
|
|
48
50
|
* @param params.blockNumber - Optional pinned block number or `BlockTag` other
|
|
49
51
|
* than `"pending"`.
|
|
50
|
-
* Defaults to `latest
|
|
52
|
+
* Defaults to `latest` (`finalized` on Monad, whose `latest` block is not
|
|
53
|
+
* final), resolved exactly once.
|
|
51
54
|
* @throws {SimulationValidationError} for invalid input (mixed senders, bad
|
|
52
55
|
* addresses, empty transactions, malformed authorizations, final-mode
|
|
53
|
-
* authorizations, malformed limits, unknown fields, a `"pending"` block tag,
|
|
56
|
+
* authorizations, malformed limits, unknown fields, a `"pending"` block tag, a
|
|
57
|
+
* `blockOverrides.gasLimit` that is not a positive bigint, a `parentHashCheck`
|
|
58
|
+
* that is not a boolean, or share quotes for
|
|
54
59
|
* `blueSupplyCollateral` / `blueWithdrawCollateral`).
|
|
55
60
|
* @throws {ConsumerLimitViolationError} when a declared `limits` bound is
|
|
56
61
|
* violated by the observed effects.
|
|
@@ -64,7 +69,7 @@ import type { SimulationConfig } from "../types.js";
|
|
|
64
69
|
* @throws {InvalidSimulationResponseError} when the node response cannot be
|
|
65
70
|
* trusted (bad shape, call-count mismatch, block that is neither the pinned
|
|
66
71
|
* state block nor its immediate successor, a successor with a mismatched
|
|
67
|
-
* `parentHash
|
|
72
|
+
* `parentHash` (unless `parentHashCheck` is off; off by default on Stable, chain 988), a block timestamp earlier than the pinned block's, a
|
|
68
73
|
* malformed per-call result, a quoted balance/position read whose non-empty
|
|
69
74
|
* return data cannot be decoded, a state-block hash that changed or a pinned
|
|
70
75
|
* block that vanished mid-flight, or an
|
|
@@ -33,10 +33,12 @@ import { runSimulation } from "./run-simulation.js";
|
|
|
33
33
|
* **Funding.** `value` transfers are funded by the sender's real native
|
|
34
34
|
* balance — no balance inflation — so under-funded bundles revert exactly as
|
|
35
35
|
* they would on-chain. `validation: false` keeps gas from being charged,
|
|
36
|
-
* separating gas from economic effects.
|
|
36
|
+
* separating gas from economic effects. Monad nodes reject `false`, so Monad
|
|
37
|
+
* simulations send `true`; its simulated block charges no gas either way.
|
|
37
38
|
*
|
|
38
|
-
* @param config - Required per-chain `eth_simulateV1` URL, optional
|
|
39
|
-
*
|
|
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.
|
|
40
42
|
* @param params - Per-call simulation input.
|
|
41
43
|
* @param params.chainId - Chain id the bundle targets; must match the endpoint.
|
|
42
44
|
* @param params.transactions - The bundle's transactions, in execution order.
|
|
@@ -46,10 +48,13 @@ import { runSimulation } from "./run-simulation.js";
|
|
|
46
48
|
* @param params.limits - Optional quotes and percentage tolerances; unquoted amounts require no reads.
|
|
47
49
|
* @param params.blockNumber - Optional pinned block number or `BlockTag` other
|
|
48
50
|
* than `"pending"`.
|
|
49
|
-
* Defaults to `latest
|
|
51
|
+
* Defaults to `latest` (`finalized` on Monad, whose `latest` block is not
|
|
52
|
+
* final), resolved exactly once.
|
|
50
53
|
* @throws {SimulationValidationError} for invalid input (mixed senders, bad
|
|
51
54
|
* addresses, empty transactions, malformed authorizations, final-mode
|
|
52
|
-
* authorizations, malformed limits, unknown fields, a `"pending"` block tag,
|
|
55
|
+
* authorizations, malformed limits, unknown fields, a `"pending"` block tag, a
|
|
56
|
+
* `blockOverrides.gasLimit` that is not a positive bigint, a `parentHashCheck`
|
|
57
|
+
* that is not a boolean, or share quotes for
|
|
53
58
|
* `blueSupplyCollateral` / `blueWithdrawCollateral`).
|
|
54
59
|
* @throws {ConsumerLimitViolationError} when a declared `limits` bound is
|
|
55
60
|
* violated by the observed effects.
|
|
@@ -63,7 +68,7 @@ import { runSimulation } from "./run-simulation.js";
|
|
|
63
68
|
* @throws {InvalidSimulationResponseError} when the node response cannot be
|
|
64
69
|
* trusted (bad shape, call-count mismatch, block that is neither the pinned
|
|
65
70
|
* state block nor its immediate successor, a successor with a mismatched
|
|
66
|
-
* `parentHash
|
|
71
|
+
* `parentHash` (unless `parentHashCheck` is off; off by default on Stable, chain 988), a block timestamp earlier than the pinned block's, a
|
|
67
72
|
* malformed per-call result, a quoted balance/position read whose non-empty
|
|
68
73
|
* return data cannot be decoded, a state-block hash that changed or a pinned
|
|
69
74
|
* block that vanished mid-flight, or an
|
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, timestamp and reorg 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`.
|
|
@@ -145,7 +160,8 @@ export interface SimulationCall {
|
|
|
145
160
|
* Gas consumed by this call's root frame, not a safe gas limit. This is
|
|
146
161
|
* post-refund consumption and does not account for EIP-150's 63/64 rule in
|
|
147
162
|
* nested calls, so consumers deriving a limit must add their own headroom,
|
|
148
|
-
* larger than headroom derived from `eth_estimateGas`.
|
|
163
|
+
* larger than headroom derived from `eth_estimateGas`. On Monad it reports the
|
|
164
|
+
* call's gas limit (150M by default) instead of gas consumed.
|
|
149
165
|
*/
|
|
150
166
|
readonly gasUsed: bigint;
|
|
151
167
|
}
|
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": "5.
|
|
4
|
+
"version": "5.1.0",
|
|
5
5
|
"author": "Morpho Association <contact@morpho.org>",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@morpho-org/blue-sdk": "^7.2.0",
|
|
25
|
-
"@morpho-org/morpho-sdk": "^6.
|
|
26
|
-
"@morpho-org/morpho-ts": "^3.2.
|
|
25
|
+
"@morpho-org/morpho-sdk": "^6.6.0",
|
|
26
|
+
"@morpho-org/morpho-ts": "^3.2.1"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"viem": "^2.0.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@morpho-org/test": "^2.10.
|
|
32
|
+
"@morpho-org/test": "^2.10.1",
|
|
33
33
|
"fast-check": "^4.9.0",
|
|
34
34
|
"typescript": "7.0.2",
|
|
35
35
|
"viem": "^2.55.10",
|