@morpho-org/evm-simulation 4.2.1 → 5.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 +109 -17
- package/lib/cjs/authorizations.d.ts +95 -0
- package/lib/cjs/authorizations.js +2 -0
- package/lib/cjs/errors.d.ts +199 -12
- package/lib/cjs/errors.js +190 -12
- package/lib/cjs/index.d.ts +10 -2
- package/lib/cjs/index.js +19 -3
- package/lib/cjs/limits.d.ts +112 -0
- package/lib/cjs/limits.js +50 -0
- package/lib/cjs/params.d.ts +25 -0
- package/lib/cjs/params.js +5 -0
- package/lib/cjs/requirements/index.d.ts +1 -0
- package/lib/cjs/requirements/index.js +5 -0
- package/lib/cjs/requirements/requirements.d.ts +64 -0
- package/lib/cjs/requirements/requirements.js +149 -0
- package/lib/cjs/result.d.ts +49 -0
- package/lib/cjs/result.js +2 -0
- package/lib/cjs/simulate/asset-changes.d.ts +7 -5
- package/lib/cjs/simulate/asset-changes.js +6 -5
- package/lib/cjs/simulate/backends/client.d.ts +16 -0
- package/lib/cjs/simulate/backends/client.js +27 -0
- package/lib/cjs/simulate/backends/eth-simulate-v1.d.ts +66 -20
- package/lib/cjs/simulate/backends/eth-simulate-v1.js +172 -98
- package/lib/cjs/simulate/backends/index.d.ts +1 -2
- package/lib/cjs/simulate/backends/index.js +3 -4
- package/lib/cjs/simulate/backends/parse-response.d.ts +69 -0
- package/lib/cjs/simulate/backends/parse-response.js +168 -0
- package/lib/cjs/simulate/backends/resolve-assets.d.ts +26 -0
- package/lib/cjs/simulate/backends/resolve-assets.js +111 -0
- package/lib/cjs/simulate/backends/resolve-pinned-block.d.ts +33 -0
- package/lib/cjs/simulate/backends/resolve-pinned-block.js +46 -0
- package/lib/cjs/simulate/context.d.ts +14 -0
- package/lib/cjs/simulate/context.js +2 -0
- package/lib/cjs/simulate/measurement-plan.d.ts +29 -0
- package/lib/cjs/simulate/measurement-plan.js +115 -0
- package/lib/cjs/simulate/parsing/transfers.d.ts +4 -3
- package/lib/cjs/simulate/parsing/transfers.js +4 -6
- package/lib/cjs/simulate/pipeline/bundles-retention.d.ts +7 -10
- package/lib/cjs/simulate/pipeline/bundles-retention.js +11 -14
- package/lib/cjs/simulate/pipeline/resolve-chain.d.ts +5 -11
- package/lib/cjs/simulate/pipeline/resolve-chain.js +5 -10
- package/lib/cjs/simulate/plan/plan-execution.d.ts +58 -0
- package/lib/cjs/simulate/plan/plan-execution.js +75 -0
- package/lib/cjs/simulate/prepare.d.ts +30 -0
- package/lib/cjs/simulate/prepare.js +80 -0
- package/lib/cjs/simulate/request/index.d.ts +1 -0
- package/lib/cjs/simulate/request/index.js +5 -0
- package/lib/cjs/simulate/request/parse-request.d.ts +44 -0
- package/lib/cjs/simulate/request/parse-request.js +759 -0
- package/lib/cjs/simulate/result.d.ts +19 -0
- package/lib/cjs/simulate/result.js +29 -0
- package/lib/cjs/simulate/run-simulation.d.ts +18 -0
- package/lib/cjs/simulate/run-simulation.js +151 -0
- package/lib/cjs/simulate/simulate.d.ts +100 -51
- package/lib/cjs/simulate/simulate.js +99 -82
- package/lib/cjs/simulate/slippage.d.ts +18 -0
- package/lib/cjs/simulate/slippage.js +41 -0
- package/lib/cjs/simulate/state/contract.d.ts +19 -0
- package/lib/cjs/simulate/state/contract.js +2 -0
- package/lib/cjs/simulate/state/read-state.d.ts +60 -0
- package/lib/cjs/simulate/state/read-state.js +148 -0
- package/lib/cjs/simulate/verify-slippage.d.ts +24 -0
- package/lib/cjs/simulate/verify-slippage.js +85 -0
- package/lib/cjs/types.d.ts +35 -95
- package/lib/esm/authorizations.d.ts +95 -0
- package/lib/esm/authorizations.js +1 -0
- package/lib/esm/errors.d.ts +199 -12
- package/lib/esm/errors.js +182 -11
- package/lib/esm/index.d.ts +10 -2
- package/lib/esm/index.js +4 -1
- package/lib/esm/limits.d.ts +112 -0
- package/lib/esm/limits.js +47 -0
- package/lib/esm/params.d.ts +25 -0
- package/lib/esm/params.js +2 -0
- package/lib/esm/requirements/index.d.ts +1 -0
- package/lib/esm/requirements/index.js +1 -0
- package/lib/esm/requirements/requirements.d.ts +64 -0
- package/lib/esm/requirements/requirements.js +146 -0
- package/lib/esm/result.d.ts +49 -0
- package/lib/esm/result.js +1 -0
- package/lib/esm/simulate/asset-changes.d.ts +7 -5
- package/lib/esm/simulate/asset-changes.js +6 -5
- package/lib/esm/simulate/backends/client.d.ts +16 -0
- package/lib/esm/simulate/backends/client.js +24 -0
- package/lib/esm/simulate/backends/eth-simulate-v1.d.ts +66 -20
- package/lib/esm/simulate/backends/eth-simulate-v1.js +170 -99
- package/lib/esm/simulate/backends/index.d.ts +1 -2
- package/lib/esm/simulate/backends/index.js +1 -2
- package/lib/esm/simulate/backends/parse-response.d.ts +69 -0
- package/lib/esm/simulate/backends/parse-response.js +165 -0
- package/lib/esm/simulate/backends/resolve-assets.d.ts +26 -0
- package/lib/esm/simulate/backends/resolve-assets.js +108 -0
- package/lib/esm/simulate/backends/resolve-pinned-block.d.ts +33 -0
- package/lib/esm/simulate/backends/resolve-pinned-block.js +43 -0
- package/lib/esm/simulate/context.d.ts +14 -0
- package/lib/esm/simulate/context.js +1 -0
- package/lib/esm/simulate/measurement-plan.d.ts +29 -0
- package/lib/esm/simulate/measurement-plan.js +112 -0
- package/lib/esm/simulate/parsing/transfers.d.ts +4 -3
- package/lib/esm/simulate/parsing/transfers.js +4 -6
- package/lib/esm/simulate/pipeline/bundles-retention.d.ts +7 -10
- package/lib/esm/simulate/pipeline/bundles-retention.js +11 -14
- package/lib/esm/simulate/pipeline/resolve-chain.d.ts +5 -11
- package/lib/esm/simulate/pipeline/resolve-chain.js +5 -10
- package/lib/esm/simulate/plan/plan-execution.d.ts +58 -0
- package/lib/esm/simulate/plan/plan-execution.js +72 -0
- package/lib/esm/simulate/prepare.d.ts +30 -0
- package/lib/esm/simulate/prepare.js +77 -0
- package/lib/esm/simulate/request/index.d.ts +1 -0
- package/lib/esm/simulate/request/index.js +1 -0
- package/lib/esm/simulate/request/parse-request.d.ts +44 -0
- package/lib/esm/simulate/request/parse-request.js +756 -0
- package/lib/esm/simulate/result.d.ts +19 -0
- package/lib/esm/simulate/result.js +26 -0
- package/lib/esm/simulate/run-simulation.d.ts +18 -0
- package/lib/esm/simulate/run-simulation.js +148 -0
- package/lib/esm/simulate/simulate.d.ts +100 -51
- package/lib/esm/simulate/simulate.js +99 -82
- package/lib/esm/simulate/slippage.d.ts +18 -0
- package/lib/esm/simulate/slippage.js +38 -0
- package/lib/esm/simulate/state/contract.d.ts +19 -0
- package/lib/esm/simulate/state/contract.js +1 -0
- package/lib/esm/simulate/state/read-state.d.ts +60 -0
- package/lib/esm/simulate/state/read-state.js +144 -0
- package/lib/esm/simulate/verify-slippage.d.ts +24 -0
- package/lib/esm/simulate/verify-slippage.js +82 -0
- package/lib/esm/types.d.ts +35 -95
- package/package.json +7 -6
- package/lib/cjs/simulate/authorizations/index.d.ts +0 -2
- package/lib/cjs/simulate/authorizations/index.js +0 -7
- package/lib/cjs/simulate/authorizations/resolve.d.ts +0 -9
- package/lib/cjs/simulate/authorizations/resolve.js +0 -29
- package/lib/cjs/simulate/authorizations/validate.d.ts +0 -6
- package/lib/cjs/simulate/authorizations/validate.js +0 -23
- package/lib/cjs/simulate/backends/tenderly-rpc.d.ts +0 -23
- package/lib/cjs/simulate/backends/tenderly-rpc.js +0 -234
- package/lib/cjs/simulate/pipeline/build-simulation-txs.d.ts +0 -17
- package/lib/cjs/simulate/pipeline/build-simulation-txs.js +0 -50
- package/lib/cjs/simulate/pipeline/execute-simulation.d.ts +0 -22
- package/lib/cjs/simulate/pipeline/execute-simulation.js +0 -82
- package/lib/cjs/simulate/pipeline/index.d.ts +0 -4
- package/lib/cjs/simulate/pipeline/index.js +0 -11
- package/lib/cjs/simulate/pipeline/validate-input.d.ts +0 -10
- package/lib/cjs/simulate/pipeline/validate-input.js +0 -55
- package/lib/esm/simulate/authorizations/index.d.ts +0 -2
- package/lib/esm/simulate/authorizations/index.js +0 -2
- package/lib/esm/simulate/authorizations/resolve.d.ts +0 -9
- package/lib/esm/simulate/authorizations/resolve.js +0 -26
- package/lib/esm/simulate/authorizations/validate.d.ts +0 -6
- package/lib/esm/simulate/authorizations/validate.js +0 -20
- package/lib/esm/simulate/backends/tenderly-rpc.d.ts +0 -23
- package/lib/esm/simulate/backends/tenderly-rpc.js +0 -231
- package/lib/esm/simulate/pipeline/build-simulation-txs.d.ts +0 -17
- package/lib/esm/simulate/pipeline/build-simulation-txs.js +0 -47
- package/lib/esm/simulate/pipeline/execute-simulation.d.ts +0 -22
- package/lib/esm/simulate/pipeline/execute-simulation.js +0 -79
- package/lib/esm/simulate/pipeline/index.d.ts +0 -4
- package/lib/esm/simulate/pipeline/index.js +0 -4
- package/lib/esm/simulate/pipeline/validate-input.d.ts +0 -10
- package/lib/esm/simulate/pipeline/validate-input.js +0 -52
package/README.md
CHANGED
|
@@ -22,13 +22,7 @@ import {
|
|
|
22
22
|
|
|
23
23
|
const config: SimulationConfig = {
|
|
24
24
|
chains: new Map([
|
|
25
|
-
[
|
|
26
|
-
1,
|
|
27
|
-
{
|
|
28
|
-
tenderlyRpc: { rpcUrl: process.env.TENDERLY_RPC_URL! },
|
|
29
|
-
simulateV1Url: process.env.MAINNET_RPC_URL,
|
|
30
|
-
},
|
|
31
|
-
],
|
|
25
|
+
[1, { simulateV1Url: process.env.MAINNET_RPC_URL! }],
|
|
32
26
|
]),
|
|
33
27
|
timeoutMs: 5000,
|
|
34
28
|
};
|
|
@@ -38,35 +32,133 @@ try {
|
|
|
38
32
|
config,
|
|
39
33
|
{
|
|
40
34
|
chainId: 1,
|
|
35
|
+
// mode: "final" (default) executes the signed calldata against actual
|
|
36
|
+
// permissions; mode: "preview" accepts typed authorization descriptors.
|
|
41
37
|
transactions: [{ from: user, to: vault, data: encodedDeposit }],
|
|
42
|
-
|
|
38
|
+
// limits: { operations: [{ type: "vaultV1Deposit", vault, quote: { sharesMinted: 1000n }, slippageTolerance: 10_000000000000000n }] },
|
|
43
39
|
},
|
|
44
40
|
);
|
|
45
41
|
} catch (err) {
|
|
46
42
|
if (err instanceof SimulationRevertedError) {
|
|
47
|
-
// show err.reason to the user
|
|
43
|
+
// show err.reason to the user; err.reasonCode is currently always "UNKNOWN_REVERT"
|
|
48
44
|
}
|
|
49
45
|
throw err;
|
|
50
46
|
}
|
|
51
47
|
```
|
|
52
48
|
|
|
53
|
-
|
|
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.
|
|
50
|
+
|
|
51
|
+
Native-ETH movements are observed through `traceTransfers` logs on the simulated calls — no `stateOverrides` or helper contracts are injected.
|
|
52
|
+
|
|
53
|
+
This is the unreleased v5 integration stack. See the [v4 → v5 migration guide](../../docs/migrations/evm-simulation-v4-to-v5.md) for the backend cutover and remaining release gates.
|
|
54
54
|
|
|
55
55
|
### API surface
|
|
56
56
|
|
|
57
57
|
All symbols below are re-exported from the package root.
|
|
58
58
|
|
|
59
59
|
- `simulate(config, params)` — run a bundle through the simulation pipeline.
|
|
60
|
-
- Config types: `SimulationConfig`, `
|
|
61
|
-
- Input types: `SimulateParams`, `
|
|
60
|
+
- Config types: `SimulationConfig`, `ChainSimulationConfig`, `SimulationLogger`.
|
|
61
|
+
- Input types: `SimulateParams` (v5 shape: `mode`, `SimulationAuthorization` requests, `SimulationLimits`), `SimulationMode`, `SimulationTransaction`.
|
|
62
|
+
- `toSimulationAuthorizations({ chainId, mode, blockNumber, owner, requirements })` — map morpho-sdk `ActionRequirement[]` onto `SimulationAuthorization[]` straight from `action.args` — nothing is decoded or validated; validation happens in `simulate()`'s request parser.
|
|
63
|
+
- Authorizations and limits: `SimulationAuthorization` and its members (`Erc20ApprovalAuthorization`, `Erc2612PermitAuthorization`, `Permit2TransferAuthorization`, `BlueAuthorization`, `BlueAuthorizationSignature`) with their EIP-712 payloads (`Eip712Domain`, `Eip712Field`, `Erc2612PermitTypedData`, `Permit2TransferTypedData`, `BlueAuthorizationTypedData`); `SimulationLimits`, `OperationLimit`, and the shared `SlippageLimits` and `SlippageQuote`.
|
|
64
|
+
- Slippage-check result types: `VerifiedSimulationResult`, `SimulationVerification`, `SimulatedOperation`, `AuthorizationPreparation`.
|
|
62
65
|
- Result types: `SimulationResult`, `SimulationCall`, `Transfer`, `AccountAssetChanges`, `AssetChange`, `RawLog`.
|
|
63
|
-
- Errors: `SimulationPackageError` (abstract base — `instanceof` it to catch any package error), `SimulationRevertedError`, `BlacklistViolationError`, `ExternalServiceError`, `SimulationValidationError`, `UnsupportedChainError`.
|
|
66
|
+
- Errors: `SimulationPackageError` (abstract base — `instanceof` it to catch any package error), `SimulationRevertedError`, `BlacklistViolationError`, `ExternalServiceError`, `SimulationValidationError`, `UnsupportedChainError`, and the verification errors `UnsupportedOperationError`, `InvalidSimulationResponseError`, `MissingVerificationEvidenceError`, `AuthorizationRequestMismatchError`, `ConsumerLimitViolationError`, `UnexpectedSimulationError`.
|
|
67
|
+
- Error helpers: `SIMULATION_ERROR_CODES` / `SimulationErrorCode` (every `error.code`), `SimulationErrorContext` (frozen `error.context`; union of the per-stage `SimulationValidationContext`, `SimulationTransportContext`, `SimulationPreparationContext`, `SimulationExecutionContext`, `SimulationVerificationContext`), `SimulationStage`, `SimulationExecutionReason` (`SimulationRevertedError.reasonCode`), `isSimulationPackageError` (structural guard narrowing to `SimulationPackageError`), `RetainedAsset`.
|
|
68
|
+
- Verification vocabulary: `SIMULATION_MODES` / `SimulationMode`, `OPERATION_TYPES` / `OperationType`, `BLUE_MARKET_OPERATION_TYPES` / `BlueMarketOperationType`, `VAULT_OPERATION_TYPES` / `VaultOperationType`, `SimulationOperationSubject` and its members `BlueMarketOperationSubject`, `BlueRefinanceSubject`, `VaultOperationSubject`, `VaultV1MigrateToV2Subject` (operation groups and the operation-keyed subject union that key limit-bound verification `SimulationErrorContext`s).
|
|
69
|
+
### Optional limits
|
|
70
|
+
|
|
71
|
+
The caller chooses the action, subject, quote, and percentage tolerance. Each
|
|
72
|
+
entry supplies `quote` with at least one raw-unit amount: `assetsReceived`,
|
|
73
|
+
`sharesMinted`, `assetsPaid`, or `sharesBurned`, plus `slippageTolerance` as a
|
|
74
|
+
WAD-scaled fraction (`10_000000000000000n` = 1%, `1e18` = 100%). Tolerance must
|
|
75
|
+
be between 0 and 100% inclusive; it has no default. Omit `limits` to skip checks.
|
|
76
|
+
Unquoted amounts stay unchecked. The simulator never decodes calldata or fetches
|
|
77
|
+
a quote to infer constraints.
|
|
78
|
+
Unknown input keys are rejected as `SimulationValidationError` rather than
|
|
79
|
+
silently ignored.
|
|
80
|
+
|
|
81
|
+
Non-empty `limits.operations` and preview authorizations require a Morpho Blue
|
|
82
|
+
address registered in blue-sdk's `getChainAddresses`; otherwise
|
|
83
|
+
`UnsupportedChainError` is thrown.
|
|
84
|
+
|
|
85
|
+
Received assets and minted supply shares must be at least
|
|
86
|
+
`ceil(quote * (1 - tolerance))`; paid assets and burned supply shares must be at
|
|
87
|
+
most `floor(quote * (1 + tolerance))`. For debt shares, minting is capped at
|
|
88
|
+
`floor(quote * (1 + tolerance))` and burning must be at least
|
|
89
|
+
`ceil(quote * (1 - tolerance))`. Equality and favorable movement pass.
|
|
64
90
|
|
|
65
|
-
|
|
91
|
+
```ts
|
|
92
|
+
const result = await simulate(config, {
|
|
93
|
+
chainId: 1,
|
|
94
|
+
transactions,
|
|
95
|
+
limits: {
|
|
96
|
+
operations: [{
|
|
97
|
+
type: "vaultV1Deposit",
|
|
98
|
+
vault,
|
|
99
|
+
account: user, // Share/position owner; defaults to transaction sender.
|
|
100
|
+
receiver: user, // Asset recipient; defaults to transaction sender.
|
|
101
|
+
quote: { sharesMinted: 1_000n, assetsPaid: 1_000n },
|
|
102
|
+
slippageTolerance: 10_000000000000000n, // 1%
|
|
103
|
+
}],
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
// result.verification.operations[0].checkedLimits contains this quote and tolerance.
|
|
107
|
+
```
|
|
66
108
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
109
|
+
Measurements cover the named subject over the **whole bundle**. Entries do not
|
|
110
|
+
attribute aggregate state changes to individual transactions. Use separate
|
|
111
|
+
simulations for per-transaction limits. Asset bounds use net wallet balance
|
|
112
|
+
changes (gas excluded). For native ETH, set `assetPaid` or `assetReceived` to
|
|
113
|
+
viem's `ethAddress` (`0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`); other
|
|
114
|
+
sentinels such as `zeroAddress` are read as ERC-20 tokens. Share bounds use the
|
|
115
|
+
selected account's vault shares or Blue position shares. Borrow/repay entries
|
|
116
|
+
use debt shares; refinance selects
|
|
117
|
+
source shares burned and target shares minted; migration selects source vault
|
|
118
|
+
shares burned and target vault shares minted. Combined collateral/borrow actions
|
|
119
|
+
measure collateral paid and loan assets received; repay/collateral-withdraw actions
|
|
120
|
+
measure loan assets paid and collateral received.
|
|
121
|
+
|
|
122
|
+
For `vaultV1InKindRedeem` and `vaultV2InKindRedeem`, `assetsReceived` measures
|
|
123
|
+
only the receiver's wallet balance of the vault asset (the idle portion); it
|
|
124
|
+
does not measure in-kind Morpho positions.
|
|
125
|
+
|
|
126
|
+
Only slippage is checked; there are no separate refund or penalty checks.
|
|
127
|
+
`sharesMinted` and `sharesBurned` quotes for `blueSupplyCollateral` and
|
|
128
|
+
`blueWithdrawCollateral` are invalid and throw `SimulationValidationError`
|
|
129
|
+
during request parsing. `MissingVerificationEvidenceError` reports runtime
|
|
130
|
+
evidence gaps: a failed state read, native outgoing traces that do not cover
|
|
131
|
+
value sent, or a metadata read that reverts or returns empty/invalid
|
|
132
|
+
data. A quoted balance/position read whose non-empty return data cannot be
|
|
133
|
+
decoded throws `InvalidSimulationResponseError`. Excessive slippage throws
|
|
134
|
+
`ConsumerLimitViolationError`.
|
|
135
|
+
|
|
136
|
+
Only quoted amounts are observed. ERC-20 assets and vault shares use `balanceOf`;
|
|
137
|
+
Blue shares use `position`. Each distinct call runs before and after the bundle.
|
|
138
|
+
Native amounts use the existing transfer traces. Without limits there are no
|
|
139
|
+
slippage reads. Quotes with an asset amount resolve `asset()` or market parameters only
|
|
140
|
+
when an explicit `assetPaid` or `assetReceived` was not supplied; share-only quotes need no metadata
|
|
141
|
+
reads. No vault factories, full entities, allocations, risk metrics, allowances,
|
|
142
|
+
or nonces are fetched for slippage.
|
|
143
|
+
|
|
144
|
+
For example, a Vault V2 deposit quoting assets paid and shares minted makes four
|
|
145
|
+
in-bundle view calls — the sender's asset balance and the `account`'s share balance, each before
|
|
146
|
+
and after execution — plus one `asset()` read unless `assetPaid` is supplied. `verification.operations[].checkedLimits` records the quote
|
|
147
|
+
and tolerance checked. The result does not include broad state snapshots or diffs;
|
|
148
|
+
`transfers` and `assetChanges` remain available.
|
|
149
|
+
|
|
150
|
+
The result's historical `VerifiedSimulationResult` name does not imply that
|
|
151
|
+
unchecked outcomes are economically verified.
|
|
152
|
+
|
|
153
|
+
Preview authorizations remain an adapter from `getRequirements()` through
|
|
154
|
+
`toSimulationAuthorizations` into preparation calls. No permission or nonce
|
|
155
|
+
read-back policy runs. Successful execution establishes success under the
|
|
156
|
+
simulated permissions; it does not prove that a future signature is valid.
|
|
157
|
+
Preparation and user-transaction failures still propagate. Final mode executes
|
|
158
|
+
actual calldata without preparation. State reads and preparation calls do not
|
|
159
|
+
receive public transaction indices.
|
|
160
|
+
|
|
161
|
+
See [AGENTS.md](./AGENTS.md) for pipeline conventions and retention rules.
|
|
70
162
|
|
|
71
163
|
## Development
|
|
72
164
|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Address, Hex } from "viem";
|
|
2
|
+
/** EIP-712 domain separator fields of a signature payload. */
|
|
3
|
+
export interface Eip712Domain {
|
|
4
|
+
readonly name?: string;
|
|
5
|
+
readonly version?: string;
|
|
6
|
+
readonly chainId: number | bigint;
|
|
7
|
+
readonly verifyingContract: Address;
|
|
8
|
+
readonly salt?: Hex;
|
|
9
|
+
}
|
|
10
|
+
/** One entry of an EIP-712 `types` field list. */
|
|
11
|
+
export interface Eip712Field {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly type: string;
|
|
14
|
+
}
|
|
15
|
+
/** ERC-2612 `Permit` typed data; `domain.verifyingContract` is the token. */
|
|
16
|
+
export interface Erc2612PermitTypedData {
|
|
17
|
+
readonly domain: Eip712Domain;
|
|
18
|
+
readonly primaryType: "Permit";
|
|
19
|
+
readonly types: {
|
|
20
|
+
readonly Permit: readonly Eip712Field[];
|
|
21
|
+
};
|
|
22
|
+
readonly message: {
|
|
23
|
+
readonly owner: Address;
|
|
24
|
+
readonly spender: Address;
|
|
25
|
+
readonly value: bigint;
|
|
26
|
+
readonly nonce: bigint;
|
|
27
|
+
readonly deadline: bigint;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** Permit2 `PermitTransferFrom` typed data; the owner is not in the message. */
|
|
31
|
+
export interface Permit2TransferTypedData {
|
|
32
|
+
readonly domain: Eip712Domain;
|
|
33
|
+
readonly primaryType: "PermitTransferFrom";
|
|
34
|
+
readonly types: {
|
|
35
|
+
readonly PermitTransferFrom: readonly Eip712Field[];
|
|
36
|
+
readonly TokenPermissions: readonly Eip712Field[];
|
|
37
|
+
};
|
|
38
|
+
readonly message: {
|
|
39
|
+
readonly permitted: {
|
|
40
|
+
readonly token: Address;
|
|
41
|
+
readonly amount: bigint;
|
|
42
|
+
};
|
|
43
|
+
readonly spender: Address;
|
|
44
|
+
readonly nonce: bigint;
|
|
45
|
+
readonly deadline: bigint;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** Morpho `Authorization` typed data consumed by `setAuthorizationWithSig`. */
|
|
49
|
+
export interface BlueAuthorizationTypedData {
|
|
50
|
+
readonly domain: Eip712Domain;
|
|
51
|
+
readonly primaryType: "Authorization";
|
|
52
|
+
readonly types: {
|
|
53
|
+
readonly Authorization: readonly Eip712Field[];
|
|
54
|
+
};
|
|
55
|
+
readonly message: {
|
|
56
|
+
readonly authorizer: Address;
|
|
57
|
+
readonly authorized: Address;
|
|
58
|
+
readonly isAuthorized: boolean;
|
|
59
|
+
readonly nonce: bigint;
|
|
60
|
+
readonly deadline: bigint;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Raw ERC-20 `approve` request. */
|
|
64
|
+
export interface Erc20ApprovalAuthorization {
|
|
65
|
+
readonly type: "erc20Approval";
|
|
66
|
+
readonly token: Address;
|
|
67
|
+
readonly owner: Address;
|
|
68
|
+
readonly spender: Address;
|
|
69
|
+
readonly amount: bigint;
|
|
70
|
+
}
|
|
71
|
+
/** ERC-2612 permit request. */
|
|
72
|
+
export interface Erc2612PermitAuthorization {
|
|
73
|
+
readonly type: "erc2612Permit";
|
|
74
|
+
readonly typedData: Erc2612PermitTypedData;
|
|
75
|
+
}
|
|
76
|
+
/** Permit2 signature transfer request. */
|
|
77
|
+
export interface Permit2TransferAuthorization {
|
|
78
|
+
readonly type: "permit2SignatureTransfer";
|
|
79
|
+
readonly owner: Address;
|
|
80
|
+
readonly typedData: Permit2TransferTypedData;
|
|
81
|
+
}
|
|
82
|
+
/** Direct Morpho `setAuthorization` request. */
|
|
83
|
+
export interface BlueAuthorization {
|
|
84
|
+
readonly type: "blueAuthorization";
|
|
85
|
+
readonly authorizer: Address;
|
|
86
|
+
readonly authorized: Address;
|
|
87
|
+
readonly isAuthorized: boolean;
|
|
88
|
+
}
|
|
89
|
+
/** Morpho `setAuthorizationWithSig` request. */
|
|
90
|
+
export interface BlueAuthorizationSignature {
|
|
91
|
+
readonly type: "blueAuthorizationSignature";
|
|
92
|
+
readonly typedData: BlueAuthorizationTypedData;
|
|
93
|
+
}
|
|
94
|
+
/** A pending wallet request passed to `simulate()` — the five typed variants. */
|
|
95
|
+
export type SimulationAuthorization = Erc20ApprovalAuthorization | Erc2612PermitAuthorization | Permit2TransferAuthorization | BlueAuthorization | BlueAuthorizationSignature;
|
package/lib/cjs/errors.d.ts
CHANGED
|
@@ -1,23 +1,138 @@
|
|
|
1
|
+
import type { Address, Hash } from "viem";
|
|
2
|
+
import type { SimulationOperationSubject } from "./limits.js";
|
|
3
|
+
import type { SimulationMode } from "./params.js";
|
|
4
|
+
/** Stable error codes thrown by this package, part of the public API. */
|
|
5
|
+
export declare const SIMULATION_ERROR_CODES: readonly ["VALIDATION_ERROR", "UNSUPPORTED_CHAIN", "EXTERNAL_SERVICE_ERROR", "SIMULATION_REVERTED", "BLACKLIST_ERROR", "UNSUPPORTED_OPERATION", "INVALID_SIMULATION_RESPONSE", "MISSING_VERIFICATION_EVIDENCE", "AUTHORIZATION_REQUEST_MISMATCH", "CONSUMER_LIMIT_VIOLATION", "UNEXPECTED_SIMULATION_ERROR"];
|
|
6
|
+
/** Stable string discriminator for log aggregation and external mapping. */
|
|
7
|
+
export type SimulationErrorCode = (typeof SIMULATION_ERROR_CODES)[number];
|
|
8
|
+
/**
|
|
9
|
+
* Machine-readable cause of an execution failure (ADR-2026-09-18 §Errors).
|
|
10
|
+
* `UNKNOWN_REVERT` is used when the revert maps to no known Morpho condition;
|
|
11
|
+
* consumers branch on it and never parse `reason`.
|
|
12
|
+
*/
|
|
13
|
+
export type SimulationExecutionReason = "INSUFFICIENT_BALANCE" | "INSUFFICIENT_ALLOWANCE" | "INSUFFICIENT_LIQUIDITY" | "POSITION_UNHEALTHY" | "SLIPPAGE_EXCEEDED" | "SIGNATURE_EXPIRED" | "SIGNATURE_INVALID" | "NONCE_ALREADY_USED" | "CAP_EXCEEDED" | "ACCESS_RESTRICTED" | "UNKNOWN_REVERT";
|
|
14
|
+
declare const SIMULATION_STAGES: readonly ["validation", "preparation", "execution", "verification", "transport"];
|
|
15
|
+
/** Pipeline stage a failure belongs to; `transport` covers RPC and response failures. */
|
|
16
|
+
export type SimulationStage = (typeof SIMULATION_STAGES)[number];
|
|
17
|
+
interface SimulationContextBase {
|
|
18
|
+
/** Request mode the failure happened in. */
|
|
19
|
+
readonly mode: SimulationMode;
|
|
20
|
+
/** Chain the request targeted. */
|
|
21
|
+
readonly chainId: number;
|
|
22
|
+
/** Block the simulation was pinned to. */
|
|
23
|
+
readonly blockNumber: bigint;
|
|
24
|
+
}
|
|
25
|
+
interface SimulationCheckContext extends SimulationContextBase {
|
|
26
|
+
/** Token whose balance, allowance or transfer was checked. */
|
|
27
|
+
readonly token?: Address;
|
|
28
|
+
/** Account whose position, balance or authorization was checked (usually the sender). */
|
|
29
|
+
readonly account?: Address;
|
|
30
|
+
/** Spender or operator granted by the checked permission. */
|
|
31
|
+
readonly spender?: Address;
|
|
32
|
+
/**
|
|
33
|
+
* Name of the checked field (e.g. `"assetsReceived"`). Unbound verification
|
|
34
|
+
* contexts instead carry the failed state read's id
|
|
35
|
+
* (`balance:<token>:<account>` or `position:<marketId>:<account>`).
|
|
36
|
+
*/
|
|
37
|
+
readonly field?: string;
|
|
38
|
+
/** Bound or value `field` was checked against; 32-byte hashes only, never calldata or signatures. */
|
|
39
|
+
readonly expected?: bigint | boolean | Address | Hash;
|
|
40
|
+
/** Value observed in the simulation, same domain as `expected`. */
|
|
41
|
+
readonly observed?: bigint | boolean | Address | Hash;
|
|
42
|
+
/**
|
|
43
|
+
* Reserved; not populated for caller-transaction reverts, whose index is on
|
|
44
|
+
* `SimulationRevertedError.details[].transactionIndex`.
|
|
45
|
+
*/
|
|
46
|
+
readonly failedTransactionIndex?: number;
|
|
47
|
+
}
|
|
48
|
+
/** Context of a failure while validating the request. */
|
|
49
|
+
export type SimulationValidationContext = SimulationContextBase & {
|
|
50
|
+
readonly stage: "validation";
|
|
51
|
+
};
|
|
52
|
+
/** Context of a failure while reaching the `eth_simulateV1` backend. */
|
|
53
|
+
export type SimulationTransportContext = SimulationContextBase & {
|
|
54
|
+
readonly stage: "transport";
|
|
55
|
+
};
|
|
56
|
+
/** Context of a failure while preparing a preview authorization. */
|
|
57
|
+
export type SimulationPreparationContext = SimulationContextBase & {
|
|
58
|
+
readonly stage: "preparation";
|
|
59
|
+
/** Index into `authorizations`. */
|
|
60
|
+
readonly authorizationIndex: number;
|
|
61
|
+
/** Index into that authorization's preparation calls. */
|
|
62
|
+
readonly preparationCallIndex?: number;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Reserved execution-stage context; `SimulationRevertedError` carries none for
|
|
66
|
+
* caller-transaction or node reverts (see `details[].transactionIndex`).
|
|
67
|
+
*/
|
|
68
|
+
export type SimulationExecutionContext = SimulationCheckContext & SimulationOperationSubject & {
|
|
69
|
+
readonly stage: "execution";
|
|
70
|
+
};
|
|
71
|
+
/** Context of a verification check that did not hold. */
|
|
72
|
+
export type SimulationVerificationContext = SimulationCheckContext & SimulationOperationSubject & {
|
|
73
|
+
readonly stage: "verification";
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Where and why a simulation failed, keyed by `stage`
|
|
77
|
+
* (ADR-2026-10-01-evm-simulation-quoted-slippage-limits).
|
|
78
|
+
* Every stage carries `mode`, `chainId` and `blockNumber`. Preparation
|
|
79
|
+
* contexts carry `authorizationIndex` and `preparationCallIndex`. Verification
|
|
80
|
+
* contexts bound to a limit take `operation` and the subject fields
|
|
81
|
+
* (`marketId`, `sourceMarketId`/`targetMarketId`, `vault`,
|
|
82
|
+
* `sourceVault`/`targetVault`) from that `OperationLimit`, not
|
|
83
|
+
* from decoded calldata; unbound ones carry only a `field` string naming the
|
|
84
|
+
* failed state read (`balance:<token>:<account>` or
|
|
85
|
+
* `position:<marketId>:<account>`).
|
|
86
|
+
* `"execution"` stays in the union, but `SimulationRevertedError` carries no
|
|
87
|
+
* `context` for caller-transaction or node reverts — the failing
|
|
88
|
+
* `transactionIndex` is reported on the error's `details`. Never contains
|
|
89
|
+
* signatures, RPC URLs, credentials, raw calldata or raw causes (`cause`
|
|
90
|
+
* stays on the error).
|
|
91
|
+
*/
|
|
92
|
+
export type SimulationErrorContext = SimulationValidationContext | SimulationTransportContext | SimulationPreparationContext | SimulationExecutionContext | SimulationVerificationContext | (SimulationCheckContext & {
|
|
93
|
+
readonly stage: "verification";
|
|
94
|
+
readonly field: string;
|
|
95
|
+
readonly operation?: never;
|
|
96
|
+
});
|
|
1
97
|
/**
|
|
2
98
|
* Base class for every error this package throws. Transport-agnostic — no HTTP status codes.
|
|
3
99
|
* Consumers pattern-match with `instanceof` on the concrete subclass.
|
|
4
100
|
*/
|
|
5
101
|
export declare abstract class SimulationPackageError extends Error {
|
|
6
102
|
/** Stable string discriminator for log aggregation and external mapping. */
|
|
7
|
-
abstract readonly code:
|
|
8
|
-
|
|
103
|
+
abstract readonly code: SimulationErrorCode;
|
|
104
|
+
/** Frozen copy of the failure context, when one was supplied. */
|
|
105
|
+
readonly context?: SimulationErrorContext;
|
|
106
|
+
constructor(message: string, options?: ErrorOptions & {
|
|
107
|
+
context?: SimulationErrorContext;
|
|
108
|
+
});
|
|
9
109
|
}
|
|
10
110
|
/** Transaction would revert on-chain. Not bypassable. */
|
|
11
111
|
export declare class SimulationRevertedError extends SimulationPackageError {
|
|
112
|
+
/** Raw revert string as reported by the backend, when any. */
|
|
12
113
|
readonly reason: string | undefined;
|
|
13
114
|
readonly details?: unknown;
|
|
115
|
+
/** Machine-readable cause; `UNKNOWN_REVERT` when the revert maps to no known Morpho condition. */
|
|
116
|
+
readonly reasonCode: SimulationExecutionReason;
|
|
117
|
+
readonly name = "SimulationRevertedError";
|
|
14
118
|
readonly code = "SIMULATION_REVERTED";
|
|
15
|
-
|
|
119
|
+
readonly context?: SimulationPreparationContext | SimulationExecutionContext;
|
|
120
|
+
constructor(
|
|
121
|
+
/** Raw revert string as reported by the backend, when any. */
|
|
122
|
+
reason: string | undefined, details?: unknown,
|
|
123
|
+
/** Machine-readable cause; `UNKNOWN_REVERT` when the revert maps to no known Morpho condition. */
|
|
124
|
+
reasonCode?: SimulationExecutionReason,
|
|
125
|
+
/** Which transaction/authorization reverted and the operation it belonged to. */
|
|
126
|
+
context?: SimulationPreparationContext | SimulationExecutionContext);
|
|
16
127
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
128
|
+
/** Per-asset net retained amount keyed by restricted contract and token. */
|
|
129
|
+
export interface RetainedAsset {
|
|
130
|
+
/** Restricted bundles contract that ended up holding the token. */
|
|
131
|
+
readonly address: Address;
|
|
132
|
+
/** Token retained (native ETH uses viem's `ethAddress`). */
|
|
133
|
+
readonly token: Address;
|
|
134
|
+
/** Net balance increase in the token's base units; always positive. */
|
|
135
|
+
readonly netRetained: bigint;
|
|
21
136
|
}
|
|
22
137
|
/**
|
|
23
138
|
* Thrown when net value above the dust threshold is retained by a restricted bundles contract
|
|
@@ -26,26 +141,98 @@ interface RetainedAsset {
|
|
|
26
141
|
*/
|
|
27
142
|
export declare class BlacklistViolationError extends SimulationPackageError {
|
|
28
143
|
/** Per-asset net retained amounts keyed by restricted contract and token. */
|
|
29
|
-
readonly assetChanges?: RetainedAsset[] | undefined;
|
|
144
|
+
readonly assetChanges?: readonly RetainedAsset[] | undefined;
|
|
145
|
+
readonly name = "BlacklistViolationError";
|
|
30
146
|
readonly code = "BLACKLIST_ERROR";
|
|
31
147
|
constructor(message: string,
|
|
32
148
|
/** Per-asset net retained amounts keyed by restricted contract and token. */
|
|
33
|
-
assetChanges?: RetainedAsset[] | undefined);
|
|
149
|
+
assetChanges?: readonly RetainedAsset[] | undefined, context?: SimulationErrorContext);
|
|
34
150
|
}
|
|
35
|
-
/**
|
|
151
|
+
/** RPC service is down or unreachable. Bypassable — user can proceed. */
|
|
36
152
|
export declare class ExternalServiceError extends SimulationPackageError {
|
|
153
|
+
readonly name = "ExternalServiceError";
|
|
37
154
|
readonly code = "EXTERNAL_SERVICE_ERROR";
|
|
38
155
|
}
|
|
39
156
|
/** Bad input to the simulation functions. Not bypassable. */
|
|
40
157
|
export declare class SimulationValidationError extends SimulationPackageError {
|
|
41
158
|
readonly fieldErrors?: string[] | undefined;
|
|
159
|
+
readonly name = "SimulationValidationError";
|
|
42
160
|
readonly code = "VALIDATION_ERROR";
|
|
43
|
-
constructor(message: string, fieldErrors?: string[] | undefined);
|
|
161
|
+
constructor(message: string, fieldErrors?: string[] | undefined, context?: SimulationErrorContext);
|
|
44
162
|
}
|
|
45
163
|
/** Chain ID not configured for any simulation method. Not bypassable. */
|
|
46
164
|
export declare class UnsupportedChainError extends SimulationPackageError {
|
|
47
165
|
readonly chainId: number;
|
|
166
|
+
readonly name = "UnsupportedChainError";
|
|
48
167
|
readonly code = "UNSUPPORTED_CHAIN";
|
|
49
|
-
constructor(chainId: number);
|
|
168
|
+
constructor(chainId: number, context?: SimulationErrorContext);
|
|
50
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* An SDK requirement passed to `toSimulationAuthorizations` cannot be
|
|
172
|
+
* converted into a simulation authorization.
|
|
173
|
+
*/
|
|
174
|
+
export declare class UnsupportedOperationError extends SimulationPackageError {
|
|
175
|
+
readonly name = "UnsupportedOperationError";
|
|
176
|
+
readonly code = "UNSUPPORTED_OPERATION";
|
|
177
|
+
}
|
|
178
|
+
/** The simulation backend returned a response that cannot be parsed. */
|
|
179
|
+
export declare class InvalidSimulationResponseError extends SimulationPackageError {
|
|
180
|
+
readonly name = "InvalidSimulationResponseError";
|
|
181
|
+
readonly code = "INVALID_SIMULATION_RESPONSE";
|
|
182
|
+
}
|
|
183
|
+
/** State needed to verify an operation could not be fetched or derived. */
|
|
184
|
+
export declare class MissingVerificationEvidenceError extends SimulationPackageError {
|
|
185
|
+
readonly name = "MissingVerificationEvidenceError";
|
|
186
|
+
readonly code = "MISSING_VERIFICATION_EVIDENCE";
|
|
187
|
+
}
|
|
188
|
+
/** A pending authorization does not match the request it was prepared for. */
|
|
189
|
+
export declare class AuthorizationRequestMismatchError extends SimulationPackageError {
|
|
190
|
+
readonly name = "AuthorizationRequestMismatchError";
|
|
191
|
+
readonly code = "AUTHORIZATION_REQUEST_MISMATCH";
|
|
192
|
+
}
|
|
193
|
+
/** A consumer-supplied limit was violated. */
|
|
194
|
+
export declare class ConsumerLimitViolationError extends SimulationPackageError {
|
|
195
|
+
readonly name = "ConsumerLimitViolationError";
|
|
196
|
+
readonly code = "CONSUMER_LIMIT_VIOLATION";
|
|
197
|
+
}
|
|
198
|
+
/** The simulation failed for a reason that fits no other code. */
|
|
199
|
+
export declare class UnexpectedSimulationError extends SimulationPackageError {
|
|
200
|
+
readonly name = "UnexpectedSimulationError";
|
|
201
|
+
readonly code = "UNEXPECTED_SIMULATION_ERROR";
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Structural guard for consumers where `instanceof` fails across bundles.
|
|
205
|
+
*
|
|
206
|
+
* @param value - Anything caught.
|
|
207
|
+
* @returns `true` for `SimulationPackageError` instances and for objects
|
|
208
|
+
* carrying a `message` string, a known `code`, the `name` of the class
|
|
209
|
+
* owning that `code`, and an absent or
|
|
210
|
+
* well-formed `context` (known `stage`, `mode`, numeric `chainId`,
|
|
211
|
+
* `bigint` `blockNumber`, `authorizationIndex` for `preparation`, and a
|
|
212
|
+
* known `operation` with its subject fields for `execution`/`verification`,
|
|
213
|
+
* or a verification `field` string with no `operation`).
|
|
214
|
+
* @example
|
|
215
|
+
* ```ts
|
|
216
|
+
* import { isSimulationPackageError, simulate } from "@morpho-org/evm-simulation";
|
|
217
|
+
* import type { Address, Hex } from "viem";
|
|
218
|
+
*
|
|
219
|
+
* declare const user: Address;
|
|
220
|
+
* declare const vault: Address;
|
|
221
|
+
* declare const encodedDeposit: Hex;
|
|
222
|
+
* const config = {
|
|
223
|
+
* chains: new Map([[1, { simulateV1Url: "https://rpc.example" }]]),
|
|
224
|
+
* };
|
|
225
|
+
* try {
|
|
226
|
+
* await simulate(config, {
|
|
227
|
+
* chainId: 1,
|
|
228
|
+
* transactions: [{ from: user, to: vault, data: encodedDeposit }],
|
|
229
|
+
* });
|
|
230
|
+
* } catch (e) {
|
|
231
|
+
* if (!isSimulationPackageError(e)) throw e;
|
|
232
|
+
* if (e.code !== "SIMULATION_REVERTED") throw e;
|
|
233
|
+
* console.log(e.context?.stage, e.message);
|
|
234
|
+
* }
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
export declare function isSimulationPackageError(value: unknown): value is SimulationPackageError;
|
|
51
238
|
export {};
|