@aztec/ethereum 3.0.0-nightly.20251214 → 3.0.0-nightly.20251217
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/dest/deploy_aztec_l1_contracts.d.ts +2 -2
- package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_aztec_l1_contracts.js +144 -107
- package/dest/l1_artifacts.d.ts +61 -41
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/l1_contract_addresses.d.ts +1 -1
- package/dest/l1_contract_addresses.d.ts.map +1 -1
- package/dest/l1_contract_addresses.js +3 -3
- package/dest/l1_tx_utils/constants.d.ts +7 -1
- package/dest/l1_tx_utils/constants.d.ts.map +1 -1
- package/dest/l1_tx_utils/constants.js +25 -0
- package/dest/l1_tx_utils/fee-strategies/index.d.ts +9 -0
- package/dest/l1_tx_utils/fee-strategies/index.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/index.js +11 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts +18 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +111 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts +32 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +173 -0
- package/dest/l1_tx_utils/fee-strategies/types.d.ts +64 -0
- package/dest/l1_tx_utils/fee-strategies/types.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/types.js +24 -0
- package/dest/l1_tx_utils/index.d.ts +3 -1
- package/dest/l1_tx_utils/index.d.ts.map +1 -1
- package/dest/l1_tx_utils/index.js +2 -0
- package/dest/l1_tx_utils/l1_fee_analyzer.d.ts +232 -0
- package/dest/l1_tx_utils/l1_fee_analyzer.d.ts.map +1 -0
- package/dest/l1_tx_utils/l1_fee_analyzer.js +506 -0
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +1 -10
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/readonly_l1_tx_utils.js +43 -121
- package/dest/utils.d.ts +14 -2
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +18 -0
- package/package.json +6 -5
- package/src/deploy_aztec_l1_contracts.ts +141 -107
- package/src/l1_contract_addresses.ts +22 -20
- package/src/l1_tx_utils/constants.ts +11 -0
- package/src/l1_tx_utils/fee-strategies/index.ts +22 -0
- package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +159 -0
- package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +241 -0
- package/src/l1_tx_utils/fee-strategies/types.ts +88 -0
- package/src/l1_tx_utils/index.ts +2 -0
- package/src/l1_tx_utils/l1_fee_analyzer.ts +803 -0
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +47 -158
- package/src/utils.ts +29 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getKeys,
|
|
1
|
+
import { getKeys, merge, pick, times } from '@aztec/foundation/collection';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
import { makeBackoff, retry } from '@aztec/foundation/retry';
|
|
4
4
|
import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
|
|
@@ -6,8 +6,10 @@ import pickBy from 'lodash.pickby';
|
|
|
6
6
|
import { MethodNotFoundRpcError, MethodNotSupportedRpcError, decodeErrorResult, formatGwei, getContractError, hexToBytes } from 'viem';
|
|
7
7
|
import { defaultL1TxUtilsConfig, l1TxUtilsConfigMappings } from './config.js';
|
|
8
8
|
import { BLOCK_TIME_MS, LARGE_GAS_LIMIT, MIN_BLOB_REPLACEMENT_BUMP_PERCENTAGE, MIN_REPLACEMENT_BUMP_PERCENTAGE, WEI_CONST } from './constants.js';
|
|
9
|
+
import { P75AllTxsPriorityFeeStrategy } from './fee-strategies/index.js';
|
|
9
10
|
import { getCalldataGasUsage, tryGetCustomErrorNameContractFunction } from './utils.js';
|
|
10
|
-
|
|
11
|
+
// Change this to the current strategy we want to use
|
|
12
|
+
const CurrentStrategy = P75AllTxsPriorityFeeStrategy;
|
|
11
13
|
export class ReadOnlyL1TxUtils {
|
|
12
14
|
client;
|
|
13
15
|
logger;
|
|
@@ -36,119 +38,32 @@ export class ReadOnlyL1TxUtils {
|
|
|
36
38
|
return this.client.getBlockNumber();
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
|
-
* Analyzes pending transactions and recent fee history to determine a competitive priority fee.
|
|
40
|
-
* Falls back to network estimate if data is unavailable or fails.
|
|
41
|
-
* @param networkEstimateResult - Result from estimateMaxPriorityFeePerGas RPC call
|
|
42
|
-
* @param pendingBlockResult - Result from getBlock with pending tag RPC call
|
|
43
|
-
* @param feeHistoryResult - Result from getFeeHistory RPC call
|
|
44
|
-
* @returns A competitive priority fee based on pending txs and recent block history
|
|
45
|
-
*/ getCompetitivePriorityFee(networkEstimateResult, pendingBlockResult, feeHistoryResult) {
|
|
46
|
-
const networkEstimate = networkEstimateResult.status === 'fulfilled' && typeof networkEstimateResult.value === 'bigint' ? networkEstimateResult.value : 0n;
|
|
47
|
-
let competitiveFee = networkEstimate;
|
|
48
|
-
if (pendingBlockResult.status === 'fulfilled' && pendingBlockResult.value !== null && pendingBlockResult.value.transactions && pendingBlockResult.value.transactions.length > 0) {
|
|
49
|
-
const pendingBlock = pendingBlockResult.value;
|
|
50
|
-
// Extract priority fees from pending transactions
|
|
51
|
-
const pendingFees = pendingBlock.transactions.map((tx)=>{
|
|
52
|
-
// Transaction can be just a hash string, so we need to check if it's an object
|
|
53
|
-
if (typeof tx === 'string') {
|
|
54
|
-
return 0n;
|
|
55
|
-
}
|
|
56
|
-
const fee = tx.maxPriorityFeePerGas || 0n;
|
|
57
|
-
// Debug: Log suspicious fees
|
|
58
|
-
if (fee > 100n * WEI_CONST) {
|
|
59
|
-
this.logger?.warn('Suspicious high priority fee in pending tx', {
|
|
60
|
-
txHash: tx.hash,
|
|
61
|
-
maxPriorityFeePerGas: formatGwei(fee),
|
|
62
|
-
maxFeePerGas: formatGwei(tx.maxFeePerGas || 0n),
|
|
63
|
-
maxFeePerBlobGas: tx.maxFeePerBlobGas ? formatGwei(tx.maxFeePerBlobGas) : 'N/A'
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
return fee;
|
|
67
|
-
}).filter((fee)=>fee > 0n);
|
|
68
|
-
if (pendingFees.length > 0) {
|
|
69
|
-
// Use 75th percentile of pending fees to be competitive
|
|
70
|
-
const sortedPendingFees = [
|
|
71
|
-
...pendingFees
|
|
72
|
-
].sort((a, b)=>a < b ? -1 : a > b ? 1 : 0);
|
|
73
|
-
const percentile75Index = Math.floor((sortedPendingFees.length - 1) * 0.75);
|
|
74
|
-
const pendingCompetitiveFee = sortedPendingFees[percentile75Index];
|
|
75
|
-
if (pendingCompetitiveFee > competitiveFee) {
|
|
76
|
-
competitiveFee = pendingCompetitiveFee;
|
|
77
|
-
}
|
|
78
|
-
this.logger?.debug('Analyzed pending transactions for competitive pricing', {
|
|
79
|
-
pendingTxCount: pendingFees.length,
|
|
80
|
-
pendingP75: formatGwei(pendingCompetitiveFee)
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
if (feeHistoryResult.status === 'fulfilled' && feeHistoryResult.value !== null && feeHistoryResult.value.reward && feeHistoryResult.value.reward.length > 0) {
|
|
85
|
-
const feeHistory = feeHistoryResult.value;
|
|
86
|
-
// Extract 75th percentile fees from each block
|
|
87
|
-
const percentile75Fees = feeHistory.reward.map((rewards)=>rewards[0] || 0n).filter((fee)=>fee > 0n);
|
|
88
|
-
if (percentile75Fees.length > 0) {
|
|
89
|
-
// Calculate median of the 75th percentile fees across blocks
|
|
90
|
-
const medianHistoricalFee = median(percentile75Fees) ?? 0n;
|
|
91
|
-
// Debug: Log suspicious fees from history
|
|
92
|
-
if (medianHistoricalFee > 100n * WEI_CONST) {
|
|
93
|
-
this.logger?.warn('Suspicious high fee in history', {
|
|
94
|
-
historicalMedian: formatGwei(medianHistoricalFee),
|
|
95
|
-
allP75Fees: percentile75Fees.map((f)=>formatGwei(f))
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
if (medianHistoricalFee > competitiveFee) {
|
|
99
|
-
competitiveFee = medianHistoricalFee;
|
|
100
|
-
}
|
|
101
|
-
this.logger?.debug('Analyzed fee history for competitive pricing', {
|
|
102
|
-
historicalMedian: formatGwei(medianHistoricalFee)
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
// Sanity check: cap competitive fee at 100x network estimate to avoid using unrealistic fees
|
|
107
|
-
// (e.g., Anvil returns inflated historical fees that don't reflect actual network conditions)
|
|
108
|
-
const maxReasonableFee = networkEstimate * 100n;
|
|
109
|
-
if (competitiveFee > maxReasonableFee) {
|
|
110
|
-
this.logger?.warn('Competitive fee exceeds sanity cap, using capped value', {
|
|
111
|
-
competitiveFee: formatGwei(competitiveFee),
|
|
112
|
-
networkEstimate: formatGwei(networkEstimate),
|
|
113
|
-
cappedTo: formatGwei(maxReasonableFee)
|
|
114
|
-
});
|
|
115
|
-
competitiveFee = maxReasonableFee;
|
|
116
|
-
}
|
|
117
|
-
// Log final decision
|
|
118
|
-
if (competitiveFee > networkEstimate) {
|
|
119
|
-
this.logger?.debug('Using competitive fee from market analysis', {
|
|
120
|
-
networkEstimate: formatGwei(networkEstimate),
|
|
121
|
-
competitive: formatGwei(competitiveFee)
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
return competitiveFee;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
41
|
* Gets the current gas price with bounds checking
|
|
128
42
|
*/ async getGasPrice(gasConfigOverrides, isBlobTx = false, attempt = 0, previousGasPrice) {
|
|
129
43
|
const gasConfig = merge(this.config, gasConfigOverrides);
|
|
130
44
|
// Make all RPC calls in parallel upfront with retry logic
|
|
45
|
+
// First 2 calls are necessary to complete
|
|
131
46
|
const latestBlockPromise = this.tryTwice(()=>this.client.getBlock({
|
|
132
47
|
blockTag: 'latest'
|
|
133
48
|
}), 'Getting latest block');
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
49
|
+
let blobBaseFeePromise = null;
|
|
50
|
+
if (isBlobTx) {
|
|
51
|
+
blobBaseFeePromise = this.tryTwice(()=>this.client.getBlobBaseFee(), 'Getting blob base fee');
|
|
52
|
+
}
|
|
53
|
+
// Get strategy promises for priority fee calculation
|
|
54
|
+
const strategyPromises = CurrentStrategy.getRequiredPromises(this.client, {
|
|
55
|
+
isBlobTx
|
|
56
|
+
});
|
|
57
|
+
const strategyPromiseKeys = [];
|
|
58
|
+
const strategyPromisesArr = [];
|
|
59
|
+
for (const [key, promise] of Object.entries(strategyPromises)){
|
|
60
|
+
strategyPromiseKeys.push(key);
|
|
61
|
+
strategyPromisesArr.push(this.tryTwice(()=>promise, `Getting strategy data for ${key}`));
|
|
62
|
+
}
|
|
63
|
+
const [latestBlockResult, blobBaseFeeResult, ...strategyResults] = await Promise.allSettled([
|
|
147
64
|
latestBlockPromise,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
feeHistoryPromise,
|
|
151
|
-
blobBaseFeePromise ?? Promise.resolve(0n)
|
|
65
|
+
blobBaseFeePromise ?? Promise.resolve(0n),
|
|
66
|
+
...strategyPromisesArr
|
|
152
67
|
]);
|
|
153
68
|
// Extract results
|
|
154
69
|
const baseFee = latestBlockResult.status === 'fulfilled' && typeof latestBlockResult.value === 'object' && latestBlockResult.value.baseFeePerGas ? latestBlockResult.value.baseFeePerGas : 0n;
|
|
@@ -159,22 +74,29 @@ export class ReadOnlyL1TxUtils {
|
|
|
159
74
|
} else if (isBlobTx) {
|
|
160
75
|
this.logger?.warn('Failed to get L1 blob base fee', attempt);
|
|
161
76
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
//
|
|
77
|
+
let priorityFee;
|
|
78
|
+
// Get competitive priority fee using strategy
|
|
79
|
+
// Reconstruct the results object with the same keys as the promises
|
|
80
|
+
const resultsObject = {};
|
|
81
|
+
strategyPromiseKeys.forEach((key, index)=>{
|
|
82
|
+
resultsObject[key] = strategyResults[index];
|
|
83
|
+
});
|
|
84
|
+
const result = CurrentStrategy.calculate(resultsObject, {
|
|
85
|
+
gasConfig,
|
|
86
|
+
isBlobTx,
|
|
87
|
+
logger: this.logger
|
|
88
|
+
});
|
|
89
|
+
priorityFee = result.priorityFee;
|
|
90
|
+
// Apply minimum priority fee floor if configured
|
|
165
91
|
if (gasConfig.minimumPriorityFeePerGas) {
|
|
166
|
-
const
|
|
167
|
-
if (
|
|
168
|
-
this.logger?.debug('
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
priorityFee = minimumFee;
|
|
173
|
-
} else {
|
|
174
|
-
this.logger?.debug('Competitive fee exceeds minimum, using competitive fee', {
|
|
175
|
-
minimumPriorityFeePerGas: formatGwei(minimumFee),
|
|
176
|
-
competitiveFee: formatGwei(priorityFee)
|
|
92
|
+
const minimumPriorityFee = BigInt(Math.trunc(gasConfig.minimumPriorityFeePerGas * Number(WEI_CONST)));
|
|
93
|
+
if (priorityFee < minimumPriorityFee) {
|
|
94
|
+
this.logger?.debug('Applying minimum priority fee floor', {
|
|
95
|
+
calculatedPriorityFee: formatGwei(priorityFee),
|
|
96
|
+
minimumPriorityFeePerGas: gasConfig.minimumPriorityFeePerGas,
|
|
97
|
+
appliedFee: formatGwei(minimumPriorityFee)
|
|
177
98
|
});
|
|
99
|
+
priorityFee = minimumPriorityFee;
|
|
178
100
|
}
|
|
179
101
|
}
|
|
180
102
|
let maxFeePerGas = baseFee;
|
package/dest/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
2
|
import type { Logger } from '@aztec/foundation/log';
|
|
3
|
-
import { type Abi, type ContractEventName, type DecodeEventLogReturnType, type Hex, type Log } from 'viem';
|
|
3
|
+
import { type Abi, type ContractEventName, type DecodeEventLogReturnType, type FormattedTransaction, type Hex, type Log } from 'viem';
|
|
4
4
|
export interface L2Claim {
|
|
5
5
|
claimSecret: Fr;
|
|
6
6
|
claimAmount: Fr;
|
|
@@ -22,4 +22,16 @@ export declare function prettyLogViemErrorMsg(err: any): any;
|
|
|
22
22
|
*/
|
|
23
23
|
export declare function formatViemError(error: any, abi?: Abi): FormattedViemError;
|
|
24
24
|
export declare function tryGetCustomErrorName(err: any): string | undefined;
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Type guard to check if a transaction is a blob transaction (EIP-4844).
|
|
27
|
+
* Blob transactions have maxFeePerBlobGas and blobVersionedHashes fields.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isBlobTransaction(tx: FormattedTransaction): tx is FormattedTransaction & {
|
|
30
|
+
maxFeePerBlobGas: bigint;
|
|
31
|
+
blobVersionedHashes: readonly Hex[];
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Calculates a percentile from an array of bigints
|
|
35
|
+
*/
|
|
36
|
+
export declare function calculatePercentile(values: bigint[], percentile: number): bigint;
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUdwRCxPQUFPLEVBQ0wsS0FBSyxHQUFHLEVBRVIsS0FBSyxpQkFBaUIsRUFFdEIsS0FBSyx3QkFBd0IsRUFDN0IsS0FBSyxvQkFBb0IsRUFDekIsS0FBSyxHQUFHLEVBQ1IsS0FBSyxHQUFHLEVBR1QsTUFBTSxNQUFNLENBQUM7QUFFZCxNQUFNLFdBQVcsT0FBTztJQUN0QixXQUFXLEVBQUUsRUFBRSxDQUFDO0lBQ2hCLFdBQVcsRUFBRSxFQUFFLENBQUM7SUFDaEIsV0FBVyxFQUFFLEdBQUcsQ0FBQztJQUNqQixnQkFBZ0IsRUFBRSxNQUFNLENBQUM7Q0FDMUI7QUFFRCxxQkFBYSxrQkFBbUIsU0FBUSxLQUFLO0lBQzNDLFlBQVksQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBRXJCLFlBQVksT0FBTyxFQUFFLE1BQU0sRUFBRSxZQUFZLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFJaEQ7Q0FDRjtBQUVELHdCQUFnQixZQUFZLENBQzFCLEtBQUssQ0FBQyxJQUFJLFNBQVMsR0FBRyxHQUFHLFNBQVMsT0FBTyxFQUFFLEVBQzNDLFVBQVUsU0FBUyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsRUFDMUMsVUFBVSxHQUFHLHdCQUF3QixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxFQUUvRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEVBQ1gsT0FBTyxFQUFFLEdBQUcsRUFDWixHQUFHLEVBQUUsSUFBSSxFQUNULFNBQVMsRUFBRSxVQUFVLEVBQ3JCLE1BQU0sQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLFVBQVUsS0FBSyxPQUFPLEVBQ3JDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sR0FDZCxVQUFVLENBTVo7QUFFRCx3QkFBZ0IsZUFBZSxDQUM3QixLQUFLLENBQUMsSUFBSSxTQUFTLEdBQUcsR0FBRyxTQUFTLE9BQU8sRUFBRSxFQUMzQyxVQUFVLFNBQVMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEVBQzFDLFVBQVUsR0FBRyx3QkFBd0IsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsRUFFL0UsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUNYLE9BQU8sRUFBRSxHQUFHLEVBQ1osR0FBRyxFQUFFLElBQUksRUFDVCxTQUFTLEVBQUUsVUFBVSxFQUNyQixNQUFNLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxVQUFVLEtBQUssT0FBTyxFQUNyQyxNQUFNLENBQUMsRUFBRSxNQUFNLEdBQ2QsVUFBVSxHQUFHLFNBQVMsQ0FnQnhCO0FBRUQsd0JBQWdCLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxHQUFHLE9BVzdDO0FBMEJEOzs7OztHQUtHO0FBQ0gsd0JBQWdCLGVBQWUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEdBQUcsR0FBRSxHQUFlLEdBQUcsa0JBQWtCLENBd0VwRjtBQXlCRCx3QkFBZ0IscUJBQXFCLENBQUMsR0FBRyxFQUFFLEdBQUcsc0JBYTdDO0FBRUQ7OztHQUdHO0FBQ0gsd0JBQWdCLGlCQUFpQixDQUFDLEVBQUUsRUFBRSxvQkFBb0IsR0FBRyxFQUFFLElBQUksb0JBQW9CLEdBQUc7SUFDeEYsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDO0lBQ3pCLG1CQUFtQixFQUFFLFNBQVMsR0FBRyxFQUFFLENBQUM7Q0FDckMsQ0FPQTtBQUVEOztHQUVHO0FBQ0gsd0JBQWdCLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsRUFBRSxVQUFVLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FPaEYifQ==
|
package/dest/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAGpD,OAAO,EACL,KAAK,GAAG,EAER,KAAK,iBAAiB,EAEtB,KAAK,wBAAwB,EAC7B,KAAK,GAAG,EACR,KAAK,GAAG,EAGT,MAAM,MAAM,CAAC;AAEd,MAAM,WAAW,OAAO;IACtB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,GAAG,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,CAAC,EAAE,GAAG,EAAE,CAAC;IAErB,YAAY,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,GAAG,EAAE,EAIhD;CACF;AAED,wBAAgB,YAAY,CAC1B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,CAMZ;AAED,wBAAgB,eAAe,CAC7B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,GAAG,SAAS,CAgBxB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,OAW7C;AA0BD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,GAAE,GAAe,GAAG,kBAAkB,CAwEpF;AAyBD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,sBAa7C"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAGpD,OAAO,EACL,KAAK,GAAG,EAER,KAAK,iBAAiB,EAEtB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,GAAG,EACR,KAAK,GAAG,EAGT,MAAM,MAAM,CAAC;AAEd,MAAM,WAAW,OAAO;IACtB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,GAAG,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,CAAC,EAAE,GAAG,EAAE,CAAC;IAErB,YAAY,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,GAAG,EAAE,EAIhD;CACF;AAED,wBAAgB,YAAY,CAC1B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,CAMZ;AAED,wBAAgB,eAAe,CAC7B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,GAAG,SAAS,CAgBxB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,OAW7C;AA0BD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,GAAE,GAAe,GAAG,kBAAkB,CAwEpF;AAyBD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,sBAa7C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,oBAAoB,GAAG,EAAE,IAAI,oBAAoB,GAAG;IACxF,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,SAAS,GAAG,EAAE,CAAC;CACrC,CAOA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAOhF"}
|
package/dest/utils.js
CHANGED
|
@@ -162,3 +162,21 @@ export function tryGetCustomErrorName(err) {
|
|
|
162
162
|
return undefined;
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Type guard to check if a transaction is a blob transaction (EIP-4844).
|
|
167
|
+
* Blob transactions have maxFeePerBlobGas and blobVersionedHashes fields.
|
|
168
|
+
*/ export function isBlobTransaction(tx) {
|
|
169
|
+
return 'maxFeePerBlobGas' in tx && tx.maxFeePerBlobGas !== undefined && 'blobVersionedHashes' in tx && tx.blobVersionedHashes !== undefined;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Calculates a percentile from an array of bigints
|
|
173
|
+
*/ export function calculatePercentile(values, percentile) {
|
|
174
|
+
if (values.length === 0) {
|
|
175
|
+
return 0n;
|
|
176
|
+
}
|
|
177
|
+
const sorted = [
|
|
178
|
+
...values
|
|
179
|
+
].sort((a, b)=>a < b ? -1 : a > b ? 1 : 0);
|
|
180
|
+
const index = Math.ceil((sorted.length - 1) * (percentile / 100));
|
|
181
|
+
return sorted[index];
|
|
182
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/ethereum",
|
|
3
|
-
"version": "3.0.0-nightly.
|
|
3
|
+
"version": "3.0.0-nightly.20251217",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./account": "./dest/account.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"./forwarder-proxy": "./dest/forwarder_proxy.js",
|
|
18
18
|
"./l1-artifacts": "./dest/l1_artifacts.js",
|
|
19
19
|
"./l1-contract-addresses": "./dest/l1_contract_addresses.js",
|
|
20
|
+
"./l1-fee-analysis": "./dest/l1_tx_utils/l1_fee_analyzer.js",
|
|
20
21
|
"./l1-reader": "./dest/l1_reader.js",
|
|
21
22
|
"./l1-tx-utils": "./dest/l1_tx_utils/index.js",
|
|
22
23
|
"./l1-tx-utils-with-blobs": "./dest/l1_tx_utils/index-blobs.js",
|
|
@@ -48,10 +49,10 @@
|
|
|
48
49
|
"../package.common.json"
|
|
49
50
|
],
|
|
50
51
|
"dependencies": {
|
|
51
|
-
"@aztec/blob-lib": "3.0.0-nightly.
|
|
52
|
-
"@aztec/constants": "3.0.0-nightly.
|
|
53
|
-
"@aztec/foundation": "3.0.0-nightly.
|
|
54
|
-
"@aztec/l1-artifacts": "3.0.0-nightly.
|
|
52
|
+
"@aztec/blob-lib": "3.0.0-nightly.20251217",
|
|
53
|
+
"@aztec/constants": "3.0.0-nightly.20251217",
|
|
54
|
+
"@aztec/foundation": "3.0.0-nightly.20251217",
|
|
55
|
+
"@aztec/l1-artifacts": "3.0.0-nightly.20251217",
|
|
55
56
|
"@viem/anvil": "^0.0.10",
|
|
56
57
|
"dotenv": "^16.0.3",
|
|
57
58
|
"lodash.chunk": "^4.2.0",
|
|
@@ -10,7 +10,9 @@ import { fileURLToPath } from '@aztec/foundation/url';
|
|
|
10
10
|
import { bn254 } from '@noble/curves/bn254';
|
|
11
11
|
import type { Abi, Narrow } from 'abitype';
|
|
12
12
|
import { spawn } from 'child_process';
|
|
13
|
-
import {
|
|
13
|
+
import { cp, mkdtemp, rm } from 'fs/promises';
|
|
14
|
+
import { tmpdir } from 'os';
|
|
15
|
+
import { dirname, join, resolve } from 'path';
|
|
14
16
|
import readline from 'readline';
|
|
15
17
|
import type { Hex } from 'viem';
|
|
16
18
|
import { foundry, mainnet } from 'viem/chains';
|
|
@@ -75,6 +77,17 @@ function runProcess<T>(
|
|
|
75
77
|
return promise;
|
|
76
78
|
}
|
|
77
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Copies the foundry cache folder to a temporary location to avoid conflicts when running forge in parallel.
|
|
82
|
+
* The cache folder is small metadata that links to the out folder, so this is a fast operation.
|
|
83
|
+
*/
|
|
84
|
+
async function copyFoundryCacheToTemp(l1ContractsPath: string): Promise<string> {
|
|
85
|
+
const cacheFolder = join(l1ContractsPath, 'cache');
|
|
86
|
+
const tempCacheFolder = await mkdtemp(join(tmpdir(), 'foundry-cache-'));
|
|
87
|
+
await cp(cacheFolder, tempCacheFolder, { recursive: true });
|
|
88
|
+
return tempCacheFolder;
|
|
89
|
+
}
|
|
90
|
+
|
|
78
91
|
// Covers an edge where where we may have a cached BlobLib that is not meant for production.
|
|
79
92
|
// Despite the profile apparently sometimes cached code remains (so says Lasse after his ignition-monorepo arc).
|
|
80
93
|
async function maybeForgeForceProductionBuild(l1ContractsPath: string, script: string, chainId: number) {
|
|
@@ -203,6 +216,7 @@ export async function deployAztecL1Contracts(
|
|
|
203
216
|
privateKey: `0x${string}`,
|
|
204
217
|
chainId: number,
|
|
205
218
|
args: DeployAztecL1ContractsArgs,
|
|
219
|
+
verifyContracts = false,
|
|
206
220
|
): Promise<DeployAztecL1ContractsReturnType> {
|
|
207
221
|
logger.info(`Deploying L1 contracts with config: ${jsonStringify(args)}`);
|
|
208
222
|
if (args.initialValidators && args.initialValidators.length > 0 && args.existingTokenAddress) {
|
|
@@ -246,90 +260,101 @@ export async function deployAztecL1Contracts(
|
|
|
246
260
|
const FORGE_SCRIPT = 'script/deploy/DeployAztecL1Contracts.s.sol';
|
|
247
261
|
await maybeForgeForceProductionBuild(l1ContractsPath, FORGE_SCRIPT, chainId);
|
|
248
262
|
|
|
249
|
-
//
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
263
|
+
// Copy cache to temp location to avoid conflicts when running forge in parallel
|
|
264
|
+
const tempCachePath = await copyFoundryCacheToTemp(l1ContractsPath);
|
|
265
|
+
|
|
266
|
+
try {
|
|
267
|
+
// From heuristic testing. More caused issues with anvil.
|
|
268
|
+
const MAGIC_ANVIL_BATCH_SIZE = 12;
|
|
269
|
+
// Anvil seems to stall with unbounded batch size. Otherwise no max batch size is desirable.
|
|
270
|
+
// On sepolia and mainnet, we verify on etherscan (if etherscan API key is in env)
|
|
271
|
+
const forgeArgs = [
|
|
272
|
+
'script',
|
|
273
|
+
FORGE_SCRIPT,
|
|
274
|
+
'--sig',
|
|
275
|
+
'run()',
|
|
276
|
+
'--private-key',
|
|
277
|
+
privateKey,
|
|
278
|
+
'--rpc-url',
|
|
279
|
+
rpcUrl,
|
|
280
|
+
'--broadcast',
|
|
281
|
+
...(chainId === foundry.id ? ['--batch-size', MAGIC_ANVIL_BATCH_SIZE.toString()] : []),
|
|
282
|
+
...(verifyContracts ? ['--verify'] : []),
|
|
283
|
+
];
|
|
284
|
+
const forgeEnv = {
|
|
285
|
+
// Protect against root leaving deployment files in docker that cannot be used later.
|
|
286
|
+
FOUNDRY_BROADCAST: process.getuid?.() === 0 ? 'broadcast-root' : tempCachePath,
|
|
287
|
+
// Env vars required by l1-contracts/script/deploy/DeploymentConfiguration.sol.
|
|
288
|
+
NETWORK: getActiveNetworkName(),
|
|
289
|
+
FOUNDRY_PROFILE: chainId === mainnet.id ? 'production' : undefined,
|
|
290
|
+
FOUNDRY_CACHE_PATH: tempCachePath,
|
|
291
|
+
...getDeployAztecL1ContractsEnvVars(args),
|
|
292
|
+
};
|
|
293
|
+
const result = await runProcess<ForgeL1ContractsDeployResult>('forge', forgeArgs, forgeEnv, l1ContractsPath);
|
|
294
|
+
if (!result) {
|
|
295
|
+
throw new Error('Forge script did not output deployment result');
|
|
296
|
+
}
|
|
297
|
+
logger.info(`Deployed L1 contracts with L1 addresses: ${jsonStringify(result)}`);
|
|
278
298
|
|
|
279
|
-
|
|
280
|
-
// @note We make a time jump PAST the very first slot to not have to deal with the edge case of the first slot.
|
|
281
|
-
// The edge case being that the genesis block is already occupying slot 0, so we cannot have another block.
|
|
282
|
-
try {
|
|
283
|
-
// Need to get the time
|
|
284
|
-
const currentSlot = await rollup.getSlotNumber();
|
|
299
|
+
const rollup = new RollupContract(l1Client, result.rollupAddress);
|
|
285
300
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
301
|
+
if (isAnvilTestChain(chainId)) {
|
|
302
|
+
// @note We make a time jump PAST the very first slot to not have to deal with the edge case of the first slot.
|
|
303
|
+
// The edge case being that the genesis block is already occupying slot 0, so we cannot have another block.
|
|
304
|
+
try {
|
|
305
|
+
// Need to get the time
|
|
290
306
|
const currentSlot = await rollup.getSlotNumber();
|
|
291
307
|
|
|
292
|
-
if (currentSlot
|
|
293
|
-
|
|
308
|
+
if (currentSlot === 0) {
|
|
309
|
+
const ts = Number(await rollup.getTimestampForSlot(SlotNumber(1)));
|
|
310
|
+
await rpcCall('evm_setNextBlockTimestamp', [ts]);
|
|
311
|
+
await rpcCall('hardhat_mine', [1]);
|
|
312
|
+
const currentSlot = await rollup.getSlotNumber();
|
|
313
|
+
|
|
314
|
+
if (currentSlot !== 1) {
|
|
315
|
+
throw new Error(`Error jumping time: current slot is ${currentSlot}`);
|
|
316
|
+
}
|
|
317
|
+
logger.info(`Jumped to slot 1`);
|
|
294
318
|
}
|
|
295
|
-
|
|
319
|
+
} catch (e) {
|
|
320
|
+
throw new Error(`Error jumping time: ${e}`);
|
|
296
321
|
}
|
|
297
|
-
} catch (e) {
|
|
298
|
-
throw new Error(`Error jumping time: ${e}`);
|
|
299
322
|
}
|
|
300
|
-
}
|
|
301
323
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
324
|
+
return {
|
|
325
|
+
l1Client,
|
|
326
|
+
rollupVersion: result.rollupVersion,
|
|
327
|
+
l1ContractAddresses: {
|
|
328
|
+
rollupAddress: EthAddress.fromString(result.rollupAddress),
|
|
329
|
+
registryAddress: EthAddress.fromString(result.registryAddress),
|
|
330
|
+
inboxAddress: EthAddress.fromString(result.inboxAddress),
|
|
331
|
+
outboxAddress: EthAddress.fromString(result.outboxAddress),
|
|
332
|
+
feeJuiceAddress: EthAddress.fromString(result.feeAssetAddress),
|
|
333
|
+
feeJuicePortalAddress: EthAddress.fromString(result.feeJuicePortalAddress),
|
|
334
|
+
coinIssuerAddress: EthAddress.fromString(result.coinIssuerAddress),
|
|
335
|
+
rewardDistributorAddress: EthAddress.fromString(result.rewardDistributorAddress),
|
|
336
|
+
governanceProposerAddress: EthAddress.fromString(result.governanceProposerAddress),
|
|
337
|
+
governanceAddress: EthAddress.fromString(result.governanceAddress),
|
|
338
|
+
stakingAssetAddress: EthAddress.fromString(result.stakingAssetAddress),
|
|
339
|
+
slashFactoryAddress: result.slashFactoryAddress ? EthAddress.fromString(result.slashFactoryAddress) : undefined,
|
|
340
|
+
feeAssetHandlerAddress: result.feeAssetHandlerAddress
|
|
341
|
+
? EthAddress.fromString(result.feeAssetHandlerAddress)
|
|
342
|
+
: undefined,
|
|
343
|
+
stakingAssetHandlerAddress: result.stakingAssetHandlerAddress
|
|
344
|
+
? EthAddress.fromString(result.stakingAssetHandlerAddress)
|
|
345
|
+
: undefined,
|
|
346
|
+
zkPassportVerifierAddress: result.zkPassportVerifierAddress
|
|
347
|
+
? EthAddress.fromString(result.zkPassportVerifierAddress)
|
|
348
|
+
: undefined,
|
|
349
|
+
gseAddress: result.gseAddress ? EthAddress.fromString(result.gseAddress) : undefined,
|
|
350
|
+
dateGatedRelayerAddress: result.dateGatedRelayerAddress
|
|
351
|
+
? EthAddress.fromString(result.dateGatedRelayerAddress)
|
|
352
|
+
: undefined,
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
} finally {
|
|
356
|
+
await rm(tempCachePath, { recursive: true, force: true });
|
|
357
|
+
}
|
|
333
358
|
}
|
|
334
359
|
|
|
335
360
|
export const DEPLOYER_ADDRESS: Hex = '0x4e59b44847b379578588920cA78FbF26c0B4956C';
|
|
@@ -509,37 +534,46 @@ export const deployRollupForUpgrade = async (
|
|
|
509
534
|
const FORGE_SCRIPT = 'script/deploy/DeployRollupForUpgrade.s.sol';
|
|
510
535
|
await maybeForgeForceProductionBuild(l1ContractsPath, FORGE_SCRIPT, chainId);
|
|
511
536
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
537
|
+
// Copy cache to temp location to avoid conflicts when running forge in parallel
|
|
538
|
+
const tempCachePath = await copyFoundryCacheToTemp(l1ContractsPath);
|
|
539
|
+
|
|
540
|
+
try {
|
|
541
|
+
const forgeArgs = [
|
|
542
|
+
'script',
|
|
543
|
+
FORGE_SCRIPT,
|
|
544
|
+
'--sig',
|
|
545
|
+
'run()',
|
|
546
|
+
'--private-key',
|
|
547
|
+
privateKey,
|
|
548
|
+
'--rpc-url',
|
|
549
|
+
rpcUrl,
|
|
550
|
+
'--broadcast',
|
|
551
|
+
];
|
|
552
|
+
const forgeEnv = {
|
|
553
|
+
FOUNDRY_PROFILE: chainId === mainnet.id ? 'production' : undefined,
|
|
554
|
+
// Env vars required by l1-contracts/script/deploy/RollupConfiguration.sol.
|
|
555
|
+
REGISTRY_ADDRESS: registryAddress.toString(),
|
|
556
|
+
NETWORK: getActiveNetworkName(),
|
|
557
|
+
FOUNDRY_CACHE_PATH: tempCachePath,
|
|
558
|
+
FOUNDRY_BROADCAST: tempCachePath,
|
|
559
|
+
...getDeployRollupForUpgradeEnvVars(args),
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
const result = await runProcess<ForgeRollupUpgradeResult>('forge', forgeArgs, forgeEnv, l1ContractsPath);
|
|
563
|
+
if (!result) {
|
|
564
|
+
throw new Error('Forge script did not output deployment result');
|
|
565
|
+
}
|
|
535
566
|
|
|
536
|
-
|
|
567
|
+
const extendedClient = createExtendedL1Client([rpcUrl], privateKey);
|
|
537
568
|
|
|
538
|
-
|
|
539
|
-
|
|
569
|
+
// Create RollupContract wrapper for the deployed rollup
|
|
570
|
+
const rollup = new RollupContract(extendedClient, result.rollupAddress);
|
|
540
571
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
572
|
+
return {
|
|
573
|
+
rollup,
|
|
574
|
+
slashFactoryAddress: result.slashFactoryAddress,
|
|
575
|
+
};
|
|
576
|
+
} finally {
|
|
577
|
+
await rm(tempCachePath, { recursive: true, force: true });
|
|
578
|
+
}
|
|
545
579
|
};
|