@aztec/ethereum 0.0.1-commit.9ef841308 → 0.0.1-commit.a89ec08

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.
@@ -31,10 +31,18 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
31
31
  }
32
32
  /** Returns the current slot */ async getSlot() {
33
33
  const ts = BigInt((await this.client.getBlock()).timestamp);
34
+ return this.getSlotAt(ts);
35
+ }
36
+ /** Returns the slot number at a given timestamp. */ async getSlotAt(timestamp) {
34
37
  return SlotNumber.fromBigInt(await this.rollup.read.getSlotAt([
35
- ts
38
+ timestamp
36
39
  ]));
37
40
  }
41
+ /** Returns the timestamp for the start of a given slot. */ async getTimestampForSlot(slot) {
42
+ return await this.rollup.read.getTimestampForSlot([
43
+ BigInt(slot)
44
+ ]);
45
+ }
38
46
  /** Returns the number of seconds until the start of the given slot based on L1 block timestamp. */ async getSecondsUntilSlot(slot) {
39
47
  const [currentTimestamp, targetTimestamp] = await Promise.all([
40
48
  this.client.getBlock().then((b)=>BigInt(b.timestamp)),
package/dest/utils.d.ts CHANGED
@@ -35,4 +35,4 @@ export declare function isBlobTransaction(tx: FormattedTransaction): tx is Forma
35
35
  * Calculates a percentile from an array of bigints
36
36
  */
37
37
  export declare function calculatePercentile(values: bigint[], percentile: number): bigint;
38
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUdwRCxPQUFPLEVBQ0wsS0FBSyxHQUFHLEVBR1IsS0FBSyxpQkFBaUIsRUFFdEIsS0FBSyx3QkFBd0IsRUFDN0IsS0FBSyxvQkFBb0IsRUFDekIsS0FBSyxHQUFHLEVBQ1IsS0FBSyxHQUFHLEVBR1QsTUFBTSxNQUFNLENBQUM7QUFHZCxNQUFNLFdBQVcsT0FBTztJQUN0QixXQUFXLEVBQUUsRUFBRSxDQUFDO0lBQ2hCLFdBQVcsRUFBRSxFQUFFLENBQUM7SUFDaEIsV0FBVyxFQUFFLEdBQUcsQ0FBQztJQUNqQixnQkFBZ0IsRUFBRSxNQUFNLENBQUM7Q0FDMUI7QUFFRCxxQkFBYSxrQkFBbUIsU0FBUSxLQUFLO0lBQzNDLFlBQVksQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBRXJCLFlBQVksT0FBTyxFQUFFLE1BQU0sRUFBRSxZQUFZLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFJaEQ7Q0FDRjtBQUVELHdCQUFnQixZQUFZLENBQzFCLEtBQUssQ0FBQyxJQUFJLFNBQVMsR0FBRyxHQUFHLFNBQVMsT0FBTyxFQUFFLEVBQzNDLFVBQVUsU0FBUyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsRUFDMUMsVUFBVSxHQUFHLHdCQUF3QixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxFQUUvRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEVBQ1gsT0FBTyxFQUFFLEdBQUcsRUFDWixHQUFHLEVBQUUsSUFBSSxFQUNULFNBQVMsRUFBRSxVQUFVLEVBQ3JCLE1BQU0sQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLFVBQVUsS0FBSyxPQUFPLEVBQ3JDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sR0FDZCxVQUFVLENBTVo7QUFFRCx3QkFBZ0IsZUFBZSxDQUM3QixLQUFLLENBQUMsSUFBSSxTQUFTLEdBQUcsR0FBRyxTQUFTLE9BQU8sRUFBRSxFQUMzQyxVQUFVLFNBQVMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEVBQzFDLFVBQVUsR0FBRyx3QkFBd0IsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsRUFFL0UsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUNYLE9BQU8sRUFBRSxHQUFHLEVBQ1osR0FBRyxFQUFFLElBQUksRUFDVCxTQUFTLEVBQUUsVUFBVSxFQUNyQixNQUFNLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxVQUFVLEtBQUssT0FBTyxFQUNyQyxNQUFNLENBQUMsRUFBRSxNQUFNLEdBQ2QsVUFBVSxHQUFHLFNBQVMsQ0FnQnhCO0FBRUQsd0JBQWdCLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxHQUFHLE9BVzdDO0FBRUQsd0JBQWdCLFNBQVMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUcsR0FBRyxDQWUxQztBQTJFRDs7Ozs7R0FLRztBQUNILHdCQUFnQixlQUFlLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxHQUFHLEdBQUUsR0FBZSxHQUFHLGtCQUFrQixDQTREcEY7QUF5QkQsd0JBQWdCLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxHQUFHLHNCQWE3QztBQUVEOzs7R0FHRztBQUNILHdCQUFnQixpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsb0JBQW9CLEdBQUcsRUFBRSxJQUFJLG9CQUFvQixHQUFHO0lBQ3hGLGdCQUFnQixFQUFFLE1BQU0sQ0FBQztJQUN6QixtQkFBbUIsRUFBRSxTQUFTLEdBQUcsRUFBRSxDQUFDO0NBQ3JDLENBT0E7QUFFRDs7R0FFRztBQUNILHdCQUFnQixtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsVUFBVSxFQUFFLE1BQU0sR0FBRyxNQUFNLENBT2hGIn0=
38
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUdwRCxPQUFPLEVBQ0wsS0FBSyxHQUFHLEVBR1IsS0FBSyxpQkFBaUIsRUFFdEIsS0FBSyx3QkFBd0IsRUFDN0IsS0FBSyxvQkFBb0IsRUFDekIsS0FBSyxHQUFHLEVBQ1IsS0FBSyxHQUFHLEVBR1QsTUFBTSxNQUFNLENBQUM7QUFHZCxNQUFNLFdBQVcsT0FBTztJQUN0QixXQUFXLEVBQUUsRUFBRSxDQUFDO0lBQ2hCLFdBQVcsRUFBRSxFQUFFLENBQUM7SUFDaEIsV0FBVyxFQUFFLEdBQUcsQ0FBQztJQUNqQixnQkFBZ0IsRUFBRSxNQUFNLENBQUM7Q0FDMUI7QUFFRCxxQkFBYSxrQkFBbUIsU0FBUSxLQUFLO0lBQzNDLFlBQVksQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBRXJCLFlBQVksT0FBTyxFQUFFLE1BQU0sRUFBRSxZQUFZLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFJaEQ7Q0FDRjtBQUVELHdCQUFnQixZQUFZLENBQzFCLEtBQUssQ0FBQyxJQUFJLFNBQVMsR0FBRyxHQUFHLFNBQVMsT0FBTyxFQUFFLEVBQzNDLFVBQVUsU0FBUyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsRUFDMUMsVUFBVSxHQUFHLHdCQUF3QixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxFQUUvRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEVBQ1gsT0FBTyxFQUFFLEdBQUcsRUFDWixHQUFHLEVBQUUsSUFBSSxFQUNULFNBQVMsRUFBRSxVQUFVLEVBQ3JCLE1BQU0sQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLFVBQVUsS0FBSyxPQUFPLEVBQ3JDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sR0FDZCxVQUFVLENBTVo7QUFFRCx3QkFBZ0IsZUFBZSxDQUM3QixLQUFLLENBQUMsSUFBSSxTQUFTLEdBQUcsR0FBRyxTQUFTLE9BQU8sRUFBRSxFQUMzQyxVQUFVLFNBQVMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEVBQzFDLFVBQVUsR0FBRyx3QkFBd0IsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsRUFFL0UsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUNYLE9BQU8sRUFBRSxHQUFHLEVBQ1osR0FBRyxFQUFFLElBQUksRUFDVCxTQUFTLEVBQUUsVUFBVSxFQUNyQixNQUFNLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxVQUFVLEtBQUssT0FBTyxFQUNyQyxNQUFNLENBQUMsRUFBRSxNQUFNLEdBQ2QsVUFBVSxHQUFHLFNBQVMsQ0FnQnhCO0FBRUQsd0JBQWdCLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxHQUFHLE9BVzdDO0FBRUQsd0JBQWdCLFNBQVMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUcsR0FBRyxDQWUxQztBQTRERDs7Ozs7R0FLRztBQUNILHdCQUFnQixlQUFlLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxHQUFHLEdBQUUsR0FBZSxHQUFHLGtCQUFrQixDQXdFcEY7QUF5QkQsd0JBQWdCLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxHQUFHLHNCQWE3QztBQUVEOzs7R0FHRztBQUNILHdCQUFnQixpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsb0JBQW9CLEdBQUcsRUFBRSxJQUFJLG9CQUFvQixHQUFHO0lBQ3hGLGdCQUFnQixFQUFFLE1BQU0sQ0FBQztJQUN6QixtQkFBbUIsRUFBRSxTQUFTLEdBQUcsRUFBRSxDQUFDO0NBQ3JDLENBT0E7QUFFRDs7R0FFRztBQUNILHdCQUFnQixtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsVUFBVSxFQUFFLE1BQU0sR0FBRyxNQUFNLENBT2hGIn0=
@@ -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,EAGR,KAAK,iBAAiB,EAEtB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,GAAG,EACR,KAAK,GAAG,EAGT,MAAM,MAAM,CAAC;AAGd,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;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAe1C;AA2ED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,GAAE,GAAe,GAAG,kBAAkB,CA4DpF;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"}
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,EAGR,KAAK,iBAAiB,EAEtB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,GAAG,EACR,KAAK,GAAG,EAGT,MAAM,MAAM,CAAC;AAGd,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;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAe1C;AA4DD;;;;;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
@@ -112,19 +112,6 @@ function getNestedErrorData(error) {
112
112
  // Not found
113
113
  return undefined;
114
114
  }
115
- /**
116
- * Truncates an error message to a safe length for log renderers.
117
- * LogExplorer can only render up to 2500 characters in its summary view.
118
- * We cap at 2000 to leave room for decorating context added by callers.
119
- */ function truncateErrorMessage(message) {
120
- const MAX = 2000;
121
- const CHUNK = 950;
122
- if (message.length <= MAX) {
123
- return message;
124
- }
125
- const truncated = message.length - 2 * CHUNK;
126
- return message.slice(0, CHUNK) + `...${truncated} characters truncated...` + message.slice(-CHUNK);
127
- }
128
115
  /**
129
116
  * Formats a Viem error into a FormattedViemError instance.
130
117
  * @param error - The error to format.
@@ -175,9 +162,18 @@ function getNestedErrorData(error) {
175
162
  }
176
163
  // If it's a regular Error instance, return it with its message
177
164
  if (error instanceof Error) {
178
- return new FormattedViemError(truncateErrorMessage(error.message), error?.metaMessages);
179
- }
180
- return new FormattedViemError(truncateErrorMessage(String(error)));
165
+ return new FormattedViemError(error.message, error?.metaMessages);
166
+ }
167
+ const body = String(error);
168
+ const length = body.length;
169
+ // LogExplorer can only render up to 2500 characters in it's summary view. Try to keep the whole message below this number
170
+ // Limit the error to 2000 chacaters in order to allow code higher up to decorate this error with extra details (up to 500 characters)
171
+ if (length > 2000) {
172
+ const chunk = 950;
173
+ const truncated = length - 2 * chunk;
174
+ return new FormattedViemError(body.slice(0, chunk) + `...${truncated} characters truncated...` + body.slice(-1 * chunk));
175
+ }
176
+ return new FormattedViemError(body);
181
177
  }
182
178
  function stripAbis(obj) {
183
179
  if (!obj || typeof obj !== 'object') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/ethereum",
3
- "version": "0.0.1-commit.9ef841308",
3
+ "version": "0.0.1-commit.a89ec08",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./account": "./dest/account.js",
@@ -50,10 +50,11 @@
50
50
  "../package.common.json"
51
51
  ],
52
52
  "dependencies": {
53
- "@aztec/blob-lib": "0.0.1-commit.9ef841308",
54
- "@aztec/constants": "0.0.1-commit.9ef841308",
55
- "@aztec/foundation": "0.0.1-commit.9ef841308",
56
- "@aztec/l1-artifacts": "0.0.1-commit.9ef841308",
53
+ "@aztec/blob-lib": "0.0.1-commit.a89ec08",
54
+ "@aztec/constants": "0.0.1-commit.a89ec08",
55
+ "@aztec/foundation": "0.0.1-commit.a89ec08",
56
+ "@aztec/l1-artifacts": "0.0.1-commit.a89ec08",
57
+ "@viem/anvil": "^0.0.10",
57
58
  "dotenv": "^16.0.3",
58
59
  "lodash.chunk": "^4.2.0",
59
60
  "lodash.pickby": "^4.5.0",
@@ -68,6 +69,7 @@
68
69
  "@types/lodash.pickby": "^4",
69
70
  "@types/node": "^22.15.17",
70
71
  "@typescript/native-preview": "7.0.0-dev.20260113.1",
72
+ "@viem/anvil": "^0.0.10",
71
73
  "get-port": "^7.1.0",
72
74
  "jest": "^30.0.0",
73
75
  "jest-mock-extended": "^4.0.0",
package/src/config.ts CHANGED
@@ -263,7 +263,7 @@ export const genesisStateConfigMappings: ConfigMappingsType<GenesisStateConfig>
263
263
  },
264
264
  prefundAddresses: {
265
265
  env: 'PREFUND_ADDRESSES',
266
- description: 'Comma-separated list of Aztec addresses to prefund with fee juice at genesis (local network only).',
266
+ description: 'Comma-separated list of Aztec addresses to prefund with fee juice at genesis.',
267
267
  parseEnv: (val: string) =>
268
268
  val
269
269
  .split(',')
@@ -2,7 +2,7 @@ import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
2
2
  import { TimeoutError } from '@aztec/foundation/error';
3
3
  import type { Logger } from '@aztec/foundation/log';
4
4
 
5
- import { type Address, type EncodeFunctionDataParameters, type Hex, encodeFunctionData, multicall3Abi } from 'viem';
5
+ import { type EncodeFunctionDataParameters, type Hex, encodeFunctionData, multicall3Abi } from 'viem';
6
6
 
7
7
  import type { L1BlobInputs, L1TxConfig, L1TxRequest, L1TxUtils } from '../l1_tx_utils/index.js';
8
8
  import type { ExtendedViemWalletClient } from '../types.js';
@@ -11,39 +11,6 @@ import { RollupContract } from './rollup.js';
11
11
 
12
12
  export const MULTI_CALL_3_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11' as const;
13
13
 
14
- /** ABI fragment for aggregate3Value — not included in viem's multicall3Abi. */
15
- export const aggregate3ValueAbi = [
16
- {
17
- inputs: [
18
- {
19
- components: [
20
- { internalType: 'address', name: 'target', type: 'address' },
21
- { internalType: 'bool', name: 'allowFailure', type: 'bool' },
22
- { internalType: 'uint256', name: 'value', type: 'uint256' },
23
- { internalType: 'bytes', name: 'callData', type: 'bytes' },
24
- ],
25
- internalType: 'struct Multicall3.Call3Value[]',
26
- name: 'calls',
27
- type: 'tuple[]',
28
- },
29
- ],
30
- name: 'aggregate3Value',
31
- outputs: [
32
- {
33
- components: [
34
- { internalType: 'bool', name: 'success', type: 'bool' },
35
- { internalType: 'bytes', name: 'returnData', type: 'bytes' },
36
- ],
37
- internalType: 'struct Multicall3.Result[]',
38
- name: 'returnData',
39
- type: 'tuple[]',
40
- },
41
- ],
42
- stateMutability: 'payable',
43
- type: 'function',
44
- },
45
- ] as const;
46
-
47
14
  export class Multicall3 {
48
15
  static async forward(
49
16
  requests: L1TxRequest[],
@@ -155,37 +122,6 @@ export class Multicall3 {
155
122
  throw err;
156
123
  }
157
124
  }
158
-
159
- /** Batch multiple value transfers into a single aggregate3Value call on Multicall3. */
160
- static async forwardValue(calls: { to: Address; value: bigint }[], l1TxUtils: L1TxUtils, logger: Logger) {
161
- const args = calls.map(c => ({
162
- target: c.to,
163
- allowFailure: false,
164
- value: c.value,
165
- callData: '0x' as Hex,
166
- }));
167
-
168
- const data = encodeFunctionData({
169
- abi: aggregate3ValueAbi,
170
- functionName: 'aggregate3Value',
171
- args: [args],
172
- });
173
-
174
- const totalValue = calls.reduce((sum, c) => sum + c.value, 0n);
175
-
176
- logger.info(`Sending aggregate3Value with ${calls.length} calls`, { totalValue });
177
- const { receipt } = await l1TxUtils.sendAndMonitorTransaction({
178
- to: MULTI_CALL_3_ADDRESS,
179
- data,
180
- value: totalValue,
181
- });
182
-
183
- if (receipt.status !== 'success') {
184
- throw new Error(`aggregate3Value transaction reverted: ${receipt.transactionHash}`);
185
- }
186
-
187
- return { receipt };
188
- }
189
125
  }
190
126
 
191
127
  export async function deployMulticall3(l1Client: ExtendedViemWalletClient, logger: Logger) {
@@ -4,7 +4,6 @@ import { Fr } from '@aztec/foundation/curves/bn254';
4
4
  import { memoize } from '@aztec/foundation/decorators';
5
5
  import { EthAddress } from '@aztec/foundation/eth-address';
6
6
  import type { ViemSignature } from '@aztec/foundation/eth-signature';
7
- import { createLogger } from '@aztec/foundation/log';
8
7
  import { makeBackoff, retry } from '@aztec/foundation/retry';
9
8
  import { EscapeHatchAbi } from '@aztec/l1-artifacts/EscapeHatchAbi';
10
9
  import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
@@ -213,7 +212,6 @@ export type CheckpointProposedLog = L1EventLog<CheckpointProposedArgs>;
213
212
 
214
213
  export class RollupContract {
215
214
  private readonly rollup: GetContractReturnType<typeof RollupAbi, ViemClient>;
216
- private readonly logger = createLogger('ethereum:rollup');
217
215
 
218
216
  private static cachedStfStorageSlot: Hex | undefined;
219
217
  private cachedEscapeHatch?: {
@@ -497,11 +495,7 @@ export class RollupContract {
497
495
 
498
496
  const [isOpen] = await escapeHatch.read.isHatchOpen([BigInt(epoch)]);
499
497
  return isOpen;
500
- } catch (err) {
501
- this.logger.warn('isEscapeHatchOpen failed (treating as closed); RPC or contract error may cause liveness risk', {
502
- epoch: Number(epoch),
503
- error: err,
504
- });
498
+ } catch {
505
499
  return false;
506
500
  }
507
501
  }
@@ -8,7 +8,7 @@ export const l1ContractsDefaultEnv = {
8
8
  AZTEC_EPOCH_DURATION: 32,
9
9
  AZTEC_TARGET_COMMITTEE_SIZE: 48,
10
10
  AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET: 2,
11
- AZTEC_LAG_IN_EPOCHS_FOR_RANDAO: 2,
11
+ AZTEC_LAG_IN_EPOCHS_FOR_RANDAO: 1,
12
12
  AZTEC_ACTIVATION_THRESHOLD: 100000000000000000000,
13
13
  AZTEC_EJECTION_THRESHOLD: 50000000000000000000,
14
14
  AZTEC_LOCAL_EJECTION_THRESHOLD: 98000000000000000000,
@@ -4,7 +4,6 @@ import { merge, pick } from '@aztec/foundation/collection';
4
4
  import { InterruptError, TimeoutError } from '@aztec/foundation/error';
5
5
  import { EthAddress } from '@aztec/foundation/eth-address';
6
6
  import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
7
- import { Semaphore } from '@aztec/foundation/queue';
8
7
  import { retryUntil } from '@aztec/foundation/retry';
9
8
  import { sleep } from '@aztec/foundation/sleep';
10
9
  import { DateProvider } from '@aztec/foundation/timer';
@@ -48,8 +47,6 @@ export class L1TxUtils extends ReadOnlyL1TxUtils {
48
47
  protected txs: L1TxState[] = [];
49
48
  /** Last nonce successfully sent to the chain. Used as a lower bound when a fallback RPC node returns a stale count. */
50
49
  private lastSentNonce: number | undefined;
51
- /** Mutex to prevent concurrent sendTransaction calls from racing on the same nonce. */
52
- private readonly sendMutex = new Semaphore(1);
53
50
  /** Tx delayer for testing. Only set when enableDelayer config is true. */
54
51
  public delayer?: Delayer;
55
52
  /** KZG instance for blob operations. */
@@ -256,27 +253,20 @@ export class L1TxUtils extends ReadOnlyL1TxUtils {
256
253
  );
257
254
  }
258
255
 
259
- let txHash: Hex;
260
- let nonce: number;
261
- let baseState: Pick<L1TxState, 'request' | 'gasLimit' | 'blobInputs' | 'gasPrice' | 'nonce'>;
256
+ const chainNonce = await this.client.getTransactionCount({ address: account, blockTag: 'pending' });
257
+ // If a fallback RPC node returns a stale count (lower than what we last sent), use our
258
+ // local lower bound to avoid sending a duplicate of an already-pending transaction.
259
+ const nonce =
260
+ this.lastSentNonce !== undefined && chainNonce <= this.lastSentNonce ? this.lastSentNonce + 1 : chainNonce;
262
261
 
263
- await this.sendMutex.acquire();
264
- try {
265
- const chainNonce = await this.client.getTransactionCount({ address: account, blockTag: 'pending' });
266
- // If a fallback RPC node returns a stale count (lower than what we last sent), use our
267
- // local lower bound to avoid sending a duplicate of an already-pending transaction.
268
- nonce =
269
- this.lastSentNonce !== undefined && chainNonce <= this.lastSentNonce ? this.lastSentNonce + 1 : chainNonce;
270
-
271
- baseState = { request, gasLimit, blobInputs, gasPrice, nonce };
272
- const txData = this.makeTxData(baseState, { isCancelTx: false });
273
-
274
- const signedRequest = await this.prepareSignedTransaction(txData);
275
- txHash = await this.client.sendRawTransaction({ serializedTransaction: signedRequest });
276
- this.lastSentNonce = nonce;
277
- } finally {
278
- this.sendMutex.release();
279
- }
262
+ const baseState = { request, gasLimit, blobInputs, gasPrice, nonce };
263
+ const txData = this.makeTxData(baseState, { isCancelTx: false });
264
+
265
+ // Send the new tx
266
+ const signedRequest = await this.prepareSignedTransaction(txData);
267
+ const txHash = await this.client.sendRawTransaction({ serializedTransaction: signedRequest });
268
+ // Update after tx is sent successfully
269
+ this.lastSentNonce = nonce;
280
270
 
281
271
  // Create the new state for monitoring
282
272
  const l1TxState: L1TxState = {
@@ -1,8 +1,6 @@
1
1
  import { pick } from '@aztec/foundation/collection';
2
2
  import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
3
- import { RunningPromise } from '@aztec/foundation/running-promise';
4
3
 
5
- import { Multicall3 } from './contracts/multicall.js';
6
4
  import { L1TxUtils, TxUtilsState } from './l1_tx_utils/index.js';
7
5
 
8
6
  // Defines the order in which we prioritise publishers based on their state (first is better)
@@ -29,72 +27,24 @@ const busyStates: TxUtilsState[] = [
29
27
 
30
28
  export type PublisherFilter<UtilsType extends L1TxUtils> = (utils: UtilsType) => boolean;
31
29
 
32
- /** Config accepted by PublisherManager. */
33
- type PublisherManagerConfig = {
34
- publisherAllowInvalidStates?: boolean;
35
- publisherFundingThreshold?: bigint;
36
- publisherFundingAmount?: bigint;
37
- };
38
-
39
30
  export class PublisherManager<UtilsType extends L1TxUtils = L1TxUtils> {
40
31
  private log: Logger;
41
- private config: PublisherManagerConfig;
42
- private static readonly FUNDING_CHECK_INTERVAL_MS = 2 * 60 * 1000;
43
- private funder?: UtilsType;
44
- private fundingPromise?: RunningPromise;
32
+ private config: { publisherAllowInvalidStates?: boolean };
45
33
 
46
34
  constructor(
47
35
  private publishers: UtilsType[],
48
- config: PublisherManagerConfig,
49
- opts?: { bindings?: LoggerBindings; funder?: UtilsType },
36
+ config: { publisherAllowInvalidStates?: boolean },
37
+ bindings?: LoggerBindings,
50
38
  ) {
51
- this.funder = opts?.funder;
52
- this.log = createLogger('publisher:manager', opts?.bindings);
39
+ this.log = createLogger('publisher:manager', bindings);
53
40
  this.log.info(`PublisherManager initialized with ${publishers.length} publishers.`);
54
41
  this.publishers = publishers;
55
- this.config = pick(config, 'publisherAllowInvalidStates', 'publisherFundingThreshold', 'publisherFundingAmount');
56
-
57
- const hasThreshold = this.config.publisherFundingThreshold !== undefined;
58
- const hasAmount = this.config.publisherFundingAmount !== undefined;
59
- if (hasThreshold !== hasAmount) {
60
- this.log.warn(`Incomplete funding config: both publisherFundingThreshold and publisherFundingAmount must be set`);
61
- }
62
-
63
- if (this.funder) {
64
- const funderAddress = this.funder.getSenderAddress();
65
- if (publishers.some(p => p.getSenderAddress().equals(funderAddress))) {
66
- this.log.error(`Funding account ${funderAddress} is also a publisher, disabling funding to avoid self-funding`);
67
- this.funder = undefined;
68
- }
69
- }
42
+ this.config = pick(config, 'publisherAllowInvalidStates');
70
43
  }
71
44
 
72
- /** Loads the state of all publishers and the funder, and starts periodic funding checks. */
73
- public async start(): Promise<void> {
74
- await Promise.all([
75
- ...this.publishers.map(pub => pub.loadStateAndResumeMonitoring()),
76
- this.funder?.loadStateAndResumeMonitoring(),
77
- ]);
78
-
79
- if (
80
- this.funder &&
81
- this.config.publisherFundingThreshold !== undefined &&
82
- this.config.publisherFundingAmount !== undefined
83
- ) {
84
- this.fundingPromise = new RunningPromise(
85
- () => this.triggerFundingIfNeeded(),
86
- this.log,
87
- PublisherManager.FUNDING_CHECK_INTERVAL_MS,
88
- );
89
- this.fundingPromise.start();
90
- }
91
- }
92
-
93
- /** Stops the funding loop and interrupts all publishers. */
94
- public async stop(): Promise<void> {
95
- await this.fundingPromise?.stop();
96
- this.publishers.forEach(pub => pub.interrupt());
97
- this.funder?.interrupt();
45
+ /** Loads the state of all publishers and resumes monitoring any pending txs */
46
+ public async loadState(): Promise<void> {
47
+ await Promise.all(this.publishers.map(pub => pub.loadStateAndResumeMonitoring()));
98
48
  }
99
49
 
100
50
  // Finds and prioritises available publishers based on
@@ -152,52 +102,7 @@ export class PublisherManager<UtilsType extends L1TxUtils = L1TxUtils> {
152
102
  return sortedPublishers[0].publisher;
153
103
  }
154
104
 
155
- /** Check all publisher balances and fund those below threshold. */
156
- private async triggerFundingIfNeeded(): Promise<void> {
157
- const { funder, config } = this;
158
- if (!funder || config.publisherFundingThreshold === undefined || config.publisherFundingAmount === undefined) {
159
- return;
160
- }
161
-
162
- const allBalances = await Promise.all(
163
- this.publishers.map(async pub => ({ balance: await pub.getSenderBalance(), publisher: pub })),
164
- );
165
- const lowBalance = allBalances.filter(p => p.balance < config.publisherFundingThreshold!);
166
- if (lowBalance.length === 0) {
167
- return;
168
- }
169
-
170
- const fundingAmount = config.publisherFundingAmount!;
171
- const funderBalance = await funder.getSenderBalance();
172
-
173
- if (funderBalance < 10n * fundingAmount) {
174
- this.log.warn(`Funding account balance is low`, { funderBalance, threshold: 10n * fundingAmount });
175
- }
176
- const affordableCount = Number(funderBalance / fundingAmount);
177
- if (affordableCount === 0) {
178
- this.log.error(`Funding account balance too low to fund any publisher`, { funderBalance, fundingAmount });
179
- return;
180
- }
181
- if (affordableCount < lowBalance.length) {
182
- this.log.warn(`Funder can only afford ${affordableCount}/${lowBalance.length} publishers`, {
183
- funderBalance,
184
- fundingAmount,
185
- });
186
- }
187
-
188
- const toFund = lowBalance.slice(0, affordableCount).map(p => p.publisher);
189
- await this.fundPublishers(toFund);
190
- }
191
-
192
- /** Fund publishers via a single Multicall3 aggregate3Value transaction. */
193
- private async fundPublishers(publishers: UtilsType[]): Promise<void> {
194
- const fundingAmount = this.config.publisherFundingAmount!;
195
- const calls = publishers.map(pub => ({
196
- to: pub.getSenderAddress().toString(),
197
- value: fundingAmount,
198
- }));
199
-
200
- await Multicall3.forwardValue(calls, this.funder!, this.log);
201
- this.log.info(`Funded ${publishers.length} publishers`);
105
+ public interrupt() {
106
+ this.publishers.forEach(pub => pub.interrupt());
202
107
  }
203
108
  }
@@ -53,7 +53,17 @@ export class RollupCheatCodes {
53
53
  /** Returns the current slot */
54
54
  public async getSlot(): Promise<SlotNumber> {
55
55
  const ts = BigInt((await this.client.getBlock()).timestamp);
56
- return SlotNumber.fromBigInt(await this.rollup.read.getSlotAt([ts]));
56
+ return this.getSlotAt(ts);
57
+ }
58
+
59
+ /** Returns the slot number at a given timestamp. */
60
+ public async getSlotAt(timestamp: bigint): Promise<SlotNumber> {
61
+ return SlotNumber.fromBigInt(await this.rollup.read.getSlotAt([timestamp]));
62
+ }
63
+
64
+ /** Returns the timestamp for the start of a given slot. */
65
+ public async getTimestampForSlot(slot: SlotNumber): Promise<bigint> {
66
+ return await this.rollup.read.getTimestampForSlot([BigInt(slot)]);
57
67
  }
58
68
 
59
69
  /** Returns the number of seconds until the start of the given slot based on L1 block timestamp. */
package/src/utils.ts CHANGED
@@ -170,21 +170,6 @@ function getNestedErrorData(error: unknown): string | undefined {
170
170
  return undefined;
171
171
  }
172
172
 
173
- /**
174
- * Truncates an error message to a safe length for log renderers.
175
- * LogExplorer can only render up to 2500 characters in its summary view.
176
- * We cap at 2000 to leave room for decorating context added by callers.
177
- */
178
- function truncateErrorMessage(message: string): string {
179
- const MAX = 2000;
180
- const CHUNK = 950;
181
- if (message.length <= MAX) {
182
- return message;
183
- }
184
- const truncated = message.length - 2 * CHUNK;
185
- return message.slice(0, CHUNK) + `...${truncated} characters truncated...` + message.slice(-CHUNK);
186
- }
187
-
188
173
  /**
189
174
  * Formats a Viem error into a FormattedViemError instance.
190
175
  * @param error - The error to format.
@@ -247,10 +232,22 @@ export function formatViemError(error: any, abi: Abi = ErrorsAbi): FormattedViem
247
232
 
248
233
  // If it's a regular Error instance, return it with its message
249
234
  if (error instanceof Error) {
250
- return new FormattedViemError(truncateErrorMessage(error.message), (error as any)?.metaMessages);
235
+ return new FormattedViemError(error.message, (error as any)?.metaMessages);
236
+ }
237
+
238
+ const body = String(error);
239
+ const length = body.length;
240
+ // LogExplorer can only render up to 2500 characters in it's summary view. Try to keep the whole message below this number
241
+ // Limit the error to 2000 chacaters in order to allow code higher up to decorate this error with extra details (up to 500 characters)
242
+ if (length > 2000) {
243
+ const chunk = 950;
244
+ const truncated = length - 2 * chunk;
245
+ return new FormattedViemError(
246
+ body.slice(0, chunk) + `...${truncated} characters truncated...` + body.slice(-1 * chunk),
247
+ );
251
248
  }
252
249
 
253
- return new FormattedViemError(truncateErrorMessage(String(error)));
250
+ return new FormattedViemError(body);
254
251
  }
255
252
 
256
253
  function stripAbis(obj: any) {