@metamask-previews/transaction-controller 72.2.1-preview-7fb08ad32 → 72.2.1-preview-66aa9ab6e

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.
@@ -9,16 +9,46 @@ export type UpdateGasRequest = {
9
9
  messenger: TransactionControllerMessenger;
10
10
  txMeta: TransactionMeta;
11
11
  };
12
+ /**
13
+ * How the gas limits of a batch are applied.
14
+ * - `eip7702` - A single gas limit for the outer EIP-7702 transaction.
15
+ * - `separate` - One gas limit per transaction, submitted separately.
16
+ */
17
+ export type EstimateGasBatchMode = 'eip7702' | 'separate';
12
18
  export type EstimateGasBatchResult = {
19
+ /** Gas limits, with a single entry if `mode` is `eip7702`. */
13
20
  gasLimits: number[];
21
+ /** How the gas limits are applied. */
22
+ mode: EstimateGasBatchMode;
23
+ /** Whether the outer EIP-7702 transaction upgrades the sender. */
14
24
  requiresAuthorizationList?: true;
25
+ /** Total of all gas limits. */
15
26
  totalGasLimit: number;
16
27
  };
17
28
  export declare const log: import("debug").Debugger;
18
29
  export declare const DEFAULT_GAS_MULTIPLIER = 1.5;
19
30
  export declare const MAX_GAS_BLOCK_PERCENT = 90;
20
- export declare const INTRINSIC_GAS = 21000;
21
31
  export declare const DUMMY_AUTHORIZATION_SIGNATURE = "0x1111111111111111111111111111111111111111111111111111111111111111";
32
+ /**
33
+ * EIP-2780 state gas charged at runtime when a valid authorization sets a
34
+ * delegation indicator for an authority that had none at the start of the
35
+ * transaction, at most once per authority.
36
+ *
37
+ * When the authority is the sender, this is the only runtime authorization
38
+ * charge: `ACCOUNT_WRITE` is covered by the transaction base cost, and the
39
+ * sender always exists in state as its nonce is incremented first.
40
+ */
41
+ export declare const EIP_2780_AUTHORIZATION_GAS = 35190;
42
+ /**
43
+ * Intrinsic gas cost for each authorization omitted from the node estimate.
44
+ */
45
+ export declare const EIP7280_AUTHORIZATION_INTRINSIC_GAS = 7816;
46
+ /**
47
+ * Gas for the upgrade authorization of the sender that is not included in the
48
+ * sum of the provided gas values of a batch: the EIP-7280 intrinsic cost of an
49
+ * authorization plus the delegation indicator charge.
50
+ */
51
+ export declare const UPGRADE_AUTHORIZATION_GAS: number;
22
52
  /**
23
53
  * Populate the gas properties of the provided transaction meta.
24
54
  *
@@ -65,7 +95,10 @@ export declare function estimateGas({ ignoreDelegationSignatures, isSimulationEn
65
95
  * standalone (e.g. predict-withdraw, where the batch's first sub-call
66
96
  * provides source-token balance to subsequent sub-calls). When 7702
67
97
  * simulation succeeds it is preferred since the bundled call has no per-tx
68
- * intrinsic gas cost and produces a tighter estimate.
98
+ * intrinsic gas cost and produces a tighter estimate. If the sender requires
99
+ * an upgrade, the fallback adds the authorization intrinsic gas and, if no
100
+ * delegation exists yet, the delegation indicator charge. The provided gas
101
+ * values do not include these authorization costs.
69
102
  *
70
103
  * @param transactions - Batch transactions to inspect.
71
104
  * @returns Parsed gas limits and total when every transaction has gas; otherwise `undefined`.
@@ -1 +1 @@
1
- {"version":3,"file":"gas.d.ts","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gas.d.ts","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,GAAG,EAAQ,MAAM,iBAAiB,CAAC;AAYjD,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,6BAA6B,CAAC;AAElF,OAAO,KAAK,EAEV,sBAAsB,EACtB,mBAAmB,EACnB,6BAA6B,EAC7B,4BAA4B,EAC5B,MAAM,EACN,6BAA6B,EAC7B,eAAe,EACf,iBAAiB,EAClB,MAAM,aAAa,CAAC;AAgBrB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,eAAe,EAAE,OAAO,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,8BAA8B,CAAC;IAC1C,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,UAAU,CAAC;AAE1D,MAAM,MAAM,sBAAsB,GAAG;IACnC,8DAA8D;IAC9D,SAAS,EAAE,MAAM,EAAE,CAAC;IAEpB,sCAAsC;IACtC,IAAI,EAAE,oBAAoB,CAAC;IAE3B,kEAAkE;IAClE,yBAAyB,CAAC,EAAE,IAAI,CAAC;IAEjC,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,GAAG,0BAA2C,CAAC;AAE5D,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC,eAAO,MAAM,6BAA6B,uEAC4B,CAAC;AAEvE;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,QAAQ,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,mCAAmC,OAAO,CAAC;AAExD;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,QAC4B,CAAC;AAQnE;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBxE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAAC,EAChC,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,EACnB,SAAS,EACT,eAAe,EACf,QAAQ,GACT,EAAE;IACD,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,8BAA8B,CAAC;IAC1C,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,EAAE,iBAAiB,CAAC;CAC7B,GAAG,OAAO,CAAC;IACV,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,eAAe,CAAC,iBAAiB,CAAC,CAAC;CACrD,CAAC,CA8GD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,sBAAsB,EAAE,GACrC;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAW5D;AAED,wBAAsB,gBAAgB,CAAC,EACrC,IAAI,EACJ,mBAAmB,EACnB,sBAAsB,EACtB,SAAS,EACT,eAAe,EACf,YAAY,GACb,EAAE;IACD,IAAI,EAAE,GAAG,CAAC;IACV,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,sBAAsB,EAAE,CACtB,OAAO,EAAE,6BAA6B,KACnC,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAC3C,SAAS,EAAE,8BAA8B,CAAC;IAC1C,eAAe,EAAE,eAAe,CAAC;IACjC,YAAY,EAAE,sBAAsB,EAAE,CAAC;CACxC,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA+GlC;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,GACjB,MAAM,CA0BR;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,OAAO,EACP,IAAI,EACJ,mBAAmB,EACnB,YAAY,GACb,EAAE;IACD,OAAO,EAAE,GAAG,CAAC;IACb,IAAI,EAAE,GAAG,CAAC;IACV,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,YAAY,EAAE,6BAA6B,EAAE,CAAC;CAC/C,GAAG,OAAO,CAAC;IAAE,aAAa,EAAE,GAAG,CAAC;IAAC,SAAS,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC,CA8CpD"}
package/dist/utils/gas.js CHANGED
@@ -4,15 +4,40 @@ import { BigNumber } from 'bignumber.js';
4
4
  import { simulateTransactions } from '../api/simulation-api.js';
5
5
  import { projectLogger } from '../logger.js';
6
6
  import { TransactionEnvelopeType } from '../types.js';
7
- import { DELEGATION_PREFIX, doesAccountSupportEIP7702, generateEIP7702BatchTransaction, } from './eip7702.js';
7
+ import { DELEGATION_PREFIX, doesAccountSupportEIP7702, generateEIP7702BatchTransaction, getAuthorizationAuthority, getDelegationAddress, isAuthorizationSigned, } from './eip7702.js';
8
8
  import { getGasEstimateBuffer, getGasEstimateFallback, } from './feature-flags.js';
9
9
  import { getChainId, rpcRequest } from './provider.js';
10
10
  import { decodeRevert } from './revert-reason.js';
11
11
  export const log = createModuleLogger(projectLogger, 'gas');
12
12
  export const DEFAULT_GAS_MULTIPLIER = 1.5;
13
13
  export const MAX_GAS_BLOCK_PERCENT = 90;
14
- export const INTRINSIC_GAS = 21000;
15
14
  export const DUMMY_AUTHORIZATION_SIGNATURE = '0x1111111111111111111111111111111111111111111111111111111111111111';
15
+ /**
16
+ * EIP-2780 state gas charged at runtime when a valid authorization sets a
17
+ * delegation indicator for an authority that had none at the start of the
18
+ * transaction, at most once per authority.
19
+ *
20
+ * When the authority is the sender, this is the only runtime authorization
21
+ * charge: `ACCOUNT_WRITE` is covered by the transaction base cost, and the
22
+ * sender always exists in state as its nonce is incremented first.
23
+ */
24
+ export const EIP_2780_AUTHORIZATION_GAS = 35190;
25
+ /**
26
+ * Intrinsic gas cost for each authorization omitted from the node estimate.
27
+ */
28
+ export const EIP7280_AUTHORIZATION_INTRINSIC_GAS = 7816;
29
+ /**
30
+ * Gas for the upgrade authorization of the sender that is not included in the
31
+ * sum of the provided gas values of a batch: the EIP-7280 intrinsic cost of an
32
+ * authorization plus the delegation indicator charge.
33
+ */
34
+ export const UPGRADE_AUTHORIZATION_GAS = EIP7280_AUTHORIZATION_INTRINSIC_GAS + EIP_2780_AUTHORIZATION_GAS;
35
+ /**
36
+ * Error for a simulated transaction that failed, as opposed to the simulation
37
+ * itself being unavailable.
38
+ */
39
+ class SimulatedTransactionError extends Error {
40
+ }
16
41
  /**
17
42
  * Populate the gas properties of the provided transaction meta.
18
43
  *
@@ -83,9 +108,21 @@ export async function estimateGas({ ignoreDelegationSignatures, isSimulationEnab
83
108
  Boolean(authorizationList?.length) &&
84
109
  Boolean(data) &&
85
110
  data !== '0x';
111
+ const type4AuthorizationList = txParams.type === TransactionEnvelopeType.setCode &&
112
+ authorizationList?.length
113
+ ? authorizationList
114
+ : undefined;
86
115
  try {
87
- if (isSimulationEnabled && isUpgradeWithData) {
88
- estimatedGas = await estimateGasUpgradeWithDataToSelf(request, messenger, networkClientId, chainId, getSimulationConfig);
116
+ if (type4AuthorizationList) {
117
+ estimatedGas = await estimateGasType4({
118
+ authorizationList: type4AuthorizationList,
119
+ chainId,
120
+ getSimulationConfig,
121
+ isSimulationEnabled,
122
+ messenger,
123
+ networkClientId,
124
+ txParams: request,
125
+ });
89
126
  }
90
127
  else if (ignoreDelegationSignatures && isSimulationEnabled) {
91
128
  estimatedGas = await simulateGas({
@@ -132,7 +169,10 @@ export async function estimateGas({ ignoreDelegationSignatures, isSimulationEnab
132
169
  * standalone (e.g. predict-withdraw, where the batch's first sub-call
133
170
  * provides source-token balance to subsequent sub-calls). When 7702
134
171
  * simulation succeeds it is preferred since the bundled call has no per-tx
135
- * intrinsic gas cost and produces a tighter estimate.
172
+ * intrinsic gas cost and produces a tighter estimate. If the sender requires
173
+ * an upgrade, the fallback adds the authorization intrinsic gas and, if no
174
+ * delegation exists yet, the delegation indicator charge. The provided gas
175
+ * values do not include these authorization costs.
136
176
  *
137
177
  * @param transactions - Batch transactions to inspect.
138
178
  * @returns Parsed gas limits and total when every transaction has gas; otherwise `undefined`.
@@ -186,17 +226,24 @@ export async function estimateGasBatch({ from, getSimulationConfig, isAtomicBatc
186
226
  txParams: params,
187
227
  });
188
228
  if (simulationFails && providedBatchGasLimits) {
189
- log('EIP-7702 estimation failed, using batch parameter gas limits', providedBatchGasLimits, simulationFails);
229
+ const upgradeGas = chainResult.delegationAddress
230
+ ? EIP7280_AUTHORIZATION_INTRINSIC_GAS
231
+ : UPGRADE_AUTHORIZATION_GAS;
232
+ const fallbackGasLimit = providedBatchGasLimits.totalGasLimit +
233
+ (isUpgradeRequired ? upgradeGas : 0);
234
+ log('EIP-7702 estimation failed, using batch parameter gas limits', { fallbackGasLimit }, simulationFails);
190
235
  return {
191
- gasLimits: [providedBatchGasLimits.totalGasLimit],
236
+ gasLimits: [fallbackGasLimit],
237
+ mode: 'eip7702',
192
238
  ...(isUpgradeRequired ? { requiresAuthorizationList: true } : {}),
193
- totalGasLimit: providedBatchGasLimits.totalGasLimit,
239
+ totalGasLimit: fallbackGasLimit,
194
240
  };
195
241
  }
196
242
  const totalGasLimit = new BigNumber(gasLimitHex).toNumber();
197
243
  log('Estimated EIP-7702 gas limit', totalGasLimit);
198
244
  return {
199
245
  gasLimits: [totalGasLimit],
246
+ mode: 'eip7702',
200
247
  ...(isUpgradeRequired ? { requiresAuthorizationList: true } : {}),
201
248
  totalGasLimit,
202
249
  };
@@ -204,7 +251,7 @@ export async function estimateGasBatch({ from, getSimulationConfig, isAtomicBatc
204
251
  const providedBatchGasLimits = getProvidedBatchGasLimits(transactions);
205
252
  if (providedBatchGasLimits) {
206
253
  log('Using batch parameter gas limits', providedBatchGasLimits);
207
- return providedBatchGasLimits;
254
+ return { ...providedBatchGasLimits, mode: 'separate' };
208
255
  }
209
256
  const { gasLimits: gasLimitsHex } = await simulateGasBatch({
210
257
  chainId,
@@ -219,7 +266,7 @@ export async function estimateGasBatch({ from, getSimulationConfig, isAtomicBatc
219
266
  : new BigNumber(gasLimitsHex[index]).toNumber());
220
267
  const totalGasLimit = gasLimits.reduce((acc, gasLimit) => acc + gasLimit, 0);
221
268
  log('Simulated batch gas limits', { totalGasLimit, gasLimits });
222
- return { totalGasLimit, gasLimits };
269
+ return { gasLimits, mode: 'separate', totalGasLimit };
223
270
  }
224
271
  /**
225
272
  * Add a buffer to the provided estimated gas.
@@ -347,87 +394,146 @@ async function getLatestBlock(messenger, networkClientId) {
347
394
  }));
348
395
  }
349
396
  /**
350
- * Estimate the gas for a type 4 transaction.
397
+ * Estimate the gas for a type 4 transaction as one outer transaction.
351
398
  *
352
- * @param txParams - The transaction parameters.
353
- * @param messenger - The messenger instance for communication.
354
- * @param networkClientId - The network client ID.
355
- * @param chainId - The chain ID of the transaction.
356
- * @param getSimulationConfig - The function to get the simulation configuration.
399
+ * - If all authorizations are signed, the selected node estimates the exact
400
+ * transaction.
401
+ * - Otherwise, the Simulation API estimates the exact transaction, with the
402
+ * authority of each authorization so that it can apply any EIP-2780 runtime
403
+ * authorization charges.
404
+ * - If the Simulation API is disabled, unsupported or unavailable, the selected
405
+ * node estimates the transaction without unsigned authorizations and with the
406
+ * delegation of the sender overridden. Intrinsic gas is added for each omitted
407
+ * authorization, plus the EIP-2780 delegation charge if the sender is not yet
408
+ * delegated. A simulated transaction error is not retried using the node.
409
+ *
410
+ * @param options - The options object.
411
+ * @param options.authorizationList - The original authorization list of the transaction.
412
+ * @param options.chainId - The chain ID of the transaction.
413
+ * @param options.getSimulationConfig - The function to get the simulation configuration.
414
+ * @param options.isSimulationEnabled - Whether the simulation is enabled.
415
+ * @param options.messenger - The messenger instance for communication.
416
+ * @param options.networkClientId - The network client ID.
417
+ * @param options.txParams - The normalized transaction parameters.
357
418
  * @returns The estimated gas.
358
419
  */
359
- async function estimateGasUpgradeWithDataToSelf(txParams, messenger, networkClientId, chainId, getSimulationConfig) {
360
- const upgradeGas = (await rpcRequest({
361
- messenger,
362
- networkClientId,
363
- method: 'eth_estimateGas',
364
- params: [
365
- {
366
- ...txParams,
367
- to: txParams.from,
368
- data: '0x',
369
- },
370
- ],
371
- }));
372
- log('Upgrade only gas', upgradeGas);
373
- const delegationAddress = txParams.authorizationList?.[0].address;
374
- let executeGas;
375
- try {
376
- executeGas = await simulateGas({
377
- chainId,
378
- delegationAddress,
379
- getSimulationConfig,
380
- transaction: txParams,
381
- });
382
- }
383
- catch (error) {
384
- log('Error while simulating data portion of upgrade', error);
420
+ async function estimateGasType4({ authorizationList, chainId, getSimulationConfig, isSimulationEnabled, messenger, networkClientId, txParams, }) {
421
+ if (authorizationList.every(isAuthorizationSigned)) {
422
+ log('Estimating type 4 gas using node as all authorizations signed');
423
+ return await estimateGasNode(messenger, networkClientId, txParams);
385
424
  }
386
- if (executeGas === undefined) {
425
+ if (isSimulationEnabled) {
426
+ const simulationAuthorizationList = authorizationList.map((authorization) => {
427
+ const authority = getAuthorizationAuthority(authorization, txParams.from);
428
+ if (!authority) {
429
+ throw new Error('Cannot determine authority of signed authorization');
430
+ }
431
+ return { address: authorization.address, from: authority };
432
+ });
433
+ log('Estimating type 4 gas using simulation', simulationAuthorizationList);
387
434
  try {
388
- executeGas = await estimateGasNode(messenger, networkClientId, { ...txParams, authorizationList: undefined, type: undefined }, delegationAddress);
435
+ return await simulateGas({
436
+ authorizationList: simulationAuthorizationList,
437
+ chainId,
438
+ getSimulationConfig,
439
+ transaction: txParams,
440
+ });
389
441
  }
390
442
  catch (error) {
391
- log('Error while estimating data portion of upgrade', error);
392
- throw error;
443
+ if (error instanceof SimulatedTransactionError) {
444
+ throw error;
445
+ }
446
+ log('Simulation unavailable, estimating type 4 gas using node', error);
393
447
  }
394
- log('Success estimating data portion of upgrade', executeGas);
395
448
  }
396
- log('Execute gas', executeGas);
397
- const total = BNToHex(hexToBN(upgradeGas).add(hexToBN(executeGas)).subn(INTRINSIC_GAS));
398
- log('Total type 4 gas', total);
399
- return total;
449
+ return await estimateGasType4Node({
450
+ authorizationList,
451
+ messenger,
452
+ networkClientId,
453
+ txParams,
454
+ });
455
+ }
456
+ /**
457
+ * Estimate the gas for a type 4 transaction with unsigned authorizations using
458
+ * the selected node.
459
+ *
460
+ * Unsigned authorizations are omitted from the node request and their intrinsic
461
+ * gas is added manually per entry. Their authority is the sender, so the
462
+ * delegation of the sender is set with a state override, and the EIP-2780 charge
463
+ * for a new delegation indicator is added once if the sender is not yet
464
+ * delegated. Signed authorizations remain in the request and are charged by the
465
+ * node.
466
+ *
467
+ * @param options - The options object.
468
+ * @param options.authorizationList - The original authorization list of the transaction.
469
+ * @param options.messenger - The messenger instance for communication.
470
+ * @param options.networkClientId - The network client ID.
471
+ * @param options.txParams - The normalized transaction parameters.
472
+ * @returns The estimated gas including omitted authorization costs.
473
+ */
474
+ async function estimateGasType4Node({ authorizationList, messenger, networkClientId, txParams, }) {
475
+ const unsignedAuthorizations = authorizationList.filter((authorization) => !isAuthorizationSigned(authorization));
476
+ const signedAuthorizations = authorizationList.filter(isAuthorizationSigned);
477
+ const nodeTxParams = {
478
+ ...txParams,
479
+ authorizationList: signedAuthorizations.length
480
+ ? signedAuthorizations
481
+ : undefined,
482
+ type: signedAuthorizations.length ? txParams.type : undefined,
483
+ };
484
+ // Unsigned authorizations are signed by the sender, and the last valid
485
+ // authorization for an authority sets its delegation.
486
+ const delegationAddress = unsignedAuthorizations[unsignedAuthorizations.length - 1].address;
487
+ const [nodeGas, currentDelegationAddress] = await Promise.all([
488
+ estimateGasNode(messenger, networkClientId, nodeTxParams, delegationAddress),
489
+ getDelegationAddress(txParams.from, messenger, networkClientId),
490
+ ]);
491
+ const intrinsicGas = unsignedAuthorizations.length * EIP7280_AUTHORIZATION_INTRINSIC_GAS;
492
+ const delegationGas = currentDelegationAddress
493
+ ? 0
494
+ : EIP_2780_AUTHORIZATION_GAS;
495
+ log('Type 4 gas using node', {
496
+ currentDelegationAddress,
497
+ delegationGas,
498
+ intrinsicGas,
499
+ nodeGas,
500
+ });
501
+ return BNToHex(hexToBN(nodeGas).addn(intrinsicGas + delegationGas));
400
502
  }
401
503
  /**
402
504
  * Simulate the required gas using the simulation API.
403
505
  *
506
+ * If an authorization list is provided, it is included in the simulated
507
+ * transaction, a simulated transaction error is thrown as a
508
+ * `SimulatedTransactionError`, and the response must include a non-zero gas
509
+ * limit.
510
+ *
404
511
  * @param options - The options object.
512
+ * @param options.authorizationList - The authorization list with the authority of each entry.
405
513
  * @param options.chainId - The chain ID of the transaction.
406
- * @param options.delegationAddress - The delegation address of the sender to mock.
407
514
  * @param options.getSimulationConfig - The function to get the simulation configuration.
408
515
  * @param options.transaction - The transaction parameters.
409
516
  * @returns The simulated gas.
410
517
  */
411
- async function simulateGas({ chainId, delegationAddress, getSimulationConfig, transaction, }) {
518
+ async function simulateGas({ authorizationList, chainId, getSimulationConfig, transaction, }) {
412
519
  const response = await simulateTransactions(chainId, {
413
520
  getSimulationConfig,
414
521
  transactions: [
415
522
  {
523
+ ...(authorizationList ? { authorizationList } : {}),
416
524
  to: transaction.to,
417
525
  from: transaction.from,
418
526
  data: transaction.data,
419
527
  value: transaction.value,
420
528
  },
421
529
  ],
422
- overrides: {
423
- [transaction.from]: {
424
- code: delegationAddress &&
425
- (DELEGATION_PREFIX + remove0x(delegationAddress)),
426
- },
427
- },
428
530
  });
429
- const gasLimit = response?.transactions?.[0].gasLimit;
430
- if (!gasLimit) {
531
+ const simulatedTransaction = response?.transactions?.[0];
532
+ const gasLimit = simulatedTransaction?.gasLimit;
533
+ if (authorizationList && simulatedTransaction?.error) {
534
+ throw new SimulatedTransactionError(`Simulation failed: ${simulatedTransaction.error}`);
535
+ }
536
+ if (!gasLimit || (authorizationList && hexToBN(gasLimit).isZero())) {
431
537
  throw new Error('No simulated gas returned');
432
538
  }
433
539
  return gasLimit;
@@ -1 +1 @@
1
- {"version":3,"file":"gas.js","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BNToHex,\n fractionBN,\n hexToBN,\n toHex,\n} from '@metamask/controller-utils';\nimport type { NetworkClientId } from '@metamask/network-controller';\nimport type { Hex, Json } from '@metamask/utils';\nimport {\n add0x,\n createModuleLogger,\n isStrictHexString,\n remove0x,\n} from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { simulateTransactions } from '../api/simulation-api.js';\nimport { projectLogger } from '../logger.js';\nimport type { TransactionControllerMessenger } from '../TransactionController.js';\nimport { TransactionEnvelopeType } from '../types.js';\nimport type {\n AuthorizationList,\n BatchTransactionParams,\n GetSimulationConfig,\n IsAtomicBatchSupportedRequest,\n IsAtomicBatchSupportedResult,\n Revert,\n TransactionBatchSingleRequest,\n TransactionMeta,\n TransactionParams,\n} from '../types.js';\nimport {\n DELEGATION_PREFIX,\n doesAccountSupportEIP7702,\n generateEIP7702BatchTransaction,\n} from './eip7702.js';\nimport {\n getGasEstimateBuffer,\n getGasEstimateFallback,\n} from './feature-flags.js';\nimport { getChainId, rpcRequest } from './provider.js';\nimport { decodeRevert } from './revert-reason.js';\n\nexport type UpdateGasRequest = {\n isCustomNetwork: boolean;\n isSimulationEnabled: boolean;\n getSimulationConfig: GetSimulationConfig;\n messenger: TransactionControllerMessenger;\n txMeta: TransactionMeta;\n};\n\nexport type EstimateGasBatchResult = {\n gasLimits: number[];\n requiresAuthorizationList?: true;\n totalGasLimit: number;\n};\n\nexport const log = createModuleLogger(projectLogger, 'gas');\n\nexport const DEFAULT_GAS_MULTIPLIER = 1.5;\nexport const MAX_GAS_BLOCK_PERCENT = 90;\nexport const INTRINSIC_GAS = 21000;\n\nexport const DUMMY_AUTHORIZATION_SIGNATURE =\n '0x1111111111111111111111111111111111111111111111111111111111111111';\n\n/**\n * Populate the gas properties of the provided transaction meta.\n *\n * @param request - The request object including the necessary parameters.\n */\nexport async function updateGas(request: UpdateGasRequest): Promise<void> {\n const { txMeta } = request;\n const initialParams = { ...txMeta.txParams };\n\n const [gas, simulationFails, gasLimitNoBuffer, gasRevert] =\n await getGas(request);\n\n txMeta.txParams.gas = gas;\n txMeta.simulationFails = simulationFails;\n txMeta.gasLimitNoBuffer = gasLimitNoBuffer;\n\n if (gasRevert) {\n txMeta.revert = { ...txMeta.revert, gas: gasRevert };\n }\n\n if (!initialParams.gas) {\n txMeta.originalGasEstimate = txMeta.txParams.gas;\n }\n\n txMeta.defaultGasEstimates ??= {};\n txMeta.defaultGasEstimates.gas = txMeta.txParams.gas;\n}\n\n/**\n * Estimate the gas for the provided transaction parameters.\n * If the gas estimate fails, the fallback value is returned.\n *\n * @param options - The options object.\n * @param options.ignoreDelegationSignatures - Ignore signature errors if submitting delegations to the DelegationManager.\n * @param options.isSimulationEnabled - Whether the simulation is enabled.\n * @param options.getSimulationConfig - The function to get the simulation configuration.\n * @param options.messenger - The messenger instance for communication.\n * @param options.networkClientId - The network client ID.\n * @param options.txParams - The transaction parameters.\n * @returns The estimated gas and related info.\n */\nexport async function estimateGas({\n ignoreDelegationSignatures,\n isSimulationEnabled,\n getSimulationConfig,\n messenger,\n networkClientId,\n txParams,\n}: {\n ignoreDelegationSignatures?: boolean;\n isSimulationEnabled: boolean;\n getSimulationConfig: GetSimulationConfig;\n messenger: TransactionControllerMessenger;\n networkClientId: NetworkClientId;\n txParams: TransactionParams;\n}): Promise<{\n blockGasLimit: string;\n estimatedGas: string;\n gasRevert?: Revert;\n isUpgradeWithData: boolean;\n simulationFails: TransactionMeta['simulationFails'];\n}> {\n const request = { ...txParams };\n const { authorizationList, data, value } = request;\n const chainId = getChainId({ messenger, networkClientId });\n\n if (ignoreDelegationSignatures && !isSimulationEnabled) {\n throw new Error(\n 'Gas estimation with ignored delegation signatures is not supported as simulation disabled',\n );\n }\n\n const { gasLimit: blockGasLimit, number: blockNumber } = await getLatestBlock(\n messenger,\n networkClientId,\n );\n\n const blockGasLimitBN = hexToBN(blockGasLimit);\n const { percentage, fixed, maxGasLimit } = getGasEstimateFallback(\n chainId,\n messenger,\n );\n\n const uncappedFallback = fixed\n ? toHex(fixed)\n : BNToHex(fractionBN(blockGasLimitBN, percentage, 100));\n\n // Clamp the fallback to the chain's per-transaction gas cap so it can never\n // exceed the gas limit the RPC will accept. Without this, a percentage of a\n // high block gas limit can overshoot the cap (e.g. 35% of Polygon's ~140M\n // block limit is ~49M, but the node caps a tx at ~33.5M and rejects it with\n // \"transaction gas limit too high\").\n const fallback =\n maxGasLimit !== undefined &&\n hexToBN(uncappedFallback).gt(hexToBN(toHex(maxGasLimit)))\n ? toHex(maxGasLimit)\n : uncappedFallback;\n\n log('Estimation fallback values', fallback);\n\n request.data = data ? add0x(data) : data;\n request.value = normalizeValue(value);\n\n request.authorizationList = normalizeAuthorizationList(\n request.authorizationList,\n chainId,\n );\n\n delete request.gasPrice;\n delete request.maxFeePerGas;\n delete request.maxPriorityFeePerGas;\n\n let estimatedGas = fallback;\n let simulationFails: TransactionMeta['simulationFails'];\n let gasRevert: Revert | undefined;\n\n const isUpgradeWithData =\n txParams.type === TransactionEnvelopeType.setCode &&\n Boolean(authorizationList?.length) &&\n Boolean(data) &&\n data !== '0x';\n\n try {\n if (isSimulationEnabled && isUpgradeWithData) {\n estimatedGas = await estimateGasUpgradeWithDataToSelf(\n request,\n messenger,\n networkClientId,\n chainId,\n getSimulationConfig,\n );\n } else if (ignoreDelegationSignatures && isSimulationEnabled) {\n estimatedGas = await simulateGas({\n chainId,\n getSimulationConfig,\n transaction: request,\n });\n } else {\n estimatedGas = await estimateGasNode(messenger, networkClientId, request);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n simulationFails = {\n reason: error.message,\n errorKey: error.errorKey,\n debug: {\n blockNumber,\n blockGasLimit,\n },\n };\n\n gasRevert = decodeRevert(error, 'gas');\n\n log('Estimation failed', { ...simulationFails, fallback, gasRevert });\n }\n\n return {\n blockGasLimit,\n estimatedGas,\n gasRevert,\n isUpgradeWithData,\n simulationFails,\n };\n}\n\n/**\n * Sum caller-provided gas limits across a batch.\n *\n * If every transaction in the batch already has a `gas` value, returns the\n * parsed per-tx limits and their sum. Otherwise returns `undefined`.\n *\n * Used by `estimateGasBatch`:\n * - non-7702 path: short-circuits simulation entirely when present.\n * - EIP-7702 path: used as a fallback when simulation fails — required for\n * callers that submit batches whose individual sub-calls cannot be simulated\n * standalone (e.g. predict-withdraw, where the batch's first sub-call\n * provides source-token balance to subsequent sub-calls). When 7702\n * simulation succeeds it is preferred since the bundled call has no per-tx\n * intrinsic gas cost and produces a tighter estimate.\n *\n * @param transactions - Batch transactions to inspect.\n * @returns Parsed gas limits and total when every transaction has gas; otherwise `undefined`.\n */\nexport function getProvidedBatchGasLimits(\n transactions: BatchTransactionParams[],\n): { gasLimits: number[]; totalGasLimit: number } | undefined {\n if (!transactions.every((transaction) => transaction.gas !== undefined)) {\n return undefined;\n }\n\n const gasLimits = transactions.map((transaction) =>\n new BigNumber(transaction.gas as Hex).toNumber(),\n );\n const totalGasLimit = gasLimits.reduce((acc, gasLimit) => acc + gasLimit, 0);\n\n return { gasLimits, totalGasLimit };\n}\n\nexport async function estimateGasBatch({\n from,\n getSimulationConfig,\n isAtomicBatchSupported,\n messenger,\n networkClientId,\n transactions,\n}: {\n from: Hex;\n getSimulationConfig: GetSimulationConfig;\n isAtomicBatchSupported: (\n request: IsAtomicBatchSupportedRequest,\n ) => Promise<IsAtomicBatchSupportedResult>;\n messenger: TransactionControllerMessenger;\n networkClientId: NetworkClientId;\n transactions: BatchTransactionParams[];\n}): Promise<EstimateGasBatchResult> {\n const chainId = getChainId({ messenger, networkClientId });\n\n const is7702Result = await isAtomicBatchSupported({\n address: from,\n chainIds: [chainId],\n });\n\n const accountSupports7702 = doesAccountSupportEIP7702(messenger, from);\n\n const chainResult = accountSupports7702\n ? is7702Result.find((result) => result.chainId === chainId)\n : undefined;\n\n const isUpgradeRequired = Boolean(chainResult && !chainResult.isSupported);\n\n if (isUpgradeRequired && !chainResult?.upgradeContractAddress) {\n throw new Error('Upgrade contract address not found');\n }\n\n if (chainResult) {\n const providedBatchGasLimits = getProvidedBatchGasLimits(transactions);\n\n const authorizationList = isUpgradeRequired\n ? [{ address: chainResult.upgradeContractAddress as Hex }]\n : undefined;\n\n const type = isUpgradeRequired\n ? TransactionEnvelopeType.setCode\n : undefined;\n\n const params: TransactionParams = {\n ...generateEIP7702BatchTransaction(from, transactions),\n authorizationList,\n from,\n type,\n };\n\n // Prefer real EIP-7702 simulation when it succeeds — the bundled call has\n // no per-tx intrinsic gas cost so the estimate is typically lower than\n // summing per-tx provided limits. Fall back to the provided sum when the\n // node-level simulation fails (e.g. predict-withdraw, where the batch's\n // first sub-call provides source-token balance to subsequent sub-calls).\n const { estimatedGas: gasLimitHex, simulationFails } = await estimateGas({\n isSimulationEnabled: true,\n getSimulationConfig,\n messenger,\n networkClientId,\n txParams: params,\n });\n\n if (simulationFails && providedBatchGasLimits) {\n log(\n 'EIP-7702 estimation failed, using batch parameter gas limits',\n providedBatchGasLimits,\n simulationFails,\n );\n return {\n gasLimits: [providedBatchGasLimits.totalGasLimit],\n ...(isUpgradeRequired ? { requiresAuthorizationList: true } : {}),\n totalGasLimit: providedBatchGasLimits.totalGasLimit,\n };\n }\n\n const totalGasLimit = new BigNumber(gasLimitHex).toNumber();\n\n log('Estimated EIP-7702 gas limit', totalGasLimit);\n\n return {\n gasLimits: [totalGasLimit],\n ...(isUpgradeRequired ? { requiresAuthorizationList: true } : {}),\n totalGasLimit,\n };\n }\n\n const providedBatchGasLimits = getProvidedBatchGasLimits(transactions);\n if (providedBatchGasLimits) {\n log('Using batch parameter gas limits', providedBatchGasLimits);\n return providedBatchGasLimits;\n }\n\n const { gasLimits: gasLimitsHex } = await simulateGasBatch({\n chainId,\n from,\n getSimulationConfig,\n transactions: transactions.map((transaction) => ({\n params: transaction,\n })),\n });\n\n const gasLimits = transactions.map((transaction, index) =>\n transaction.gas\n ? new BigNumber(transaction.gas).toNumber()\n : new BigNumber(gasLimitsHex[index]).toNumber(),\n );\n\n const totalGasLimit = gasLimits.reduce((acc, gasLimit) => acc + gasLimit, 0);\n\n log('Simulated batch gas limits', { totalGasLimit, gasLimits });\n\n return { totalGasLimit, gasLimits };\n}\n\n/**\n * Add a buffer to the provided estimated gas.\n * The buffer is calculated based on the block gas limit and a multiplier.\n *\n * @param estimatedGas - The estimated gas.\n * @param blockGasLimit - The block gas limit.\n * @param multiplier - The multiplier to apply to the estimated gas.\n * @returns The gas with the buffer applied.\n */\nexport function addGasBuffer(\n estimatedGas: string,\n blockGasLimit: string,\n multiplier: number,\n): string {\n const estimatedGasBN = hexToBN(estimatedGas);\n\n const maxGasBN = fractionBN(\n hexToBN(blockGasLimit),\n MAX_GAS_BLOCK_PERCENT,\n 100,\n );\n\n const paddedGasBN = fractionBN(estimatedGasBN, multiplier * 100, 100);\n\n if (estimatedGasBN.gt(maxGasBN)) {\n const estimatedGasHex = add0x(estimatedGas);\n log('Using estimated value', estimatedGasHex);\n return estimatedGasHex;\n }\n\n if (paddedGasBN.lt(maxGasBN)) {\n const paddedHex = add0x(BNToHex(paddedGasBN));\n log('Using padded estimate', paddedHex, multiplier);\n return paddedHex;\n }\n\n const maxHex = add0x(BNToHex(maxGasBN));\n log('Using 90% of block gas limit', maxHex);\n return maxHex;\n}\n\n/**\n * Simulate the required gas for a batch of transactions using the simulation API.\n *\n * @param options - The options object.\n * @param options.chainId - The chain ID of the transactions.\n * @param options.from - The address of the sender.\n * @param options.getSimulationConfig - The function to get the simulation configuration.\n * @param options.transactions - The array of transactions within a batch request.\n * @returns An object containing the transactions with their gas limits and the total gas limit.\n */\nexport async function simulateGasBatch({\n chainId,\n from,\n getSimulationConfig,\n transactions,\n}: {\n chainId: Hex;\n from: Hex;\n getSimulationConfig: GetSimulationConfig;\n transactions: TransactionBatchSingleRequest[];\n}): Promise<{ totalGasLimit: Hex; gasLimits: Hex[] }> {\n try {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\n transactions: transactions.map((transaction) => ({\n ...transaction.params,\n from,\n })),\n });\n\n if (response?.transactions?.length !== transactions.length) {\n throw new Error('Simulation response does not match transaction count');\n }\n\n return response.transactions.reduce<{\n totalGasLimit: Hex;\n gasLimits: Hex[];\n }>(\n (acc, transaction) => {\n const gasLimit = transaction?.gasLimit;\n\n if (!gasLimit) {\n throw new Error(\n 'No simulated gas returned for one of the transactions',\n );\n }\n\n acc.gasLimits.push(gasLimit);\n\n acc.totalGasLimit = BNToHex(\n hexToBN(acc.totalGasLimit).add(hexToBN(gasLimit)),\n );\n\n return acc;\n },\n {\n totalGasLimit: '0x0',\n gasLimits: [],\n },\n );\n } catch (error: unknown) {\n log('Error while simulating gas batch', error);\n throw new Error(\n 'Cannot estimate transaction batch total gas as simulation failed',\n );\n }\n}\n\n/**\n * Determine the gas for the provided request.\n *\n * @param request - The request object including the necessary parameters.\n * @returns The final gas value and the estimate used.\n */\nasync function getGas(\n request: UpdateGasRequest,\n): Promise<[string, TransactionMeta['simulationFails']?, string?, Revert?]> {\n const {\n isCustomNetwork,\n isSimulationEnabled,\n getSimulationConfig,\n messenger,\n txMeta,\n } = request;\n const { networkClientId } = txMeta;\n const chainId = getChainId({ messenger, networkClientId });\n const { disableGasBuffer } = txMeta;\n\n if (txMeta.txParams.gas) {\n log('Using value from request', txMeta.txParams.gas);\n return [txMeta.txParams.gas, undefined, txMeta.txParams.gas];\n }\n\n const {\n blockGasLimit,\n estimatedGas,\n gasRevert,\n isUpgradeWithData,\n simulationFails,\n } = await estimateGas({\n isSimulationEnabled,\n getSimulationConfig,\n messenger,\n networkClientId,\n txParams: txMeta.txParams,\n });\n\n log('Original estimated gas', estimatedGas);\n\n if (simulationFails) {\n log('Using original fallback estimate as simulation failed');\n }\n\n if (disableGasBuffer) {\n log('Gas buffer disabled');\n }\n\n if (simulationFails || disableGasBuffer) {\n return [estimatedGas, simulationFails, estimatedGas, gasRevert];\n }\n\n const bufferMultiplier = getGasEstimateBuffer({\n chainId,\n isCustomRPC: isCustomNetwork,\n isUpgradeWithData,\n messenger,\n });\n\n log('Buffer', bufferMultiplier);\n\n const bufferedGas = addGasBuffer(\n estimatedGas,\n blockGasLimit,\n bufferMultiplier,\n );\n\n log('Buffered gas', bufferedGas);\n\n return [bufferedGas, simulationFails, estimatedGas, gasRevert];\n}\n\n/**\n * Get the latest block from the network.\n *\n * @param messenger - The messenger instance for communication.\n * @param networkClientId - The network client ID.\n * @returns The latest block number.\n */\nasync function getLatestBlock(\n messenger: TransactionControllerMessenger,\n networkClientId: NetworkClientId,\n): Promise<{ gasLimit: string; number: string }> {\n return (await rpcRequest({\n messenger,\n networkClientId,\n method: 'eth_getBlockByNumber',\n params: ['latest', false],\n })) as { gasLimit: string; number: string };\n}\n\n/**\n * Estimate the gas for a type 4 transaction.\n *\n * @param txParams - The transaction parameters.\n * @param messenger - The messenger instance for communication.\n * @param networkClientId - The network client ID.\n * @param chainId - The chain ID of the transaction.\n * @param getSimulationConfig - The function to get the simulation configuration.\n * @returns The estimated gas.\n */\nasync function estimateGasUpgradeWithDataToSelf(\n txParams: TransactionParams,\n messenger: TransactionControllerMessenger,\n networkClientId: NetworkClientId,\n chainId: Hex,\n getSimulationConfig: GetSimulationConfig,\n): Promise<Hex> {\n const upgradeGas = (await rpcRequest({\n messenger,\n networkClientId,\n method: 'eth_estimateGas',\n params: [\n {\n ...txParams,\n to: txParams.from,\n data: '0x',\n },\n ],\n })) as Hex;\n\n log('Upgrade only gas', upgradeGas);\n\n const delegationAddress = txParams.authorizationList?.[0].address as Hex;\n\n let executeGas: Hex | undefined;\n\n try {\n executeGas = await simulateGas({\n chainId,\n delegationAddress,\n getSimulationConfig,\n transaction: txParams,\n });\n } catch (error: unknown) {\n log('Error while simulating data portion of upgrade', error);\n }\n\n if (executeGas === undefined) {\n try {\n executeGas = await estimateGasNode(\n messenger,\n networkClientId,\n { ...txParams, authorizationList: undefined, type: undefined },\n delegationAddress,\n );\n } catch (error: unknown) {\n log('Error while estimating data portion of upgrade', error);\n throw error;\n }\n\n log('Success estimating data portion of upgrade', executeGas);\n }\n\n log('Execute gas', executeGas);\n\n const total = BNToHex(\n hexToBN(upgradeGas).add(hexToBN(executeGas)).subn(INTRINSIC_GAS),\n );\n\n log('Total type 4 gas', total);\n\n return total;\n}\n\n/**\n * Simulate the required gas using the simulation API.\n *\n * @param options - The options object.\n * @param options.chainId - The chain ID of the transaction.\n * @param options.delegationAddress - The delegation address of the sender to mock.\n * @param options.getSimulationConfig - The function to get the simulation configuration.\n * @param options.transaction - The transaction parameters.\n * @returns The simulated gas.\n */\nasync function simulateGas({\n chainId,\n delegationAddress,\n getSimulationConfig,\n transaction,\n}: {\n chainId: Hex;\n delegationAddress?: Hex;\n getSimulationConfig: GetSimulationConfig;\n transaction: TransactionParams;\n}): Promise<Hex> {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\n transactions: [\n {\n to: transaction.to as Hex,\n from: transaction.from as Hex,\n data: transaction.data as Hex,\n value: transaction.value as Hex,\n },\n ],\n overrides: {\n [transaction.from]: {\n code:\n delegationAddress &&\n ((DELEGATION_PREFIX + remove0x(delegationAddress)) as Hex),\n },\n },\n });\n\n const gasLimit = response?.transactions?.[0].gasLimit;\n\n if (!gasLimit) {\n throw new Error('No simulated gas returned');\n }\n\n return gasLimit;\n}\n\n/**\n * Populate the authorization list with dummy values.\n *\n * @param authorizationList - The authorization list to prepare.\n * @param chainId - The chain ID to use.\n * @returns The authorization list with dummy values.\n */\nfunction normalizeAuthorizationList(\n authorizationList: AuthorizationList | undefined,\n chainId: Hex,\n): AuthorizationList | undefined {\n return authorizationList?.map((authorization) => ({\n ...authorization,\n chainId: authorization.chainId ?? chainId,\n nonce: authorization.nonce ?? '0x1',\n r: authorization.r ?? DUMMY_AUTHORIZATION_SIGNATURE,\n s: authorization.s ?? DUMMY_AUTHORIZATION_SIGNATURE,\n yParity: authorization.yParity ?? '0x1',\n }));\n}\n\n/**\n * Normalize the value to a canonical hex quantity with no leading zero digits.\n * Some RPC nodes (e.g. Go's `hexutil`) reject quantities such as `0x00` or\n * `0x0de0b6b3a7640000`, failing gas estimation entirely.\n *\n * @param value - The transaction value to normalize.\n * @returns The normalized transaction value.\n */\nfunction normalizeValue(value: string | undefined): string {\n const valueOrDefault = value ?? '0x0';\n\n if (!isStrictHexString(valueOrDefault)) {\n return valueOrDefault;\n }\n\n const stripped = remove0x(valueOrDefault).replace(/^0+/u, '');\n\n return stripped.length === 0 ? '0x0' : add0x(stripped);\n}\n\n/**\n * Estimate the gas for a transaction using the `eth_estimateGas` method.\n *\n * @param messenger - The messenger instance for communication.\n * @param networkClientId - The network client ID.\n * @param txParams - The transaction parameters.\n * @param delegationAddress - The delegation address of the sender to mock.\n * @returns The estimated gas as a hex string.\n */\nasync function estimateGasNode(\n messenger: TransactionControllerMessenger,\n networkClientId: NetworkClientId,\n txParams: TransactionParams,\n delegationAddress?: Hex,\n): Promise<Hex> {\n const { from } = txParams;\n const params = [txParams] as Json[];\n\n if (delegationAddress) {\n params.push('latest');\n\n params.push({\n [from]: {\n code: DELEGATION_PREFIX + remove0x(delegationAddress),\n },\n });\n }\n\n return (await rpcRequest({\n messenger,\n networkClientId,\n method: 'eth_estimateGas',\n params,\n })) as Hex;\n}\n"]}
1
+ {"version":3,"file":"gas.js","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BNToHex,\n fractionBN,\n hexToBN,\n toHex,\n} from '@metamask/controller-utils';\nimport type { NetworkClientId } from '@metamask/network-controller';\nimport type { Hex, Json } from '@metamask/utils';\nimport {\n add0x,\n createModuleLogger,\n isStrictHexString,\n remove0x,\n} from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { simulateTransactions } from '../api/simulation-api.js';\nimport type { SimulationRequestTransaction } from '../api/simulation-api.js';\nimport { projectLogger } from '../logger.js';\nimport type { TransactionControllerMessenger } from '../TransactionController.js';\nimport { TransactionEnvelopeType } from '../types.js';\nimport type {\n AuthorizationList,\n BatchTransactionParams,\n GetSimulationConfig,\n IsAtomicBatchSupportedRequest,\n IsAtomicBatchSupportedResult,\n Revert,\n TransactionBatchSingleRequest,\n TransactionMeta,\n TransactionParams,\n} from '../types.js';\nimport {\n DELEGATION_PREFIX,\n doesAccountSupportEIP7702,\n generateEIP7702BatchTransaction,\n getAuthorizationAuthority,\n getDelegationAddress,\n isAuthorizationSigned,\n} from './eip7702.js';\nimport {\n getGasEstimateBuffer,\n getGasEstimateFallback,\n} from './feature-flags.js';\nimport { getChainId, rpcRequest } from './provider.js';\nimport { decodeRevert } from './revert-reason.js';\n\nexport type UpdateGasRequest = {\n isCustomNetwork: boolean;\n isSimulationEnabled: boolean;\n getSimulationConfig: GetSimulationConfig;\n messenger: TransactionControllerMessenger;\n txMeta: TransactionMeta;\n};\n\n/**\n * How the gas limits of a batch are applied.\n * - `eip7702` - A single gas limit for the outer EIP-7702 transaction.\n * - `separate` - One gas limit per transaction, submitted separately.\n */\nexport type EstimateGasBatchMode = 'eip7702' | 'separate';\n\nexport type EstimateGasBatchResult = {\n /** Gas limits, with a single entry if `mode` is `eip7702`. */\n gasLimits: number[];\n\n /** How the gas limits are applied. */\n mode: EstimateGasBatchMode;\n\n /** Whether the outer EIP-7702 transaction upgrades the sender. */\n requiresAuthorizationList?: true;\n\n /** Total of all gas limits. */\n totalGasLimit: number;\n};\n\nexport const log = createModuleLogger(projectLogger, 'gas');\n\nexport const DEFAULT_GAS_MULTIPLIER = 1.5;\nexport const MAX_GAS_BLOCK_PERCENT = 90;\n\nexport const DUMMY_AUTHORIZATION_SIGNATURE =\n '0x1111111111111111111111111111111111111111111111111111111111111111';\n\n/**\n * EIP-2780 state gas charged at runtime when a valid authorization sets a\n * delegation indicator for an authority that had none at the start of the\n * transaction, at most once per authority.\n *\n * When the authority is the sender, this is the only runtime authorization\n * charge: `ACCOUNT_WRITE` is covered by the transaction base cost, and the\n * sender always exists in state as its nonce is incremented first.\n */\nexport const EIP_2780_AUTHORIZATION_GAS = 35190;\n\n/**\n * Intrinsic gas cost for each authorization omitted from the node estimate.\n */\nexport const EIP7280_AUTHORIZATION_INTRINSIC_GAS = 7816;\n\n/**\n * Gas for the upgrade authorization of the sender that is not included in the\n * sum of the provided gas values of a batch: the EIP-7280 intrinsic cost of an\n * authorization plus the delegation indicator charge.\n */\nexport const UPGRADE_AUTHORIZATION_GAS =\n EIP7280_AUTHORIZATION_INTRINSIC_GAS + EIP_2780_AUTHORIZATION_GAS;\n\n/**\n * Error for a simulated transaction that failed, as opposed to the simulation\n * itself being unavailable.\n */\nclass SimulatedTransactionError extends Error {}\n\n/**\n * Populate the gas properties of the provided transaction meta.\n *\n * @param request - The request object including the necessary parameters.\n */\nexport async function updateGas(request: UpdateGasRequest): Promise<void> {\n const { txMeta } = request;\n const initialParams = { ...txMeta.txParams };\n\n const [gas, simulationFails, gasLimitNoBuffer, gasRevert] =\n await getGas(request);\n\n txMeta.txParams.gas = gas;\n txMeta.simulationFails = simulationFails;\n txMeta.gasLimitNoBuffer = gasLimitNoBuffer;\n\n if (gasRevert) {\n txMeta.revert = { ...txMeta.revert, gas: gasRevert };\n }\n\n if (!initialParams.gas) {\n txMeta.originalGasEstimate = txMeta.txParams.gas;\n }\n\n txMeta.defaultGasEstimates ??= {};\n txMeta.defaultGasEstimates.gas = txMeta.txParams.gas;\n}\n\n/**\n * Estimate the gas for the provided transaction parameters.\n * If the gas estimate fails, the fallback value is returned.\n *\n * @param options - The options object.\n * @param options.ignoreDelegationSignatures - Ignore signature errors if submitting delegations to the DelegationManager.\n * @param options.isSimulationEnabled - Whether the simulation is enabled.\n * @param options.getSimulationConfig - The function to get the simulation configuration.\n * @param options.messenger - The messenger instance for communication.\n * @param options.networkClientId - The network client ID.\n * @param options.txParams - The transaction parameters.\n * @returns The estimated gas and related info.\n */\nexport async function estimateGas({\n ignoreDelegationSignatures,\n isSimulationEnabled,\n getSimulationConfig,\n messenger,\n networkClientId,\n txParams,\n}: {\n ignoreDelegationSignatures?: boolean;\n isSimulationEnabled: boolean;\n getSimulationConfig: GetSimulationConfig;\n messenger: TransactionControllerMessenger;\n networkClientId: NetworkClientId;\n txParams: TransactionParams;\n}): Promise<{\n blockGasLimit: string;\n estimatedGas: string;\n gasRevert?: Revert;\n isUpgradeWithData: boolean;\n simulationFails: TransactionMeta['simulationFails'];\n}> {\n const request = { ...txParams };\n const { authorizationList, data, value } = request;\n const chainId = getChainId({ messenger, networkClientId });\n\n if (ignoreDelegationSignatures && !isSimulationEnabled) {\n throw new Error(\n 'Gas estimation with ignored delegation signatures is not supported as simulation disabled',\n );\n }\n\n const { gasLimit: blockGasLimit, number: blockNumber } = await getLatestBlock(\n messenger,\n networkClientId,\n );\n\n const blockGasLimitBN = hexToBN(blockGasLimit);\n const { percentage, fixed, maxGasLimit } = getGasEstimateFallback(\n chainId,\n messenger,\n );\n\n const uncappedFallback = fixed\n ? toHex(fixed)\n : BNToHex(fractionBN(blockGasLimitBN, percentage, 100));\n\n // Clamp the fallback to the chain's per-transaction gas cap so it can never\n // exceed the gas limit the RPC will accept. Without this, a percentage of a\n // high block gas limit can overshoot the cap (e.g. 35% of Polygon's ~140M\n // block limit is ~49M, but the node caps a tx at ~33.5M and rejects it with\n // \"transaction gas limit too high\").\n const fallback =\n maxGasLimit !== undefined &&\n hexToBN(uncappedFallback).gt(hexToBN(toHex(maxGasLimit)))\n ? toHex(maxGasLimit)\n : uncappedFallback;\n\n log('Estimation fallback values', fallback);\n\n request.data = data ? add0x(data) : data;\n request.value = normalizeValue(value);\n\n request.authorizationList = normalizeAuthorizationList(\n request.authorizationList,\n chainId,\n );\n\n delete request.gasPrice;\n delete request.maxFeePerGas;\n delete request.maxPriorityFeePerGas;\n\n let estimatedGas = fallback;\n let simulationFails: TransactionMeta['simulationFails'];\n let gasRevert: Revert | undefined;\n\n const isUpgradeWithData =\n txParams.type === TransactionEnvelopeType.setCode &&\n Boolean(authorizationList?.length) &&\n Boolean(data) &&\n data !== '0x';\n\n const type4AuthorizationList =\n txParams.type === TransactionEnvelopeType.setCode &&\n authorizationList?.length\n ? authorizationList\n : undefined;\n\n try {\n if (type4AuthorizationList) {\n estimatedGas = await estimateGasType4({\n authorizationList: type4AuthorizationList,\n chainId,\n getSimulationConfig,\n isSimulationEnabled,\n messenger,\n networkClientId,\n txParams: request,\n });\n } else if (ignoreDelegationSignatures && isSimulationEnabled) {\n estimatedGas = await simulateGas({\n chainId,\n getSimulationConfig,\n transaction: request,\n });\n } else {\n estimatedGas = await estimateGasNode(messenger, networkClientId, request);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n simulationFails = {\n reason: error.message,\n errorKey: error.errorKey,\n debug: {\n blockNumber,\n blockGasLimit,\n },\n };\n\n gasRevert = decodeRevert(error, 'gas');\n\n log('Estimation failed', { ...simulationFails, fallback, gasRevert });\n }\n\n return {\n blockGasLimit,\n estimatedGas,\n gasRevert,\n isUpgradeWithData,\n simulationFails,\n };\n}\n\n/**\n * Sum caller-provided gas limits across a batch.\n *\n * If every transaction in the batch already has a `gas` value, returns the\n * parsed per-tx limits and their sum. Otherwise returns `undefined`.\n *\n * Used by `estimateGasBatch`:\n * - non-7702 path: short-circuits simulation entirely when present.\n * - EIP-7702 path: used as a fallback when simulation fails — required for\n * callers that submit batches whose individual sub-calls cannot be simulated\n * standalone (e.g. predict-withdraw, where the batch's first sub-call\n * provides source-token balance to subsequent sub-calls). When 7702\n * simulation succeeds it is preferred since the bundled call has no per-tx\n * intrinsic gas cost and produces a tighter estimate. If the sender requires\n * an upgrade, the fallback adds the authorization intrinsic gas and, if no\n * delegation exists yet, the delegation indicator charge. The provided gas\n * values do not include these authorization costs.\n *\n * @param transactions - Batch transactions to inspect.\n * @returns Parsed gas limits and total when every transaction has gas; otherwise `undefined`.\n */\nexport function getProvidedBatchGasLimits(\n transactions: BatchTransactionParams[],\n): { gasLimits: number[]; totalGasLimit: number } | undefined {\n if (!transactions.every((transaction) => transaction.gas !== undefined)) {\n return undefined;\n }\n\n const gasLimits = transactions.map((transaction) =>\n new BigNumber(transaction.gas as Hex).toNumber(),\n );\n const totalGasLimit = gasLimits.reduce((acc, gasLimit) => acc + gasLimit, 0);\n\n return { gasLimits, totalGasLimit };\n}\n\nexport async function estimateGasBatch({\n from,\n getSimulationConfig,\n isAtomicBatchSupported,\n messenger,\n networkClientId,\n transactions,\n}: {\n from: Hex;\n getSimulationConfig: GetSimulationConfig;\n isAtomicBatchSupported: (\n request: IsAtomicBatchSupportedRequest,\n ) => Promise<IsAtomicBatchSupportedResult>;\n messenger: TransactionControllerMessenger;\n networkClientId: NetworkClientId;\n transactions: BatchTransactionParams[];\n}): Promise<EstimateGasBatchResult> {\n const chainId = getChainId({ messenger, networkClientId });\n\n const is7702Result = await isAtomicBatchSupported({\n address: from,\n chainIds: [chainId],\n });\n\n const accountSupports7702 = doesAccountSupportEIP7702(messenger, from);\n\n const chainResult = accountSupports7702\n ? is7702Result.find((result) => result.chainId === chainId)\n : undefined;\n\n const isUpgradeRequired = Boolean(chainResult && !chainResult.isSupported);\n\n if (isUpgradeRequired && !chainResult?.upgradeContractAddress) {\n throw new Error('Upgrade contract address not found');\n }\n\n if (chainResult) {\n const providedBatchGasLimits = getProvidedBatchGasLimits(transactions);\n\n const authorizationList = isUpgradeRequired\n ? [{ address: chainResult.upgradeContractAddress as Hex }]\n : undefined;\n\n const type = isUpgradeRequired\n ? TransactionEnvelopeType.setCode\n : undefined;\n\n const params: TransactionParams = {\n ...generateEIP7702BatchTransaction(from, transactions),\n authorizationList,\n from,\n type,\n };\n\n // Prefer real EIP-7702 simulation when it succeeds — the bundled call has\n // no per-tx intrinsic gas cost so the estimate is typically lower than\n // summing per-tx provided limits. Fall back to the provided sum when the\n // node-level simulation fails (e.g. predict-withdraw, where the batch's\n // first sub-call provides source-token balance to subsequent sub-calls).\n const { estimatedGas: gasLimitHex, simulationFails } = await estimateGas({\n isSimulationEnabled: true,\n getSimulationConfig,\n messenger,\n networkClientId,\n txParams: params,\n });\n\n if (simulationFails && providedBatchGasLimits) {\n const upgradeGas = chainResult.delegationAddress\n ? EIP7280_AUTHORIZATION_INTRINSIC_GAS\n : UPGRADE_AUTHORIZATION_GAS;\n const fallbackGasLimit =\n providedBatchGasLimits.totalGasLimit +\n (isUpgradeRequired ? upgradeGas : 0);\n\n log(\n 'EIP-7702 estimation failed, using batch parameter gas limits',\n { fallbackGasLimit },\n simulationFails,\n );\n\n return {\n gasLimits: [fallbackGasLimit],\n mode: 'eip7702',\n ...(isUpgradeRequired ? { requiresAuthorizationList: true } : {}),\n totalGasLimit: fallbackGasLimit,\n };\n }\n\n const totalGasLimit = new BigNumber(gasLimitHex).toNumber();\n\n log('Estimated EIP-7702 gas limit', totalGasLimit);\n\n return {\n gasLimits: [totalGasLimit],\n mode: 'eip7702',\n ...(isUpgradeRequired ? { requiresAuthorizationList: true } : {}),\n totalGasLimit,\n };\n }\n\n const providedBatchGasLimits = getProvidedBatchGasLimits(transactions);\n if (providedBatchGasLimits) {\n log('Using batch parameter gas limits', providedBatchGasLimits);\n return { ...providedBatchGasLimits, mode: 'separate' };\n }\n\n const { gasLimits: gasLimitsHex } = await simulateGasBatch({\n chainId,\n from,\n getSimulationConfig,\n transactions: transactions.map((transaction) => ({\n params: transaction,\n })),\n });\n\n const gasLimits = transactions.map((transaction, index) =>\n transaction.gas\n ? new BigNumber(transaction.gas).toNumber()\n : new BigNumber(gasLimitsHex[index]).toNumber(),\n );\n\n const totalGasLimit = gasLimits.reduce((acc, gasLimit) => acc + gasLimit, 0);\n\n log('Simulated batch gas limits', { totalGasLimit, gasLimits });\n\n return { gasLimits, mode: 'separate', totalGasLimit };\n}\n\n/**\n * Add a buffer to the provided estimated gas.\n * The buffer is calculated based on the block gas limit and a multiplier.\n *\n * @param estimatedGas - The estimated gas.\n * @param blockGasLimit - The block gas limit.\n * @param multiplier - The multiplier to apply to the estimated gas.\n * @returns The gas with the buffer applied.\n */\nexport function addGasBuffer(\n estimatedGas: string,\n blockGasLimit: string,\n multiplier: number,\n): string {\n const estimatedGasBN = hexToBN(estimatedGas);\n\n const maxGasBN = fractionBN(\n hexToBN(blockGasLimit),\n MAX_GAS_BLOCK_PERCENT,\n 100,\n );\n\n const paddedGasBN = fractionBN(estimatedGasBN, multiplier * 100, 100);\n\n if (estimatedGasBN.gt(maxGasBN)) {\n const estimatedGasHex = add0x(estimatedGas);\n log('Using estimated value', estimatedGasHex);\n return estimatedGasHex;\n }\n\n if (paddedGasBN.lt(maxGasBN)) {\n const paddedHex = add0x(BNToHex(paddedGasBN));\n log('Using padded estimate', paddedHex, multiplier);\n return paddedHex;\n }\n\n const maxHex = add0x(BNToHex(maxGasBN));\n log('Using 90% of block gas limit', maxHex);\n return maxHex;\n}\n\n/**\n * Simulate the required gas for a batch of transactions using the simulation API.\n *\n * @param options - The options object.\n * @param options.chainId - The chain ID of the transactions.\n * @param options.from - The address of the sender.\n * @param options.getSimulationConfig - The function to get the simulation configuration.\n * @param options.transactions - The array of transactions within a batch request.\n * @returns An object containing the transactions with their gas limits and the total gas limit.\n */\nexport async function simulateGasBatch({\n chainId,\n from,\n getSimulationConfig,\n transactions,\n}: {\n chainId: Hex;\n from: Hex;\n getSimulationConfig: GetSimulationConfig;\n transactions: TransactionBatchSingleRequest[];\n}): Promise<{ totalGasLimit: Hex; gasLimits: Hex[] }> {\n try {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\n transactions: transactions.map((transaction) => ({\n ...transaction.params,\n from,\n })),\n });\n\n if (response?.transactions?.length !== transactions.length) {\n throw new Error('Simulation response does not match transaction count');\n }\n\n return response.transactions.reduce<{\n totalGasLimit: Hex;\n gasLimits: Hex[];\n }>(\n (acc, transaction) => {\n const gasLimit = transaction?.gasLimit;\n\n if (!gasLimit) {\n throw new Error(\n 'No simulated gas returned for one of the transactions',\n );\n }\n\n acc.gasLimits.push(gasLimit);\n\n acc.totalGasLimit = BNToHex(\n hexToBN(acc.totalGasLimit).add(hexToBN(gasLimit)),\n );\n\n return acc;\n },\n {\n totalGasLimit: '0x0',\n gasLimits: [],\n },\n );\n } catch (error: unknown) {\n log('Error while simulating gas batch', error);\n throw new Error(\n 'Cannot estimate transaction batch total gas as simulation failed',\n );\n }\n}\n\n/**\n * Determine the gas for the provided request.\n *\n * @param request - The request object including the necessary parameters.\n * @returns The final gas value and the estimate used.\n */\nasync function getGas(\n request: UpdateGasRequest,\n): Promise<[string, TransactionMeta['simulationFails']?, string?, Revert?]> {\n const {\n isCustomNetwork,\n isSimulationEnabled,\n getSimulationConfig,\n messenger,\n txMeta,\n } = request;\n const { networkClientId } = txMeta;\n const chainId = getChainId({ messenger, networkClientId });\n const { disableGasBuffer } = txMeta;\n\n if (txMeta.txParams.gas) {\n log('Using value from request', txMeta.txParams.gas);\n return [txMeta.txParams.gas, undefined, txMeta.txParams.gas];\n }\n\n const {\n blockGasLimit,\n estimatedGas,\n gasRevert,\n isUpgradeWithData,\n simulationFails,\n } = await estimateGas({\n isSimulationEnabled,\n getSimulationConfig,\n messenger,\n networkClientId,\n txParams: txMeta.txParams,\n });\n\n log('Original estimated gas', estimatedGas);\n\n if (simulationFails) {\n log('Using original fallback estimate as simulation failed');\n }\n\n if (disableGasBuffer) {\n log('Gas buffer disabled');\n }\n\n if (simulationFails || disableGasBuffer) {\n return [estimatedGas, simulationFails, estimatedGas, gasRevert];\n }\n\n const bufferMultiplier = getGasEstimateBuffer({\n chainId,\n isCustomRPC: isCustomNetwork,\n isUpgradeWithData,\n messenger,\n });\n\n log('Buffer', bufferMultiplier);\n\n const bufferedGas = addGasBuffer(\n estimatedGas,\n blockGasLimit,\n bufferMultiplier,\n );\n\n log('Buffered gas', bufferedGas);\n\n return [bufferedGas, simulationFails, estimatedGas, gasRevert];\n}\n\n/**\n * Get the latest block from the network.\n *\n * @param messenger - The messenger instance for communication.\n * @param networkClientId - The network client ID.\n * @returns The latest block number.\n */\nasync function getLatestBlock(\n messenger: TransactionControllerMessenger,\n networkClientId: NetworkClientId,\n): Promise<{ gasLimit: string; number: string }> {\n return (await rpcRequest({\n messenger,\n networkClientId,\n method: 'eth_getBlockByNumber',\n params: ['latest', false],\n })) as { gasLimit: string; number: string };\n}\n\n/**\n * Estimate the gas for a type 4 transaction as one outer transaction.\n *\n * - If all authorizations are signed, the selected node estimates the exact\n * transaction.\n * - Otherwise, the Simulation API estimates the exact transaction, with the\n * authority of each authorization so that it can apply any EIP-2780 runtime\n * authorization charges.\n * - If the Simulation API is disabled, unsupported or unavailable, the selected\n * node estimates the transaction without unsigned authorizations and with the\n * delegation of the sender overridden. Intrinsic gas is added for each omitted\n * authorization, plus the EIP-2780 delegation charge if the sender is not yet\n * delegated. A simulated transaction error is not retried using the node.\n *\n * @param options - The options object.\n * @param options.authorizationList - The original authorization list of the transaction.\n * @param options.chainId - The chain ID of the transaction.\n * @param options.getSimulationConfig - The function to get the simulation configuration.\n * @param options.isSimulationEnabled - Whether the simulation is enabled.\n * @param options.messenger - The messenger instance for communication.\n * @param options.networkClientId - The network client ID.\n * @param options.txParams - The normalized transaction parameters.\n * @returns The estimated gas.\n */\nasync function estimateGasType4({\n authorizationList,\n chainId,\n getSimulationConfig,\n isSimulationEnabled,\n messenger,\n networkClientId,\n txParams,\n}: {\n authorizationList: AuthorizationList;\n chainId: Hex;\n getSimulationConfig: GetSimulationConfig;\n isSimulationEnabled: boolean;\n messenger: TransactionControllerMessenger;\n networkClientId: NetworkClientId;\n txParams: TransactionParams;\n}): Promise<Hex> {\n if (authorizationList.every(isAuthorizationSigned)) {\n log('Estimating type 4 gas using node as all authorizations signed');\n return await estimateGasNode(messenger, networkClientId, txParams);\n }\n\n if (isSimulationEnabled) {\n const simulationAuthorizationList = authorizationList.map(\n (authorization) => {\n const authority = getAuthorizationAuthority(\n authorization,\n txParams.from,\n );\n\n if (!authority) {\n throw new Error('Cannot determine authority of signed authorization');\n }\n\n return { address: authorization.address, from: authority };\n },\n );\n\n log('Estimating type 4 gas using simulation', simulationAuthorizationList);\n\n try {\n return await simulateGas({\n authorizationList: simulationAuthorizationList,\n chainId,\n getSimulationConfig,\n transaction: txParams,\n });\n } catch (error) {\n if (error instanceof SimulatedTransactionError) {\n throw error;\n }\n\n log('Simulation unavailable, estimating type 4 gas using node', error);\n }\n }\n\n return await estimateGasType4Node({\n authorizationList,\n messenger,\n networkClientId,\n txParams,\n });\n}\n\n/**\n * Estimate the gas for a type 4 transaction with unsigned authorizations using\n * the selected node.\n *\n * Unsigned authorizations are omitted from the node request and their intrinsic\n * gas is added manually per entry. Their authority is the sender, so the\n * delegation of the sender is set with a state override, and the EIP-2780 charge\n * for a new delegation indicator is added once if the sender is not yet\n * delegated. Signed authorizations remain in the request and are charged by the\n * node.\n *\n * @param options - The options object.\n * @param options.authorizationList - The original authorization list of the transaction.\n * @param options.messenger - The messenger instance for communication.\n * @param options.networkClientId - The network client ID.\n * @param options.txParams - The normalized transaction parameters.\n * @returns The estimated gas including omitted authorization costs.\n */\nasync function estimateGasType4Node({\n authorizationList,\n messenger,\n networkClientId,\n txParams,\n}: {\n authorizationList: AuthorizationList;\n messenger: TransactionControllerMessenger;\n networkClientId: NetworkClientId;\n txParams: TransactionParams;\n}): Promise<Hex> {\n const unsignedAuthorizations = authorizationList.filter(\n (authorization) => !isAuthorizationSigned(authorization),\n );\n const signedAuthorizations = authorizationList.filter(isAuthorizationSigned);\n const nodeTxParams = {\n ...txParams,\n authorizationList: signedAuthorizations.length\n ? signedAuthorizations\n : undefined,\n type: signedAuthorizations.length ? txParams.type : undefined,\n };\n\n // Unsigned authorizations are signed by the sender, and the last valid\n // authorization for an authority sets its delegation.\n const delegationAddress =\n unsignedAuthorizations[unsignedAuthorizations.length - 1].address;\n\n const [nodeGas, currentDelegationAddress] = await Promise.all([\n estimateGasNode(\n messenger,\n networkClientId,\n nodeTxParams,\n delegationAddress,\n ),\n getDelegationAddress(txParams.from as Hex, messenger, networkClientId),\n ]);\n\n const intrinsicGas =\n unsignedAuthorizations.length * EIP7280_AUTHORIZATION_INTRINSIC_GAS;\n const delegationGas = currentDelegationAddress\n ? 0\n : EIP_2780_AUTHORIZATION_GAS;\n\n log('Type 4 gas using node', {\n currentDelegationAddress,\n delegationGas,\n intrinsicGas,\n nodeGas,\n });\n\n return BNToHex(hexToBN(nodeGas).addn(intrinsicGas + delegationGas));\n}\n\n/**\n * Simulate the required gas using the simulation API.\n *\n * If an authorization list is provided, it is included in the simulated\n * transaction, a simulated transaction error is thrown as a\n * `SimulatedTransactionError`, and the response must include a non-zero gas\n * limit.\n *\n * @param options - The options object.\n * @param options.authorizationList - The authorization list with the authority of each entry.\n * @param options.chainId - The chain ID of the transaction.\n * @param options.getSimulationConfig - The function to get the simulation configuration.\n * @param options.transaction - The transaction parameters.\n * @returns The simulated gas.\n */\nasync function simulateGas({\n authorizationList,\n chainId,\n getSimulationConfig,\n transaction,\n}: {\n authorizationList?: SimulationRequestTransaction['authorizationList'];\n chainId: Hex;\n getSimulationConfig: GetSimulationConfig;\n transaction: TransactionParams;\n}): Promise<Hex> {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\n transactions: [\n {\n ...(authorizationList ? { authorizationList } : {}),\n to: transaction.to as Hex,\n from: transaction.from as Hex,\n data: transaction.data as Hex,\n value: transaction.value as Hex,\n },\n ],\n });\n\n const simulatedTransaction = response?.transactions?.[0];\n const gasLimit = simulatedTransaction?.gasLimit;\n\n if (authorizationList && simulatedTransaction?.error) {\n throw new SimulatedTransactionError(\n `Simulation failed: ${simulatedTransaction.error}`,\n );\n }\n\n if (!gasLimit || (authorizationList && hexToBN(gasLimit).isZero())) {\n throw new Error('No simulated gas returned');\n }\n\n return gasLimit;\n}\n\n/**\n * Populate the authorization list with dummy values.\n *\n * @param authorizationList - The authorization list to prepare.\n * @param chainId - The chain ID to use.\n * @returns The authorization list with dummy values.\n */\nfunction normalizeAuthorizationList(\n authorizationList: AuthorizationList | undefined,\n chainId: Hex,\n): AuthorizationList | undefined {\n return authorizationList?.map((authorization) => ({\n ...authorization,\n chainId: authorization.chainId ?? chainId,\n nonce: authorization.nonce ?? '0x1',\n r: authorization.r ?? DUMMY_AUTHORIZATION_SIGNATURE,\n s: authorization.s ?? DUMMY_AUTHORIZATION_SIGNATURE,\n yParity: authorization.yParity ?? '0x1',\n }));\n}\n\n/**\n * Normalize the value to a canonical hex quantity with no leading zero digits.\n * Some RPC nodes (e.g. Go's `hexutil`) reject quantities such as `0x00` or\n * `0x0de0b6b3a7640000`, failing gas estimation entirely.\n *\n * @param value - The transaction value to normalize.\n * @returns The normalized transaction value.\n */\nfunction normalizeValue(value: string | undefined): string {\n const valueOrDefault = value ?? '0x0';\n\n if (!isStrictHexString(valueOrDefault)) {\n return valueOrDefault;\n }\n\n const stripped = remove0x(valueOrDefault).replace(/^0+/u, '');\n\n return stripped.length === 0 ? '0x0' : add0x(stripped);\n}\n\n/**\n * Estimate the gas for a transaction using the `eth_estimateGas` method.\n *\n * @param messenger - The messenger instance for communication.\n * @param networkClientId - The network client ID.\n * @param txParams - The transaction parameters.\n * @param delegationAddress - The delegation address of the sender to mock.\n * @returns The estimated gas as a hex string.\n */\nasync function estimateGasNode(\n messenger: TransactionControllerMessenger,\n networkClientId: NetworkClientId,\n txParams: TransactionParams,\n delegationAddress?: Hex,\n): Promise<Hex> {\n const { from } = txParams;\n const params = [txParams] as Json[];\n\n if (delegationAddress) {\n params.push('latest');\n\n params.push({\n [from]: {\n code: DELEGATION_PREFIX + remove0x(delegationAddress),\n },\n });\n }\n\n return (await rpcRequest({\n messenger,\n networkClientId,\n method: 'eth_estimateGas',\n params,\n })) as Hex;\n}\n"]}