@aztec/ethereum 0.0.1-commit.c7c42ec → 0.0.1-commit.f295ac2

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.
Files changed (77) hide show
  1. package/dest/config.d.ts +13 -28
  2. package/dest/config.d.ts.map +1 -1
  3. package/dest/config.js +41 -55
  4. package/dest/contracts/fee_asset_handler.d.ts +6 -5
  5. package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
  6. package/dest/contracts/fee_asset_handler.js +9 -9
  7. package/dest/contracts/governance_proposer.js +382 -8
  8. package/dest/contracts/inbox.d.ts +18 -1
  9. package/dest/contracts/inbox.d.ts.map +1 -1
  10. package/dest/contracts/inbox.js +32 -1
  11. package/dest/contracts/index.d.ts +3 -1
  12. package/dest/contracts/index.d.ts.map +1 -1
  13. package/dest/contracts/index.js +2 -0
  14. package/dest/contracts/log.d.ts +13 -0
  15. package/dest/contracts/log.d.ts.map +1 -0
  16. package/dest/contracts/log.js +1 -0
  17. package/dest/contracts/outbox.d.ts +41 -0
  18. package/dest/contracts/outbox.d.ts.map +1 -0
  19. package/dest/contracts/outbox.js +86 -0
  20. package/dest/contracts/rollup.d.ts +159 -95
  21. package/dest/contracts/rollup.d.ts.map +1 -1
  22. package/dest/contracts/rollup.js +666 -127
  23. package/dest/deploy_aztec_l1_contracts.d.ts +13 -2
  24. package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
  25. package/dest/deploy_aztec_l1_contracts.js +73 -12
  26. package/dest/generated/l1-contracts-defaults.d.ts +29 -0
  27. package/dest/generated/l1-contracts-defaults.d.ts.map +1 -0
  28. package/dest/generated/l1-contracts-defaults.js +29 -0
  29. package/dest/l1_artifacts.d.ts +4060 -1503
  30. package/dest/l1_artifacts.d.ts.map +1 -1
  31. package/dest/l1_tx_utils/fee-strategies/index.d.ts +3 -2
  32. package/dest/l1_tx_utils/fee-strategies/index.d.ts.map +1 -1
  33. package/dest/l1_tx_utils/fee-strategies/index.js +2 -1
  34. package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts +2 -12
  35. package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts.map +1 -1
  36. package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +35 -17
  37. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts +2 -11
  38. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts.map +1 -1
  39. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +36 -18
  40. package/dest/l1_tx_utils/fee-strategies/types.d.ts +14 -27
  41. package/dest/l1_tx_utils/fee-strategies/types.d.ts.map +1 -1
  42. package/dest/l1_tx_utils/fee-strategies/types.js +0 -21
  43. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts +2 -2
  44. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts.map +1 -1
  45. package/dest/l1_tx_utils/l1_fee_analyzer.js +3 -3
  46. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +1 -5
  47. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
  48. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +14 -51
  49. package/dest/queries.d.ts +2 -2
  50. package/dest/queries.d.ts.map +1 -1
  51. package/dest/queries.js +4 -2
  52. package/dest/test/chain_monitor.js +1 -2
  53. package/dest/test/eth_cheat_codes.d.ts +13 -1
  54. package/dest/test/eth_cheat_codes.d.ts.map +1 -1
  55. package/dest/test/rollup_cheat_codes.d.ts +2 -1
  56. package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
  57. package/dest/test/rollup_cheat_codes.js +9 -1
  58. package/package.json +8 -7
  59. package/src/config.ts +48 -54
  60. package/src/contracts/README.md +157 -0
  61. package/src/contracts/fee_asset_handler.ts +8 -7
  62. package/src/contracts/inbox.ts +48 -1
  63. package/src/contracts/index.ts +2 -0
  64. package/src/contracts/log.ts +13 -0
  65. package/src/contracts/outbox.ts +98 -0
  66. package/src/contracts/rollup.ts +332 -92
  67. package/src/deploy_aztec_l1_contracts.ts +75 -14
  68. package/src/generated/l1-contracts-defaults.ts +31 -0
  69. package/src/l1_tx_utils/fee-strategies/index.ts +1 -1
  70. package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +45 -41
  71. package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +48 -44
  72. package/src/l1_tx_utils/fee-strategies/types.ts +14 -46
  73. package/src/l1_tx_utils/l1_fee_analyzer.ts +2 -3
  74. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +20 -59
  75. package/src/queries.ts +4 -3
  76. package/src/test/chain_monitor.ts +1 -1
  77. package/src/test/rollup_cheat_codes.ts +10 -1
@@ -1,4 +1,4 @@
1
- import { RollupContract } from '@aztec/ethereum/contracts';
1
+ import { OutboxContract, RollupContract } from '@aztec/ethereum/contracts';
2
2
  import { CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
3
3
  import { EthAddress } from '@aztec/foundation/eth-address';
4
4
  import { createLogger } from '@aztec/foundation/log';
@@ -211,6 +211,14 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
211
211
  return newInProgress;
212
212
  });
213
213
  }
214
+ insertOutbox(epoch, outHash) {
215
+ return this.ethCheatCodes.execWithPausedAnvil(async ()=>{
216
+ const outboxAddress = await this.rollup.read.getOutbox();
217
+ const epochRootSlot = OutboxContract.getEpochRootStorageSlot(epoch);
218
+ await this.ethCheatCodes.store(EthAddress.fromString(outboxAddress), epochRootSlot, outHash);
219
+ this.logger.warn(`Advanced outbox to epoch ${epoch} with out hash ${outHash}`);
220
+ });
221
+ }
214
222
  /**
215
223
  * Executes an action impersonated as the owner of the Rollup contract.
216
224
  * @param action - The action to execute
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/ethereum",
3
- "version": "0.0.1-commit.c7c42ec",
3
+ "version": "0.0.1-commit.f295ac2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./account": "./dest/account.js",
@@ -40,7 +40,8 @@
40
40
  "build": "yarn clean && ../scripts/tsc.sh",
41
41
  "build:dev": "../scripts/tsc.sh --watch",
42
42
  "clean": "rm -rf ./dest .tsbuildinfo",
43
- "start:dev": "concurrently -k \"tsgo -b -w\" \"nodemon --watch dest --exec yarn start\"",
43
+ "generate": "./scripts/generate.sh",
44
+ "start:dev": "concurrently -k \"../scripts/tsc.sh --watch\" \"nodemon --watch dest --exec yarn start\"",
44
45
  "start": "node ./dest/index.js",
45
46
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}",
46
47
  "proposer-address": "node ./dest/cli/forwarder_address.js"
@@ -49,10 +50,10 @@
49
50
  "../package.common.json"
50
51
  ],
51
52
  "dependencies": {
52
- "@aztec/blob-lib": "0.0.1-commit.c7c42ec",
53
- "@aztec/constants": "0.0.1-commit.c7c42ec",
54
- "@aztec/foundation": "0.0.1-commit.c7c42ec",
55
- "@aztec/l1-artifacts": "0.0.1-commit.c7c42ec",
53
+ "@aztec/blob-lib": "0.0.1-commit.f295ac2",
54
+ "@aztec/constants": "0.0.1-commit.f295ac2",
55
+ "@aztec/foundation": "0.0.1-commit.f295ac2",
56
+ "@aztec/l1-artifacts": "0.0.1-commit.f295ac2",
56
57
  "@viem/anvil": "^0.0.10",
57
58
  "dotenv": "^16.0.3",
58
59
  "lodash.chunk": "^4.2.0",
@@ -67,7 +68,7 @@
67
68
  "@types/jest": "^30.0.0",
68
69
  "@types/lodash.pickby": "^4",
69
70
  "@types/node": "^22.15.17",
70
- "@typescript/native-preview": "7.0.0-dev.20251126.1",
71
+ "@typescript/native-preview": "7.0.0-dev.20260113.1",
71
72
  "@viem/anvil": "^0.0.10",
72
73
  "get-port": "^7.1.0",
73
74
  "jest": "^30.0.0",
package/src/config.ts CHANGED
@@ -1,15 +1,16 @@
1
1
  import {
2
2
  type ConfigMappingsType,
3
- // type NetworkNames,
4
3
  bigintConfigHelper,
5
4
  booleanConfigHelper,
6
5
  enumConfigHelper,
7
6
  getConfigFromMappings,
7
+ getDefaultConfig,
8
8
  numberConfigHelper,
9
9
  optionalNumberConfigHelper,
10
10
  } from '@aztec/foundation/config';
11
11
  import { EthAddress } from '@aztec/foundation/eth-address';
12
12
 
13
+ import { l1ContractsDefaultEnv } from './generated/l1-contracts-defaults.js';
13
14
  import { type L1TxUtilsConfig, l1TxUtilsConfigMappings } from './l1_tx_utils/config.js';
14
15
 
15
16
  export type GenesisStateConfig = {
@@ -68,6 +69,8 @@ export type L1ContractsConfig = {
68
69
  governanceProposerQuorum?: number;
69
70
  /** Governance proposing round size */
70
71
  governanceProposerRoundSize: number;
72
+ /** Governance voting duration in seconds (only for local/devnet/next-net, default 3600) */
73
+ governanceVotingDuration?: number;
71
74
  /** The mana target for the rollup */
72
75
  manaTarget: bigint;
73
76
  /** The proving cost per mana */
@@ -76,116 +79,96 @@ export type L1ContractsConfig = {
76
79
  exitDelaySeconds: number;
77
80
  } & L1TxUtilsConfig;
78
81
 
79
- export const DefaultL1ContractsConfig = {
80
- ethereumSlotDuration: 12,
81
- aztecSlotDuration: 36,
82
- aztecEpochDuration: 32,
83
- aztecTargetCommitteeSize: 48,
84
- lagInEpochsForValidatorSet: 2,
85
- lagInEpochsForRandao: 2, // For PROD, this value should be > lagInEpochsForValidatorSet
86
- inboxLag: 1, // Default inbox lag to prevent sequencer DOS attacks
87
- aztecProofSubmissionEpochs: 1, // you have a full epoch to submit a proof after the epoch to prove ends
88
- activationThreshold: 100n * 10n ** 18n,
89
- ejectionThreshold: 50n * 10n ** 18n,
90
- localEjectionThreshold: 98n * 10n ** 18n,
91
- slashAmountSmall: 10n * 10n ** 18n,
92
- slashAmountMedium: 20n * 10n ** 18n,
93
- slashAmountLarge: 50n * 10n ** 18n,
94
- slashingRoundSizeInEpochs: 4,
95
- slashingLifetimeInRounds: 5,
96
- slashingExecutionDelayInRounds: 0, // round N may be submitted in round N + 1
97
- slashingVetoer: EthAddress.ZERO,
98
- governanceProposerRoundSize: 300,
99
- manaTarget: BigInt(100e6),
100
- provingCostPerMana: BigInt(100),
101
- exitDelaySeconds: 2 * 24 * 60 * 60,
102
- slasherFlavor: 'tally' as const,
103
- slashingOffsetInRounds: 2,
104
- slashingDisableDuration: 5 * 24 * 60 * 60, // 5 days in seconds
105
- } satisfies L1ContractsConfig;
106
-
82
+ /**
83
+ * Config mappings for L1ContractsConfig.
84
+ * Default values come from generated l1-contracts-defaults.json (source: defaults.yml).
85
+ * Real deployments use forge scripts which require explicit env vars (vm.envUint).
86
+ */
107
87
  export const l1ContractsConfigMappings: ConfigMappingsType<L1ContractsConfig> = {
108
88
  ethereumSlotDuration: {
109
89
  env: 'ETHEREUM_SLOT_DURATION',
110
90
  description: 'How many seconds an L1 slot lasts.',
111
- ...numberConfigHelper(DefaultL1ContractsConfig.ethereumSlotDuration),
91
+ ...numberConfigHelper(l1ContractsDefaultEnv.ETHEREUM_SLOT_DURATION),
112
92
  },
113
93
  aztecSlotDuration: {
114
94
  env: 'AZTEC_SLOT_DURATION',
115
95
  description: 'How many seconds an L2 slots lasts (must be multiple of ethereum slot duration).',
116
- ...numberConfigHelper(DefaultL1ContractsConfig.aztecSlotDuration),
96
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_SLOT_DURATION),
117
97
  },
118
98
  aztecEpochDuration: {
119
99
  env: 'AZTEC_EPOCH_DURATION',
120
100
  description: `How many L2 slots an epoch lasts (maximum AZTEC_MAX_EPOCH_DURATION).`,
121
- ...numberConfigHelper(DefaultL1ContractsConfig.aztecEpochDuration),
101
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_EPOCH_DURATION),
122
102
  },
123
103
  aztecTargetCommitteeSize: {
124
104
  env: 'AZTEC_TARGET_COMMITTEE_SIZE',
125
105
  description: 'The target validator committee size.',
126
- ...numberConfigHelper(DefaultL1ContractsConfig.aztecTargetCommitteeSize),
106
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_TARGET_COMMITTEE_SIZE),
127
107
  },
128
108
  lagInEpochsForValidatorSet: {
129
109
  env: 'AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET',
130
110
  description: 'The number of epochs to lag behind the current epoch for validator selection.',
131
- ...numberConfigHelper(DefaultL1ContractsConfig.lagInEpochsForValidatorSet),
111
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET),
132
112
  },
133
113
  lagInEpochsForRandao: {
134
114
  env: 'AZTEC_LAG_IN_EPOCHS_FOR_RANDAO',
135
115
  description: 'The number of epochs to lag behind the current epoch for randao selection.',
136
- ...numberConfigHelper(DefaultL1ContractsConfig.lagInEpochsForRandao),
116
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_LAG_IN_EPOCHS_FOR_RANDAO),
137
117
  },
138
118
  inboxLag: {
139
119
  env: 'AZTEC_INBOX_LAG',
140
120
  description: 'The number of checkpoints to lag in the inbox (prevents sequencer DOS attacks).',
141
- ...numberConfigHelper(DefaultL1ContractsConfig.inboxLag),
121
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_INBOX_LAG),
142
122
  },
143
123
  aztecProofSubmissionEpochs: {
144
124
  env: 'AZTEC_PROOF_SUBMISSION_EPOCHS',
145
125
  description: 'The number of epochs after an epoch ends that proofs are still accepted.',
146
- ...numberConfigHelper(DefaultL1ContractsConfig.aztecProofSubmissionEpochs),
126
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_PROOF_SUBMISSION_EPOCHS),
147
127
  },
148
128
  activationThreshold: {
149
129
  env: 'AZTEC_ACTIVATION_THRESHOLD',
150
130
  description: 'The deposit amount for a validator',
151
- ...bigintConfigHelper(DefaultL1ContractsConfig.activationThreshold),
131
+ ...bigintConfigHelper(BigInt(l1ContractsDefaultEnv.AZTEC_ACTIVATION_THRESHOLD)),
152
132
  },
153
133
  ejectionThreshold: {
154
134
  env: 'AZTEC_EJECTION_THRESHOLD',
155
135
  description: 'The minimum stake for a validator.',
156
- ...bigintConfigHelper(DefaultL1ContractsConfig.ejectionThreshold),
136
+ ...bigintConfigHelper(BigInt(l1ContractsDefaultEnv.AZTEC_EJECTION_THRESHOLD)),
157
137
  },
158
138
  localEjectionThreshold: {
159
139
  env: 'AZTEC_LOCAL_EJECTION_THRESHOLD',
160
140
  description:
161
141
  'The local ejection threshold for a validator. Stricter than ejectionThreshold but local to a specific rollup',
162
- ...bigintConfigHelper(DefaultL1ContractsConfig.localEjectionThreshold),
142
+ ...bigintConfigHelper(BigInt(l1ContractsDefaultEnv.AZTEC_LOCAL_EJECTION_THRESHOLD)),
163
143
  },
164
144
  slashingOffsetInRounds: {
165
145
  env: 'AZTEC_SLASHING_OFFSET_IN_ROUNDS',
166
146
  description:
167
147
  'How many slashing rounds back we slash (ie when slashing in round N, we slash for offenses committed during epochs of round N-offset)',
168
- ...numberConfigHelper(DefaultL1ContractsConfig.slashingOffsetInRounds),
148
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_SLASHING_OFFSET_IN_ROUNDS),
169
149
  },
170
150
  slasherFlavor: {
171
151
  env: 'AZTEC_SLASHER_FLAVOR',
172
152
  description: 'Type of slasher proposer (empire, tally, or none)',
173
- ...enumConfigHelper(['empire', 'tally', 'none'] as const, DefaultL1ContractsConfig.slasherFlavor),
153
+ ...enumConfigHelper(
154
+ ['empire', 'tally', 'none'] as const,
155
+ l1ContractsDefaultEnv.AZTEC_SLASHER_FLAVOR as 'empire' | 'tally' | 'none',
156
+ ),
174
157
  },
175
158
  slashAmountSmall: {
176
159
  env: 'AZTEC_SLASH_AMOUNT_SMALL',
177
160
  description: 'Small slashing amount for light offenses',
178
- ...bigintConfigHelper(DefaultL1ContractsConfig.slashAmountSmall),
161
+ ...bigintConfigHelper(BigInt(l1ContractsDefaultEnv.AZTEC_SLASH_AMOUNT_SMALL)),
179
162
  },
180
163
  slashAmountMedium: {
181
164
  env: 'AZTEC_SLASH_AMOUNT_MEDIUM',
182
165
  description: 'Medium slashing amount for moderate offenses',
183
- ...bigintConfigHelper(DefaultL1ContractsConfig.slashAmountMedium),
166
+ ...bigintConfigHelper(BigInt(l1ContractsDefaultEnv.AZTEC_SLASH_AMOUNT_MEDIUM)),
184
167
  },
185
168
  slashAmountLarge: {
186
169
  env: 'AZTEC_SLASH_AMOUNT_LARGE',
187
170
  description: 'Large slashing amount for severe offenses',
188
- ...bigintConfigHelper(DefaultL1ContractsConfig.slashAmountLarge),
171
+ ...bigintConfigHelper(BigInt(l1ContractsDefaultEnv.AZTEC_SLASH_AMOUNT_LARGE)),
189
172
  },
190
173
  slashingQuorum: {
191
174
  env: 'AZTEC_SLASHING_QUORUM',
@@ -195,28 +178,28 @@ export const l1ContractsConfigMappings: ConfigMappingsType<L1ContractsConfig> =
195
178
  slashingRoundSizeInEpochs: {
196
179
  env: 'AZTEC_SLASHING_ROUND_SIZE_IN_EPOCHS',
197
180
  description: 'The slashing round size',
198
- ...numberConfigHelper(DefaultL1ContractsConfig.slashingRoundSizeInEpochs),
181
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_SLASHING_ROUND_SIZE_IN_EPOCHS),
199
182
  },
200
183
  slashingLifetimeInRounds: {
201
184
  env: 'AZTEC_SLASHING_LIFETIME_IN_ROUNDS',
202
185
  description: 'The slashing lifetime in rounds',
203
- ...numberConfigHelper(DefaultL1ContractsConfig.slashingLifetimeInRounds),
186
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_SLASHING_LIFETIME_IN_ROUNDS),
204
187
  },
205
188
  slashingExecutionDelayInRounds: {
206
189
  env: 'AZTEC_SLASHING_EXECUTION_DELAY_IN_ROUNDS',
207
190
  description: 'The slashing execution delay in rounds',
208
- ...numberConfigHelper(DefaultL1ContractsConfig.slashingExecutionDelayInRounds),
191
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_SLASHING_EXECUTION_DELAY_IN_ROUNDS),
209
192
  },
210
193
  slashingVetoer: {
211
194
  env: 'AZTEC_SLASHING_VETOER',
212
195
  description: 'The slashing vetoer',
213
196
  parseEnv: (val: string) => EthAddress.fromString(val),
214
- defaultValue: DefaultL1ContractsConfig.slashingVetoer,
197
+ defaultValue: EthAddress.fromString(l1ContractsDefaultEnv.AZTEC_SLASHING_VETOER),
215
198
  },
216
199
  slashingDisableDuration: {
217
200
  env: 'AZTEC_SLASHING_DISABLE_DURATION',
218
201
  description: 'How long slashing can be disabled for in seconds when vetoer disables it',
219
- ...numberConfigHelper(DefaultL1ContractsConfig.slashingDisableDuration),
202
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_SLASHING_DISABLE_DURATION),
220
203
  },
221
204
  governanceProposerQuorum: {
222
205
  env: 'AZTEC_GOVERNANCE_PROPOSER_QUORUM',
@@ -226,26 +209,37 @@ export const l1ContractsConfigMappings: ConfigMappingsType<L1ContractsConfig> =
226
209
  governanceProposerRoundSize: {
227
210
  env: 'AZTEC_GOVERNANCE_PROPOSER_ROUND_SIZE',
228
211
  description: 'The governance proposing round size',
229
- ...numberConfigHelper(DefaultL1ContractsConfig.governanceProposerRoundSize),
212
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_GOVERNANCE_PROPOSER_ROUND_SIZE),
213
+ },
214
+ governanceVotingDuration: {
215
+ env: 'AZTEC_GOVERNANCE_VOTING_DURATION',
216
+ description: 'Governance voting duration in seconds (only for local/devnet/next-net)',
217
+ ...numberConfigHelper(3600), // 1 hour default, not in generated defaults as it's deployment-time only
230
218
  },
231
219
  manaTarget: {
232
220
  env: 'AZTEC_MANA_TARGET',
233
221
  description: 'The mana target for the rollup',
234
- ...bigintConfigHelper(DefaultL1ContractsConfig.manaTarget),
222
+ ...bigintConfigHelper(BigInt(l1ContractsDefaultEnv.AZTEC_MANA_TARGET)),
235
223
  },
236
224
  provingCostPerMana: {
237
225
  env: 'AZTEC_PROVING_COST_PER_MANA',
238
226
  description: 'The proving cost per mana',
239
- ...bigintConfigHelper(DefaultL1ContractsConfig.provingCostPerMana),
227
+ ...bigintConfigHelper(BigInt(l1ContractsDefaultEnv.AZTEC_PROVING_COST_PER_MANA)),
240
228
  },
241
229
  exitDelaySeconds: {
242
230
  env: 'AZTEC_EXIT_DELAY_SECONDS',
243
231
  description: 'The delay before a validator can exit the set',
244
- ...numberConfigHelper(DefaultL1ContractsConfig.exitDelaySeconds),
232
+ ...numberConfigHelper(l1ContractsDefaultEnv.AZTEC_EXIT_DELAY_SECONDS),
245
233
  },
246
234
  ...l1TxUtilsConfigMappings,
247
235
  };
248
236
 
237
+ /**
238
+ * Default L1 contracts configuration derived from l1ContractsConfigMappings.
239
+ * Source of truth: spartan/environments/defaults.yml -> defaults.l1-contracts
240
+ */
241
+ export const DefaultL1ContractsConfig = getDefaultConfig(l1ContractsConfigMappings);
242
+
249
243
  export const genesisStateConfigMappings: ConfigMappingsType<GenesisStateConfig> = {
250
244
  testAccounts: {
251
245
  env: 'TEST_ACCOUNTS',
@@ -0,0 +1,157 @@
1
+ # L1 Contract Wrappers
2
+
3
+ This folder contains TypeScript wrappers for L1 contracts defined in `l1-contracts/`. These wrappers are used by the node client to interact with the rollup and related contracts on Ethereum.
4
+
5
+ ## Purpose
6
+
7
+ The goal of wrapping is to shield consumers from L1-specific and viem-specific details. Clients using these wrappers interact with domain types and branded types native to the Aztec codebase, without needing to understand viem's ABI type system or deal with raw types like `Hex` and `bigint`.
8
+
9
+ ## Type Safety
10
+
11
+ ### Explicit Return Types
12
+
13
+ Every function in the contract wrappers must declare its return type explicitly. This is critical because viem's type inference over ABI types is slow and significantly impacts IDE performance.
14
+
15
+ ```typescript
16
+ // Good: Explicit return type
17
+ async getSlotNumber(): Promise<SlotNumber> {
18
+ return SlotNumber.fromBigInt(await this.rollup.read.getCurrentSlot());
19
+ }
20
+
21
+ // Bad: Inferred return type (slow)
22
+ async getSlotNumber() {
23
+ return SlotNumber.fromBigInt(await this.rollup.read.getCurrentSlot());
24
+ }
25
+ ```
26
+
27
+ ### Branded and Domain Types
28
+
29
+ Use branded types and domain-specific types instead of viem's autogenerated types for both arguments and return values:
30
+
31
+ - `CheckpointNumber`, `EpochNumber`, `SlotNumber` instead of `bigint`
32
+ - `EthAddress` instead of `` `0x${string}` `` or `Hex`
33
+ - `Fr`, `Buffer32` instead of `Hex` for hashes and field elements
34
+ - Custom domain types (e.g., `CheckpointLog`, `AttesterView`) instead of raw tuples
35
+
36
+ Type conversions happen inside wrapper methods, not at the call site:
37
+
38
+ ```typescript
39
+ async getCheckpoint(checkpointNumber: CheckpointNumber): Promise<CheckpointLog> {
40
+ const result = await this.rollup.read.getCheckpoint([BigInt(checkpointNumber)]);
41
+ return {
42
+ archive: Fr.fromString(result.archive),
43
+ headerHash: Buffer32.fromString(result.headerHash),
44
+ blockCount: result.blockCount,
45
+ };
46
+ }
47
+ ```
48
+
49
+ ## Wrapper Pattern
50
+
51
+ ### Basic Structure
52
+
53
+ Each wrapper follows a consistent structure:
54
+
55
+ ```typescript
56
+ export class FooContract {
57
+ private readonly foo: GetContractReturnType<typeof FooAbi, ViemClient>;
58
+
59
+ constructor(
60
+ public readonly client: ViemClient,
61
+ address: Hex | EthAddress,
62
+ ) {
63
+ if (address instanceof EthAddress) {
64
+ address = address.toString();
65
+ }
66
+ this.foo = getContract({ address, abi: FooAbi, client });
67
+ }
68
+
69
+ public get address(): Hex {
70
+ return this.foo.address;
71
+ }
72
+
73
+ public getContract(): GetContractReturnType<typeof FooAbi, ViemClient> {
74
+ return this.foo;
75
+ }
76
+ }
77
+ ```
78
+
79
+ The raw contract is exposed via `getContract()` for cases where direct access is needed, but most consumers should use the typed wrapper methods. Relying on `getContract()` is a code smell and should be avoided.
80
+
81
+ ### Static Factory Methods
82
+
83
+ Wrappers may provide static factory methods for common initialization patterns:
84
+
85
+ - `getFromConfig(config)` - construct from configuration object
86
+ - `getFromL1ContractsValues(deployResult)` - construct from deployment result
87
+
88
+ ### Wallet Assertions
89
+
90
+ For write operations that require a wallet, use an assertion helper:
91
+
92
+ ```typescript
93
+ private assertWallet(): GetContractReturnType<typeof FooAbi, ExtendedViemWalletClient> {
94
+ if (!isExtendedClient(this.client)) {
95
+ throw new Error('Wallet client is required for this operation');
96
+ }
97
+ return this.foo as GetContractReturnType<typeof FooAbi, ExtendedViemWalletClient>;
98
+ }
99
+ ```
100
+
101
+ ## Event Handling
102
+
103
+ ### Event Log Types
104
+
105
+ Event logs are wrapped in `L1EventLog<T>` to include L1 block context:
106
+
107
+ ```typescript
108
+ type L1EventLog<T> = {
109
+ l1BlockNumber: bigint;
110
+ l1BlockHash: Buffer32;
111
+ l1TransactionHash: Hex;
112
+ args: T;
113
+ };
114
+ ```
115
+
116
+ ### Event Fetching
117
+
118
+ Methods that fetch events convert viem's raw logs to domain types:
119
+
120
+ ```typescript
121
+ async getCheckpointProposedEvents(fromBlock: bigint, toBlock: bigint): Promise<CheckpointProposedLog[]> {
122
+ const logs = await this.rollup.getEvents.CheckpointProposed({}, { fromBlock, toBlock });
123
+ return logs.map(log => ({
124
+ l1BlockNumber: log.blockNumber!,
125
+ l1BlockHash: Buffer32.fromString(log.blockHash!),
126
+ l1TransactionHash: log.transactionHash!,
127
+ args: {
128
+ checkpointNumber: CheckpointNumber.fromBigInt(log.args.checkpointNumber!),
129
+ // ... convert other fields
130
+ },
131
+ }));
132
+ }
133
+ ```
134
+
135
+ ### Event Listeners
136
+
137
+ For reactive event handling, wrapper methods convert arguments before invoking callbacks:
138
+
139
+ ```typescript
140
+ public listenToCheckpointInvalidated(
141
+ callback: (args: { checkpointNumber: CheckpointNumber }) => unknown,
142
+ ): WatchContractEventReturnType {
143
+ return this.rollup.watchEvent.CheckpointInvalidated({}, {
144
+ onLogs: logs => {
145
+ for (const log of logs) {
146
+ if (log.args.checkpointNumber !== undefined) {
147
+ callback({ checkpointNumber: CheckpointNumber.fromBigInt(log.args.checkpointNumber) });
148
+ }
149
+ }
150
+ },
151
+ });
152
+ }
153
+ ```
154
+
155
+ ## Error Handling
156
+
157
+ Custom error classes in `errors.ts` extend `Error` and set `this.name` for proper error identification. Include relevant context as public readonly properties.
@@ -4,13 +4,14 @@ import { FeeAssetHandlerAbi } from '@aztec/l1-artifacts/FeeAssetHandlerAbi';
4
4
  import { type Hex, encodeFunctionData, getContract } from 'viem';
5
5
 
6
6
  import type { L1TxUtils } from '../l1_tx_utils/index.js';
7
+ import type { ViemClient } from '../types.js';
7
8
 
8
9
  export class FeeAssetHandlerContract {
9
10
  public address: EthAddress;
10
11
 
11
12
  constructor(
13
+ public readonly client: ViemClient,
12
14
  address: Hex | EthAddress,
13
- public readonly txUtils: L1TxUtils,
14
15
  ) {
15
16
  if (address instanceof EthAddress) {
16
17
  address = address.toString();
@@ -22,7 +23,7 @@ export class FeeAssetHandlerContract {
22
23
  const contract = getContract({
23
24
  abi: FeeAssetHandlerAbi,
24
25
  address: this.address.toString(),
25
- client: this.txUtils.client,
26
+ client: this.client,
26
27
  });
27
28
  return EthAddress.fromString(await contract.read.owner());
28
29
  }
@@ -31,16 +32,16 @@ export class FeeAssetHandlerContract {
31
32
  const contract = getContract({
32
33
  abi: FeeAssetHandlerAbi,
33
34
  address: this.address.toString(),
34
- client: this.txUtils.client,
35
+ client: this.client,
35
36
  });
36
37
  return contract.read.mintAmount();
37
38
  }
38
39
 
39
- public mint(recipient: Hex | EthAddress) {
40
+ public mint(txUtils: L1TxUtils, recipient: Hex | EthAddress) {
40
41
  if (recipient instanceof EthAddress) {
41
42
  recipient = recipient.toString();
42
43
  }
43
- return this.txUtils.sendAndMonitorTransaction({
44
+ return txUtils.sendAndMonitorTransaction({
44
45
  to: this.address.toString(),
45
46
  data: encodeFunctionData({
46
47
  abi: FeeAssetHandlerAbi,
@@ -50,8 +51,8 @@ export class FeeAssetHandlerContract {
50
51
  });
51
52
  }
52
53
 
53
- public setMintAmount(amount: bigint) {
54
- return this.txUtils.sendAndMonitorTransaction({
54
+ public setMintAmount(txUtils: L1TxUtils, amount: bigint) {
55
+ return txUtils.sendAndMonitorTransaction({
55
56
  to: this.address.toString(),
56
57
  data: encodeFunctionData({
57
58
  abi: FeeAssetHandlerAbi,
@@ -1,4 +1,6 @@
1
- import { Buffer16 } from '@aztec/foundation/buffer';
1
+ import { CheckpointNumber } from '@aztec/foundation/branded-types';
2
+ import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
4
  import { EthAddress } from '@aztec/foundation/eth-address';
3
5
  import { InboxAbi } from '@aztec/l1-artifacts/InboxAbi';
4
6
 
@@ -8,8 +10,20 @@ import { getPublicClient } from '../client.js';
8
10
  import type { DeployAztecL1ContractsReturnType } from '../deploy_aztec_l1_contracts.js';
9
11
  import type { L1ReaderConfig } from '../l1_reader.js';
10
12
  import type { ViemClient } from '../types.js';
13
+ import type { L1EventLog } from './log.js';
11
14
  import { checkBlockTag } from './utils.js';
12
15
 
16
+ /** Arguments for the MessageSent event. */
17
+ export type MessageSentArgs = {
18
+ index: bigint;
19
+ leaf: Fr;
20
+ checkpointNumber: CheckpointNumber;
21
+ rollingHash: Buffer16;
22
+ };
23
+
24
+ /** Log type for MessageSent events. */
25
+ export type MessageSentLog = L1EventLog<MessageSentArgs>;
26
+
13
27
  export class InboxContract {
14
28
  private readonly inbox: GetContractReturnType<typeof InboxAbi, ViemClient>;
15
29
 
@@ -59,6 +73,39 @@ export class InboxContract {
59
73
  treeInProgress: state.inProgress,
60
74
  };
61
75
  }
76
+
77
+ /** Fetches MessageSent events within the given block range. */
78
+ async getMessageSentEvents(fromBlock: bigint, toBlock: bigint): Promise<MessageSentLog[]> {
79
+ const logs = await this.inbox.getEvents.MessageSent({}, { fromBlock, toBlock });
80
+ return logs
81
+ .filter(log => log.blockNumber! >= fromBlock && log.blockNumber! <= toBlock)
82
+ .map(log => this.mapMessageSentLog(log));
83
+ }
84
+
85
+ /** Fetches MessageSent events for a specific message hash within the given block range. */
86
+ async getMessageSentEventByHash(hash: Hex, fromBlock: bigint, toBlock: bigint): Promise<MessageSentLog[]> {
87
+ const logs = await this.inbox.getEvents.MessageSent({ hash }, { fromBlock, toBlock });
88
+ return logs.map(log => this.mapMessageSentLog(log));
89
+ }
90
+
91
+ private mapMessageSentLog(log: {
92
+ blockNumber: bigint | null;
93
+ blockHash: `0x${string}` | null;
94
+ transactionHash: `0x${string}` | null;
95
+ args: { index?: bigint; hash?: `0x${string}`; checkpointNumber?: bigint; rollingHash?: `0x${string}` };
96
+ }): MessageSentLog {
97
+ return {
98
+ l1BlockNumber: log.blockNumber!,
99
+ l1BlockHash: Buffer32.fromString(log.blockHash!),
100
+ l1TransactionHash: log.transactionHash!,
101
+ args: {
102
+ index: log.args.index!,
103
+ leaf: Fr.fromString(log.args.hash!),
104
+ checkpointNumber: CheckpointNumber.fromBigInt(log.args.checkpointNumber!),
105
+ rollingHash: Buffer16.fromString(log.args.rollingHash!),
106
+ },
107
+ };
108
+ }
62
109
  }
63
110
 
64
111
  export type InboxContractState = {
@@ -6,7 +6,9 @@ export * from './governance.js';
6
6
  export * from './governance_proposer.js';
7
7
  export * from './gse.js';
8
8
  export * from './inbox.js';
9
+ export * from './log.js';
9
10
  export * from './multicall.js';
11
+ export * from './outbox.js';
10
12
  export * from './registry.js';
11
13
  export * from './rollup.js';
12
14
  export * from './empire_slashing_proposer.js';
@@ -0,0 +1,13 @@
1
+ import type { Buffer32 } from '@aztec/foundation/buffer';
2
+
3
+ /** Base L1 event log with common fields. */
4
+ export type L1EventLog<T> = {
5
+ /** L1 block number where the event was emitted. */
6
+ l1BlockNumber: bigint;
7
+ /** L1 block hash. */
8
+ l1BlockHash: Buffer32;
9
+ /** L1 transaction hash that emitted the event. */
10
+ l1TransactionHash: `0x${string}`;
11
+ /** Event-specific arguments. */
12
+ args: T;
13
+ };