@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
package/src/l1_reader.ts CHANGED
@@ -1,4 +1,9 @@
1
- import { type ConfigMappingsType, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config';
1
+ import {
2
+ type ConfigMappingsType,
3
+ getConfigFromMappings,
4
+ numberConfigHelper,
5
+ optionalNumberConfigHelper,
6
+ } from '@aztec/foundation/config';
2
7
 
3
8
  import { type L1ContractAddresses, l1ContractAddressesMapping } from './l1_contract_addresses.js';
4
9
 
@@ -6,12 +11,16 @@ import { type L1ContractAddresses, l1ContractAddressesMapping } from './l1_contr
6
11
  export interface L1ReaderConfig {
7
12
  /** List of URLs of Ethereum RPC nodes that services will connect to (comma separated). */
8
13
  l1RpcUrls: string[];
14
+ /** The RPC Url of the ethereum debug host for trace and debug methods. */
15
+ l1DebugRpcUrls: string[];
9
16
  /** The chain ID of the ethereum host. */
10
17
  l1ChainId: number;
11
18
  /** The deployed l1 contract addresses */
12
19
  l1Contracts: L1ContractAddresses;
13
20
  /** The polling interval viem uses in ms */
14
21
  viemPollingIntervalMS: number;
22
+ /** Timeout for HTTP requests to the L1 RPC node in ms. */
23
+ l1HttpTimeoutMS?: number;
15
24
  }
16
25
 
17
26
  export const l1ReaderConfigMappings: ConfigMappingsType<L1ReaderConfig> = {
@@ -21,7 +30,7 @@ export const l1ReaderConfigMappings: ConfigMappingsType<L1ReaderConfig> = {
21
30
  },
22
31
  l1ChainId: {
23
32
  env: 'L1_CHAIN_ID',
24
- parseEnv: (val: string) => +val,
33
+ ...optionalNumberConfigHelper(),
25
34
  description: 'The chain ID of the ethereum host.',
26
35
  },
27
36
  l1RpcUrls: {
@@ -30,11 +39,22 @@ export const l1ReaderConfigMappings: ConfigMappingsType<L1ReaderConfig> = {
30
39
  parseEnv: (val: string) => val.split(',').map(url => url.trim()),
31
40
  defaultValue: [],
32
41
  },
42
+ l1DebugRpcUrls: {
43
+ env: 'ETHEREUM_DEBUG_HOSTS',
44
+ description: 'The RPC Url of the ethereum debug host for trace and debug methods.',
45
+ parseEnv: (val: string) => val.split(',').map(url => url.trim()),
46
+ defaultValue: [],
47
+ },
33
48
  viemPollingIntervalMS: {
34
49
  env: 'L1_READER_VIEM_POLLING_INTERVAL_MS',
35
50
  description: 'The polling interval viem uses in ms',
36
51
  ...numberConfigHelper(1_000),
37
52
  },
53
+ l1HttpTimeoutMS: {
54
+ env: 'ETHEREUM_HTTP_TIMEOUT_MS',
55
+ description: 'Timeout for HTTP requests to the L1 RPC node in ms.',
56
+ ...optionalNumberConfigHelper(),
57
+ },
38
58
  };
39
59
 
40
60
  export function getL1ReaderConfigFromEnv(): L1ReaderConfig {
@@ -5,6 +5,7 @@ import {
5
5
  getConfigFromMappings,
6
6
  getDefaultConfig,
7
7
  numberConfigHelper,
8
+ optionalNumberConfigHelper,
8
9
  } from '@aztec/foundation/config';
9
10
 
10
11
  export interface L1TxUtilsConfig {
@@ -29,9 +30,9 @@ export interface L1TxUtilsConfig {
29
30
  */
30
31
  priorityFeeRetryBumpPercentage?: number;
31
32
  /**
32
- * Fixed priority fee per gas in Gwei. Overrides any priority fee bump percentage config
33
+ * Minimum priority fee per gas in Gwei. Acts as a floor for the computed priority fee.
33
34
  */
34
- fixedPriorityFeePerGas?: number;
35
+ minimumPriorityFeePerGas?: number;
35
36
  /**
36
37
  * Maximum number of speed-up attempts
37
38
  */
@@ -60,6 +61,12 @@ export interface L1TxUtilsConfig {
60
61
  * How long a tx nonce can be unseen in the mempool before considering it dropped
61
62
  */
62
63
  txUnseenConsideredDroppedMs?: number;
64
+ /** Enable tx delayer. When true, wraps the viem client to intercept and delay txs. Test-only. */
65
+ enableDelayer?: boolean;
66
+ /** Max seconds into an L1 slot for tx inclusion. Txs sent later are deferred to next slot. Only used when enableDelayer is true. */
67
+ txDelayerMaxInclusionTimeIntoSlot?: number;
68
+ /** How many seconds an L1 slot lasts. */
69
+ ethereumSlotDuration?: number;
63
70
  }
64
71
 
65
72
  export const l1TxUtilsConfigMappings: ConfigMappingsType<L1TxUtilsConfig> = {
@@ -90,10 +97,21 @@ export const l1TxUtilsConfigMappings: ConfigMappingsType<L1TxUtilsConfig> = {
90
97
  env: 'L1_PRIORITY_FEE_RETRY_BUMP_PERCENTAGE',
91
98
  ...numberConfigHelper(50),
92
99
  },
93
- fixedPriorityFeePerGas: {
94
- description: 'Fixed priority fee per gas in Gwei. Overrides any priority fee bump percentage',
95
- env: 'L1_FIXED_PRIORITY_FEE_PER_GAS',
96
- fallback: ['L1_FIXED_PRIORITY_FEE_PER_GAS_GWEI'],
100
+ minimumPriorityFeePerGas: {
101
+ description:
102
+ 'Minimum priority fee per gas in Gwei. Acts as a floor for the computed priority fee. If network conditions require a higher fee, the higher fee will be used.',
103
+ env: 'L1_MINIMUM_PRIORITY_FEE_PER_GAS_GWEI',
104
+ fallback: ['L1_FIXED_PRIORITY_FEE_PER_GAS', 'L1_FIXED_PRIORITY_FEE_PER_GAS_GWEI'],
105
+ deprecatedFallback: [
106
+ {
107
+ env: 'L1_FIXED_PRIORITY_FEE_PER_GAS',
108
+ message: deprecatedFixedFeeMessage('L1_FIXED_PRIORITY_FEE_PER_GAS'),
109
+ },
110
+ {
111
+ env: 'L1_FIXED_PRIORITY_FEE_PER_GAS_GWEI',
112
+ message: deprecatedFixedFeeMessage('L1_FIXED_PRIORITY_FEE_PER_GAS_GWEI'),
113
+ },
114
+ ],
97
115
  ...floatConfigHelper(0),
98
116
  },
99
117
  maxSpeedUpAttempts: {
@@ -131,6 +149,19 @@ export const l1TxUtilsConfigMappings: ConfigMappingsType<L1TxUtilsConfig> = {
131
149
  env: 'L1_TX_MONITOR_TX_UNSEEN_CONSIDERED_DROPPED_MS',
132
150
  ...numberConfigHelper(6 * 12 * 1000), // 6 L1 blocks
133
151
  },
152
+ enableDelayer: {
153
+ description: 'Enable tx delayer for testing.',
154
+ ...booleanConfigHelper(false),
155
+ },
156
+ txDelayerMaxInclusionTimeIntoSlot: {
157
+ description: 'Max seconds into L1 slot for tx inclusion when delayer is enabled.',
158
+ ...optionalNumberConfigHelper(),
159
+ },
160
+ ethereumSlotDuration: {
161
+ env: 'ETHEREUM_SLOT_DURATION',
162
+ description: 'How many seconds an L1 slot lasts.',
163
+ ...numberConfigHelper(12),
164
+ },
134
165
  };
135
166
 
136
167
  // We abuse the fact that all mappings above have a non null default value and force-type this to Required
@@ -141,3 +172,10 @@ export const defaultL1TxUtilsConfig = getDefaultConfig<L1TxUtilsConfig>(
141
172
  export function getL1TxUtilsConfigEnvVars(): L1TxUtilsConfig {
142
173
  return getConfigFromMappings(l1TxUtilsConfigMappings);
143
174
  }
175
+
176
+ function deprecatedFixedFeeMessage(envVar: string): string {
177
+ return (
178
+ `Environment variable ${envVar} is deprecated. It is now used as a MINIMUM priority fee rather than a fixed value. ` +
179
+ 'Please use L1_MINIMUM_PRIORITY_FEE_PER_GAS_GWEI instead. If network conditions require a higher fee, the higher fee will be used.'
180
+ );
181
+ }
@@ -3,8 +3,8 @@
3
3
  // 1_000_000_000_000_000_000 Wei = 1 ETH
4
4
  export const WEI_CONST = 1_000_000_000n;
5
5
 
6
- // @note using this large gas limit to avoid the issue of `gas limit too low` when estimating gas in reth
7
- export const LARGE_GAS_LIMIT = 12_000_000n;
6
+ // EIP-7825: protocol-level cap on tx gas limit (2^24). Clients reject above this.
7
+ export const MAX_L1_TX_LIMIT = 16_777_216n;
8
8
 
9
9
  // setting a minimum bump percentage to 10% due to geth's implementation
10
10
  // https://github.com/ethereum/go-ethereum/blob/e3d61e6db028c412f74bc4d4c7e117a9e29d0de0/core/txpool/legacypool/list.go#L298
@@ -16,3 +16,14 @@ export const MIN_BLOB_REPLACEMENT_BUMP_PERCENTAGE = 100;
16
16
 
17
17
  // Avg ethereum block time is ~12s
18
18
  export const BLOCK_TIME_MS = 12_000;
19
+
20
+ // Gas per blob (EIP-4844)
21
+ export const GAS_PER_BLOB = 131072n;
22
+
23
+ // Blob capacity schedule based on Ethereum upgrades
24
+ export const BLOB_CAPACITY_SCHEDULE = [
25
+ { timestamp: 1734357600, target: 14, max: 21 }, // BPO2: Dec 17, 2025
26
+ { timestamp: 1733752800, target: 10, max: 15 }, // BPO1: Dec 9, 2025
27
+ { timestamp: 1733234400, target: 6, max: 9 }, // Fusaka: Dec 3, 2025
28
+ { timestamp: 0, target: 6, max: 9 }, // Pectra/earlier
29
+ ];
@@ -1,64 +1,64 @@
1
+ import type { BlobKzgInstance } from '@aztec/blob-lib/types';
1
2
  import { EthAddress } from '@aztec/foundation/eth-address';
2
3
  import type { Logger } from '@aztec/foundation/log';
3
4
  import { DateProvider } from '@aztec/foundation/timer';
4
5
 
5
- import type { TransactionSerializable } from 'viem';
6
-
7
6
  import type { EthSigner } from '../eth-signer/eth-signer.js';
8
7
  import type { ExtendedViemWalletClient, ViemClient } from '../types.js';
9
8
  import type { L1TxUtilsConfig } from './config.js';
10
9
  import type { IL1TxMetrics, IL1TxStore } from './interfaces.js';
11
10
  import { L1TxUtils } from './l1_tx_utils.js';
12
11
  import { createViemSigner } from './signer.js';
12
+ import { Delayer } from './tx_delayer.js';
13
13
  import type { SigningCallback } from './types.js';
14
14
 
15
- export function createL1TxUtilsFromViemWallet(
16
- client: ExtendedViemWalletClient,
17
- deps?: {
18
- logger?: Logger;
19
- dateProvider?: DateProvider;
20
- store?: IL1TxStore;
21
- metrics?: IL1TxMetrics;
22
- },
23
- config?: Partial<L1TxUtilsConfig> & { debugMaxGasLimit?: boolean },
24
- ): L1TxUtils {
25
- return new L1TxUtils(
15
+ /** Source of signing capability: either a wallet client or a separate client + signer. */
16
+ export type L1SignerSource = ExtendedViemWalletClient | { client: ViemClient; signer: EthSigner };
17
+
18
+ export function resolveSignerSource(source: L1SignerSource): {
19
+ client: ViemClient;
20
+ address: EthAddress;
21
+ signingCallback: SigningCallback;
22
+ } {
23
+ if ('account' in source && source.account) {
24
+ return {
25
+ client: source as ExtendedViemWalletClient,
26
+ address: EthAddress.fromString((source as ExtendedViemWalletClient).account.address),
27
+ signingCallback: createViemSigner(source as ExtendedViemWalletClient),
28
+ };
29
+ }
30
+ const { client, signer } = source as { client: ViemClient; signer: EthSigner };
31
+ return {
26
32
  client,
27
- EthAddress.fromString(client.account.address),
28
- createViemSigner(client),
29
- deps?.logger,
30
- deps?.dateProvider,
31
- config,
32
- config?.debugMaxGasLimit ?? false,
33
- deps?.store,
34
- deps?.metrics,
35
- );
33
+ address: signer.address,
34
+ signingCallback: async (tx, _addr) => (await signer.signTransaction(tx)).toViemTransactionSignature(),
35
+ };
36
36
  }
37
37
 
38
- export function createL1TxUtilsFromEthSigner(
39
- client: ViemClient,
40
- signer: EthSigner,
38
+ export function createL1TxUtils(
39
+ source: L1SignerSource,
41
40
  deps?: {
42
41
  logger?: Logger;
43
42
  dateProvider?: DateProvider;
44
43
  store?: IL1TxStore;
45
44
  metrics?: IL1TxMetrics;
45
+ kzg?: BlobKzgInstance;
46
+ delayer?: Delayer;
46
47
  },
47
48
  config?: Partial<L1TxUtilsConfig> & { debugMaxGasLimit?: boolean },
48
49
  ): L1TxUtils {
49
- const callback: SigningCallback = async (transaction: TransactionSerializable, _signingAddress) => {
50
- return (await signer.signTransaction(transaction)).toViemTransactionSignature();
51
- };
52
-
50
+ const { client, address, signingCallback } = resolveSignerSource(source);
53
51
  return new L1TxUtils(
54
52
  client,
55
- signer.address,
56
- callback,
53
+ address,
54
+ signingCallback,
57
55
  deps?.logger,
58
56
  deps?.dateProvider,
59
57
  config,
60
58
  config?.debugMaxGasLimit ?? false,
61
59
  deps?.store,
62
60
  deps?.metrics,
61
+ deps?.kzg,
62
+ deps?.delayer,
63
63
  );
64
64
  }
@@ -0,0 +1,22 @@
1
+ import { P75AllTxsPriorityFeeStrategy } from './p75_competitive.js';
2
+ import { P75BlobTxsOnlyPriorityFeeStrategy } from './p75_competitive_blob_txs_only.js';
3
+ import type { PriorityFeeStrategy } from './types.js';
4
+
5
+ export {
6
+ HISTORICAL_BLOCK_COUNT,
7
+ type PriorityFeeStrategy,
8
+ type PriorityFeeStrategyContext,
9
+ type PriorityFeeStrategyResult,
10
+ } from './types.js';
11
+
12
+ export { P75AllTxsPriorityFeeStrategy } from './p75_competitive.js';
13
+ export { P75BlobTxsOnlyPriorityFeeStrategy } from './p75_competitive_blob_txs_only.js';
14
+
15
+ /**
16
+ * Default list of priority fee strategies to analyze.
17
+ * Add more strategies here for comparison.
18
+ */
19
+ export const DEFAULT_PRIORITY_FEE_STRATEGIES: PriorityFeeStrategy[] = [
20
+ P75AllTxsPriorityFeeStrategy,
21
+ P75BlobTxsOnlyPriorityFeeStrategy,
22
+ ];
@@ -0,0 +1,163 @@
1
+ import { median } from '@aztec/foundation/collection';
2
+
3
+ import { formatGwei } from 'viem';
4
+
5
+ import type { ViemClient } from '../../types.js';
6
+ import { calculatePercentile } from '../../utils.js';
7
+ import { WEI_CONST } from '../constants.js';
8
+ import {
9
+ HISTORICAL_BLOCK_COUNT,
10
+ type PriorityFeeStrategy,
11
+ type PriorityFeeStrategyContext,
12
+ type PriorityFeeStrategyResult,
13
+ } from './types.js';
14
+
15
+ /**
16
+ * Our current competitive priority fee strategy.
17
+ * Analyzes p75 of pending transactions and 5-block fee history to determine a competitive priority fee.
18
+ * Falls back to network estimate if data is unavailable.
19
+ */
20
+ export const P75AllTxsPriorityFeeStrategy: PriorityFeeStrategy = {
21
+ name: 'Competitive (P75 + History) - CURRENT',
22
+ id: 'p75_pending_txs_and_history_all_txs',
23
+
24
+ async execute(client: ViemClient, context: PriorityFeeStrategyContext): Promise<PriorityFeeStrategyResult> {
25
+ const { isBlobTx, logger } = context;
26
+
27
+ // Fire all RPC calls in parallel
28
+ const [latestBlockResult, blobBaseFeeResult, networkEstimateResult, pendingBlockResult, feeHistoryResult] =
29
+ await Promise.allSettled([
30
+ client.getBlock({ blockTag: 'latest' }),
31
+ isBlobTx ? client.getBlobBaseFee() : Promise.resolve(undefined),
32
+ client.estimateMaxPriorityFeePerGas().catch(() => 0n),
33
+ client.getBlock({ blockTag: 'pending', includeTransactions: true }).catch(() => null),
34
+ client
35
+ .getFeeHistory({
36
+ blockCount: HISTORICAL_BLOCK_COUNT,
37
+ rewardPercentiles: [75],
38
+ blockTag: 'latest',
39
+ })
40
+ .catch(() => null),
41
+ ]);
42
+
43
+ // Extract latest block
44
+ if (latestBlockResult.status === 'rejected') {
45
+ throw new Error(`Failed to get latest block: ${latestBlockResult.reason}`);
46
+ }
47
+ const latestBlock = latestBlockResult.value;
48
+
49
+ // Extract blob base fee (only for blob txs)
50
+ let blobBaseFee: bigint | undefined;
51
+ if (isBlobTx) {
52
+ if (blobBaseFeeResult.status === 'fulfilled' && typeof blobBaseFeeResult.value === 'bigint') {
53
+ blobBaseFee = blobBaseFeeResult.value;
54
+ } else {
55
+ logger?.warn('Failed to get L1 blob base fee');
56
+ }
57
+ }
58
+
59
+ // Extract network estimate
60
+ const networkEstimate =
61
+ networkEstimateResult.status === 'fulfilled' && typeof networkEstimateResult.value === 'bigint'
62
+ ? networkEstimateResult.value
63
+ : 0n;
64
+
65
+ let competitiveFee = networkEstimate;
66
+ const debugInfo: Record<string, string | number> = {
67
+ networkEstimateGwei: formatGwei(networkEstimate),
68
+ };
69
+
70
+ // Extract pending block
71
+ const pendingBlock = pendingBlockResult.status === 'fulfilled' ? pendingBlockResult.value : null;
72
+
73
+ // Analyze pending block transactions
74
+ if (pendingBlock?.transactions && pendingBlock.transactions.length > 0) {
75
+ const pendingFees = pendingBlock.transactions
76
+ .map(tx => {
77
+ if (typeof tx === 'string') {
78
+ return 0n;
79
+ }
80
+ return tx.maxPriorityFeePerGas || 0n;
81
+ })
82
+ .filter((fee: bigint) => fee > 0n);
83
+
84
+ if (pendingFees.length > 0) {
85
+ // Use 75th percentile of pending fees to be competitive
86
+ const pendingCompetitiveFee = calculatePercentile(pendingFees, 75);
87
+
88
+ if (pendingCompetitiveFee > competitiveFee) {
89
+ competitiveFee = pendingCompetitiveFee;
90
+ }
91
+
92
+ debugInfo.pendingTxCount = pendingFees.length;
93
+ debugInfo.pendingP75Gwei = formatGwei(pendingCompetitiveFee);
94
+
95
+ logger?.debug('Analyzed pending transactions for competitive pricing', {
96
+ pendingTxCount: pendingFees.length,
97
+ pendingP75: formatGwei(pendingCompetitiveFee),
98
+ });
99
+ }
100
+ }
101
+
102
+ // Extract fee history
103
+ const feeHistory = feeHistoryResult.status === 'fulfilled' ? feeHistoryResult.value : null;
104
+
105
+ // Analyze fee history
106
+ if (feeHistory?.reward && feeHistory.reward.length > 0) {
107
+ // Extract 75th percentile fees from each block
108
+ const percentile75Fees = feeHistory.reward.map(rewards => rewards[0] || 0n).filter(fee => fee > 0n);
109
+
110
+ if (percentile75Fees.length > 0) {
111
+ // Calculate median of the 75th percentile fees across blocks
112
+ const medianHistoricalFee = median(percentile75Fees) ?? 0n;
113
+
114
+ // Debug: Log suspicious fees from history
115
+ if (medianHistoricalFee > 100n * WEI_CONST) {
116
+ logger?.warn('Suspicious high fee in history', {
117
+ historicalMedian: formatGwei(medianHistoricalFee),
118
+ allP75Fees: percentile75Fees.map(f => formatGwei(f)),
119
+ });
120
+ }
121
+
122
+ if (medianHistoricalFee > competitiveFee) {
123
+ competitiveFee = medianHistoricalFee;
124
+ }
125
+
126
+ debugInfo.historicalMedianGwei = formatGwei(medianHistoricalFee);
127
+
128
+ logger?.debug('Analyzed fee history for competitive pricing', {
129
+ historicalMedian: formatGwei(medianHistoricalFee),
130
+ });
131
+ }
132
+ }
133
+
134
+ // Sanity check: cap competitive fee at 100x network estimate to avoid using unrealistic fees
135
+ const maxReasonableFee = networkEstimate * 100n;
136
+ if (competitiveFee > maxReasonableFee && networkEstimate > 0n) {
137
+ logger?.debug('Competitive fee exceeds sanity cap, using capped value', {
138
+ competitiveFee: formatGwei(competitiveFee),
139
+ networkEstimate: formatGwei(networkEstimate),
140
+ cappedTo: formatGwei(maxReasonableFee),
141
+ });
142
+ competitiveFee = maxReasonableFee;
143
+ debugInfo.cappedToGwei = formatGwei(maxReasonableFee);
144
+ }
145
+
146
+ // Log final decision
147
+ if (competitiveFee > networkEstimate) {
148
+ logger?.debug('Using competitive fee from market analysis', {
149
+ networkEstimate: formatGwei(networkEstimate),
150
+ competitive: formatGwei(competitiveFee),
151
+ });
152
+ }
153
+
154
+ debugInfo.finalFeeGwei = formatGwei(competitiveFee);
155
+
156
+ return {
157
+ priorityFee: competitiveFee,
158
+ latestBlock,
159
+ blobBaseFee,
160
+ debugInfo,
161
+ };
162
+ },
163
+ };