@aztec/ethereum 0.0.1-commit.f2ce05ee → 0.0.1-commit.f5a9928

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 (181) hide show
  1. package/dest/client.d.ts +27 -3
  2. package/dest/client.d.ts.map +1 -1
  3. package/dest/client.js +63 -8
  4. package/dest/config.d.ts +17 -6
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +38 -10
  7. package/dest/contracts/chain_state_override.d.ts +78 -0
  8. package/dest/contracts/chain_state_override.d.ts.map +1 -0
  9. package/dest/contracts/chain_state_override.js +137 -0
  10. package/dest/contracts/fee_asset_price_oracle.d.ts +105 -0
  11. package/dest/contracts/fee_asset_price_oracle.d.ts.map +1 -0
  12. package/dest/contracts/fee_asset_price_oracle.js +656 -0
  13. package/dest/contracts/governance.d.ts +135 -35
  14. package/dest/contracts/governance.d.ts.map +1 -1
  15. package/dest/contracts/governance.js +229 -18
  16. package/dest/contracts/governance_proposer.d.ts +33 -2
  17. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  18. package/dest/contracts/governance_proposer.js +54 -6
  19. package/dest/contracts/gse.d.ts +4 -2
  20. package/dest/contracts/gse.d.ts.map +1 -1
  21. package/dest/contracts/gse.js +2 -2
  22. package/dest/contracts/inbox.d.ts +3 -3
  23. package/dest/contracts/inbox.d.ts.map +1 -1
  24. package/dest/contracts/inbox.js +12 -7
  25. package/dest/contracts/index.d.ts +4 -3
  26. package/dest/contracts/index.d.ts.map +1 -1
  27. package/dest/contracts/index.js +3 -2
  28. package/dest/contracts/multicall.d.ts +127 -12
  29. package/dest/contracts/multicall.d.ts.map +1 -1
  30. package/dest/contracts/multicall.js +201 -94
  31. package/dest/contracts/outbox.d.ts +27 -4
  32. package/dest/contracts/outbox.d.ts.map +1 -1
  33. package/dest/contracts/outbox.js +34 -7
  34. package/dest/contracts/registry.d.ts +3 -1
  35. package/dest/contracts/registry.d.ts.map +1 -1
  36. package/dest/contracts/registry.js +30 -1
  37. package/dest/contracts/rollup.d.ts +5437 -34
  38. package/dest/contracts/rollup.d.ts.map +1 -1
  39. package/dest/contracts/rollup.js +448 -104
  40. package/dest/contracts/slashing_proposer.d.ts +171 -0
  41. package/dest/contracts/slashing_proposer.d.ts.map +1 -0
  42. package/dest/contracts/slashing_proposer.js +753 -0
  43. package/dest/contracts/watch_event.d.ts +36 -0
  44. package/dest/contracts/watch_event.d.ts.map +1 -0
  45. package/dest/contracts/watch_event.js +66 -0
  46. package/dest/deploy_aztec_l1_contracts.d.ts +5 -9
  47. package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
  48. package/dest/deploy_aztec_l1_contracts.js +48 -27
  49. package/dest/deploy_l1_contract.js +3 -3
  50. package/dest/foundry_binary.d.ts +13 -0
  51. package/dest/foundry_binary.d.ts.map +1 -0
  52. package/dest/foundry_binary.js +52 -0
  53. package/dest/generated/l1-contracts-defaults.d.ts +3 -3
  54. package/dest/generated/l1-contracts-defaults.js +3 -3
  55. package/dest/l1_artifacts.d.ts +15524 -15847
  56. package/dest/l1_artifacts.d.ts.map +1 -1
  57. package/dest/l1_artifacts.js +9 -24
  58. package/dest/l1_contract_addresses.d.ts +61 -65
  59. package/dest/l1_contract_addresses.d.ts.map +1 -1
  60. package/dest/l1_contract_addresses.js +101 -82
  61. package/dest/l1_reader.d.ts +5 -5
  62. package/dest/l1_reader.d.ts.map +1 -1
  63. package/dest/l1_reader.js +9 -7
  64. package/dest/l1_tx_utils/config.d.ts +7 -1
  65. package/dest/l1_tx_utils/config.d.ts.map +1 -1
  66. package/dest/l1_tx_utils/config.js +17 -4
  67. package/dest/l1_tx_utils/factory.d.ts +18 -10
  68. package/dest/l1_tx_utils/factory.d.ts.map +1 -1
  69. package/dest/l1_tx_utils/factory.js +17 -7
  70. package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +1 -1
  71. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +1 -1
  72. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +15 -15
  73. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -1
  74. package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +9 -15
  75. package/dest/l1_tx_utils/index-blobs.d.ts +3 -3
  76. package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -1
  77. package/dest/l1_tx_utils/index-blobs.js +2 -2
  78. package/dest/l1_tx_utils/index.d.ts +2 -1
  79. package/dest/l1_tx_utils/index.d.ts.map +1 -1
  80. package/dest/l1_tx_utils/index.js +1 -0
  81. package/dest/l1_tx_utils/l1_tx_utils.d.ts +26 -7
  82. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
  83. package/dest/l1_tx_utils/l1_tx_utils.js +156 -79
  84. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +1 -1
  85. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
  86. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +57 -23
  87. package/dest/l1_tx_utils/tx_delayer.d.ts +58 -0
  88. package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -0
  89. package/dest/{test → l1_tx_utils}/tx_delayer.js +67 -37
  90. package/dest/publisher_manager.d.ts +34 -8
  91. package/dest/publisher_manager.d.ts.map +1 -1
  92. package/dest/publisher_manager.js +119 -8
  93. package/dest/queries.d.ts +13 -2
  94. package/dest/queries.d.ts.map +1 -1
  95. package/dest/queries.js +62 -3
  96. package/dest/test/blob_kzg_warmup.d.ts +19 -0
  97. package/dest/test/blob_kzg_warmup.d.ts.map +1 -0
  98. package/dest/test/blob_kzg_warmup.js +64 -0
  99. package/dest/test/chain_monitor.d.ts +55 -4
  100. package/dest/test/chain_monitor.d.ts.map +1 -1
  101. package/dest/test/chain_monitor.js +104 -3
  102. package/dest/test/eth_cheat_codes.d.ts +31 -6
  103. package/dest/test/eth_cheat_codes.d.ts.map +1 -1
  104. package/dest/test/eth_cheat_codes.js +67 -44
  105. package/dest/test/index.d.ts +2 -3
  106. package/dest/test/index.d.ts.map +1 -1
  107. package/dest/test/index.js +1 -2
  108. package/dest/test/recording_rpc_server.d.ts +18 -0
  109. package/dest/test/recording_rpc_server.d.ts.map +1 -0
  110. package/dest/test/recording_rpc_server.js +68 -0
  111. package/dest/test/rollup_cheat_codes.d.ts +60 -3
  112. package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
  113. package/dest/test/rollup_cheat_codes.js +86 -7
  114. package/dest/test/start_anvil.d.ts +23 -3
  115. package/dest/test/start_anvil.d.ts.map +1 -1
  116. package/dest/test/start_anvil.js +182 -32
  117. package/dest/test/upgrade_utils.js +2 -2
  118. package/dest/utils.d.ts +9 -2
  119. package/dest/utils.d.ts.map +1 -1
  120. package/dest/utils.js +59 -24
  121. package/package.json +6 -8
  122. package/src/client.ts +72 -2
  123. package/src/config.ts +58 -14
  124. package/src/contracts/chain_state_override.ts +200 -0
  125. package/src/contracts/fee_asset_price_oracle.ts +285 -0
  126. package/src/contracts/governance.ts +313 -13
  127. package/src/contracts/governance_proposer.ts +58 -9
  128. package/src/contracts/gse.ts +7 -2
  129. package/src/contracts/inbox.ts +13 -5
  130. package/src/contracts/index.ts +3 -2
  131. package/src/contracts/multicall.ts +243 -105
  132. package/src/contracts/outbox.ts +42 -8
  133. package/src/contracts/registry.ts +31 -1
  134. package/src/contracts/rollup.ts +507 -109
  135. package/src/contracts/{tally_slashing_proposer.ts → slashing_proposer.ts} +119 -45
  136. package/src/contracts/watch_event.ts +110 -0
  137. package/src/deploy_aztec_l1_contracts.ts +75 -39
  138. package/src/deploy_l1_contract.ts +3 -3
  139. package/src/foundry_binary.ts +57 -0
  140. package/src/generated/l1-contracts-defaults.ts +3 -3
  141. package/src/l1_artifacts.ts +12 -35
  142. package/src/l1_contract_addresses.ts +120 -94
  143. package/src/l1_reader.ts +17 -10
  144. package/src/l1_tx_utils/config.ts +23 -3
  145. package/src/l1_tx_utils/factory.ts +31 -31
  146. package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +1 -1
  147. package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +1 -1
  148. package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +43 -54
  149. package/src/l1_tx_utils/index-blobs.ts +2 -2
  150. package/src/l1_tx_utils/index.ts +1 -0
  151. package/src/l1_tx_utils/l1_tx_utils.ts +149 -64
  152. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +57 -17
  153. package/src/{test → l1_tx_utils}/tx_delayer.ts +93 -56
  154. package/src/publisher_manager.ts +143 -12
  155. package/src/queries.ts +70 -4
  156. package/src/test/blob_kzg_warmup.ts +65 -0
  157. package/src/test/chain_monitor.ts +148 -3
  158. package/src/test/eth_cheat_codes.ts +63 -47
  159. package/src/test/index.ts +1 -2
  160. package/src/test/recording_rpc_server.ts +69 -0
  161. package/src/test/rollup_cheat_codes.ts +115 -6
  162. package/src/test/start_anvil.ts +212 -32
  163. package/src/test/upgrade_utils.ts +2 -2
  164. package/src/utils.ts +56 -29
  165. package/dest/contracts/empire_slashing_proposer.d.ts +0 -67
  166. package/dest/contracts/empire_slashing_proposer.d.ts.map +0 -1
  167. package/dest/contracts/empire_slashing_proposer.js +0 -207
  168. package/dest/contracts/tally_slashing_proposer.d.ts +0 -140
  169. package/dest/contracts/tally_slashing_proposer.d.ts.map +0 -1
  170. package/dest/contracts/tally_slashing_proposer.js +0 -320
  171. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +0 -26
  172. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +0 -1
  173. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +0 -26
  174. package/dest/test/delayed_tx_utils.d.ts +0 -13
  175. package/dest/test/delayed_tx_utils.d.ts.map +0 -1
  176. package/dest/test/delayed_tx_utils.js +0 -28
  177. package/dest/test/tx_delayer.d.ts +0 -36
  178. package/dest/test/tx_delayer.d.ts.map +0 -1
  179. package/src/contracts/empire_slashing_proposer.ts +0 -259
  180. package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +0 -77
  181. package/src/test/delayed_tx_utils.ts +0 -52
@@ -1,109 +1,216 @@
1
- import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
2
- import { TimeoutError } from '@aztec/foundation/error';
3
- import { encodeFunctionData, multicall3Abi } from 'viem';
4
- import { FormattedViemError, formatViemError } from '../utils.js';
5
- import { RollupContract } from './rollup.js';
1
+ import { EthAddress } from '@aztec/foundation/eth-address';
2
+ import { decodeFunctionResult, encodeFunctionData, multicall3Abi } from 'viem';
3
+ import { tryDecodeRevertReason } from '../utils.js';
6
4
  export const MULTI_CALL_3_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11';
5
+ /**
6
+ * Thrown by `Multicall3.forward` when the forwarder transaction lands but the receipt reports a
7
+ * reverted status. This is not expected (aggregate3 uses allowFailure: true), so callers should
8
+ * treat it as a fatal on-chain failure rather than retrying on a different publisher.
9
+ */ export class MulticallForwarderRevertedError extends Error {
10
+ receipt;
11
+ constructor(receipt){
12
+ super(`Multicall3 forwarder tx reverted: ${receipt.transactionHash}`), this.receipt = receipt;
13
+ this.name = 'MulticallForwarderRevertedError';
14
+ }
15
+ }
16
+ /** ABI fragment for aggregate3Value — not included in viem's multicall3Abi. */ export const aggregate3ValueAbi = [
17
+ {
18
+ inputs: [
19
+ {
20
+ components: [
21
+ {
22
+ internalType: 'address',
23
+ name: 'target',
24
+ type: 'address'
25
+ },
26
+ {
27
+ internalType: 'bool',
28
+ name: 'allowFailure',
29
+ type: 'bool'
30
+ },
31
+ {
32
+ internalType: 'uint256',
33
+ name: 'value',
34
+ type: 'uint256'
35
+ },
36
+ {
37
+ internalType: 'bytes',
38
+ name: 'callData',
39
+ type: 'bytes'
40
+ }
41
+ ],
42
+ internalType: 'struct Multicall3.Call3Value[]',
43
+ name: 'calls',
44
+ type: 'tuple[]'
45
+ }
46
+ ],
47
+ name: 'aggregate3Value',
48
+ outputs: [
49
+ {
50
+ components: [
51
+ {
52
+ internalType: 'bool',
53
+ name: 'success',
54
+ type: 'bool'
55
+ },
56
+ {
57
+ internalType: 'bytes',
58
+ name: 'returnData',
59
+ type: 'bytes'
60
+ }
61
+ ],
62
+ internalType: 'struct Multicall3.Result[]',
63
+ name: 'returnData',
64
+ type: 'tuple[]'
65
+ }
66
+ ],
67
+ stateMutability: 'payable',
68
+ type: 'function'
69
+ }
70
+ ];
7
71
  export class Multicall3 {
8
- static async forward(requests, l1TxUtils, gasConfig, blobConfig, rollupAddress, logger, opts = {}) {
9
- requests = requests.filter((request)=>request.to !== null);
10
- const args = requests.map((r)=>({
72
+ /**
73
+ * Returns true iff Multicall3 bytecode is deployed at MULTI_CALL_3_ADDRESS. An empty result from
74
+ * a non-existent contract would otherwise silently validate any bundle that uses Multicall3.
75
+ */ static async hasCode(l1TxUtils) {
76
+ const code = await l1TxUtils.getCode(EthAddress.fromString(MULTI_CALL_3_ADDRESS));
77
+ return !!code && code !== '0x';
78
+ }
79
+ /**
80
+ * Simulates an aggregate3 call composed of the given requests via eth_simulateV1 and decodes the
81
+ * per-entry Result[]. Entries that revert are returned with a decoded revertReason (if the request
82
+ * provided an abi).
83
+ *
84
+ * Use this to pre-validate a bundle before sending it through `Multicall3.forward`. The caller can
85
+ * drop reverted entries from the bundle and re-simulate with the reduced list to get an accurate
86
+ * `gasUsed`.
87
+ */ static async simulateAggregate3(requests, l1TxUtils, opts = {}) {
88
+ const calldata = encodeFunctionData({
89
+ abi: multicall3Abi,
90
+ functionName: 'aggregate3',
91
+ args: [
92
+ requests.map((r)=>({
93
+ target: r.to,
94
+ callData: r.data,
95
+ allowFailure: true
96
+ }))
97
+ ]
98
+ });
99
+ const stateOverrides = [
100
+ ...opts.stateOverrides ?? []
101
+ ];
102
+ if (opts.fakeSenderBalance !== undefined) {
103
+ stateOverrides.push({
104
+ address: l1TxUtils.getSenderAddress().toString(),
105
+ balance: opts.fakeSenderBalance
106
+ });
107
+ }
108
+ const simResult = await l1TxUtils.simulate({
109
+ to: MULTI_CALL_3_ADDRESS,
110
+ data: calldata,
111
+ gas: opts.gas
112
+ }, opts.blockOverrides, stateOverrides, multicall3Abi, {
113
+ fallbackGasEstimate: opts.fallbackGasEstimate
114
+ });
115
+ if (simResult.result === '0x') {
116
+ return {
117
+ kind: 'fallback',
118
+ gasUsed: simResult.gasUsed
119
+ };
120
+ }
121
+ const decoded = decodeFunctionResult({
122
+ abi: multicall3Abi,
123
+ functionName: 'aggregate3',
124
+ data: simResult.result
125
+ });
126
+ const entries = decoded.map((entry, i)=>{
127
+ if (entry.success) {
128
+ return {
129
+ success: true,
130
+ returnData: entry.returnData
131
+ };
132
+ }
133
+ const abi = requests[i].abi;
134
+ const revertReason = abi ? tryDecodeRevertReason(entry.returnData, abi) : undefined;
135
+ return {
136
+ success: false,
137
+ returnData: entry.returnData,
138
+ revertReason
139
+ };
140
+ });
141
+ return {
142
+ kind: 'decoded',
143
+ entries,
144
+ gasUsed: simResult.gasUsed
145
+ };
146
+ }
147
+ /**
148
+ * Sends a batch of requests through aggregate3. Individual calls may fail (allowFailure: true),
149
+ * but the top-level multicall is expected to land successfully. Throws if the send fails or if
150
+ * the receipt reports a reverted status.
151
+ */ static async forward(requests, l1TxUtils, gasConfig, blobConfig, opts = {}) {
152
+ if (opts.gasLimitRequired && !gasConfig?.gasLimit) {
153
+ throw new Error('Multicall gasLimit is required when gasLimitRequired is true');
154
+ }
155
+ const args = requests.filter((request)=>request.to !== null).map((r)=>({
11
156
  target: r.to,
12
157
  callData: r.data,
13
- allowFailure: !opts.revertOnFailure
158
+ allowFailure: true
14
159
  }));
15
- const forwarderFunctionData = {
160
+ const encodedForwarderData = encodeFunctionData({
16
161
  abi: multicall3Abi,
17
162
  functionName: 'aggregate3',
18
163
  args: [
19
164
  args
20
165
  ]
166
+ });
167
+ const { receipt } = await l1TxUtils.sendAndMonitorTransaction({
168
+ to: MULTI_CALL_3_ADDRESS,
169
+ data: encodedForwarderData,
170
+ abi: multicall3Abi
171
+ }, gasConfig, blobConfig);
172
+ // This shouldn't happen. Any failure in individual calls is swallowed by forward since we set
173
+ // allowFailure to true for all calls, so a reverted status here would indicate a problem with
174
+ // the Multicall3 contract itself or the forwarder transaction (such as an out-of-gas).
175
+ if (receipt.status !== 'success') {
176
+ throw new MulticallForwarderRevertedError(receipt);
177
+ }
178
+ const stats = await l1TxUtils.getTransactionStats(receipt.transactionHash);
179
+ return {
180
+ receipt,
181
+ stats,
182
+ multicallData: encodedForwarderData
21
183
  };
22
- const encodedForwarderData = encodeFunctionData(forwarderFunctionData);
23
- try {
24
- const { receipt, state } = await l1TxUtils.sendAndMonitorTransaction({
25
- to: MULTI_CALL_3_ADDRESS,
26
- data: encodedForwarderData,
27
- abi: multicall3Abi
28
- }, gasConfig, blobConfig);
29
- if (receipt.status === 'success') {
30
- const stats = await l1TxUtils.getTransactionStats(receipt.transactionHash);
31
- return {
32
- receipt,
33
- stats
34
- };
35
- } else {
36
- logger.error('Forwarder transaction failed', undefined, {
37
- receipt
38
- });
39
- const args = {
40
- ...forwarderFunctionData,
41
- address: MULTI_CALL_3_ADDRESS
42
- };
43
- let errorMsg;
44
- if (blobConfig) {
45
- const maxFeePerBlobGas = blobConfig.maxFeePerBlobGas ?? state.gasPrice.maxFeePerBlobGas;
46
- if (maxFeePerBlobGas === undefined) {
47
- errorMsg = 'maxFeePerBlobGas is required to get the error message';
48
- } else {
49
- logger.debug('Trying to get error from reverted tx with blob config');
50
- errorMsg = await l1TxUtils.tryGetErrorFromRevertedTx(encodedForwarderData, args, {
51
- blobs: blobConfig.blobs,
52
- kzg: blobConfig.kzg,
53
- maxFeePerBlobGas
54
- }, [
55
- {
56
- address: rollupAddress,
57
- stateDiff: [
58
- {
59
- slot: toPaddedHex(RollupContract.checkBlobStorageSlot, true),
60
- value: toPaddedHex(0n, true)
61
- }
62
- ]
63
- }
64
- ]);
65
- }
66
- } else {
67
- logger.debug('Trying to get error from reverted tx without blob config');
68
- errorMsg = await l1TxUtils.tryGetErrorFromRevertedTx(encodedForwarderData, args, undefined, []);
69
- }
70
- return {
71
- receipt,
72
- errorMsg
73
- };
74
- }
75
- } catch (err) {
76
- if (err instanceof TimeoutError) {
77
- throw err;
78
- }
79
- for (const request of requests){
80
- logger.debug('Simulating request', {
81
- request
82
- });
83
- const result = await l1TxUtils.simulate(request, undefined, [
84
- {
85
- address: rollupAddress,
86
- stateDiff: [
87
- {
88
- slot: toPaddedHex(RollupContract.checkBlobStorageSlot, true),
89
- value: toPaddedHex(0n, true)
90
- }
91
- ]
92
- }
93
- ]).catch((err)=>formatViemError(err, request.abi));
94
- if (result instanceof FormattedViemError) {
95
- logger.error('Found error in simulation', result, {
96
- to: request.to ?? 'null',
97
- data: request.data
98
- });
99
- return result;
100
- }
101
- }
102
- logger.warn('Failed to get error from reverted tx', {
103
- err
104
- });
105
- throw err;
184
+ }
185
+ /** Batch multiple value transfers into a single aggregate3Value call on Multicall3. */ static async forwardValue(calls, l1TxUtils, logger) {
186
+ const args = calls.map((c)=>({
187
+ target: c.to,
188
+ allowFailure: false,
189
+ value: c.value,
190
+ callData: '0x'
191
+ }));
192
+ const data = encodeFunctionData({
193
+ abi: aggregate3ValueAbi,
194
+ functionName: 'aggregate3Value',
195
+ args: [
196
+ args
197
+ ]
198
+ });
199
+ const totalValue = calls.reduce((sum, c)=>sum + c.value, 0n);
200
+ logger.info(`Sending aggregate3Value with ${calls.length} calls`, {
201
+ totalValue
202
+ });
203
+ const { receipt } = await l1TxUtils.sendAndMonitorTransaction({
204
+ to: MULTI_CALL_3_ADDRESS,
205
+ data,
206
+ value: totalValue
207
+ });
208
+ if (receipt.status !== 'success') {
209
+ throw new Error(`aggregate3Value transaction reverted: ${receipt.transactionHash}`);
106
210
  }
211
+ return {
212
+ receipt
213
+ };
107
214
  }
108
215
  }
109
216
  export async function deployMulticall3(l1Client, logger) {
@@ -1,4 +1,5 @@
1
1
  import type { EpochNumber } from '@aztec/foundation/branded-types';
2
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
3
  import { EthAddress } from '@aztec/foundation/eth-address';
3
4
  import { OutboxAbi } from '@aztec/l1-artifacts/OutboxAbi';
4
5
  import { type GetContractReturnType, type Hex } from 'viem';
@@ -23,19 +24,41 @@ export declare class OutboxContract {
23
24
  private readonly outbox;
24
25
  static getFromL1ContractsValues(deployL1ContractsValues: DeployAztecL1ContractsReturnType): OutboxContract;
25
26
  static getFromConfig(config: L1ReaderConfig): OutboxContract;
26
- static getEpochRootStorageSlot(epoch: EpochNumber): bigint;
27
+ /**
28
+ * Storage slot of `epochs[epoch].roots[numCheckpointsInEpoch - 1]` in the Outbox contract.
29
+ *
30
+ * The Outbox lays out storage as `mapping(Epoch => EpochData) internal epochs` at base slot 0
31
+ * (ROLLUP and VERSION are immutable and do not occupy slots). For a mapping at slot `b`, the
32
+ * value for key `k` begins at `keccak256(abi.encode(k, b))`. `EpochData` starts with a fixed-
33
+ * size `bytes32[MAX_CHECKPOINTS_PER_EPOCH] roots` array, so `roots[i]` sits at the EpochData's
34
+ * base slot plus `i`. `numCheckpointsInEpoch` is 1-indexed (matches `Outbox.insert`/`consume`).
35
+ */
36
+ static getEpochRootStorageSlot(epoch: EpochNumber, numCheckpointsInEpoch: number): bigint;
27
37
  constructor(client: ViemClient, address: Hex | EthAddress);
28
38
  get address(): `0x${string}`;
29
39
  getContract(): GetContractReturnType<typeof OutboxAbi, ViemClient>;
30
40
  hasMessageBeenConsumedAtEpoch(epoch: EpochNumber, leafId: bigint): Promise<boolean>;
31
- getRootData(epoch: EpochNumber): Promise<`0x${string}`>;
32
- consume(message: ViemL2ToL1Msg, epoch: EpochNumber, leafIndex: bigint, path: Hex[]): Promise<`0x${string}`>;
41
+ getRootData(epoch: EpochNumber, numCheckpointsInEpoch: number): Promise<`0x${string}`>;
42
+ /**
43
+ * Returns every root stored for `epoch`. Slot `i` of the returned array holds the root inserted
44
+ * for `numCheckpointsInEpoch = i + 1`, or `Fr.ZERO` if no proof of that depth has been inserted
45
+ * yet. The array length is always `MAX_CHECKPOINTS_PER_EPOCH`.
46
+ *
47
+ * @param opts - Optional viem read options. Pass `blockNumber` to pin the read to a specific L1
48
+ * block, which is important for callers that want a consistent snapshot across multiple reads
49
+ * (e.g. the archiver's outbox-trees resolver, which pins to the node's synced L1 block).
50
+ */
51
+ getRoots(epoch: EpochNumber, opts?: {
52
+ blockNumber?: bigint;
53
+ }): Promise<Fr[]>;
54
+ consume(message: ViemL2ToL1Msg, epoch: EpochNumber, numCheckpointsInEpoch: number, leafIndex: bigint, path: Hex[]): Promise<`0x${string}`>;
33
55
  getMessageConsumedEvents(l1BlockHash: Hex): Promise<{
34
56
  epoch: bigint;
35
57
  root: Hex;
36
58
  messageHash: Hex;
37
59
  leafId: bigint;
60
+ numCheckpointsInEpoch: bigint;
38
61
  }[]>;
39
62
  private assertWallet;
40
63
  }
41
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym94LmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29udHJhY3RzL291dGJveC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDM0QsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTFELE9BQU8sRUFBRSxLQUFLLHFCQUFxQixFQUFFLEtBQUssR0FBRyxFQUE0RCxNQUFNLE1BQU0sQ0FBQztBQUd0SCxPQUFPLEtBQUssRUFBRSxnQ0FBZ0MsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3hGLE9BQU8sS0FBSyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3RELE9BQU8sRUFBaUMsS0FBSyxVQUFVLEVBQW9CLE1BQU0sYUFBYSxDQUFDO0FBRS9GLE1BQU0sTUFBTSxXQUFXLEdBQUc7SUFDeEIsS0FBSyxFQUFFLEdBQUcsQ0FBQztJQUNYLE9BQU8sRUFBRSxNQUFNLENBQUM7Q0FDakIsQ0FBQztBQUVGLE1BQU0sTUFBTSxXQUFXLEdBQUc7SUFDeEIsS0FBSyxFQUFFLEdBQUcsQ0FBQztJQUNYLE9BQU8sRUFBRSxNQUFNLENBQUM7Q0FDakIsQ0FBQztBQUVGLE1BQU0sTUFBTSxhQUFhLEdBQUc7SUFDMUIsTUFBTSxFQUFFLFdBQVcsQ0FBQztJQUNwQixTQUFTLEVBQUUsV0FBVyxDQUFDO0lBQ3ZCLE9BQU8sRUFBRSxHQUFHLENBQUM7Q0FDZCxDQUFDO0FBRUYscUJBQWEsY0FBYzthQXNCUCxNQUFNLEVBQUUsVUFBVTtJQXJCcEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQXNEO0lBRTdFLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyx1QkFBdUIsRUFBRSxnQ0FBZ0Msa0JBTXhGO0lBRUQsTUFBTSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsY0FBYyxrQkFJMUM7SUFFRCxNQUFNLENBQUMsdUJBQXVCLENBQUMsS0FBSyxFQUFFLFdBQVcsVUFFaEQ7SUFFRCxZQUNrQixNQUFNLEVBQUUsVUFBVSxFQUNsQyxPQUFPLEVBQUUsR0FBRyxHQUFHLFVBQVUsRUFNMUI7SUFFRCxJQUFXLE9BQU8sa0JBRWpCO0lBRU0sV0FBVyxJQUFJLHFCQUFxQixDQUFDLE9BQU8sU0FBUyxFQUFFLFVBQVUsQ0FBQyxDQUV4RTtJQUVNLDZCQUE2QixDQUFDLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBRXRFO0lBRU0sV0FBVyxDQUFDLEtBQUssRUFBRSxXQUFXLDBCQUVwQztJQUVNLE9BQU8sQ0FBQyxPQUFPLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLDBCQUd4RjtJQUVZLHdCQUF3QixDQUNuQyxXQUFXLEVBQUUsR0FBRyxHQUNmLE9BQU8sQ0FBQztRQUFFLEtBQUssRUFBRSxNQUFNLENBQUM7UUFBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO1FBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQztRQUFDLE1BQU0sRUFBRSxNQUFNLENBQUE7S0FBRSxFQUFFLENBQUMsQ0FRM0U7SUFFRCxPQUFPLENBQUMsWUFBWTtDQU1yQiJ9
64
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym94LmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29udHJhY3RzL291dGJveC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzNELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUUxRCxPQUFPLEVBQUUsS0FBSyxxQkFBcUIsRUFBRSxLQUFLLEdBQUcsRUFBNEQsTUFBTSxNQUFNLENBQUM7QUFHdEgsT0FBTyxLQUFLLEVBQUUsZ0NBQWdDLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN4RixPQUFPLEtBQUssRUFBRSxjQUFjLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN0RCxPQUFPLEVBQWlDLEtBQUssVUFBVSxFQUFvQixNQUFNLGFBQWEsQ0FBQztBQUUvRixNQUFNLE1BQU0sV0FBVyxHQUFHO0lBQ3hCLEtBQUssRUFBRSxHQUFHLENBQUM7SUFDWCxPQUFPLEVBQUUsTUFBTSxDQUFDO0NBQ2pCLENBQUM7QUFFRixNQUFNLE1BQU0sV0FBVyxHQUFHO0lBQ3hCLEtBQUssRUFBRSxHQUFHLENBQUM7SUFDWCxPQUFPLEVBQUUsTUFBTSxDQUFDO0NBQ2pCLENBQUM7QUFFRixNQUFNLE1BQU0sYUFBYSxHQUFHO0lBQzFCLE1BQU0sRUFBRSxXQUFXLENBQUM7SUFDcEIsU0FBUyxFQUFFLFdBQVcsQ0FBQztJQUN2QixPQUFPLEVBQUUsR0FBRyxDQUFDO0NBQ2QsQ0FBQztBQUVGLHFCQUFhLGNBQWM7YUFrQ1AsTUFBTSxFQUFFLFVBQVU7SUFqQ3BDLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFzRDtJQUU3RSxNQUFNLENBQUMsd0JBQXdCLENBQUMsdUJBQXVCLEVBQUUsZ0NBQWdDLGtCQU14RjtJQUVELE1BQU0sQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLGNBQWMsa0JBSTFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSCxNQUFNLENBQUMsdUJBQXVCLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLFVBSy9FO0lBRUQsWUFDa0IsTUFBTSxFQUFFLFVBQVUsRUFDbEMsT0FBTyxFQUFFLEdBQUcsR0FBRyxVQUFVLEVBTTFCO0lBRUQsSUFBVyxPQUFPLGtCQUVqQjtJQUVNLFdBQVcsSUFBSSxxQkFBcUIsQ0FBQyxPQUFPLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FFeEU7SUFFTSw2QkFBNkIsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxNQUFNLG9CQUV0RTtJQUVNLFdBQVcsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMEJBRW5FO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDVSxRQUFRLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsRUFBRTtRQUFFLFdBQVcsQ0FBQyxFQUFFLE1BQU0sQ0FBQTtLQUFFLEdBQUcsT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBR3hGO0lBRU0sT0FBTyxDQUNaLE9BQU8sRUFBRSxhQUFhLEVBQ3RCLEtBQUssRUFBRSxXQUFXLEVBQ2xCLHFCQUFxQixFQUFFLE1BQU0sRUFDN0IsU0FBUyxFQUFFLE1BQU0sRUFDakIsSUFBSSxFQUFFLEdBQUcsRUFBRSwwQkFJWjtJQUVZLHdCQUF3QixDQUNuQyxXQUFXLEVBQUUsR0FBRyxHQUNmLE9BQU8sQ0FBQztRQUFFLEtBQUssRUFBRSxNQUFNLENBQUM7UUFBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO1FBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQztRQUFDLE1BQU0sRUFBRSxNQUFNLENBQUM7UUFBQyxxQkFBcUIsRUFBRSxNQUFNLENBQUE7S0FBRSxFQUFFLENBQUMsQ0FTMUc7SUFFRCxPQUFPLENBQUMsWUFBWTtDQU1yQiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/contracts/outbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE1D,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,GAAG,EAA4D,MAAM,MAAM,CAAC;AAGtH,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,iCAAiC,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAiC,KAAK,UAAU,EAAoB,MAAM,aAAa,CAAC;AAE/F,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,WAAW,CAAC;IACvB,OAAO,EAAE,GAAG,CAAC;CACd,CAAC;AAEF,qBAAa,cAAc;aAsBP,MAAM,EAAE,UAAU;IArBpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsD;IAE7E,MAAM,CAAC,wBAAwB,CAAC,uBAAuB,EAAE,gCAAgC,kBAMxF;IAED,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,cAAc,kBAI1C;IAED,MAAM,CAAC,uBAAuB,CAAC,KAAK,EAAE,WAAW,UAEhD;IAED,YACkB,MAAM,EAAE,UAAU,EAClC,OAAO,EAAE,GAAG,GAAG,UAAU,EAM1B;IAED,IAAW,OAAO,kBAEjB;IAEM,WAAW,IAAI,qBAAqB,CAAC,OAAO,SAAS,EAAE,UAAU,CAAC,CAExE;IAEM,6BAA6B,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,oBAEtE;IAEM,WAAW,CAAC,KAAK,EAAE,WAAW,0BAEpC;IAEM,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,0BAGxF;IAEY,wBAAwB,CACnC,WAAW,EAAE,GAAG,GACf,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,CAAC;QAAC,WAAW,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAQ3E;IAED,OAAO,CAAC,YAAY;CAMrB"}
1
+ {"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/contracts/outbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE1D,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,GAAG,EAA4D,MAAM,MAAM,CAAC;AAGtH,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,iCAAiC,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAiC,KAAK,UAAU,EAAoB,MAAM,aAAa,CAAC;AAE/F,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,WAAW,CAAC;IACvB,OAAO,EAAE,GAAG,CAAC;CACd,CAAC;AAEF,qBAAa,cAAc;aAkCP,MAAM,EAAE,UAAU;IAjCpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsD;IAE7E,MAAM,CAAC,wBAAwB,CAAC,uBAAuB,EAAE,gCAAgC,kBAMxF;IAED,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,cAAc,kBAI1C;IAED;;;;;;;;OAQG;IACH,MAAM,CAAC,uBAAuB,CAAC,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,UAK/E;IAED,YACkB,MAAM,EAAE,UAAU,EAClC,OAAO,EAAE,GAAG,GAAG,UAAU,EAM1B;IAED,IAAW,OAAO,kBAEjB;IAEM,WAAW,IAAI,qBAAqB,CAAC,OAAO,SAAS,EAAE,UAAU,CAAC,CAExE;IAEM,6BAA6B,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,oBAEtE;IAEM,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,0BAEnE;IAED;;;;;;;;OAQG;IACU,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,EAAE,EAAE,CAAC,CAGxF;IAEM,OAAO,CACZ,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,WAAW,EAClB,qBAAqB,EAAE,MAAM,EAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,GAAG,EAAE,0BAIZ;IAEY,wBAAwB,CACnC,WAAW,EAAE,GAAG,GACf,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,CAAC;QAAC,WAAW,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,qBAAqB,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAS1G;IAED,OAAO,CAAC,YAAY;CAMrB"}
@@ -1,3 +1,4 @@
1
+ import { Fr } from '@aztec/foundation/curves/bn254';
1
2
  import { EthAddress } from '@aztec/foundation/eth-address';
2
3
  import { OutboxAbi } from '@aztec/l1-artifacts/OutboxAbi';
3
4
  import { encodeAbiParameters, getContract, hexToBigInt, keccak256 } from 'viem';
@@ -12,11 +13,19 @@ export class OutboxContract {
12
13
  }
13
14
  static getFromConfig(config) {
14
15
  const client = getPublicClient(config);
15
- const address = config.l1Contracts.outboxAddress.toString();
16
+ const address = config.outboxAddress.toString();
16
17
  return new OutboxContract(client, address);
17
18
  }
18
- static getEpochRootStorageSlot(epoch) {
19
- return hexToBigInt(keccak256(encodeAbiParameters([
19
+ /**
20
+ * Storage slot of `epochs[epoch].roots[numCheckpointsInEpoch - 1]` in the Outbox contract.
21
+ *
22
+ * The Outbox lays out storage as `mapping(Epoch => EpochData) internal epochs` at base slot 0
23
+ * (ROLLUP and VERSION are immutable and do not occupy slots). For a mapping at slot `b`, the
24
+ * value for key `k` begins at `keccak256(abi.encode(k, b))`. `EpochData` starts with a fixed-
25
+ * size `bytes32[MAX_CHECKPOINTS_PER_EPOCH] roots` array, so `roots[i]` sits at the EpochData's
26
+ * base slot plus `i`. `numCheckpointsInEpoch` is 1-indexed (matches `Outbox.insert`/`consume`).
27
+ */ static getEpochRootStorageSlot(epoch, numCheckpointsInEpoch) {
28
+ const epochDataSlot = hexToBigInt(keccak256(encodeAbiParameters([
20
29
  {
21
30
  type: 'uint256'
22
31
  },
@@ -27,6 +36,7 @@ export class OutboxContract {
27
36
  BigInt(epoch),
28
37
  0n
29
38
  ])));
39
+ return epochDataSlot + BigInt(numCheckpointsInEpoch - 1);
30
40
  }
31
41
  constructor(client, address){
32
42
  this.client = client;
@@ -51,16 +61,32 @@ export class OutboxContract {
51
61
  leafId
52
62
  ]);
53
63
  }
54
- getRootData(epoch) {
64
+ getRootData(epoch, numCheckpointsInEpoch) {
55
65
  return this.outbox.read.getRootData([
56
- BigInt(epoch)
66
+ BigInt(epoch),
67
+ BigInt(numCheckpointsInEpoch)
57
68
  ]);
58
69
  }
59
- consume(message, epoch, leafIndex, path) {
70
+ /**
71
+ * Returns every root stored for `epoch`. Slot `i` of the returned array holds the root inserted
72
+ * for `numCheckpointsInEpoch = i + 1`, or `Fr.ZERO` if no proof of that depth has been inserted
73
+ * yet. The array length is always `MAX_CHECKPOINTS_PER_EPOCH`.
74
+ *
75
+ * @param opts - Optional viem read options. Pass `blockNumber` to pin the read to a specific L1
76
+ * block, which is important for callers that want a consistent snapshot across multiple reads
77
+ * (e.g. the archiver's outbox-trees resolver, which pins to the node's synced L1 block).
78
+ */ async getRoots(epoch, opts) {
79
+ const raw = await this.outbox.read.getRoots([
80
+ BigInt(epoch)
81
+ ], opts);
82
+ return raw.map((hex)=>Fr.fromString(hex));
83
+ }
84
+ consume(message, epoch, numCheckpointsInEpoch, leafIndex, path) {
60
85
  const wallet = this.assertWallet();
61
86
  return wallet.write.consume([
62
87
  message,
63
88
  BigInt(epoch),
89
+ BigInt(numCheckpointsInEpoch),
64
90
  leafIndex,
65
91
  path
66
92
  ]);
@@ -74,7 +100,8 @@ export class OutboxContract {
74
100
  epoch: event.args.epoch,
75
101
  root: event.args.root,
76
102
  messageHash: event.args.messageHash,
77
- leafId: event.args.leafId
103
+ leafId: event.args.leafId,
104
+ numCheckpointsInEpoch: event.args.numCheckpointsInEpoch
78
105
  }));
79
106
  }
80
107
  assertWallet() {
@@ -25,5 +25,7 @@ export declare class RegistryContract {
25
25
  getNumberOfVersions(): Promise<number>;
26
26
  getRollupVersions(): Promise<bigint[]>;
27
27
  getRewardDistributor(): Promise<EthAddress>;
28
+ /** Returns the L1 timestamp at which the given rollup was registered via addRollup(). */
29
+ getCanonicalRollupRegistrationTimestamp(rollupAddress: EthAddress, fromBlock?: bigint): Promise<bigint | undefined>;
28
30
  }
29
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0cnkuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb250cmFjdHMvcmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBSzNELE9BQU8sRUFBOEIsS0FBSyxHQUFHLEVBQWUsTUFBTSxNQUFNLENBQUM7QUFFekUsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUN2RSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFJOUMscUJBQWEsZ0JBQWdCO2FBT1QsTUFBTSxFQUFFLFVBQVU7SUFON0IsT0FBTyxFQUFFLFVBQVUsQ0FBQztJQUUzQixPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBK0M7SUFDbkUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQXdEO0lBRWpGLFlBQ2tCLE1BQU0sRUFBRSxVQUFVLEVBQ2xDLE9BQU8sRUFBRSxHQUFHLEdBQUcsVUFBVSxFQU8xQjtJQUVZLFFBQVEsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLENBRTNDO0lBRUQ7Ozs7T0FJRztJQUNVLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxNQUFNLEdBQUcsTUFBTSxHQUFHLFdBQVcsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLENBc0J6RjtJQUVEOzs7T0FHRztJQUNVLG1CQUFtQixJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FFdEQ7SUFFWSxzQkFBc0IsSUFBSSxPQUFPLENBQzVDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSwyQkFBMkIsR0FBRyxtQkFBbUIsQ0FBQyxDQUM3RSxDQVFBO0lBRUQsT0FBb0IsZ0JBQWdCLENBQ2xDLE1BQU0sRUFBRSxVQUFVLEVBQ2xCLGVBQWUsRUFBRSxHQUFHLEdBQUcsVUFBVSxFQUNqQyxhQUFhLEVBQUUsTUFBTSxHQUFHLE1BQU0sR0FBRyxXQUFXLEdBQzNDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQXVCOUI7SUFFWSxtQkFBbUIsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLENBR2xEO0lBRVksaUJBQWlCLElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBU2xEO0lBRVksb0JBQW9CLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUV2RDtDQUNGIn0=
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0cnkuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb250cmFjdHMvcmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBSzNELE9BQU8sRUFBOEIsS0FBSyxHQUFHLEVBQTJCLE1BQU0sTUFBTSxDQUFDO0FBRXJGLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDdkUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBSTlDLHFCQUFhLGdCQUFnQjthQU9ULE1BQU0sRUFBRSxVQUFVO0lBTjdCLE9BQU8sRUFBRSxVQUFVLENBQUM7SUFFM0IsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQStDO0lBQ25FLE9BQU8sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUF3RDtJQUVqRixZQUNrQixNQUFNLEVBQUUsVUFBVSxFQUNsQyxPQUFPLEVBQUUsR0FBRyxHQUFHLFVBQVUsRUFPMUI7SUFFWSxRQUFRLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUUzQztJQUVEOzs7O09BSUc7SUFDVSxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsTUFBTSxHQUFHLE1BQU0sR0FBRyxXQUFXLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQXNCekY7SUFFRDs7O09BR0c7SUFDVSxtQkFBbUIsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLENBRXREO0lBRVksc0JBQXNCLElBQUksT0FBTyxDQUM1QyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsMkJBQTJCLEdBQUcsbUJBQW1CLENBQUMsQ0FDN0UsQ0FRQTtJQUVELE9BQW9CLGdCQUFnQixDQUNsQyxNQUFNLEVBQUUsVUFBVSxFQUNsQixlQUFlLEVBQUUsR0FBRyxHQUFHLFVBQVUsRUFDakMsYUFBYSxFQUFFLE1BQU0sR0FBRyxNQUFNLEdBQUcsV0FBVyxHQUMzQyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0F1QjlCO0lBRVksbUJBQW1CLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUdsRDtJQUVZLGlCQUFpQixJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQVNsRDtJQUVZLG9CQUFvQixJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FFdkQ7SUFFRCx5RkFBeUY7SUFDNUUsdUNBQXVDLENBQ2xELGFBQWEsRUFBRSxVQUFVLEVBQ3pCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sR0FDakIsT0FBTyxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0F3QjdCO0NBQ0YifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/contracts/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAK3D,OAAO,EAA8B,KAAK,GAAG,EAAe,MAAM,MAAM,CAAC;AAEzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9C,qBAAa,gBAAgB;aAOT,MAAM,EAAE,UAAU;IAN7B,OAAO,EAAE,UAAU,CAAC;IAE3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA+C;IACnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwD;IAEjF,YACkB,MAAM,EAAE,UAAU,EAClC,OAAO,EAAE,GAAG,GAAG,UAAU,EAO1B;IAEY,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,CAE3C;IAED;;;;OAIG;IACU,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAsBzF;IAED;;;OAGG;IACU,mBAAmB,IAAI,OAAO,CAAC,UAAU,CAAC,CAEtD;IAEY,sBAAsB,IAAI,OAAO,CAC5C,IAAI,CAAC,mBAAmB,EAAE,2BAA2B,GAAG,mBAAmB,CAAC,CAC7E,CAQA;IAED,OAAoB,gBAAgB,CAClC,MAAM,EAAE,UAAU,EAClB,eAAe,EAAE,GAAG,GAAG,UAAU,EACjC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,GAC3C,OAAO,CAAC,mBAAmB,CAAC,CAuB9B;IAEY,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGlD;IAEY,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CASlD;IAEY,oBAAoB,IAAI,OAAO,CAAC,UAAU,CAAC,CAEvD;CACF"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/contracts/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAK3D,OAAO,EAA8B,KAAK,GAAG,EAA2B,MAAM,MAAM,CAAC;AAErF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9C,qBAAa,gBAAgB;aAOT,MAAM,EAAE,UAAU;IAN7B,OAAO,EAAE,UAAU,CAAC;IAE3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA+C;IACnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwD;IAEjF,YACkB,MAAM,EAAE,UAAU,EAClC,OAAO,EAAE,GAAG,GAAG,UAAU,EAO1B;IAEY,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,CAE3C;IAED;;;;OAIG;IACU,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAsBzF;IAED;;;OAGG;IACU,mBAAmB,IAAI,OAAO,CAAC,UAAU,CAAC,CAEtD;IAEY,sBAAsB,IAAI,OAAO,CAC5C,IAAI,CAAC,mBAAmB,EAAE,2BAA2B,GAAG,mBAAmB,CAAC,CAC7E,CAQA;IAED,OAAoB,gBAAgB,CAClC,MAAM,EAAE,UAAU,EAClB,eAAe,EAAE,GAAG,GAAG,UAAU,EACjC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,GAC3C,OAAO,CAAC,mBAAmB,CAAC,CAuB9B;IAEY,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGlD;IAEY,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CASlD;IAEY,oBAAoB,IAAI,OAAO,CAAC,UAAU,CAAC,CAEvD;IAED,yFAAyF;IAC5E,uCAAuC,CAClD,aAAa,EAAE,UAAU,EACzB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAwB7B;CACF"}
@@ -2,7 +2,7 @@ import { EthAddress } from '@aztec/foundation/eth-address';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
3
  import { RegistryAbi } from '@aztec/l1-artifacts/RegistryAbi';
4
4
  import { TestERC20Abi } from '@aztec/l1-artifacts/TestERC20Abi';
5
- import { getContract } from 'viem';
5
+ import { getAbiItem, getContract } from 'viem';
6
6
  import { ReadOnlyGovernanceContract } from './governance.js';
7
7
  import { RollupContract } from './rollup.js';
8
8
  export class RegistryContract {
@@ -110,4 +110,33 @@ export class RegistryContract {
110
110
  async getRewardDistributor() {
111
111
  return EthAddress.fromString(await this.registry.read.getRewardDistributor());
112
112
  }
113
+ /** Returns the L1 timestamp at which the given rollup was registered via addRollup(). */ async getCanonicalRollupRegistrationTimestamp(rollupAddress, fromBlock) {
114
+ const event = getAbiItem({
115
+ abi: RegistryAbi,
116
+ name: 'CanonicalRollupUpdated'
117
+ });
118
+ const start = fromBlock ?? 0n;
119
+ const latestBlock = await this.client.getBlockNumber();
120
+ const chunkSize = 1_000n;
121
+ for(let from = start; from <= latestBlock; from += chunkSize){
122
+ const to = from + chunkSize - 1n > latestBlock ? latestBlock : from + chunkSize - 1n;
123
+ const logs = await this.client.getLogs({
124
+ address: this.address.toString(),
125
+ fromBlock: from,
126
+ toBlock: to,
127
+ strict: true,
128
+ event,
129
+ args: {
130
+ instance: rollupAddress.toString()
131
+ }
132
+ });
133
+ if (logs.length > 0) {
134
+ const block = await this.client.getBlock({
135
+ blockNumber: logs[0].blockNumber
136
+ });
137
+ return block.timestamp;
138
+ }
139
+ }
140
+ return undefined;
141
+ }
113
142
  }