@aztec/ethereum 3.0.0-nightly.20250911 → 3.0.0-nightly.20250913

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/utils.js CHANGED
@@ -118,34 +118,16 @@ function getNestedErrorData(error) {
118
118
  if (error instanceof Error) {
119
119
  return new FormattedViemError(error.message, error?.metaMessages);
120
120
  }
121
- // Extract the actual error message and highlight it for clarity
122
- let formattedRes = extractAndFormatRequestBody(error?.message || String(error));
123
- let errorDetail = '';
124
- // Look for specific details in known locations
125
- if (error) {
126
- // Check for details property which often has the most specific error message
127
- if (typeof error.details === 'string' && error.details) {
128
- errorDetail = error.details;
129
- } else if (typeof error.shortMessage === 'string' && error.shortMessage) {
130
- errorDetail = error.shortMessage;
131
- }
132
- }
133
- // If we found a specific error detail, format it clearly
134
- if (errorDetail) {
135
- // Look for key sections of the formatted result to replace with highlighted error
136
- let replaced = false;
137
- // Try to find the Details: section
138
- const detailsMatch = formattedRes.match(/Details: ([^\n]+)/);
139
- if (detailsMatch) {
140
- formattedRes = formattedRes.replace(detailsMatch[0], `Details: *${errorDetail}*`);
141
- replaced = true;
142
- }
143
- // If we didn't find a Details section, add the error at the beginning
144
- if (!replaced) {
145
- formattedRes = `Error: *${errorDetail}*\n\n${formattedRes}`;
146
- }
147
- }
148
- return new FormattedViemError(formattedRes.replace(/\\n/g, '\n'), error?.metaMessages);
121
+ const body = String(error);
122
+ const length = body.length;
123
+ // LogExplorer can only render up to 2500 characters in it's summary view. Try to keep the whole message below this number
124
+ // Limit the error to 2000 chacaters in order to allow code higher up to decorate this error with extra details (up to 500 characters)
125
+ if (length > 2000) {
126
+ const chunk = 950;
127
+ const truncated = length - 2 * chunk;
128
+ return new FormattedViemError(body.slice(0, chunk) + `...${truncated} characters truncated...` + body.slice(-1 * chunk));
129
+ }
130
+ return new FormattedViemError(body);
149
131
  }
150
132
  function stripAbis(obj) {
151
133
  if (!obj || typeof obj !== 'object') {
@@ -166,139 +148,6 @@ function stripAbis(obj) {
166
148
  }
167
149
  });
168
150
  }
169
- function extractAndFormatRequestBody(message) {
170
- // First check if message is extremely large and contains very large hex strings
171
- if (message.length > 50000) {
172
- message = replaceHexStrings(message, {
173
- minLength: 10000,
174
- truncateLength: 200
175
- });
176
- }
177
- // Add a specific check for RPC calls with large params
178
- if (message.includes('"method":"eth_sendRawTransaction"')) {
179
- message = replaceHexStrings(message, {
180
- pattern: /"params":\s*\[\s*"(0x[a-fA-F0-9]{1000,})"\s*\]/g,
181
- transform: (hex)=>`"params":["${truncateHex(hex, 200)}"]`
182
- });
183
- }
184
- // First handle Request body JSON
185
- const requestBodyRegex = /Request body: ({[\s\S]*?})\n/g;
186
- let result = message.replace(requestBodyRegex, (match, body)=>{
187
- return `Request body: ${formatRequestBody(body)}\n`;
188
- });
189
- // Then handle Arguments section
190
- const argsRegex = /((?:Request |Estimate Gas )?Arguments:[\s\S]*?(?=\n\n|$))/g;
191
- result = result.replace(argsRegex, (section)=>{
192
- const lines = section.split('\n');
193
- const processedLines = lines.map((line)=>{
194
- // Check if line contains a colon followed by content
195
- const colonIndex = line.indexOf(':');
196
- if (colonIndex !== -1) {
197
- const [prefix, content] = [
198
- line.slice(0, colonIndex + 1),
199
- line.slice(colonIndex + 1).trim()
200
- ];
201
- // If content contains a hex string, truncate it
202
- if (content.includes('0x')) {
203
- const processedContent = replaceHexStrings(content);
204
- return `${prefix} ${processedContent}`;
205
- }
206
- }
207
- return line;
208
- });
209
- return processedLines.join('\n');
210
- });
211
- // Finally, catch any remaining hex strings in the message
212
- result = replaceHexStrings(result);
213
- return result;
214
- }
215
- function truncateHex(hex, length = 100) {
216
- if (!hex || typeof hex !== 'string') {
217
- return hex;
218
- }
219
- if (!hex.startsWith('0x')) {
220
- return hex;
221
- }
222
- if (hex.length <= length * 2) {
223
- return hex;
224
- }
225
- // For extremely large hex strings, use more aggressive truncation
226
- if (hex.length > 10000) {
227
- return `${hex.slice(0, length)}...<${hex.length - length * 2} chars omitted>...${hex.slice(-length)}`;
228
- }
229
- return `${hex.slice(0, length)}...${hex.slice(-length)}`;
230
- }
231
- function replaceHexStrings(text, options = {}) {
232
- const { minLength = 10, maxLength = Infinity, truncateLength = 100, pattern, transform = (hex)=>truncateHex(hex, truncateLength) } = options;
233
- const hexRegex = pattern ?? new RegExp(`(0x[a-fA-F0-9]{${minLength},${maxLength}})`, 'g');
234
- return text.replace(hexRegex, (match)=>transform(match));
235
- }
236
- function formatRequestBody(body) {
237
- try {
238
- // Special handling for eth_sendRawTransaction
239
- if (body.includes('"method":"eth_sendRawTransaction"')) {
240
- try {
241
- const parsed = JSON.parse(body);
242
- if (parsed.params && Array.isArray(parsed.params) && parsed.params.length > 0) {
243
- // These are likely large transaction hex strings
244
- parsed.params = parsed.params.map((param)=>{
245
- if (typeof param === 'string' && param.startsWith('0x') && param.length > 1000) {
246
- return truncateHex(param, 200);
247
- }
248
- return param;
249
- });
250
- }
251
- return JSON.stringify(parsed, null, 2);
252
- } catch {
253
- // If specific parsing fails, fall back to regex-based truncation
254
- return replaceHexStrings(body, {
255
- pattern: /"params":\s*\[\s*"(0x[a-fA-F0-9]{1000,})"\s*\]/g,
256
- transform: (hex)=>`"params":["${truncateHex(hex, 200)}"]`
257
- });
258
- }
259
- }
260
- // For extremely large request bodies, use simple truncation instead of parsing
261
- if (body.length > 50000) {
262
- const jsonStart = body.indexOf('{');
263
- const jsonEnd = body.lastIndexOf('}');
264
- if (jsonStart >= 0 && jsonEnd > jsonStart) {
265
- return replaceHexStrings(body, {
266
- minLength: 10000,
267
- truncateLength: 200
268
- });
269
- }
270
- }
271
- const parsed = JSON.parse(body);
272
- // Process the entire request body
273
- const processed = processParams(parsed);
274
- return JSON.stringify(processed, null, 2);
275
- } catch {
276
- // If JSON parsing fails, do a simple truncation of any large hex strings
277
- return replaceHexStrings(body, {
278
- minLength: 1000,
279
- truncateLength: 150
280
- });
281
- }
282
- }
283
- // Recursively process all parameters that might contain hex strings
284
- function processParams(obj) {
285
- if (Array.isArray(obj)) {
286
- return obj.map((item)=>processParams(item));
287
- }
288
- if (typeof obj === 'object' && obj !== null) {
289
- const result = {};
290
- for (const [key, value] of Object.entries(obj)){
291
- result[key] = processParams(value);
292
- }
293
- return result;
294
- }
295
- if (typeof obj === 'string') {
296
- if (obj.startsWith('0x')) {
297
- return truncateHex(obj);
298
- }
299
- }
300
- return obj;
301
- }
302
151
  export function tryGetCustomErrorName(err) {
303
152
  try {
304
153
  // See https://viem.sh/docs/contract/simulateContract#handling-custom-errors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/ethereum",
3
- "version": "3.0.0-nightly.20250911",
3
+ "version": "3.0.0-nightly.20250913",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -31,10 +31,10 @@
31
31
  "../package.common.json"
32
32
  ],
33
33
  "dependencies": {
34
- "@aztec/blob-lib": "3.0.0-nightly.20250911",
35
- "@aztec/constants": "3.0.0-nightly.20250911",
36
- "@aztec/foundation": "3.0.0-nightly.20250911",
37
- "@aztec/l1-artifacts": "3.0.0-nightly.20250911",
34
+ "@aztec/blob-lib": "3.0.0-nightly.20250913",
35
+ "@aztec/constants": "3.0.0-nightly.20250913",
36
+ "@aztec/foundation": "3.0.0-nightly.20250913",
37
+ "@aztec/l1-artifacts": "3.0.0-nightly.20250913",
38
38
  "@viem/anvil": "^0.0.10",
39
39
  "dotenv": "^16.0.3",
40
40
  "lodash.chunk": "^4.2.0",
package/src/config.ts CHANGED
@@ -28,6 +28,8 @@ export type L1ContractsConfig = {
28
28
  aztecEpochDuration: number;
29
29
  /** The target validator committee size. */
30
30
  aztecTargetCommitteeSize: number;
31
+ /** The number of epochs to lag behind the current epoch for validator selection. */
32
+ lagInEpochs: number;
31
33
  /** The number of epochs after an epoch ends that proofs are still accepted. */
32
34
  aztecProofSubmissionEpochs: number;
33
35
  /** The deposit amount for a validator */
@@ -48,6 +50,8 @@ export type L1ContractsConfig = {
48
50
  slashingVetoer: EthAddress;
49
51
  /** How many slashing rounds back we slash (ie when slashing in round N, we slash for offenses committed during epochs of round N-offset) */
50
52
  slashingOffsetInRounds: number;
53
+ /** How long slashing can be disabled for in seconds when vetoer disables it */
54
+ slashingDisableDuration: number;
51
55
  /** Type of slasher proposer */
52
56
  slasherFlavor: 'empire' | 'tally' | 'none';
53
57
  /** Minimum amount that can be slashed in tally slashing */
@@ -73,6 +77,7 @@ export const DefaultL1ContractsConfig = {
73
77
  aztecSlotDuration: 36,
74
78
  aztecEpochDuration: 32,
75
79
  aztecTargetCommitteeSize: 48,
80
+ lagInEpochs: 2,
76
81
  aztecProofSubmissionEpochs: 1, // you have a full epoch to submit a proof after the epoch to prove ends
77
82
  activationThreshold: BigInt(100e18),
78
83
  ejectionThreshold: BigInt(50e18),
@@ -90,6 +95,7 @@ export const DefaultL1ContractsConfig = {
90
95
  exitDelaySeconds: 2 * 24 * 60 * 60,
91
96
  slasherFlavor: 'tally' as const,
92
97
  slashingOffsetInRounds: 2,
98
+ slashingDisableDuration: 5 * 24 * 60 * 60, // 5 days in seconds
93
99
  } satisfies L1ContractsConfig;
94
100
 
95
101
  const LocalGovernanceConfiguration = {
@@ -303,6 +309,11 @@ export const l1ContractsConfigMappings: ConfigMappingsType<L1ContractsConfig> =
303
309
  description: 'The target validator committee size.',
304
310
  ...numberConfigHelper(DefaultL1ContractsConfig.aztecTargetCommitteeSize),
305
311
  },
312
+ lagInEpochs: {
313
+ env: 'AZTEC_LAG_IN_EPOCHS',
314
+ description: 'The number of epochs to lag behind the current epoch for validator selection.',
315
+ ...numberConfigHelper(DefaultL1ContractsConfig.lagInEpochs),
316
+ },
306
317
  aztecProofSubmissionEpochs: {
307
318
  env: 'AZTEC_PROOF_SUBMISSION_EPOCHS',
308
319
  description: 'The number of epochs after an epoch ends that proofs are still accepted.',
@@ -376,6 +387,11 @@ export const l1ContractsConfigMappings: ConfigMappingsType<L1ContractsConfig> =
376
387
  parseEnv: (val: string) => EthAddress.fromString(val),
377
388
  defaultValue: DefaultL1ContractsConfig.slashingVetoer,
378
389
  },
390
+ slashingDisableDuration: {
391
+ env: 'AZTEC_SLASHING_DISABLE_DURATION',
392
+ description: 'How long slashing can be disabled for in seconds when vetoer disables it',
393
+ ...numberConfigHelper(DefaultL1ContractsConfig.slashingDisableDuration),
394
+ },
379
395
  governanceProposerQuorum: {
380
396
  env: 'AZTEC_GOVERNANCE_PROPOSER_QUORUM',
381
397
  description: 'The governance proposing quorum',
@@ -449,7 +465,7 @@ export function validateConfig(config: Omit<L1ContractsConfig, keyof L1TxUtilsCo
449
465
  }
450
466
 
451
467
  // EmpireBase constructor validations for governance/slashing proposers
452
- // From: require(QUORUM_SIZE > ROUND_SIZE / 2, Errors.GovernanceProposer__InvalidQuorumAndRoundSize(QUORUM_SIZE, ROUND_SIZE));
468
+ // From: require(QUORUM_SIZE > ROUND_SIZE / 2, Errors.EmpireBase__InvalidQuorumAndRoundSize(QUORUM_SIZE, ROUND_SIZE));
453
469
  const { governanceProposerQuorum, governanceProposerRoundSize } = config;
454
470
  if (
455
471
  governanceProposerQuorum !== undefined &&
@@ -460,7 +476,7 @@ export function validateConfig(config: Omit<L1ContractsConfig, keyof L1TxUtilsCo
460
476
  );
461
477
  }
462
478
 
463
- // From: require(QUORUM_SIZE <= ROUND_SIZE, Errors.GovernanceProposer__QuorumCannotBeLargerThanRoundSize(QUORUM_SIZE, ROUND_SIZE));
479
+ // From: require(QUORUM_SIZE <= ROUND_SIZE, Errors.EmpireBase__QuorumCannotBeLargerThanRoundSize(QUORUM_SIZE, ROUND_SIZE));
464
480
  if (governanceProposerQuorum !== undefined && governanceProposerQuorum > governanceProposerRoundSize) {
465
481
  errors.push(
466
482
  `governanceProposerQuorum (${governanceProposerQuorum}) cannot be larger than governanceProposerRoundSize (${governanceProposerRoundSize})`,
@@ -10,6 +10,7 @@ import {
10
10
  type GetContractReturnType,
11
11
  type Hex,
12
12
  type StateOverride,
13
+ type WatchContractEventReturnType,
13
14
  encodeFunctionData,
14
15
  getContract,
15
16
  hexToBigInt,
@@ -225,6 +226,11 @@ export class RollupContract {
225
226
  return this.rollup.read.getLocalEjectionThreshold();
226
227
  }
227
228
 
229
+ @memoize
230
+ getLagInEpochs() {
231
+ return this.rollup.read.getLagInEpochs();
232
+ }
233
+
228
234
  @memoize
229
235
  getActivationThreshold() {
230
236
  return this.rollup.read.getActivationThreshold();
@@ -436,8 +442,15 @@ export class RollupContract {
436
442
  return this.rollup.read.getEntryQueueLength();
437
443
  }
438
444
 
439
- async getEpochNumber(blockNumber?: bigint) {
440
- blockNumber ??= await this.getBlockNumber();
445
+ getNextFlushableEpoch() {
446
+ return this.rollup.read.getNextFlushableEpoch();
447
+ }
448
+
449
+ getCurrentEpochNumber(): Promise<bigint> {
450
+ return this.rollup.read.getCurrentEpoch();
451
+ }
452
+
453
+ getEpochNumberForBlock(blockNumber: bigint) {
441
454
  return this.rollup.read.getEpochForBlock([BigInt(blockNumber)]);
442
455
  }
443
456
 
@@ -722,7 +735,9 @@ export class RollupContract {
722
735
  });
723
736
  }
724
737
 
725
- public listenToSlasherChanged(callback: (args: { oldSlasher: `0x${string}`; newSlasher: `0x${string}` }) => unknown) {
738
+ public listenToSlasherChanged(
739
+ callback: (args: { oldSlasher: `0x${string}`; newSlasher: `0x${string}` }) => unknown,
740
+ ): WatchContractEventReturnType {
726
741
  return this.rollup.watchEvent.SlasherUpdated(
727
742
  {},
728
743
  {
@@ -738,6 +753,22 @@ export class RollupContract {
738
753
  );
739
754
  }
740
755
 
756
+ public listenToBlockInvalidated(callback: (args: { blockNumber: bigint }) => unknown): WatchContractEventReturnType {
757
+ return this.rollup.watchEvent.BlockInvalidated(
758
+ {},
759
+ {
760
+ onLogs: logs => {
761
+ for (const log of logs) {
762
+ const args = log.args;
763
+ if (args.blockNumber !== undefined) {
764
+ callback({ blockNumber: args.blockNumber });
765
+ }
766
+ }
767
+ },
768
+ },
769
+ );
770
+ }
771
+
741
772
  public async getSlashEvents(l1BlockHash: Hex): Promise<{ amount: bigint; attester: EthAddress }[]> {
742
773
  const events = await this.rollup.getEvents.Slashed({}, { blockHash: l1BlockHash, strict: true });
743
774
  return events.map(event => ({
@@ -746,7 +777,9 @@ export class RollupContract {
746
777
  }));
747
778
  }
748
779
 
749
- public listenToSlash(callback: (args: { amount: bigint; attester: EthAddress }) => unknown) {
780
+ public listenToSlash(
781
+ callback: (args: { amount: bigint; attester: EthAddress }) => unknown,
782
+ ): WatchContractEventReturnType {
750
783
  return this.rollup.watchEvent.Slashed(
751
784
  {},
752
785
  {
@@ -38,6 +38,19 @@ export class SlasherContract {
38
38
  }
39
39
  }
40
40
 
41
+ /**
42
+ * Checks if slashing is currently enabled. Slashing can be disabled by the vetoer.
43
+ * @returns True if slashing is enabled, false otherwise
44
+ */
45
+ public async isSlashingEnabled(): Promise<boolean> {
46
+ try {
47
+ return await this.contract.read.isSlashingEnabled();
48
+ } catch (error) {
49
+ this.log.error(`Error checking if slashing is enabled`, error);
50
+ throw error;
51
+ }
52
+ }
53
+
41
54
  /**
42
55
  * Gets the current vetoer address.
43
56
  * @returns The vetoer address
@@ -47,6 +60,15 @@ export class SlasherContract {
47
60
  return EthAddress.fromString(vetoer);
48
61
  }
49
62
 
63
+ /**
64
+ * Gets the disable duration by the vetoer.
65
+ * @returns The disable duration in seconds
66
+ */
67
+ public async getSlashingDisableDuration(): Promise<number> {
68
+ const duration = await this.contract.read.SLASHING_DISABLE_DURATION();
69
+ return Number(duration);
70
+ }
71
+
50
72
  /**
51
73
  * Gets the current governance address.
52
74
  * @returns The governance address
@@ -5,6 +5,7 @@ import { EthAddress } from '@aztec/foundation/eth-address';
5
5
  import type { Fr } from '@aztec/foundation/fields';
6
6
  import { jsonStringify } from '@aztec/foundation/json-rpc';
7
7
  import { type Logger, createLogger } from '@aztec/foundation/log';
8
+ import { retryUntil } from '@aztec/foundation/retry';
8
9
  import { DateProvider } from '@aztec/foundation/timer';
9
10
  import type { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
10
11
 
@@ -430,6 +431,7 @@ export const deployRollupForUpgrade = async (
430
431
  registryAddress: EthAddress,
431
432
  logger: Logger,
432
433
  txUtilsConfig: L1TxUtilsConfig,
434
+ flushEntryQueue: boolean = true,
433
435
  ) => {
434
436
  const deployer = new L1Deployer(
435
437
  extendedClient,
@@ -442,7 +444,14 @@ export const deployRollupForUpgrade = async (
442
444
 
443
445
  const addresses = await RegistryContract.collectAddresses(extendedClient, registryAddress, 'canonical');
444
446
 
445
- const { rollup, slashFactoryAddress } = await deployRollup(extendedClient, deployer, args, addresses, logger);
447
+ const { rollup, slashFactoryAddress } = await deployRollup(
448
+ extendedClient,
449
+ deployer,
450
+ args,
451
+ addresses,
452
+ flushEntryQueue,
453
+ logger,
454
+ );
446
455
 
447
456
  await deployer.waitForDeployments();
448
457
 
@@ -501,6 +510,7 @@ export const deployRollup = async (
501
510
  | 'gseAddress'
502
511
  | 'governanceAddress'
503
512
  >,
513
+ flushEntryQueue: boolean,
504
514
  logger: Logger,
505
515
  ) => {
506
516
  if (!addresses.gseAddress) {
@@ -530,6 +540,7 @@ export const deployRollup = async (
530
540
  aztecSlotDuration: BigInt(args.aztecSlotDuration),
531
541
  aztecEpochDuration: BigInt(args.aztecEpochDuration),
532
542
  targetCommitteeSize: BigInt(args.aztecTargetCommitteeSize),
543
+ lagInEpochs: BigInt(args.lagInEpochs),
533
544
  aztecProofSubmissionEpochs: BigInt(args.aztecProofSubmissionEpochs),
534
545
  slashingQuorum: BigInt(args.slashingQuorum ?? (args.slashingRoundSizeInEpochs * args.aztecEpochDuration) / 2 + 1),
535
546
  slashingRoundSize: BigInt(args.slashingRoundSizeInEpochs * args.aztecEpochDuration),
@@ -547,6 +558,7 @@ export const deployRollup = async (
547
558
  slashingOffsetInRounds: BigInt(args.slashingOffsetInRounds),
548
559
  slashAmounts: [args.slashAmountSmall, args.slashAmountMedium, args.slashAmountLarge],
549
560
  localEjectionThreshold: args.localEjectionThreshold,
561
+ slashingDisableDuration: BigInt(args.slashingDisableDuration ?? 0n),
550
562
  };
551
563
 
552
564
  const genesisStateArgs = {
@@ -674,6 +686,7 @@ export const deployRollup = async (
674
686
  addresses.stakingAssetAddress.toString(),
675
687
  args.initialValidators,
676
688
  args.acceleratedTestDeployments,
689
+ flushEntryQueue,
677
690
  logger,
678
691
  );
679
692
  }
@@ -850,6 +863,7 @@ export const addMultipleValidators = async (
850
863
  stakingAssetAddress: Hex,
851
864
  validators: Operator[],
852
865
  acceleratedTestDeployments: boolean | undefined,
866
+ flushEntryQueue: boolean,
853
867
  logger: Logger,
854
868
  ) => {
855
869
  const rollup = new RollupContract(extendedClient, rollupAddress);
@@ -916,7 +930,7 @@ export const addMultipleValidators = async (
916
930
  data: encodeFunctionData({
917
931
  abi: MultiAdderArtifact.contractAbi,
918
932
  functionName: 'addValidators',
919
- args: [validatorsTuples, true],
933
+ args: [validatorsTuples, /* skip flushing */ true],
920
934
  }),
921
935
  },
922
936
  {
@@ -924,19 +938,49 @@ export const addMultipleValidators = async (
924
938
  },
925
939
  );
926
940
 
927
- await deployer.l1TxUtils.sendAndMonitorTransaction(
928
- {
929
- to: rollupAddress,
930
- data: encodeFunctionData({
931
- abi: RollupArtifact.contractAbi,
932
- functionName: 'flushEntryQueue',
933
- args: [],
934
- }),
935
- },
936
- {
937
- gasLimit: 40_000_000n,
938
- },
939
- );
941
+ let queueLength = await rollup.getEntryQueueLength();
942
+ while (flushEntryQueue && queueLength > 0n) {
943
+ logger.info(`Flushing entry queue with ${queueLength} entries`);
944
+
945
+ try {
946
+ await deployer.l1TxUtils.sendAndMonitorTransaction(
947
+ {
948
+ to: rollupAddress,
949
+ data: encodeFunctionData({
950
+ abi: RollupArtifact.contractAbi,
951
+ functionName: 'flushEntryQueue',
952
+ args: [],
953
+ }),
954
+ },
955
+ {
956
+ gasLimit: 20_000_000n,
957
+ },
958
+ );
959
+ } catch (err) {
960
+ logger.warn('Failed to flush queue', { err });
961
+ }
962
+
963
+ queueLength = await rollup.getEntryQueueLength();
964
+ // check if we drained the queue enough here so we can avoid sleep
965
+ if (queueLength === 0n) {
966
+ break;
967
+ }
968
+
969
+ logger.info(`Waiting for next flushable epoch to flush remaining ${queueLength} entries`);
970
+ await retryUntil(
971
+ async () => {
972
+ const [currentEpoch, flushableEpoch] = await Promise.all([
973
+ rollup.getCurrentEpochNumber(),
974
+ rollup.getNextFlushableEpoch(),
975
+ ]);
976
+ logger.debug(`Next flushable epoch is ${flushableEpoch} (current epoch is ${currentEpoch})`);
977
+ return currentEpoch >= flushableEpoch;
978
+ },
979
+ 'wait for next flushable epoch',
980
+ 3600,
981
+ 12,
982
+ );
983
+ }
940
984
  } else {
941
985
  await deployer.l1TxUtils.sendAndMonitorTransaction(
942
986
  {
@@ -944,7 +988,7 @@ export const addMultipleValidators = async (
944
988
  data: encodeFunctionData({
945
989
  abi: MultiAdderArtifact.contractAbi,
946
990
  functionName: 'addValidators',
947
- args: [validatorsTuples, false],
991
+ args: [validatorsTuples, /* skip flushing */ !flushEntryQueue],
948
992
  }),
949
993
  },
950
994
  {
@@ -1027,6 +1071,7 @@ export const deployL1Contracts = async (
1027
1071
  args: DeployL1ContractsArgs,
1028
1072
  txUtilsConfig: L1TxUtilsConfig = getL1TxUtilsConfigEnvVars(),
1029
1073
  createVerificationJson: string | false = false,
1074
+ flushEntryQueue: boolean = true,
1030
1075
  ): Promise<DeployL1ContractsReturnType> => {
1031
1076
  logger.info(`Deploying L1 contracts with config: ${jsonStringify(args)}`);
1032
1077
  validateConfig(args);
@@ -1093,6 +1138,7 @@ export const deployL1Contracts = async (
1093
1138
  stakingAssetAddress,
1094
1139
  governanceAddress,
1095
1140
  },
1141
+ flushEntryQueue,
1096
1142
  logger,
1097
1143
  );
1098
1144
 
@@ -279,7 +279,13 @@ export class ReadOnlyL1TxUtils {
279
279
  let blobBaseFee = 0n;
280
280
  if (isBlobTx) {
281
281
  try {
282
- blobBaseFee = await this.client.getBlobBaseFee();
282
+ blobBaseFee = await retry<bigint>(
283
+ () => this.client.getBlobBaseFee(),
284
+ 'Getting L1 blob base fee',
285
+ makeBackoff(times(2, () => 1)),
286
+ this.logger,
287
+ true,
288
+ );
283
289
  this.logger?.debug('L1 Blob base fee:', { blobBaseFee: formatGwei(blobBaseFee) });
284
290
  } catch {
285
291
  this.logger?.warn('Failed to get L1 blob base fee', attempt);
@@ -864,7 +870,7 @@ export class L1TxUtils extends ReadOnlyL1TxUtils {
864
870
  },
865
871
  );
866
872
 
867
- const txData = {
873
+ const txData: PrepareTransactionRequestRequest = {
868
874
  ...request,
869
875
  ...blobInputs,
870
876
  nonce,
@@ -872,6 +878,9 @@ export class L1TxUtils extends ReadOnlyL1TxUtils {
872
878
  maxFeePerGas: newGasPrice.maxFeePerGas,
873
879
  maxPriorityFeePerGas: newGasPrice.maxPriorityFeePerGas,
874
880
  };
881
+ if (isBlobTx && newGasPrice.maxFeePerBlobGas) {
882
+ (txData as any).maxFeePerBlobGas = newGasPrice.maxFeePerBlobGas;
883
+ }
875
884
  const signedRequest = await this.prepareSignedTransaction(txData);
876
885
  const newHash = await this.client.sendRawTransaction({ serializedTransaction: signedRequest });
877
886
  if (!isCancelTx) {
package/src/queries.ts CHANGED
@@ -33,6 +33,7 @@ export async function getL1ContractsConfig(
33
33
  aztecSlotDuration,
34
34
  aztecProofSubmissionEpochs,
35
35
  aztecTargetCommitteeSize,
36
+ lagInEpochs,
36
37
  activationThreshold,
37
38
  ejectionThreshold,
38
39
  localEjectionThreshold,
@@ -45,6 +46,7 @@ export async function getL1ContractsConfig(
45
46
  slashingOffsetInRounds,
46
47
  slashingAmounts,
47
48
  slashingVetoer,
49
+ slashingDisableDuration,
48
50
  manaTarget,
49
51
  provingCostPerMana,
50
52
  rollupVersion,
@@ -57,6 +59,7 @@ export async function getL1ContractsConfig(
57
59
  rollup.getSlotDuration(),
58
60
  rollup.getProofSubmissionEpochs(),
59
61
  rollup.getTargetCommitteeSize(),
62
+ rollup.getLagInEpochs(),
60
63
  rollup.getActivationThreshold(),
61
64
  rollup.getEjectionThreshold(),
62
65
  rollup.getLocalEjectionThreshold(),
@@ -69,6 +72,7 @@ export async function getL1ContractsConfig(
69
72
  slasherProposer?.type === 'tally' ? slasherProposer.getSlashOffsetInRounds() : 0n,
70
73
  slasherProposer?.type === 'tally' ? slasherProposer.getSlashingAmounts() : [0n, 0n, 0n],
71
74
  slasher?.getVetoer() ?? EthAddress.ZERO,
75
+ slasher?.getSlashingDisableDuration() ?? 0,
72
76
  rollup.getManaTarget(),
73
77
  rollup.getProvingCostPerMana(),
74
78
  rollup.getVersion(),
@@ -83,6 +87,7 @@ export async function getL1ContractsConfig(
83
87
  aztecSlotDuration: Number(aztecSlotDuration),
84
88
  aztecProofSubmissionEpochs: Number(aztecProofSubmissionEpochs),
85
89
  aztecTargetCommitteeSize: Number(aztecTargetCommitteeSize),
90
+ lagInEpochs: Number(lagInEpochs),
86
91
  governanceProposerQuorum: Number(governanceProposerQuorum),
87
92
  governanceProposerRoundSize: Number(governanceProposerRoundSize),
88
93
  activationThreshold,
@@ -93,7 +98,8 @@ export async function getL1ContractsConfig(
93
98
  slashingLifetimeInRounds: Number(slashingLifetimeInRounds),
94
99
  slashingExecutionDelayInRounds: Number(slashingExecutionDelayInRounds),
95
100
  slashingVetoer,
96
- manaTarget: manaTarget,
101
+ slashingDisableDuration,
102
+ manaTarget,
97
103
  provingCostPerMana: provingCostPerMana,
98
104
  rollupVersion: Number(rollupVersion),
99
105
  genesisArchiveTreeRoot,