@aztec-labs/ethereum 6.0.0-nightly.20260829

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 (272) hide show
  1. package/README.md +3 -0
  2. package/dest/account.d.ts +2 -0
  3. package/dest/account.d.ts.map +1 -0
  4. package/dest/account.js +4 -0
  5. package/dest/chain.d.ts +25 -0
  6. package/dest/chain.d.ts.map +1 -0
  7. package/dest/chain.js +53 -0
  8. package/dest/client.d.ts +42 -0
  9. package/dest/client.d.ts.map +1 -0
  10. package/dest/client.js +104 -0
  11. package/dest/config.d.ts +103 -0
  12. package/dest/config.d.ts.map +1 -0
  13. package/dest/config.js +233 -0
  14. package/dest/constants.d.ts +4 -0
  15. package/dest/constants.d.ts.map +1 -0
  16. package/dest/constants.js +2 -0
  17. package/dest/contracts/chain_state_override.d.ts +81 -0
  18. package/dest/contracts/chain_state_override.d.ts.map +1 -0
  19. package/dest/contracts/chain_state_override.js +139 -0
  20. package/dest/contracts/empire_base.d.ts +30 -0
  21. package/dest/contracts/empire_base.d.ts.map +1 -0
  22. package/dest/contracts/empire_base.js +84 -0
  23. package/dest/contracts/errors.d.ts +7 -0
  24. package/dest/contracts/errors.d.ts.map +1 -0
  25. package/dest/contracts/errors.js +12 -0
  26. package/dest/contracts/fee_asset_handler.d.ts +20 -0
  27. package/dest/contracts/fee_asset_handler.d.ts.map +1 -0
  28. package/dest/contracts/fee_asset_handler.js +59 -0
  29. package/dest/contracts/fee_asset_price_oracle.d.ts +105 -0
  30. package/dest/contracts/fee_asset_price_oracle.d.ts.map +1 -0
  31. package/dest/contracts/fee_asset_price_oracle.js +656 -0
  32. package/dest/contracts/fee_juice.d.ts +14 -0
  33. package/dest/contracts/fee_juice.d.ts.map +1 -0
  34. package/dest/contracts/fee_juice.js +59 -0
  35. package/dest/contracts/governance.d.ts +192 -0
  36. package/dest/contracts/governance.d.ts.map +1 -0
  37. package/dest/contracts/governance.js +471 -0
  38. package/dest/contracts/governance_proposer.d.ts +63 -0
  39. package/dest/contracts/governance_proposer.d.ts.map +1 -0
  40. package/dest/contracts/governance_proposer.js +536 -0
  41. package/dest/contracts/gse.d.ts +38 -0
  42. package/dest/contracts/gse.d.ts.map +1 -0
  43. package/dest/contracts/gse.js +81 -0
  44. package/dest/contracts/inbox.d.ts +94 -0
  45. package/dest/contracts/inbox.d.ts.map +1 -0
  46. package/dest/contracts/inbox.js +141 -0
  47. package/dest/contracts/index.d.ts +18 -0
  48. package/dest/contracts/index.d.ts.map +1 -0
  49. package/dest/contracts/index.js +17 -0
  50. package/dest/contracts/log.d.ts +13 -0
  51. package/dest/contracts/log.d.ts.map +1 -0
  52. package/dest/contracts/log.js +1 -0
  53. package/dest/contracts/multicall.d.ts +138 -0
  54. package/dest/contracts/multicall.d.ts.map +1 -0
  55. package/dest/contracts/multicall.js +266 -0
  56. package/dest/contracts/outbox.d.ts +64 -0
  57. package/dest/contracts/outbox.d.ts.map +1 -0
  58. package/dest/contracts/outbox.js +113 -0
  59. package/dest/contracts/registry.d.ts +31 -0
  60. package/dest/contracts/registry.d.ts.map +1 -0
  61. package/dest/contracts/registry.js +142 -0
  62. package/dest/contracts/rollup.d.ts +5836 -0
  63. package/dest/contracts/rollup.d.ts.map +1 -0
  64. package/dest/contracts/rollup.js +1612 -0
  65. package/dest/contracts/slasher_contract.d.ts +44 -0
  66. package/dest/contracts/slasher_contract.d.ts.map +1 -0
  67. package/dest/contracts/slasher_contract.js +75 -0
  68. package/dest/contracts/slashing_proposer.d.ts +174 -0
  69. package/dest/contracts/slashing_proposer.d.ts.map +1 -0
  70. package/dest/contracts/slashing_proposer.js +755 -0
  71. package/dest/contracts/utils.d.ts +3 -0
  72. package/dest/contracts/utils.d.ts.map +1 -0
  73. package/dest/contracts/utils.js +11 -0
  74. package/dest/contracts/watch_event.d.ts +36 -0
  75. package/dest/contracts/watch_event.d.ts.map +1 -0
  76. package/dest/contracts/watch_event.js +66 -0
  77. package/dest/deploy_aztec_l1_contracts.d.ts +267 -0
  78. package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -0
  79. package/dest/deploy_aztec_l1_contracts.js +424 -0
  80. package/dest/deploy_l1_contract.d.ts +68 -0
  81. package/dest/deploy_l1_contract.d.ts.map +1 -0
  82. package/dest/deploy_l1_contract.js +312 -0
  83. package/dest/eth-signer/eth-signer.d.ts +21 -0
  84. package/dest/eth-signer/eth-signer.d.ts.map +1 -0
  85. package/dest/eth-signer/eth-signer.js +5 -0
  86. package/dest/eth-signer/index.d.ts +2 -0
  87. package/dest/eth-signer/index.d.ts.map +1 -0
  88. package/dest/eth-signer/index.js +1 -0
  89. package/dest/forwarder_proxy.d.ts +32 -0
  90. package/dest/forwarder_proxy.d.ts.map +1 -0
  91. package/dest/forwarder_proxy.js +93 -0
  92. package/dest/foundry_binary.d.ts +13 -0
  93. package/dest/foundry_binary.d.ts.map +1 -0
  94. package/dest/foundry_binary.js +52 -0
  95. package/dest/l1_artifacts.d.ts +81896 -0
  96. package/dest/l1_artifacts.d.ts.map +1 -0
  97. package/dest/l1_artifacts.js +151 -0
  98. package/dest/l1_contract_addresses.d.ts +73 -0
  99. package/dest/l1_contract_addresses.d.ts.map +1 -0
  100. package/dest/l1_contract_addresses.js +120 -0
  101. package/dest/l1_reader.d.ts +18 -0
  102. package/dest/l1_reader.d.ts.map +1 -0
  103. package/dest/l1_reader.js +35 -0
  104. package/dest/l1_tx_utils/config.d.ts +65 -0
  105. package/dest/l1_tx_utils/config.d.ts.map +1 -0
  106. package/dest/l1_tx_utils/config.js +109 -0
  107. package/dest/l1_tx_utils/constants.d.ts +12 -0
  108. package/dest/l1_tx_utils/constants.d.ts.map +1 -0
  109. package/dest/l1_tx_utils/constants.js +39 -0
  110. package/dest/l1_tx_utils/factory.d.ts +32 -0
  111. package/dest/l1_tx_utils/factory.d.ts.map +1 -0
  112. package/dest/l1_tx_utils/factory.js +22 -0
  113. package/dest/l1_tx_utils/fee-strategies/index.d.ts +10 -0
  114. package/dest/l1_tx_utils/fee-strategies/index.d.ts.map +1 -0
  115. package/dest/l1_tx_utils/fee-strategies/index.js +12 -0
  116. package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts +8 -0
  117. package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts.map +1 -0
  118. package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +129 -0
  119. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts +23 -0
  120. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts.map +1 -0
  121. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +191 -0
  122. package/dest/l1_tx_utils/fee-strategies/types.d.ts +51 -0
  123. package/dest/l1_tx_utils/fee-strategies/types.d.ts.map +1 -0
  124. package/dest/l1_tx_utils/fee-strategies/types.js +3 -0
  125. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +41 -0
  126. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -0
  127. package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +42 -0
  128. package/dest/l1_tx_utils/index-blobs.d.ts +3 -0
  129. package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -0
  130. package/dest/l1_tx_utils/index-blobs.js +2 -0
  131. package/dest/l1_tx_utils/index.d.ts +13 -0
  132. package/dest/l1_tx_utils/index.d.ts.map +1 -0
  133. package/dest/l1_tx_utils/index.js +13 -0
  134. package/dest/l1_tx_utils/interfaces.d.ts +76 -0
  135. package/dest/l1_tx_utils/interfaces.d.ts.map +1 -0
  136. package/dest/l1_tx_utils/interfaces.js +4 -0
  137. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts +252 -0
  138. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts.map +1 -0
  139. package/dest/l1_tx_utils/l1_fee_analyzer.js +568 -0
  140. package/dest/l1_tx_utils/l1_tx_utils.d.ts +113 -0
  141. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -0
  142. package/dest/l1_tx_utils/l1_tx_utils.js +720 -0
  143. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +83 -0
  144. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -0
  145. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +357 -0
  146. package/dest/l1_tx_utils/signer.d.ts +4 -0
  147. package/dest/l1_tx_utils/signer.d.ts.map +1 -0
  148. package/dest/l1_tx_utils/signer.js +16 -0
  149. package/dest/l1_tx_utils/tx_delayer.d.ts +58 -0
  150. package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -0
  151. package/dest/l1_tx_utils/tx_delayer.js +223 -0
  152. package/dest/l1_tx_utils/types.d.ts +93 -0
  153. package/dest/l1_tx_utils/types.d.ts.map +1 -0
  154. package/dest/l1_tx_utils/types.js +36 -0
  155. package/dest/l1_tx_utils/utils.d.ts +4 -0
  156. package/dest/l1_tx_utils/utils.d.ts.map +1 -0
  157. package/dest/l1_tx_utils/utils.js +14 -0
  158. package/dest/l1_types.d.ts +6 -0
  159. package/dest/l1_types.d.ts.map +1 -0
  160. package/dest/l1_types.js +1 -0
  161. package/dest/publisher_manager.d.ts +42 -0
  162. package/dest/publisher_manager.d.ts.map +1 -0
  163. package/dest/publisher_manager.js +199 -0
  164. package/dest/queries.d.ts +25 -0
  165. package/dest/queries.d.ts.map +1 -0
  166. package/dest/queries.js +144 -0
  167. package/dest/test/blob_kzg_warmup.d.ts +19 -0
  168. package/dest/test/blob_kzg_warmup.d.ts.map +1 -0
  169. package/dest/test/blob_kzg_warmup.js +64 -0
  170. package/dest/test/chain_monitor.d.ts +126 -0
  171. package/dest/test/chain_monitor.d.ts.map +1 -0
  172. package/dest/test/chain_monitor.js +314 -0
  173. package/dest/test/eth_cheat_codes.d.ts +260 -0
  174. package/dest/test/eth_cheat_codes.d.ts.map +1 -0
  175. package/dest/test/eth_cheat_codes.js +608 -0
  176. package/dest/test/eth_cheat_codes_with_state.d.ts +18 -0
  177. package/dest/test/eth_cheat_codes_with_state.d.ts.map +1 -0
  178. package/dest/test/eth_cheat_codes_with_state.js +34 -0
  179. package/dest/test/index.d.ts +8 -0
  180. package/dest/test/index.d.ts.map +1 -0
  181. package/dest/test/index.js +7 -0
  182. package/dest/test/recording_rpc_server.d.ts +18 -0
  183. package/dest/test/recording_rpc_server.d.ts.map +1 -0
  184. package/dest/test/recording_rpc_server.js +68 -0
  185. package/dest/test/rollup_cheat_codes.d.ts +142 -0
  186. package/dest/test/rollup_cheat_codes.d.ts.map +1 -0
  187. package/dest/test/rollup_cheat_codes.js +338 -0
  188. package/dest/test/start_anvil.d.ts +40 -0
  189. package/dest/test/start_anvil.d.ts.map +1 -0
  190. package/dest/test/start_anvil.js +210 -0
  191. package/dest/test/upgrade_utils.d.ts +12 -0
  192. package/dest/test/upgrade_utils.d.ts.map +1 -0
  193. package/dest/test/upgrade_utils.js +111 -0
  194. package/dest/types.d.ts +68 -0
  195. package/dest/types.d.ts.map +1 -0
  196. package/dest/types.js +3 -0
  197. package/dest/utils.d.ts +45 -0
  198. package/dest/utils.d.ts.map +1 -0
  199. package/dest/utils.js +260 -0
  200. package/dest/zkPassportVerifierAddress.d.ts +15 -0
  201. package/dest/zkPassportVerifierAddress.d.ts.map +1 -0
  202. package/dest/zkPassportVerifierAddress.js +11 -0
  203. package/package.json +122 -0
  204. package/src/account.ts +5 -0
  205. package/src/chain.ts +71 -0
  206. package/src/client.ts +165 -0
  207. package/src/config.ts +342 -0
  208. package/src/constants.ts +4 -0
  209. package/src/contracts/README.md +157 -0
  210. package/src/contracts/chain_state_override.ts +203 -0
  211. package/src/contracts/empire_base.ts +89 -0
  212. package/src/contracts/errors.ts +13 -0
  213. package/src/contracts/fee_asset_handler.ts +66 -0
  214. package/src/contracts/fee_asset_price_oracle.ts +284 -0
  215. package/src/contracts/fee_juice.ts +57 -0
  216. package/src/contracts/governance.ts +597 -0
  217. package/src/contracts/governance_proposer.ts +181 -0
  218. package/src/contracts/gse.ts +105 -0
  219. package/src/contracts/inbox.ts +223 -0
  220. package/src/contracts/index.ts +17 -0
  221. package/src/contracts/log.ts +13 -0
  222. package/src/contracts/multicall.ts +298 -0
  223. package/src/contracts/outbox.ts +132 -0
  224. package/src/contracts/registry.ts +161 -0
  225. package/src/contracts/rollup.ts +1502 -0
  226. package/src/contracts/slasher_contract.ts +89 -0
  227. package/src/contracts/slashing_proposer.ts +397 -0
  228. package/src/contracts/utils.ts +14 -0
  229. package/src/contracts/watch_event.ts +109 -0
  230. package/src/deploy_aztec_l1_contracts.ts +663 -0
  231. package/src/deploy_l1_contract.ts +361 -0
  232. package/src/eth-signer/eth-signer.ts +24 -0
  233. package/src/eth-signer/index.ts +1 -0
  234. package/src/forwarder_proxy.ts +107 -0
  235. package/src/foundry_binary.ts +57 -0
  236. package/src/l1_artifacts.ts +231 -0
  237. package/src/l1_contract_addresses.ts +149 -0
  238. package/src/l1_reader.ts +57 -0
  239. package/src/l1_tx_utils/README.md +177 -0
  240. package/src/l1_tx_utils/config.ts +181 -0
  241. package/src/l1_tx_utils/constants.ts +29 -0
  242. package/src/l1_tx_utils/factory.ts +64 -0
  243. package/src/l1_tx_utils/fee-strategies/index.ts +22 -0
  244. package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +162 -0
  245. package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +244 -0
  246. package/src/l1_tx_utils/fee-strategies/types.ts +55 -0
  247. package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +107 -0
  248. package/src/l1_tx_utils/index-blobs.ts +2 -0
  249. package/src/l1_tx_utils/index.ts +15 -0
  250. package/src/l1_tx_utils/interfaces.ts +86 -0
  251. package/src/l1_tx_utils/l1_fee_analyzer.ts +874 -0
  252. package/src/l1_tx_utils/l1_tx_utils.ts +840 -0
  253. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +459 -0
  254. package/src/l1_tx_utils/signer.ts +27 -0
  255. package/src/l1_tx_utils/tx_delayer.ts +302 -0
  256. package/src/l1_tx_utils/types.ts +116 -0
  257. package/src/l1_tx_utils/utils.ts +15 -0
  258. package/src/l1_types.ts +6 -0
  259. package/src/publisher_manager.ts +239 -0
  260. package/src/queries.ts +189 -0
  261. package/src/test/blob_kzg_warmup.ts +65 -0
  262. package/src/test/chain_monitor.ts +389 -0
  263. package/src/test/eth_cheat_codes.ts +624 -0
  264. package/src/test/eth_cheat_codes_with_state.ts +38 -0
  265. package/src/test/index.ts +7 -0
  266. package/src/test/recording_rpc_server.ts +69 -0
  267. package/src/test/rollup_cheat_codes.ts +398 -0
  268. package/src/test/start_anvil.ts +255 -0
  269. package/src/test/upgrade_utils.ts +109 -0
  270. package/src/types.ts +97 -0
  271. package/src/utils.ts +344 -0
  272. package/src/zkPassportVerifierAddress.ts +15 -0
@@ -0,0 +1,181 @@
1
+ import { GovernanceProposerAbi } from '@aztec/l1-artifacts/GovernanceProposerAbi';
2
+
3
+ import { SlotNumber } from '@aztec-labs/foundation/branded-types';
4
+ import { memoize } from '@aztec-labs/foundation/decorators';
5
+ import { EthAddress } from '@aztec-labs/foundation/eth-address';
6
+ import {
7
+ type GetContractReturnType,
8
+ type Hex,
9
+ type TransactionReceipt,
10
+ type TypedDataDefinition,
11
+ encodeFunctionData,
12
+ getContract,
13
+ } from 'viem';
14
+
15
+ import type { L1TxRequest, L1TxUtils } from '../l1_tx_utils/index.js';
16
+ import type { ViemClient } from '../types.js';
17
+ import { type IEmpireBase, encodeSignal, encodeSignalWithSignature, signSignalWithSig } from './empire_base.js';
18
+ import { type PayloadProposalStatus, ReadOnlyGovernanceContract, extractProposalIdFromLogs } from './governance.js';
19
+
20
+ export class GovernanceProposerContract implements IEmpireBase {
21
+ private readonly proposer: GetContractReturnType<typeof GovernanceProposerAbi, ViemClient>;
22
+
23
+ /**
24
+ * Cache of bytecode-existence checks keyed by payload address. The check is stable for a
25
+ * contract's lifetime -- a contract either has code or it does not, and code cannot be removed
26
+ * after deployment (selfdestruct aside, which is not relevant here). Safe to memoize
27
+ * indefinitely for the lifetime of this instance.
28
+ */
29
+ private readonly emptyPayloadCache: Map<Hex, boolean> = new Map();
30
+
31
+ constructor(
32
+ public readonly client: ViemClient,
33
+ address: Hex | EthAddress,
34
+ ) {
35
+ if (address instanceof EthAddress) {
36
+ address = address.toString();
37
+ }
38
+ this.proposer = getContract({ address, abi: GovernanceProposerAbi, client });
39
+ }
40
+
41
+ public get address(): EthAddress {
42
+ return EthAddress.fromString(this.proposer.address);
43
+ }
44
+
45
+ public async getRollupAddress(): Promise<EthAddress> {
46
+ return EthAddress.fromString(await this.proposer.read.getInstance());
47
+ }
48
+
49
+ @memoize
50
+ public async getRegistryAddress(): Promise<EthAddress> {
51
+ return EthAddress.fromString(await this.proposer.read.REGISTRY());
52
+ }
53
+
54
+ public getQuorumSize(): Promise<bigint> {
55
+ return this.proposer.read.QUORUM_SIZE();
56
+ }
57
+
58
+ public getRoundSize(): Promise<bigint> {
59
+ return this.proposer.read.ROUND_SIZE();
60
+ }
61
+
62
+ public computeRound(slot: SlotNumber): Promise<bigint> {
63
+ return this.proposer.read.computeRound([BigInt(slot)]);
64
+ }
65
+
66
+ public async getRoundInfo(
67
+ rollupAddress: Hex,
68
+ round: bigint,
69
+ ): Promise<{ lastSignalSlot: SlotNumber; payloadWithMostSignals: Hex; quorumReached: boolean; executed: boolean }> {
70
+ const result = await this.proposer.read.getRoundData([rollupAddress, round]);
71
+ const [signalCount, quorum] = await Promise.all([
72
+ this.proposer.read.signalCount([rollupAddress, round, result.payloadWithMostSignals]),
73
+ this.getQuorumSize(),
74
+ ]);
75
+ return {
76
+ lastSignalSlot: SlotNumber.fromBigInt(result.lastSignalSlot),
77
+ payloadWithMostSignals: result.payloadWithMostSignals,
78
+ quorumReached: signalCount >= quorum,
79
+ executed: result.executed,
80
+ };
81
+ }
82
+
83
+ public getPayloadSignals(rollupAddress: Hex, round: bigint, payload: Hex): Promise<bigint> {
84
+ return this.proposer.read.signalCount([rollupAddress, round, payload]);
85
+ }
86
+
87
+ public createSignalRequest(payload: Hex): L1TxRequest {
88
+ return {
89
+ to: this.address.toString(),
90
+ abi: GovernanceProposerAbi,
91
+ data: encodeSignal(payload),
92
+ };
93
+ }
94
+
95
+ public async createSignalRequestWithSignature(
96
+ payload: Hex,
97
+ slot: SlotNumber,
98
+ chainId: number,
99
+ signerAddress: Hex,
100
+ signer: (msg: TypedDataDefinition) => Promise<Hex>,
101
+ ): Promise<L1TxRequest> {
102
+ const signature = await signSignalWithSig(
103
+ signer,
104
+ payload,
105
+ slot,
106
+ (await this.getRollupAddress()).toString(),
107
+ this.address.toString(),
108
+ chainId,
109
+ );
110
+ return {
111
+ to: this.address.toString(),
112
+ abi: GovernanceProposerAbi,
113
+ data: encodeSignalWithSignature(payload, signature),
114
+ };
115
+ }
116
+
117
+ /**
118
+ * Resolves the Governance contract this proposer submits winners to. Lazily reads
119
+ * `GovernanceProposer.getGovernance()` (which itself looks the address up via the registry) and
120
+ * memoizes the resulting wrapper.
121
+ */
122
+ @memoize
123
+ public async getGovernance(): Promise<ReadOnlyGovernanceContract> {
124
+ const address = await this.proposer.read.getGovernance();
125
+ return new ReadOnlyGovernanceContract(address, this.client);
126
+ }
127
+
128
+ /**
129
+ * Classifies the given original payload against the Governance proposal history (`'live'` /
130
+ * `'executed'` / `'none'`). Delegates to `ReadOnlyGovernanceContract.getPayloadProposalStatus`,
131
+ * which implements the actual sweep against the Governance contract -- this method exists only as
132
+ * a convenience wrapper so callers that already hold a GovernanceProposer reference don't have to
133
+ * resolve the Governance address themselves.
134
+ */
135
+ public async getPayloadProposalStatus(payload: Hex): Promise<PayloadProposalStatus> {
136
+ const governance = await this.getGovernance();
137
+ return governance.getPayloadProposalStatus(payload);
138
+ }
139
+
140
+ /**
141
+ * Returns true if the given payload address has no deployed bytecode. Used as a cheap
142
+ * pre-flight check before casting a governance signal — voting for a zero-code address
143
+ * is unrecoverable.
144
+ *
145
+ * We only cache the `false` result (address has bytecode). The `true` result is NOT
146
+ * cached because a CREATE2-redeployed address could go from empty to populated, and
147
+ * caching `true` would make us keep skipping a payload that later becomes valid.
148
+ */
149
+ public async isPayloadEmpty(payload: EthAddress): Promise<boolean> {
150
+ const key = payload.toString() as Hex;
151
+ if (this.emptyPayloadCache.get(key) === false) {
152
+ return false;
153
+ }
154
+ const code = await this.client.getCode({ address: key });
155
+ const isEmpty = !code || code === '0x';
156
+ if (!isEmpty) {
157
+ this.emptyPayloadCache.set(key, false);
158
+ }
159
+ return isEmpty;
160
+ }
161
+
162
+ public async submitRoundWinner(
163
+ round: bigint,
164
+ l1TxUtils: L1TxUtils,
165
+ ): Promise<{
166
+ receipt: TransactionReceipt;
167
+ proposalId: bigint;
168
+ }> {
169
+ const { receipt } = await l1TxUtils.sendAndMonitorTransaction({
170
+ to: this.address.toString(),
171
+ abi: GovernanceProposerAbi,
172
+ data: encodeFunctionData({
173
+ abi: GovernanceProposerAbi,
174
+ functionName: 'submitRoundWinner',
175
+ args: [round],
176
+ }),
177
+ });
178
+ const proposalId = extractProposalIdFromLogs(receipt.logs);
179
+ return { receipt, proposalId };
180
+ }
181
+ }
@@ -0,0 +1,105 @@
1
+ import { GSEAbi } from '@aztec/l1-artifacts/GSEAbi';
2
+
3
+ import { EthAddress } from '@aztec-labs/foundation/eth-address';
4
+ import type { ProjPointType } from '@noble/curves/abstract/weierstrass';
5
+ import { bn254 } from '@noble/curves/bn254';
6
+ import { type GetContractReturnType, type Hex, getContract } from 'viem';
7
+
8
+ import type { ViemClient } from '../types.js';
9
+
10
+ export type RegistrationTuple = {
11
+ publicKeyInG1: {
12
+ x: bigint;
13
+ y: bigint;
14
+ };
15
+ publicKeyInG2: {
16
+ x0: bigint;
17
+ x1: bigint;
18
+ y0: bigint;
19
+ y1: bigint;
20
+ };
21
+ proofOfPossession: {
22
+ x: bigint;
23
+ y: bigint;
24
+ };
25
+ };
26
+
27
+ export class GSEContract {
28
+ public address: EthAddress;
29
+ private readonly gse: GetContractReturnType<typeof GSEAbi, ViemClient>;
30
+
31
+ constructor(
32
+ public readonly client: ViemClient,
33
+ address: Hex | EthAddress,
34
+ ) {
35
+ if (address instanceof EthAddress) {
36
+ address = address.toString();
37
+ }
38
+ this.address = EthAddress.fromString(address);
39
+ this.gse = getContract({ address, abi: GSEAbi, client });
40
+ }
41
+
42
+ public async getOwner(): Promise<EthAddress> {
43
+ return EthAddress.fromString(await this.gse.read.owner());
44
+ }
45
+
46
+ public async getGovernance(): Promise<EthAddress> {
47
+ return EthAddress.fromString(await this.gse.read.getGovernance());
48
+ }
49
+
50
+ getAttestersFromIndicesAtTime(
51
+ instance: Hex | EthAddress,
52
+ ts: bigint,
53
+ indices: bigint[],
54
+ options?: { blockNumber?: bigint },
55
+ ) {
56
+ if (instance instanceof EthAddress) {
57
+ instance = instance.toString();
58
+ }
59
+ return this.gse.read.getAttestersFromIndicesAtTime([instance, ts, indices], options);
60
+ }
61
+
62
+ /** Number of attesters registered to `instance` as of the given L1 timestamp. */
63
+ public async getAttesterCountAtTime(
64
+ instance: Hex | EthAddress,
65
+ ts: bigint,
66
+ options?: { blockNumber?: bigint },
67
+ ): Promise<number> {
68
+ if (instance instanceof EthAddress) {
69
+ instance = instance.toString();
70
+ }
71
+ return Number(await this.gse.read.getAttesterCountAtTime([instance, ts], options));
72
+ }
73
+
74
+ public async getRegistrationDigest(publicKey: ProjPointType<bigint>): Promise<ProjPointType<bigint>> {
75
+ const affinePublicKey = publicKey.toAffine();
76
+ const g1PointDigest = await this.gse.read.getRegistrationDigest([{ x: affinePublicKey.x, y: affinePublicKey.y }]);
77
+ return bn254.G1.ProjectivePoint.fromAffine(g1PointDigest);
78
+ }
79
+
80
+ public async makeRegistrationTuple(privateKey: bigint): Promise<RegistrationTuple> {
81
+ const publicKeyG1 = bn254.G1.ProjectivePoint.BASE.multiply(privateKey);
82
+ const digest = await this.getRegistrationDigest(publicKeyG1);
83
+ const signature = digest.multiply(privateKey);
84
+ const publicKeyG2 = bn254.G2.ProjectivePoint.BASE.multiply(privateKey);
85
+ const publicKeyG1Affine = publicKeyG1.toAffine();
86
+ const signatureAffine = signature.toAffine();
87
+ const publicKeyG2Affine = publicKeyG2.toAffine();
88
+ return {
89
+ publicKeyInG1: {
90
+ x: publicKeyG1Affine.x,
91
+ y: publicKeyG1Affine.y,
92
+ },
93
+ publicKeyInG2: {
94
+ x0: publicKeyG2Affine.x.c0,
95
+ x1: publicKeyG2Affine.x.c1,
96
+ y0: publicKeyG2Affine.y.c0,
97
+ y1: publicKeyG2Affine.y.c1,
98
+ },
99
+ proofOfPossession: {
100
+ x: signatureAffine.x,
101
+ y: signatureAffine.y,
102
+ },
103
+ };
104
+ }
105
+ }
@@ -0,0 +1,223 @@
1
+ import { InboxAbi } from '@aztec/l1-artifacts/InboxAbi';
2
+
3
+ import { asyncPool } from '@aztec-labs/foundation/async-pool';
4
+ import { maxBigint } from '@aztec-labs/foundation/bigint';
5
+ import { Buffer32 } from '@aztec-labs/foundation/buffer';
6
+ import { Fr } from '@aztec-labs/foundation/curves/bn254';
7
+ import { EthAddress } from '@aztec-labs/foundation/eth-address';
8
+ import { type BlockTag, type GetContractReturnType, type Hex, getContract } from 'viem';
9
+
10
+ import { getPublicClient } from '../client.js';
11
+ import type { DeployAztecL1ContractsReturnType } from '../deploy_aztec_l1_contracts.js';
12
+ import type { L1ReaderConfig } from '../l1_reader.js';
13
+ import type { ViemClient } from '../types.js';
14
+ import type { L1EventLog } from './log.js';
15
+ import { checkBlockTag } from './utils.js';
16
+
17
+ /** The full L1-to-L2 message emitted by the Inbox, decoded from the event. Hashing it yields `leaf`. */
18
+ export type MessageSentMessage = {
19
+ sender: { actor: `0x${string}`; chainId: bigint };
20
+ recipient: { actor: Fr; version: bigint };
21
+ content: Fr;
22
+ secretHash: Fr;
23
+ index: bigint;
24
+ };
25
+
26
+ /** Arguments for the MessageSent event. */
27
+ export type MessageSentArgs = {
28
+ /** Compact cumulative index of the message in the Inbox insertion order (lifted from `message.index`). */
29
+ index: bigint;
30
+ leaf: Fr;
31
+ /** Consensus rolling hash (truncated sha256 chain) after this message. */
32
+ inboxRollingHash: Fr;
33
+ /** Sequence number of the Inbox bucket this message was absorbed into. */
34
+ bucketSeq: bigint;
35
+ /** The full message as emitted, making the event a self-contained record. */
36
+ message: MessageSentMessage;
37
+ };
38
+
39
+ /** Log type for MessageSent events, enriched with the emitting L1 block's timestamp (the bucket recency key). */
40
+ export type MessageSentLog = L1EventLog<MessageSentArgs> & {
41
+ /** Timestamp (in seconds) of the L1 block that emitted the event; the key of the message's Inbox bucket. */
42
+ l1BlockTimestamp: bigint;
43
+ };
44
+
45
+ export class InboxContract {
46
+ private readonly inbox: GetContractReturnType<typeof InboxAbi, ViemClient>;
47
+
48
+ static getFromL1ContractsValues(deployL1ContractsValues: DeployAztecL1ContractsReturnType) {
49
+ const {
50
+ l1Client,
51
+ l1ContractAddresses: { inboxAddress },
52
+ } = deployL1ContractsValues;
53
+ return new InboxContract(l1Client, inboxAddress.toString());
54
+ }
55
+
56
+ static getFromConfig(config: L1ReaderConfig) {
57
+ const client = getPublicClient(config);
58
+ const address = config.inboxAddress.toString();
59
+ return new InboxContract(client, address);
60
+ }
61
+
62
+ constructor(
63
+ public readonly client: ViemClient,
64
+ address: Hex | EthAddress,
65
+ ) {
66
+ if (address instanceof EthAddress) {
67
+ address = address.toString();
68
+ }
69
+ this.inbox = getContract({ address, abi: InboxAbi, client });
70
+ }
71
+
72
+ public get address() {
73
+ return this.inbox.address;
74
+ }
75
+
76
+ public getContract(): GetContractReturnType<typeof InboxAbi, ViemClient> {
77
+ return this.inbox;
78
+ }
79
+
80
+ /**
81
+ * Returns the Inbox's live chain position in one atomic call: the consensus rolling hash and cumulative total
82
+ * after the most recent message, plus the current bucket sequence. Used by the archiver's message sync and
83
+ * L1-reorg detection.
84
+ */
85
+ public async getState(opts: { blockTag?: BlockTag; blockNumber?: bigint } = {}): Promise<InboxContractState> {
86
+ await checkBlockTag(opts.blockNumber, this.client);
87
+ const state = await this.inbox.read.getState(opts);
88
+ return {
89
+ rollingHash: Fr.fromString(state.rollingHash),
90
+ totalMessagesInserted: state.totalMessagesInserted,
91
+ currentBucketSeq: state.currentBucketSeq,
92
+ };
93
+ }
94
+
95
+ /** Returns the sequence number of the Inbox bucket currently accumulating messages. */
96
+ public async getCurrentBucketSeq(opts: { blockTag?: BlockTag; blockNumber?: bigint } = {}): Promise<bigint> {
97
+ await checkBlockTag(opts.blockNumber, this.client);
98
+ return this.inbox.read.getCurrentBucketSeq(opts);
99
+ }
100
+
101
+ /** Returns the Inbox bucket with the given sequence number. */
102
+ public async getBucket(
103
+ seq: bigint,
104
+ opts: { blockTag?: BlockTag; blockNumber?: bigint } = {},
105
+ ): Promise<InboxContractBucket> {
106
+ await checkBlockTag(opts.blockNumber, this.client);
107
+ const bucket = await this.inbox.read.getBucket([seq], opts);
108
+ return {
109
+ rollingHash: Fr.fromString(bucket.rollingHash),
110
+ totalMsgCount: bucket.totalMsgCount,
111
+ timestamp: bucket.timestamp,
112
+ msgCount: bucket.msgCount,
113
+ };
114
+ }
115
+
116
+ /** Fetches MessageSent events within the given block range. */
117
+ async getMessageSentEvents(fromBlock: bigint, toBlock: bigint): Promise<MessageSentLog[]> {
118
+ const logs = (await this.inbox.getEvents.MessageSent({}, { fromBlock, toBlock })).filter(
119
+ log => log.blockNumber! >= fromBlock && log.blockNumber! <= toBlock,
120
+ );
121
+ const timestamps = await this.getBlockTimestamps(logs.map(log => log.blockHash!));
122
+ return logs.map(log => this.mapMessageSentLog(log, timestamps.get(log.blockHash!)!));
123
+ }
124
+
125
+ /** Fetches MessageSent events for a specific message hash around a specific block. */
126
+ async getMessageSentEventByHash(msgHash: Hex, aroundL1BlockNumber: bigint): Promise<MessageSentLog> {
127
+ // 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
128
+ // due to an L1 reorg. The use case for this method is usually checking if a message still exists on the Inbox after
129
+ // a reorg, so it's possible the message was moved one block up or down, and that the original L1 block where we
130
+ // saw it no longer exists, rendering the block-by-hash approach invalid.
131
+ const [log] = await this.inbox.getEvents.MessageSent(
132
+ { hash: msgHash },
133
+ { fromBlock: maxBigint(aroundL1BlockNumber - 5n, 1n), toBlock: aroundL1BlockNumber + 5n },
134
+ );
135
+ if (!log) {
136
+ return log as unknown as MessageSentLog;
137
+ }
138
+ const [timestamp] = (await this.getBlockTimestamps([log.blockHash!])).values();
139
+ return this.mapMessageSentLog(log, timestamp);
140
+ }
141
+
142
+ /**
143
+ * Fetches the timestamp of each distinct L1 block, so each MessageSent log can carry its bucket key. Blocks are
144
+ * resolved by hash, which pins them to the same fork the logs were read from: resolving by number would silently
145
+ * return the same-height block of another fork if the chain reorgs between the log query and this lookup, storing a
146
+ * timestamp that never applied to the message. By hash, such a reorg fails the lookup instead, and the caller
147
+ * retries against the reorged chain. Fetched with bounded concurrency to keep a large sync batch from fanning out
148
+ * unbounded RPC requests.
149
+ */
150
+ private async getBlockTimestamps(blockHashes: Hex[]): Promise<Map<Hex, bigint>> {
151
+ const uniqueBlockHashes = [...new Set(blockHashes)];
152
+ const timestamps = new Map<Hex, bigint>();
153
+ await asyncPool(10, uniqueBlockHashes, async blockHash => {
154
+ const block = await this.client.getBlock({ blockHash, includeTransactions: false });
155
+ timestamps.set(blockHash, block.timestamp);
156
+ });
157
+ return timestamps;
158
+ }
159
+
160
+ private mapMessageSentLog(
161
+ log: {
162
+ blockNumber: bigint | null;
163
+ blockHash: `0x${string}` | null;
164
+ transactionHash: `0x${string}` | null;
165
+ args: {
166
+ hash?: `0x${string}`;
167
+ inboxRollingHash?: `0x${string}`;
168
+ bucketSeq?: bigint;
169
+ message?: {
170
+ sender: { actor: `0x${string}`; chainId: bigint };
171
+ recipient: { actor: `0x${string}`; version: bigint };
172
+ content: `0x${string}`;
173
+ secretHash: `0x${string}`;
174
+ index: bigint;
175
+ };
176
+ };
177
+ },
178
+ l1BlockTimestamp: bigint,
179
+ ): MessageSentLog {
180
+ const message = log.args.message!;
181
+ return {
182
+ l1BlockNumber: log.blockNumber!,
183
+ l1BlockHash: Buffer32.fromString(log.blockHash!),
184
+ l1TransactionHash: log.transactionHash!,
185
+ l1BlockTimestamp,
186
+ args: {
187
+ index: message.index,
188
+ leaf: Fr.fromString(log.args.hash!),
189
+ inboxRollingHash: Fr.fromString(log.args.inboxRollingHash!),
190
+ bucketSeq: log.args.bucketSeq!,
191
+ message: {
192
+ sender: message.sender,
193
+ recipient: { actor: Fr.fromString(message.recipient.actor), version: message.recipient.version },
194
+ content: Fr.fromString(message.content),
195
+ secretHash: Fr.fromString(message.secretHash),
196
+ index: message.index,
197
+ },
198
+ },
199
+ };
200
+ }
201
+ }
202
+
203
+ /** The Inbox's live chain position, read atomically from the contract's getState. */
204
+ export type InboxContractState = {
205
+ /** Consensus rolling hash after the most recently inserted message (zero when none was ever inserted). */
206
+ rollingHash: Fr;
207
+ /** Cumulative number of messages inserted into the Inbox. */
208
+ totalMessagesInserted: bigint;
209
+ /** Sequence number of the bucket currently accumulating messages. */
210
+ currentBucketSeq: bigint;
211
+ };
212
+
213
+ /** A snapshot of an on-chain Inbox rolling-hash bucket. */
214
+ export type InboxContractBucket = {
215
+ /** Consensus rolling hash (truncated sha256 chain) after the last message absorbed into this bucket. */
216
+ rollingHash: Fr;
217
+ /** Cumulative number of messages inserted into the Inbox up to and including this bucket. */
218
+ totalMsgCount: bigint;
219
+ /** L1 block timestamp at which this bucket was opened; its recency key, in seconds. */
220
+ timestamp: bigint;
221
+ /** Number of messages absorbed into this bucket. */
222
+ msgCount: number;
223
+ };
@@ -0,0 +1,17 @@
1
+ export * from './chain_state_override.js';
2
+ export * from './empire_base.js';
3
+ export * from './errors.js';
4
+ export * from './fee_asset_handler.js';
5
+ export * from './fee_asset_price_oracle.js';
6
+ export * from './fee_juice.js';
7
+ export * from './governance.js';
8
+ export * from './governance_proposer.js';
9
+ export * from './gse.js';
10
+ export * from './inbox.js';
11
+ export * from './log.js';
12
+ export * from './multicall.js';
13
+ export * from './outbox.js';
14
+ export * from './registry.js';
15
+ export * from './rollup.js';
16
+ export * from './slashing_proposer.js';
17
+ export * from './slasher_contract.js';
@@ -0,0 +1,13 @@
1
+ import type { Buffer32 } from '@aztec-labs/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
+ };