@aztec/ethereum 0.0.1-commit.5daedc8 → 0.0.1-commit.6201a7b05

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 (212) hide show
  1. package/dest/client.d.ts +16 -2
  2. package/dest/client.d.ts.map +1 -1
  3. package/dest/client.js +27 -3
  4. package/dest/config.d.ts +26 -73
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +64 -387
  7. package/dest/contracts/chain_state_override.d.ts +38 -0
  8. package/dest/contracts/chain_state_override.d.ts.map +1 -0
  9. package/dest/contracts/chain_state_override.js +100 -0
  10. package/dest/contracts/empire_base.d.ts +4 -1
  11. package/dest/contracts/empire_base.d.ts.map +1 -1
  12. package/dest/contracts/fee_asset_handler.d.ts +6 -5
  13. package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
  14. package/dest/contracts/fee_asset_handler.js +11 -9
  15. package/dest/contracts/fee_asset_price_oracle.d.ts +101 -0
  16. package/dest/contracts/fee_asset_price_oracle.d.ts.map +1 -0
  17. package/dest/contracts/fee_asset_price_oracle.js +651 -0
  18. package/dest/contracts/governance.d.ts +3 -1
  19. package/dest/contracts/governance.d.ts.map +1 -1
  20. package/dest/contracts/governance.js +14 -4
  21. package/dest/contracts/governance_proposer.d.ts +4 -1
  22. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  23. package/dest/contracts/governance_proposer.js +404 -9
  24. package/dest/contracts/inbox.d.ts +24 -3
  25. package/dest/contracts/inbox.d.ts.map +1 -1
  26. package/dest/contracts/inbox.js +41 -1
  27. package/dest/contracts/index.d.ts +6 -3
  28. package/dest/contracts/index.d.ts.map +1 -1
  29. package/dest/contracts/index.js +5 -2
  30. package/dest/contracts/log.d.ts +13 -0
  31. package/dest/contracts/log.d.ts.map +1 -0
  32. package/dest/contracts/log.js +1 -0
  33. package/dest/contracts/multicall.d.ts +51 -2
  34. package/dest/contracts/multicall.d.ts.map +1 -1
  35. package/dest/contracts/multicall.js +87 -1
  36. package/dest/contracts/outbox.d.ts +41 -0
  37. package/dest/contracts/outbox.d.ts.map +1 -0
  38. package/dest/contracts/outbox.js +86 -0
  39. package/dest/contracts/registry.d.ts +3 -1
  40. package/dest/contracts/registry.d.ts.map +1 -1
  41. package/dest/contracts/registry.js +30 -1
  42. package/dest/contracts/rollup.d.ts +5178 -108
  43. package/dest/contracts/rollup.d.ts.map +1 -1
  44. package/dest/contracts/rollup.js +1004 -188
  45. package/dest/contracts/{tally_slashing_proposer.d.ts → slashing_proposer.d.ts} +5 -5
  46. package/dest/contracts/slashing_proposer.d.ts.map +1 -0
  47. package/dest/contracts/{tally_slashing_proposer.js → slashing_proposer.js} +18 -13
  48. package/dest/deploy_aztec_l1_contracts.d.ts +256 -0
  49. package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -0
  50. package/dest/deploy_aztec_l1_contracts.js +411 -0
  51. package/dest/deploy_l1_contract.d.ts +68 -0
  52. package/dest/deploy_l1_contract.d.ts.map +1 -0
  53. package/dest/deploy_l1_contract.js +312 -0
  54. package/dest/forwarder_proxy.d.ts +32 -0
  55. package/dest/forwarder_proxy.d.ts.map +1 -0
  56. package/dest/forwarder_proxy.js +93 -0
  57. package/dest/generated/l1-contracts-defaults.d.ts +30 -0
  58. package/dest/generated/l1-contracts-defaults.d.ts.map +1 -0
  59. package/dest/generated/l1-contracts-defaults.js +30 -0
  60. package/dest/l1_artifacts.d.ts +14161 -17158
  61. package/dest/l1_artifacts.d.ts.map +1 -1
  62. package/dest/l1_artifacts.js +9 -24
  63. package/dest/l1_contract_addresses.d.ts +1 -5
  64. package/dest/l1_contract_addresses.d.ts.map +1 -1
  65. package/dest/l1_contract_addresses.js +3 -9
  66. package/dest/l1_reader.d.ts +5 -1
  67. package/dest/l1_reader.d.ts.map +1 -1
  68. package/dest/l1_reader.js +13 -2
  69. package/dest/l1_tx_utils/config.d.ts +9 -3
  70. package/dest/l1_tx_utils/config.d.ts.map +1 -1
  71. package/dest/l1_tx_utils/config.js +31 -4
  72. package/dest/l1_tx_utils/constants.d.ts +8 -2
  73. package/dest/l1_tx_utils/constants.d.ts.map +1 -1
  74. package/dest/l1_tx_utils/constants.js +27 -2
  75. package/dest/l1_tx_utils/factory.d.ts +18 -10
  76. package/dest/l1_tx_utils/factory.d.ts.map +1 -1
  77. package/dest/l1_tx_utils/factory.js +17 -7
  78. package/dest/l1_tx_utils/fee-strategies/index.d.ts +10 -0
  79. package/dest/l1_tx_utils/fee-strategies/index.d.ts.map +1 -0
  80. package/dest/l1_tx_utils/fee-strategies/index.js +12 -0
  81. package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts +8 -0
  82. package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts.map +1 -0
  83. package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +129 -0
  84. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts +23 -0
  85. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts.map +1 -0
  86. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +191 -0
  87. package/dest/l1_tx_utils/fee-strategies/types.d.ts +51 -0
  88. package/dest/l1_tx_utils/fee-strategies/types.d.ts.map +1 -0
  89. package/dest/l1_tx_utils/fee-strategies/types.js +3 -0
  90. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +41 -0
  91. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -0
  92. package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +42 -0
  93. package/dest/l1_tx_utils/index-blobs.d.ts +3 -0
  94. package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -0
  95. package/dest/l1_tx_utils/index-blobs.js +2 -0
  96. package/dest/l1_tx_utils/index.d.ts +4 -1
  97. package/dest/l1_tx_utils/index.d.ts.map +1 -1
  98. package/dest/l1_tx_utils/index.js +3 -0
  99. package/dest/l1_tx_utils/interfaces.d.ts +2 -2
  100. package/dest/l1_tx_utils/interfaces.d.ts.map +1 -1
  101. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts +233 -0
  102. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts.map +1 -0
  103. package/dest/l1_tx_utils/l1_fee_analyzer.js +506 -0
  104. package/dest/l1_tx_utils/l1_tx_utils.d.ts +20 -7
  105. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
  106. package/dest/l1_tx_utils/l1_tx_utils.js +98 -61
  107. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +4 -15
  108. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
  109. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +61 -164
  110. package/dest/l1_tx_utils/tx_delayer.d.ts +56 -0
  111. package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -0
  112. package/dest/{test → l1_tx_utils}/tx_delayer.js +65 -36
  113. package/dest/publisher_manager.d.ts +21 -6
  114. package/dest/publisher_manager.d.ts.map +1 -1
  115. package/dest/publisher_manager.js +81 -7
  116. package/dest/queries.d.ts +14 -3
  117. package/dest/queries.d.ts.map +1 -1
  118. package/dest/queries.js +74 -7
  119. package/dest/test/chain_monitor.d.ts +36 -14
  120. package/dest/test/chain_monitor.d.ts.map +1 -1
  121. package/dest/test/chain_monitor.js +45 -11
  122. package/dest/test/eth_cheat_codes.d.ts +18 -4
  123. package/dest/test/eth_cheat_codes.d.ts.map +1 -1
  124. package/dest/test/eth_cheat_codes.js +10 -6
  125. package/dest/test/index.d.ts +1 -3
  126. package/dest/test/index.d.ts.map +1 -1
  127. package/dest/test/index.js +0 -2
  128. package/dest/test/rollup_cheat_codes.d.ts +13 -6
  129. package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
  130. package/dest/test/rollup_cheat_codes.js +41 -7
  131. package/dest/test/start_anvil.d.ts +24 -2
  132. package/dest/test/start_anvil.d.ts.map +1 -1
  133. package/dest/test/start_anvil.js +143 -29
  134. package/dest/test/upgrade_utils.js +2 -2
  135. package/dest/types.d.ts +57 -2
  136. package/dest/types.d.ts.map +1 -1
  137. package/dest/utils.d.ts +16 -3
  138. package/dest/utils.d.ts.map +1 -1
  139. package/dest/utils.js +80 -12
  140. package/package.json +33 -16
  141. package/src/client.ts +28 -2
  142. package/src/config.ts +82 -468
  143. package/src/contracts/README.md +157 -0
  144. package/src/contracts/chain_state_override.ts +147 -0
  145. package/src/contracts/empire_base.ts +3 -1
  146. package/src/contracts/fee_asset_handler.ts +10 -7
  147. package/src/contracts/fee_asset_price_oracle.ts +280 -0
  148. package/src/contracts/governance.ts +13 -4
  149. package/src/contracts/governance_proposer.ts +16 -2
  150. package/src/contracts/inbox.ts +63 -3
  151. package/src/contracts/index.ts +5 -2
  152. package/src/contracts/log.ts +13 -0
  153. package/src/contracts/multicall.ts +70 -3
  154. package/src/contracts/outbox.ts +98 -0
  155. package/src/contracts/registry.ts +31 -1
  156. package/src/contracts/rollup.ts +701 -149
  157. package/src/contracts/{tally_slashing_proposer.ts → slashing_proposer.ts} +18 -14
  158. package/src/deploy_aztec_l1_contracts.ts +646 -0
  159. package/src/deploy_l1_contract.ts +362 -0
  160. package/src/forwarder_proxy.ts +108 -0
  161. package/src/generated/l1-contracts-defaults.ts +32 -0
  162. package/src/l1_artifacts.ts +12 -35
  163. package/src/l1_contract_addresses.ts +21 -26
  164. package/src/l1_reader.ts +22 -2
  165. package/src/l1_tx_utils/config.ts +44 -6
  166. package/src/l1_tx_utils/constants.ts +13 -2
  167. package/src/l1_tx_utils/factory.ts +31 -31
  168. package/src/l1_tx_utils/fee-strategies/index.ts +22 -0
  169. package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +163 -0
  170. package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +245 -0
  171. package/src/l1_tx_utils/fee-strategies/types.ts +56 -0
  172. package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +108 -0
  173. package/src/l1_tx_utils/index-blobs.ts +2 -0
  174. package/src/l1_tx_utils/index.ts +3 -0
  175. package/src/l1_tx_utils/interfaces.ts +1 -1
  176. package/src/l1_tx_utils/l1_fee_analyzer.ts +803 -0
  177. package/src/l1_tx_utils/l1_tx_utils.ts +98 -40
  178. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +75 -210
  179. package/src/{test → l1_tx_utils}/tx_delayer.ts +82 -52
  180. package/src/publisher_manager.ts +107 -10
  181. package/src/queries.ts +81 -7
  182. package/src/test/chain_monitor.ts +82 -18
  183. package/src/test/eth_cheat_codes.ts +8 -6
  184. package/src/test/index.ts +0 -2
  185. package/src/test/rollup_cheat_codes.ts +43 -10
  186. package/src/test/start_anvil.ts +178 -28
  187. package/src/test/upgrade_utils.ts +2 -2
  188. package/src/types.ts +62 -0
  189. package/src/utils.ts +100 -15
  190. package/dest/contracts/empire_slashing_proposer.d.ts +0 -66
  191. package/dest/contracts/empire_slashing_proposer.d.ts.map +0 -1
  192. package/dest/contracts/empire_slashing_proposer.js +0 -200
  193. package/dest/contracts/tally_slashing_proposer.d.ts.map +0 -1
  194. package/dest/deploy_l1_contracts.d.ts +0 -673
  195. package/dest/deploy_l1_contracts.d.ts.map +0 -1
  196. package/dest/deploy_l1_contracts.js +0 -1491
  197. package/dest/index.d.ts +0 -18
  198. package/dest/index.d.ts.map +0 -1
  199. package/dest/index.js +0 -17
  200. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +0 -26
  201. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +0 -1
  202. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +0 -26
  203. package/dest/test/delayed_tx_utils.d.ts +0 -13
  204. package/dest/test/delayed_tx_utils.d.ts.map +0 -1
  205. package/dest/test/delayed_tx_utils.js +0 -28
  206. package/dest/test/tx_delayer.d.ts +0 -36
  207. package/dest/test/tx_delayer.d.ts.map +0 -1
  208. package/src/contracts/empire_slashing_proposer.ts +0 -265
  209. package/src/deploy_l1_contracts.ts +0 -1869
  210. package/src/index.ts +0 -17
  211. package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +0 -77
  212. package/src/test/delayed_tx_utils.ts +0 -52
@@ -14,7 +14,7 @@ import {
14
14
  } from 'viem';
15
15
 
16
16
  import type { L1ContractAddresses } from '../l1_contract_addresses.js';
17
- import { createL1TxUtilsFromViemWallet } from '../l1_tx_utils/index.js';
17
+ import { createL1TxUtils } from '../l1_tx_utils/index.js';
18
18
  import { type ExtendedViemWalletClient, type ViemClient, isExtendedClient } from '../types.js';
19
19
 
20
20
  export type L1GovernanceContractAddresses = Pick<
@@ -174,6 +174,13 @@ export class GovernanceContract extends ReadOnlyGovernanceContract {
174
174
  return this.governanceContract.read.powerAt([this.client.account.address, now.timestamp]);
175
175
  }
176
176
 
177
+ /** Returns the user's voting power for a specific proposal, checked at pendingThrough timestamp. */
178
+ public async getPowerForProposal(proposalId: bigint): Promise<bigint> {
179
+ const proposal = await this.getProposal(proposalId);
180
+ const pendingThrough = proposal.creation + proposal.config.votingDelay;
181
+ return this.governanceContract.read.powerAt([this.client.account.address, pendingThrough]);
182
+ }
183
+
177
184
  public async vote({
178
185
  proposalId,
179
186
  voteAmount,
@@ -187,10 +194,10 @@ export class GovernanceContract extends ReadOnlyGovernanceContract {
187
194
  retries: number;
188
195
  logger: Logger;
189
196
  }) {
190
- const l1TxUtils = createL1TxUtilsFromViemWallet(this.client, { logger });
197
+ const l1TxUtils = createL1TxUtils(this.client, { logger });
191
198
  const retryDelaySeconds = 12;
192
199
 
193
- voteAmount = voteAmount ?? (await this.getPower());
200
+ voteAmount = voteAmount ?? (await this.getPowerForProposal(proposalId));
194
201
 
195
202
  let success = false;
196
203
  for (let i = 0; i < retries; i++) {
@@ -204,6 +211,7 @@ export class GovernanceContract extends ReadOnlyGovernanceContract {
204
211
 
205
212
  const { receipt } = await l1TxUtils.sendAndMonitorTransaction({
206
213
  to: this.governanceContract.address,
214
+ abi: GovernanceAbi,
207
215
  data: encodedVoteData,
208
216
  });
209
217
 
@@ -244,7 +252,7 @@ export class GovernanceContract extends ReadOnlyGovernanceContract {
244
252
  retries: number;
245
253
  logger: Logger;
246
254
  }) {
247
- const l1TxUtils = createL1TxUtilsFromViemWallet(this.client, { logger });
255
+ const l1TxUtils = createL1TxUtils(this.client, { logger });
248
256
  const retryDelaySeconds = 12;
249
257
  let success = false;
250
258
  for (let i = 0; i < retries; i++) {
@@ -258,6 +266,7 @@ export class GovernanceContract extends ReadOnlyGovernanceContract {
258
266
 
259
267
  const { receipt } = await l1TxUtils.sendAndMonitorTransaction({
260
268
  to: this.governanceContract.address,
269
+ abi: GovernanceAbi,
261
270
  data: encodedExecuteData,
262
271
  });
263
272
 
@@ -62,11 +62,16 @@ export class GovernanceProposerContract implements IEmpireBase {
62
62
  public async getRoundInfo(
63
63
  rollupAddress: Hex,
64
64
  round: bigint,
65
- ): Promise<{ lastSignalSlot: SlotNumber; payloadWithMostSignals: Hex; executed: boolean }> {
65
+ ): Promise<{ lastSignalSlot: SlotNumber; payloadWithMostSignals: Hex; quorumReached: boolean; executed: boolean }> {
66
66
  const result = await this.proposer.read.getRoundData([rollupAddress, round]);
67
+ const [signalCount, quorum] = await Promise.all([
68
+ this.proposer.read.signalCount([rollupAddress, round, result.payloadWithMostSignals]),
69
+ this.getQuorumSize(),
70
+ ]);
67
71
  return {
68
72
  lastSignalSlot: SlotNumber.fromBigInt(result.lastSignalSlot),
69
73
  payloadWithMostSignals: result.payloadWithMostSignals,
74
+ quorumReached: signalCount >= quorum,
70
75
  executed: result.executed,
71
76
  };
72
77
  }
@@ -78,6 +83,7 @@ export class GovernanceProposerContract implements IEmpireBase {
78
83
  public createSignalRequest(payload: Hex): L1TxRequest {
79
84
  return {
80
85
  to: this.address.toString(),
86
+ abi: GovernanceProposerAbi,
81
87
  data: encodeSignal(payload),
82
88
  };
83
89
  }
@@ -99,10 +105,17 @@ export class GovernanceProposerContract implements IEmpireBase {
99
105
  );
100
106
  return {
101
107
  to: this.address.toString(),
108
+ abi: GovernanceProposerAbi,
102
109
  data: encodeSignalWithSignature(payload, signature),
103
110
  };
104
111
  }
105
112
 
113
+ /** Checks if a payload was ever submitted to governance via submitRoundWinner. */
114
+ public async hasPayloadBeenProposed(payload: Hex, fromBlock: bigint): Promise<boolean> {
115
+ const events = await this.proposer.getEvents.PayloadSubmitted({ payload }, { fromBlock, strict: true });
116
+ return events.length > 0;
117
+ }
118
+
106
119
  public async submitRoundWinner(
107
120
  round: bigint,
108
121
  l1TxUtils: L1TxUtils,
@@ -112,8 +125,9 @@ export class GovernanceProposerContract implements IEmpireBase {
112
125
  }> {
113
126
  const { receipt } = await l1TxUtils.sendAndMonitorTransaction({
114
127
  to: this.address.toString(),
128
+ abi: GovernanceProposerAbi,
115
129
  data: encodeFunctionData({
116
- abi: this.proposer.abi,
130
+ abi: GovernanceProposerAbi,
117
131
  functionName: 'submitRoundWinner',
118
132
  args: [round],
119
133
  }),
@@ -1,19 +1,34 @@
1
- import { Buffer16 } from '@aztec/foundation/buffer';
1
+ import { maxBigint } from '@aztec/foundation/bigint';
2
+ import { CheckpointNumber } from '@aztec/foundation/branded-types';
3
+ import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
4
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
5
  import { EthAddress } from '@aztec/foundation/eth-address';
3
6
  import { InboxAbi } from '@aztec/l1-artifacts/InboxAbi';
4
7
 
5
8
  import { type BlockTag, type GetContractReturnType, type Hex, getContract } from 'viem';
6
9
 
7
10
  import { getPublicClient } from '../client.js';
8
- import type { DeployL1ContractsReturnType } from '../deploy_l1_contracts.js';
11
+ import type { DeployAztecL1ContractsReturnType } from '../deploy_aztec_l1_contracts.js';
9
12
  import type { L1ReaderConfig } from '../l1_reader.js';
10
13
  import type { ViemClient } from '../types.js';
14
+ import type { L1EventLog } from './log.js';
11
15
  import { checkBlockTag } from './utils.js';
12
16
 
17
+ /** Arguments for the MessageSent event. */
18
+ export type MessageSentArgs = {
19
+ index: bigint;
20
+ leaf: Fr;
21
+ checkpointNumber: CheckpointNumber;
22
+ rollingHash: Buffer16;
23
+ };
24
+
25
+ /** Log type for MessageSent events. */
26
+ export type MessageSentLog = L1EventLog<MessageSentArgs>;
27
+
13
28
  export class InboxContract {
14
29
  private readonly inbox: GetContractReturnType<typeof InboxAbi, ViemClient>;
15
30
 
16
- static getFromL1ContractsValues(deployL1ContractsValues: DeployL1ContractsReturnType) {
31
+ static getFromL1ContractsValues(deployL1ContractsValues: DeployAztecL1ContractsReturnType) {
17
32
  const {
18
33
  l1Client,
19
34
  l1ContractAddresses: { inboxAddress },
@@ -45,6 +60,11 @@ export class InboxContract {
45
60
  return this.inbox;
46
61
  }
47
62
 
63
+ public async getLag(opts: { blockTag?: BlockTag; blockNumber?: bigint } = {}): Promise<bigint> {
64
+ await checkBlockTag(opts.blockNumber, this.client);
65
+ return await this.inbox.read.LAG(opts);
66
+ }
67
+
48
68
  public async getState(opts: { blockTag?: BlockTag; blockNumber?: bigint } = {}): Promise<InboxContractState> {
49
69
  await checkBlockTag(opts.blockNumber, this.client);
50
70
  const state = await this.inbox.read.getState(opts);
@@ -54,6 +74,46 @@ export class InboxContract {
54
74
  treeInProgress: state.inProgress,
55
75
  };
56
76
  }
77
+
78
+ /** Fetches MessageSent events within the given block range. */
79
+ async getMessageSentEvents(fromBlock: bigint, toBlock: bigint): Promise<MessageSentLog[]> {
80
+ const logs = await this.inbox.getEvents.MessageSent({}, { fromBlock, toBlock });
81
+ return logs
82
+ .filter(log => log.blockNumber! >= fromBlock && log.blockNumber! <= toBlock)
83
+ .map(log => this.mapMessageSentLog(log));
84
+ }
85
+
86
+ /** Fetches MessageSent events for a specific message hash around a specific block. */
87
+ async getMessageSentEventByHash(msgHash: Hex, aroundL1BlockNumber: bigint): Promise<MessageSentLog> {
88
+ // We don't use blockHash here because we don't want the query to throw if the L1 block number no longer exists on chain
89
+ // due to an L1 reorg. The use case for this method is usually checking if a message still exists on the Inbox after
90
+ // a reorg, so it's possible the message was moved one block up or down, and that the original L1 block where we
91
+ // saw it no longer exists, rendering the block-by-hash approach invalid.
92
+ const [log] = await this.inbox.getEvents.MessageSent(
93
+ { hash: msgHash },
94
+ { fromBlock: maxBigint(aroundL1BlockNumber - 5n, 1n), toBlock: aroundL1BlockNumber + 5n },
95
+ );
96
+ return log && this.mapMessageSentLog(log);
97
+ }
98
+
99
+ private mapMessageSentLog(log: {
100
+ blockNumber: bigint | null;
101
+ blockHash: `0x${string}` | null;
102
+ transactionHash: `0x${string}` | null;
103
+ args: { index?: bigint; hash?: `0x${string}`; checkpointNumber?: bigint; rollingHash?: `0x${string}` };
104
+ }): MessageSentLog {
105
+ return {
106
+ l1BlockNumber: log.blockNumber!,
107
+ l1BlockHash: Buffer32.fromString(log.blockHash!),
108
+ l1TransactionHash: log.transactionHash!,
109
+ args: {
110
+ index: log.args.index!,
111
+ leaf: Fr.fromString(log.args.hash!),
112
+ checkpointNumber: CheckpointNumber.fromBigInt(log.args.checkpointNumber!),
113
+ rollingHash: Buffer16.fromString(log.args.rollingHash!),
114
+ },
115
+ };
116
+ }
57
117
  }
58
118
 
59
119
  export type InboxContractState = {
@@ -1,14 +1,17 @@
1
+ export * from './chain_state_override.js';
1
2
  export * from './empire_base.js';
2
3
  export * from './errors.js';
3
4
  export * from './fee_asset_handler.js';
5
+ export * from './fee_asset_price_oracle.js';
4
6
  export * from './fee_juice.js';
5
7
  export * from './governance.js';
6
8
  export * from './governance_proposer.js';
7
9
  export * from './gse.js';
8
10
  export * from './inbox.js';
11
+ export * from './log.js';
9
12
  export * from './multicall.js';
13
+ export * from './outbox.js';
10
14
  export * from './registry.js';
11
15
  export * from './rollup.js';
12
- export * from './empire_slashing_proposer.js';
13
- export * from './tally_slashing_proposer.js';
16
+ export * from './slashing_proposer.js';
14
17
  export * from './slasher_contract.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
+ };
@@ -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 EncodeFunctionDataParameters, type Hex, encodeFunctionData, multicall3Abi } from 'viem';
5
+ import { type Address, 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,6 +11,39 @@ 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
+
14
47
  export class Multicall3 {
15
48
  static async forward(
16
49
  requests: L1TxRequest[],
@@ -34,10 +67,13 @@ export class Multicall3 {
34
67
  };
35
68
 
36
69
  const encodedForwarderData = encodeFunctionData(forwarderFunctionData);
37
-
38
70
  try {
39
71
  const { receipt, state } = await l1TxUtils.sendAndMonitorTransaction(
40
- { to: MULTI_CALL_3_ADDRESS, data: encodedForwarderData },
72
+ {
73
+ to: MULTI_CALL_3_ADDRESS,
74
+ data: encodedForwarderData,
75
+ abi: multicall3Abi,
76
+ },
41
77
  gasConfig,
42
78
  blobConfig,
43
79
  );
@@ -119,6 +155,37 @@ export class Multicall3 {
119
155
  throw err;
120
156
  }
121
157
  }
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
+ }
122
189
  }
123
190
 
124
191
  export async function deployMulticall3(l1Client: ExtendedViemWalletClient, logger: Logger) {
@@ -0,0 +1,98 @@
1
+ import type { EpochNumber } from '@aztec/foundation/branded-types';
2
+ import { EthAddress } from '@aztec/foundation/eth-address';
3
+ import { OutboxAbi } from '@aztec/l1-artifacts/OutboxAbi';
4
+
5
+ import { type GetContractReturnType, type Hex, encodeAbiParameters, getContract, hexToBigInt, keccak256 } from 'viem';
6
+
7
+ import { getPublicClient } from '../client.js';
8
+ import type { DeployAztecL1ContractsReturnType } from '../deploy_aztec_l1_contracts.js';
9
+ import type { L1ReaderConfig } from '../l1_reader.js';
10
+ import { type ExtendedViemWalletClient, type ViemClient, isExtendedClient } from '../types.js';
11
+
12
+ export type ViemL1Actor = {
13
+ actor: Hex;
14
+ chainId: bigint;
15
+ };
16
+
17
+ export type ViemL2Actor = {
18
+ actor: Hex;
19
+ version: bigint;
20
+ };
21
+
22
+ export type ViemL2ToL1Msg = {
23
+ sender: ViemL2Actor;
24
+ recipient: ViemL1Actor;
25
+ content: Hex;
26
+ };
27
+
28
+ export class OutboxContract {
29
+ private readonly outbox: GetContractReturnType<typeof OutboxAbi, ViemClient>;
30
+
31
+ static getFromL1ContractsValues(deployL1ContractsValues: DeployAztecL1ContractsReturnType) {
32
+ const {
33
+ l1Client,
34
+ l1ContractAddresses: { outboxAddress },
35
+ } = deployL1ContractsValues;
36
+ return new OutboxContract(l1Client, outboxAddress.toString());
37
+ }
38
+
39
+ static getFromConfig(config: L1ReaderConfig) {
40
+ const client = getPublicClient(config);
41
+ const address = config.l1Contracts.outboxAddress.toString();
42
+ return new OutboxContract(client, address);
43
+ }
44
+
45
+ static getEpochRootStorageSlot(epoch: EpochNumber) {
46
+ return hexToBigInt(keccak256(encodeAbiParameters([{ type: 'uint256' }, { type: 'uint256' }], [BigInt(epoch), 0n])));
47
+ }
48
+
49
+ constructor(
50
+ public readonly client: ViemClient,
51
+ address: Hex | EthAddress,
52
+ ) {
53
+ if (address instanceof EthAddress) {
54
+ address = address.toString();
55
+ }
56
+ this.outbox = getContract({ address, abi: OutboxAbi, client });
57
+ }
58
+
59
+ public get address() {
60
+ return this.outbox.address;
61
+ }
62
+
63
+ public getContract(): GetContractReturnType<typeof OutboxAbi, ViemClient> {
64
+ return this.outbox;
65
+ }
66
+
67
+ public hasMessageBeenConsumedAtEpoch(epoch: EpochNumber, leafId: bigint) {
68
+ return this.outbox.read.hasMessageBeenConsumedAtEpoch([BigInt(epoch), leafId]);
69
+ }
70
+
71
+ public getRootData(epoch: EpochNumber) {
72
+ return this.outbox.read.getRootData([BigInt(epoch)]);
73
+ }
74
+
75
+ public consume(message: ViemL2ToL1Msg, epoch: EpochNumber, leafIndex: bigint, path: Hex[]) {
76
+ const wallet = this.assertWallet();
77
+ return wallet.write.consume([message, BigInt(epoch), leafIndex, path]);
78
+ }
79
+
80
+ public async getMessageConsumedEvents(
81
+ l1BlockHash: Hex,
82
+ ): Promise<{ epoch: bigint; root: Hex; messageHash: Hex; leafId: bigint }[]> {
83
+ const events = await this.outbox.getEvents.MessageConsumed({}, { blockHash: l1BlockHash, strict: true });
84
+ return events.map(event => ({
85
+ epoch: event.args.epoch!,
86
+ root: event.args.root!,
87
+ messageHash: event.args.messageHash!,
88
+ leafId: event.args.leafId!,
89
+ }));
90
+ }
91
+
92
+ private assertWallet(): GetContractReturnType<typeof OutboxAbi, ExtendedViemWalletClient> {
93
+ if (!isExtendedClient(this.client)) {
94
+ throw new Error('Wallet client is required for this operation');
95
+ }
96
+ return this.outbox as GetContractReturnType<typeof OutboxAbi, ExtendedViemWalletClient>;
97
+ }
98
+ }
@@ -3,7 +3,7 @@ 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
5
 
6
- import { type GetContractReturnType, type Hex, getContract } from 'viem';
6
+ import { type GetContractReturnType, type Hex, getAbiItem, getContract } from 'viem';
7
7
 
8
8
  import type { L1ContractAddresses } from '../l1_contract_addresses.js';
9
9
  import type { ViemClient } from '../types.js';
@@ -128,4 +128,34 @@ export class RegistryContract {
128
128
  public async getRewardDistributor(): Promise<EthAddress> {
129
129
  return EthAddress.fromString(await this.registry.read.getRewardDistributor());
130
130
  }
131
+
132
+ /** Returns the L1 timestamp at which the given rollup was registered via addRollup(). */
133
+ public async getCanonicalRollupRegistrationTimestamp(
134
+ rollupAddress: EthAddress,
135
+ fromBlock?: bigint,
136
+ ): Promise<bigint | undefined> {
137
+ const event = getAbiItem({ abi: RegistryAbi, name: 'CanonicalRollupUpdated' });
138
+ const start = fromBlock ?? 0n;
139
+ const latestBlock = await this.client.getBlockNumber();
140
+ const chunkSize = 1_000n;
141
+
142
+ for (let from = start; from <= latestBlock; from += chunkSize) {
143
+ const to = from + chunkSize - 1n > latestBlock ? latestBlock : from + chunkSize - 1n;
144
+ const logs = await this.client.getLogs({
145
+ address: this.address.toString(),
146
+ fromBlock: from,
147
+ toBlock: to,
148
+ strict: true,
149
+ event,
150
+ args: { instance: rollupAddress.toString() },
151
+ });
152
+
153
+ if (logs.length > 0) {
154
+ const block = await this.client.getBlock({ blockNumber: logs[0].blockNumber });
155
+ return block.timestamp;
156
+ }
157
+ }
158
+
159
+ return undefined;
160
+ }
131
161
  }