@aztec/ethereum 3.0.0-nightly.20250910 → 3.0.0-nightly.20250912
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/config.d.ts +6 -4
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +12 -30
- package/dest/contracts/empire_slashing_proposer.d.ts +1 -1
- package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/empire_slashing_proposer.js +1 -1
- package/dest/contracts/rollup.d.ts +13 -6
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +49 -23
- package/dest/deploy_l1_contracts.d.ts +4 -4
- package/dest/deploy_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_l1_contracts.js +51 -25
- package/dest/l1_artifacts.d.ts +689 -62
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/l1_tx_utils.d.ts +4 -2
- package/dest/l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils.js +21 -13
- package/dest/l1_tx_utils_with_blobs.d.ts +2 -1
- package/dest/l1_tx_utils_with_blobs.d.ts.map +1 -1
- package/dest/l1_tx_utils_with_blobs.js +7 -5
- package/dest/queries.d.ts.map +1 -1
- package/dest/queries.js +8 -11
- package/dest/test/chain_monitor.d.ts +4 -0
- package/dest/test/chain_monitor.d.ts.map +1 -1
- package/dest/test/chain_monitor.js +57 -11
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +10 -161
- package/package.json +5 -5
- package/src/config.ts +17 -35
- package/src/contracts/empire_slashing_proposer.ts +6 -2
- package/src/contracts/rollup.ts +58 -22
- package/src/deploy_l1_contracts.ts +65 -22
- package/src/l1_tx_utils.ts +28 -9
- package/src/l1_tx_utils_with_blobs.ts +8 -2
- package/src/queries.ts +9 -7
- package/src/test/chain_monitor.ts +64 -8
- package/src/utils.ts +13 -185
|
@@ -10,7 +10,7 @@ import type { ViemClient } from '../types.js';
|
|
|
10
10
|
|
|
11
11
|
export type ChainMonitorEventMap = {
|
|
12
12
|
'l1-block': [{ l1BlockNumber: number; timestamp: bigint }];
|
|
13
|
-
'l2-block': [{ l2BlockNumber: number; l1BlockNumber: number; timestamp: bigint }];
|
|
13
|
+
'l2-block': [{ l2BlockNumber: number; l1BlockNumber: number; l2SlotNumber: number; timestamp: bigint }];
|
|
14
14
|
'l2-block-proven': [{ l2ProvenBlockNumber: number; l1BlockNumber: number; timestamp: bigint }];
|
|
15
15
|
'l2-messages': [{ totalL2Messages: number; l1BlockNumber: number }];
|
|
16
16
|
'l2-epoch': [{ l2EpochNumber: number; timestamp: bigint; committee: EthAddress[] | undefined }];
|
|
@@ -102,8 +102,13 @@ export class ChainMonitor extends EventEmitter<ChainMonitorEventMap> {
|
|
|
102
102
|
}
|
|
103
103
|
this.l1BlockNumber = newL1BlockNumber;
|
|
104
104
|
|
|
105
|
-
const
|
|
106
|
-
|
|
105
|
+
const [l2SlotNumber, l2Epoch, l1block] = await Promise.all([
|
|
106
|
+
this.rollup.getSlotNumber(),
|
|
107
|
+
this.rollup.getCurrentEpoch(),
|
|
108
|
+
this.l1Client.getBlock({ blockNumber: BigInt(newL1BlockNumber), includeTransactions: false }),
|
|
109
|
+
]);
|
|
110
|
+
|
|
111
|
+
const timestamp = l1block.timestamp;
|
|
107
112
|
const timestampString = new Date(Number(timestamp) * 1000).toTimeString().split(' ')[0];
|
|
108
113
|
|
|
109
114
|
this.emit('l1-block', { l1BlockNumber: newL1BlockNumber, timestamp });
|
|
@@ -111,16 +116,21 @@ export class ChainMonitor extends EventEmitter<ChainMonitorEventMap> {
|
|
|
111
116
|
|
|
112
117
|
const newL2BlockNumber = Number(await this.rollup.getBlockNumber());
|
|
113
118
|
if (this.l2BlockNumber !== newL2BlockNumber) {
|
|
114
|
-
const epochNumber = await this.rollup.
|
|
119
|
+
const epochNumber = await this.rollup.getEpochNumberForBlock(BigInt(newL2BlockNumber));
|
|
115
120
|
msg += ` with new L2 block ${newL2BlockNumber} for epoch ${epochNumber}`;
|
|
116
121
|
this.l2BlockNumber = newL2BlockNumber;
|
|
117
122
|
this.l2BlockTimestamp = timestamp;
|
|
118
|
-
this.emit('l2-block', {
|
|
123
|
+
this.emit('l2-block', {
|
|
124
|
+
l2BlockNumber: newL2BlockNumber,
|
|
125
|
+
l1BlockNumber: newL1BlockNumber,
|
|
126
|
+
l2SlotNumber: Number(l2SlotNumber),
|
|
127
|
+
timestamp,
|
|
128
|
+
});
|
|
119
129
|
}
|
|
120
130
|
|
|
121
131
|
const newL2ProvenBlockNumber = Number(await this.rollup.getProvenBlockNumber());
|
|
122
132
|
if (this.l2ProvenBlockNumber !== newL2ProvenBlockNumber) {
|
|
123
|
-
const epochNumber = await this.rollup.
|
|
133
|
+
const epochNumber = await this.rollup.getEpochNumberForBlock(BigInt(newL2ProvenBlockNumber));
|
|
124
134
|
msg += ` with proof up to L2 block ${newL2ProvenBlockNumber} for epoch ${epochNumber}`;
|
|
125
135
|
this.l2ProvenBlockNumber = newL2ProvenBlockNumber;
|
|
126
136
|
this.l2ProvenBlockTimestamp = timestamp;
|
|
@@ -139,8 +149,6 @@ export class ChainMonitor extends EventEmitter<ChainMonitorEventMap> {
|
|
|
139
149
|
this.emit('l2-messages', { totalL2Messages: newTotalL2Messages, l1BlockNumber: newL1BlockNumber });
|
|
140
150
|
}
|
|
141
151
|
|
|
142
|
-
const [l2SlotNumber, l2Epoch] = await Promise.all([this.rollup.getSlotNumber(), this.rollup.getCurrentEpoch()]);
|
|
143
|
-
|
|
144
152
|
let committee: EthAddress[] | undefined;
|
|
145
153
|
if (l2Epoch !== this.l2EpochNumber) {
|
|
146
154
|
this.l2EpochNumber = l2Epoch;
|
|
@@ -184,4 +192,52 @@ export class ChainMonitor extends EventEmitter<ChainMonitorEventMap> {
|
|
|
184
192
|
this.on('l2-slot', listener);
|
|
185
193
|
});
|
|
186
194
|
}
|
|
195
|
+
|
|
196
|
+
public waitUntilL1Block(block: number | bigint): Promise<void> {
|
|
197
|
+
const targetBlock = typeof block === 'bigint' ? block.valueOf() : block;
|
|
198
|
+
if (this.l1BlockNumber >= targetBlock) {
|
|
199
|
+
return Promise.resolve();
|
|
200
|
+
}
|
|
201
|
+
return new Promise(resolve => {
|
|
202
|
+
const listener = (data: { l1BlockNumber: number; timestamp: bigint }) => {
|
|
203
|
+
if (data.l1BlockNumber >= targetBlock) {
|
|
204
|
+
this.off('l1-block', listener);
|
|
205
|
+
resolve();
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
this.on('l1-block', listener);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
public waitUntilL1Timestamp(timestamp: number | bigint): Promise<void> {
|
|
213
|
+
const targetTimestamp = typeof timestamp === 'bigint' ? timestamp.valueOf() : timestamp;
|
|
214
|
+
if (this.l1BlockNumber >= targetTimestamp) {
|
|
215
|
+
return Promise.resolve();
|
|
216
|
+
}
|
|
217
|
+
return new Promise(resolve => {
|
|
218
|
+
const listener = (data: { l1BlockNumber: number; timestamp: bigint }) => {
|
|
219
|
+
if (data.timestamp >= targetTimestamp) {
|
|
220
|
+
this.off('l1-block', listener);
|
|
221
|
+
resolve();
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
this.on('l1-block', listener);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
public waitUntilL2Block(l2BlockNumber: number | bigint): Promise<void> {
|
|
229
|
+
const targetBlock = typeof l2BlockNumber === 'bigint' ? l2BlockNumber.valueOf() : l2BlockNumber;
|
|
230
|
+
if (this.l2BlockNumber >= targetBlock) {
|
|
231
|
+
return Promise.resolve();
|
|
232
|
+
}
|
|
233
|
+
return new Promise(resolve => {
|
|
234
|
+
const listener = (data: { l2BlockNumber: number; timestamp: bigint }) => {
|
|
235
|
+
if (data.l2BlockNumber >= targetBlock) {
|
|
236
|
+
this.off('l2-block', listener);
|
|
237
|
+
resolve();
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
this.on('l2-block', listener);
|
|
241
|
+
});
|
|
242
|
+
}
|
|
187
243
|
}
|
package/src/utils.ts
CHANGED
|
@@ -181,41 +181,19 @@ export function formatViemError(error: any, abi: Abi = ErrorsAbi): FormattedViem
|
|
|
181
181
|
return new FormattedViemError(error.message, (error as any)?.metaMessages);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// If we found a specific error detail, format it clearly
|
|
201
|
-
if (errorDetail) {
|
|
202
|
-
// Look for key sections of the formatted result to replace with highlighted error
|
|
203
|
-
let replaced = false;
|
|
204
|
-
|
|
205
|
-
// Try to find the Details: section
|
|
206
|
-
const detailsMatch = formattedRes.match(/Details: ([^\n]+)/);
|
|
207
|
-
if (detailsMatch) {
|
|
208
|
-
formattedRes = formattedRes.replace(detailsMatch[0], `Details: *${errorDetail}*`);
|
|
209
|
-
replaced = true;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// If we didn't find a Details section, add the error at the beginning
|
|
213
|
-
if (!replaced) {
|
|
214
|
-
formattedRes = `Error: *${errorDetail}*\n\n${formattedRes}`;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return new FormattedViemError(formattedRes.replace(/\\n/g, '\n'), error?.metaMessages);
|
|
184
|
+
const body = String(error);
|
|
185
|
+
const length = body.length;
|
|
186
|
+
// LogExplorer can only render up to 2500 characters in it's summary view. Try to keep the whole message below this number
|
|
187
|
+
// Limit the error to 2000 chacaters in order to allow code higher up to decorate this error with extra details (up to 500 characters)
|
|
188
|
+
if (length > 2000) {
|
|
189
|
+
const chunk = 950;
|
|
190
|
+
const truncated = length - 2 * chunk;
|
|
191
|
+
return new FormattedViemError(
|
|
192
|
+
body.slice(0, chunk) + `...${truncated} characters truncated...` + body.slice(-1 * chunk),
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return new FormattedViemError(body);
|
|
219
197
|
}
|
|
220
198
|
|
|
221
199
|
function stripAbis(obj: any) {
|
|
@@ -241,156 +219,6 @@ function stripAbis(obj: any) {
|
|
|
241
219
|
});
|
|
242
220
|
}
|
|
243
221
|
|
|
244
|
-
function extractAndFormatRequestBody(message: string): string {
|
|
245
|
-
// First check if message is extremely large and contains very large hex strings
|
|
246
|
-
if (message.length > 50000) {
|
|
247
|
-
message = replaceHexStrings(message, { minLength: 10000, truncateLength: 200 });
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Add a specific check for RPC calls with large params
|
|
251
|
-
if (message.includes('"method":"eth_sendRawTransaction"')) {
|
|
252
|
-
message = replaceHexStrings(message, {
|
|
253
|
-
pattern: /"params":\s*\[\s*"(0x[a-fA-F0-9]{1000,})"\s*\]/g,
|
|
254
|
-
transform: hex => `"params":["${truncateHex(hex, 200)}"]`,
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// First handle Request body JSON
|
|
259
|
-
const requestBodyRegex = /Request body: ({[\s\S]*?})\n/g;
|
|
260
|
-
let result = message.replace(requestBodyRegex, (match, body) => {
|
|
261
|
-
return `Request body: ${formatRequestBody(body)}\n`;
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
// Then handle Arguments section
|
|
265
|
-
const argsRegex = /((?:Request |Estimate Gas )?Arguments:[\s\S]*?(?=\n\n|$))/g;
|
|
266
|
-
result = result.replace(argsRegex, section => {
|
|
267
|
-
const lines = section.split('\n');
|
|
268
|
-
const processedLines = lines.map(line => {
|
|
269
|
-
// Check if line contains a colon followed by content
|
|
270
|
-
const colonIndex = line.indexOf(':');
|
|
271
|
-
if (colonIndex !== -1) {
|
|
272
|
-
const [prefix, content] = [line.slice(0, colonIndex + 1), line.slice(colonIndex + 1).trim()];
|
|
273
|
-
// If content contains a hex string, truncate it
|
|
274
|
-
if (content.includes('0x')) {
|
|
275
|
-
const processedContent = replaceHexStrings(content);
|
|
276
|
-
return `${prefix} ${processedContent}`;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
return line;
|
|
280
|
-
});
|
|
281
|
-
return processedLines.join('\n');
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
// Finally, catch any remaining hex strings in the message
|
|
285
|
-
result = replaceHexStrings(result);
|
|
286
|
-
|
|
287
|
-
return result;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
function truncateHex(hex: string, length = 100) {
|
|
291
|
-
if (!hex || typeof hex !== 'string') {
|
|
292
|
-
return hex;
|
|
293
|
-
}
|
|
294
|
-
if (!hex.startsWith('0x')) {
|
|
295
|
-
return hex;
|
|
296
|
-
}
|
|
297
|
-
if (hex.length <= length * 2) {
|
|
298
|
-
return hex;
|
|
299
|
-
}
|
|
300
|
-
// For extremely large hex strings, use more aggressive truncation
|
|
301
|
-
if (hex.length > 10000) {
|
|
302
|
-
return `${hex.slice(0, length)}...<${hex.length - length * 2} chars omitted>...${hex.slice(-length)}`;
|
|
303
|
-
}
|
|
304
|
-
return `${hex.slice(0, length)}...${hex.slice(-length)}`;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
function replaceHexStrings(
|
|
308
|
-
text: string,
|
|
309
|
-
options: {
|
|
310
|
-
minLength?: number;
|
|
311
|
-
maxLength?: number;
|
|
312
|
-
truncateLength?: number;
|
|
313
|
-
pattern?: RegExp;
|
|
314
|
-
transform?: (hex: string) => string;
|
|
315
|
-
} = {},
|
|
316
|
-
): string {
|
|
317
|
-
const {
|
|
318
|
-
minLength = 10,
|
|
319
|
-
maxLength = Infinity,
|
|
320
|
-
truncateLength = 100,
|
|
321
|
-
pattern,
|
|
322
|
-
transform = hex => truncateHex(hex, truncateLength),
|
|
323
|
-
} = options;
|
|
324
|
-
|
|
325
|
-
const hexRegex = pattern ?? new RegExp(`(0x[a-fA-F0-9]{${minLength},${maxLength}})`, 'g');
|
|
326
|
-
return text.replace(hexRegex, match => transform(match));
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
function formatRequestBody(body: string) {
|
|
330
|
-
try {
|
|
331
|
-
// Special handling for eth_sendRawTransaction
|
|
332
|
-
if (body.includes('"method":"eth_sendRawTransaction"')) {
|
|
333
|
-
try {
|
|
334
|
-
const parsed = JSON.parse(body);
|
|
335
|
-
if (parsed.params && Array.isArray(parsed.params) && parsed.params.length > 0) {
|
|
336
|
-
// These are likely large transaction hex strings
|
|
337
|
-
parsed.params = parsed.params.map((param: any) => {
|
|
338
|
-
if (typeof param === 'string' && param.startsWith('0x') && param.length > 1000) {
|
|
339
|
-
return truncateHex(param, 200);
|
|
340
|
-
}
|
|
341
|
-
return param;
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
return JSON.stringify(parsed, null, 2);
|
|
345
|
-
} catch {
|
|
346
|
-
// If specific parsing fails, fall back to regex-based truncation
|
|
347
|
-
return replaceHexStrings(body, {
|
|
348
|
-
pattern: /"params":\s*\[\s*"(0x[a-fA-F0-9]{1000,})"\s*\]/g,
|
|
349
|
-
transform: hex => `"params":["${truncateHex(hex, 200)}"]`,
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// For extremely large request bodies, use simple truncation instead of parsing
|
|
355
|
-
if (body.length > 50000) {
|
|
356
|
-
const jsonStart = body.indexOf('{');
|
|
357
|
-
const jsonEnd = body.lastIndexOf('}');
|
|
358
|
-
if (jsonStart >= 0 && jsonEnd > jsonStart) {
|
|
359
|
-
return replaceHexStrings(body, { minLength: 10000, truncateLength: 200 });
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const parsed = JSON.parse(body);
|
|
364
|
-
|
|
365
|
-
// Process the entire request body
|
|
366
|
-
const processed = processParams(parsed);
|
|
367
|
-
return JSON.stringify(processed, null, 2);
|
|
368
|
-
} catch {
|
|
369
|
-
// If JSON parsing fails, do a simple truncation of any large hex strings
|
|
370
|
-
return replaceHexStrings(body, { minLength: 1000, truncateLength: 150 });
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// Recursively process all parameters that might contain hex strings
|
|
375
|
-
function processParams(obj: any): any {
|
|
376
|
-
if (Array.isArray(obj)) {
|
|
377
|
-
return obj.map(item => processParams(item));
|
|
378
|
-
}
|
|
379
|
-
if (typeof obj === 'object' && obj !== null) {
|
|
380
|
-
const result: any = {};
|
|
381
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
382
|
-
result[key] = processParams(value);
|
|
383
|
-
}
|
|
384
|
-
return result;
|
|
385
|
-
}
|
|
386
|
-
if (typeof obj === 'string') {
|
|
387
|
-
if (obj.startsWith('0x')) {
|
|
388
|
-
return truncateHex(obj);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
return obj;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
222
|
export function tryGetCustomErrorName(err: any) {
|
|
395
223
|
try {
|
|
396
224
|
// See https://viem.sh/docs/contract/simulateContract#handling-custom-errors
|