@aztec/ethereum 0.0.1-commit.03f7ef2 → 0.0.1-commit.08c5969dc
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.
- package/dest/config.d.ts +17 -27
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +51 -54
- package/dest/contracts/empire_slashing_proposer.d.ts +1 -1
- package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/empire_slashing_proposer.js +13 -15
- package/dest/contracts/fee_asset_handler.d.ts +6 -5
- package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
- package/dest/contracts/fee_asset_handler.js +11 -9
- package/dest/contracts/governance.d.ts +3 -1
- package/dest/contracts/governance.d.ts.map +1 -1
- package/dest/contracts/governance.js +11 -1
- package/dest/contracts/governance_proposer.d.ts +1 -1
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +386 -9
- package/dest/contracts/inbox.d.ts +22 -1
- package/dest/contracts/inbox.d.ts.map +1 -1
- package/dest/contracts/inbox.js +36 -1
- package/dest/contracts/index.d.ts +3 -1
- package/dest/contracts/index.d.ts.map +1 -1
- package/dest/contracts/index.js +2 -0
- package/dest/contracts/log.d.ts +13 -0
- package/dest/contracts/log.d.ts.map +1 -0
- package/dest/contracts/log.js +1 -0
- package/dest/contracts/multicall.d.ts +1 -1
- package/dest/contracts/multicall.d.ts.map +1 -1
- package/dest/contracts/multicall.js +2 -1
- package/dest/contracts/outbox.d.ts +41 -0
- package/dest/contracts/outbox.d.ts.map +1 -0
- package/dest/contracts/outbox.js +86 -0
- package/dest/contracts/rollup.d.ts +161 -96
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +677 -132
- package/dest/contracts/tally_slashing_proposer.d.ts +1 -1
- package/dest/contracts/tally_slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/tally_slashing_proposer.js +8 -1
- package/dest/deploy_aztec_l1_contracts.d.ts +17 -2
- package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_aztec_l1_contracts.js +111 -33
- package/dest/generated/l1-contracts-defaults.d.ts +30 -0
- package/dest/generated/l1-contracts-defaults.d.ts.map +1 -0
- package/dest/generated/l1-contracts-defaults.js +30 -0
- package/dest/l1_artifacts.d.ts +4904 -1533
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/l1_tx_utils/constants.d.ts +1 -1
- package/dest/l1_tx_utils/constants.js +2 -2
- package/dest/l1_tx_utils/fee-strategies/index.d.ts +3 -2
- package/dest/l1_tx_utils/fee-strategies/index.d.ts.map +1 -1
- package/dest/l1_tx_utils/fee-strategies/index.js +2 -1
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts +2 -12
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts.map +1 -1
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +36 -18
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts +2 -11
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts.map +1 -1
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +37 -19
- package/dest/l1_tx_utils/fee-strategies/types.d.ts +14 -27
- package/dest/l1_tx_utils/fee-strategies/types.d.ts.map +1 -1
- package/dest/l1_tx_utils/fee-strategies/types.js +0 -21
- package/dest/l1_tx_utils/l1_fee_analyzer.d.ts +2 -2
- package/dest/l1_tx_utils/l1_fee_analyzer.d.ts.map +1 -1
- package/dest/l1_tx_utils/l1_fee_analyzer.js +3 -3
- package/dest/l1_tx_utils/l1_tx_utils.js +6 -6
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +1 -5
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/readonly_l1_tx_utils.js +17 -54
- package/dest/publisher_manager.d.ts +3 -2
- package/dest/publisher_manager.d.ts.map +1 -1
- package/dest/publisher_manager.js +2 -2
- package/dest/queries.d.ts +2 -2
- package/dest/queries.d.ts.map +1 -1
- package/dest/queries.js +12 -4
- package/dest/test/chain_monitor.js +1 -2
- package/dest/test/eth_cheat_codes.d.ts +13 -1
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.d.ts +5 -2
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +19 -2
- package/dest/test/start_anvil.js +1 -1
- package/dest/utils.d.ts +2 -1
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +46 -0
- package/package.json +8 -7
- package/src/config.ts +62 -53
- package/src/contracts/README.md +157 -0
- package/src/contracts/empire_slashing_proposer.ts +16 -27
- package/src/contracts/fee_asset_handler.ts +10 -7
- package/src/contracts/governance.ts +10 -1
- package/src/contracts/governance_proposer.ts +4 -1
- package/src/contracts/inbox.ts +53 -1
- package/src/contracts/index.ts +2 -0
- package/src/contracts/log.ts +13 -0
- package/src/contracts/multicall.ts +5 -2
- package/src/contracts/outbox.ts +98 -0
- package/src/contracts/rollup.ts +348 -100
- package/src/contracts/tally_slashing_proposer.ts +5 -1
- package/src/deploy_aztec_l1_contracts.ts +117 -40
- package/src/generated/l1-contracts-defaults.ts +32 -0
- package/src/l1_tx_utils/constants.ts +2 -2
- package/src/l1_tx_utils/fee-strategies/index.ts +1 -1
- package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +46 -42
- package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +49 -45
- package/src/l1_tx_utils/fee-strategies/types.ts +14 -46
- package/src/l1_tx_utils/l1_fee_analyzer.ts +2 -3
- package/src/l1_tx_utils/l1_tx_utils.ts +6 -6
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +23 -62
- package/src/publisher_manager.ts +4 -2
- package/src/queries.ts +11 -3
- package/src/test/chain_monitor.ts +1 -1
- package/src/test/rollup_cheat_codes.ts +21 -3
- package/src/test/start_anvil.ts +1 -1
- package/src/utils.ts +53 -0
|
@@ -12,15 +12,6 @@ import {
|
|
|
12
12
|
type PriorityFeeStrategyResult,
|
|
13
13
|
} from './types.js';
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
* Type for the promises required by the competitive strategy
|
|
17
|
-
*/
|
|
18
|
-
type P75AllTxsStrategyPromises = {
|
|
19
|
-
networkEstimate: Promise<bigint>;
|
|
20
|
-
pendingBlock: Promise<Awaited<ReturnType<ViemClient['getBlock']>> | null>;
|
|
21
|
-
feeHistory: Promise<Awaited<ReturnType<ViemClient['getFeeHistory']>> | null>;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
15
|
/**
|
|
25
16
|
* Fetches historical blocks and calculates reward percentiles for blob transactions only.
|
|
26
17
|
* Returns data in the same format as getFeeHistory for easy drop-in replacement.
|
|
@@ -114,38 +105,51 @@ export async function getBlobPriorityFeeHistory(
|
|
|
114
105
|
* Analyzes p75 of pending transactions and 5-block fee history to determine a competitive priority fee.
|
|
115
106
|
* Falls back to network estimate if data is unavailable.
|
|
116
107
|
*/
|
|
117
|
-
export const P75BlobTxsOnlyPriorityFeeStrategy: PriorityFeeStrategy
|
|
108
|
+
export const P75BlobTxsOnlyPriorityFeeStrategy: PriorityFeeStrategy = {
|
|
118
109
|
name: 'Competitive (P75 + History) - Blob Txs Only',
|
|
119
110
|
id: 'p75_pending_txs_and_history_blob_txs_only',
|
|
120
111
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
112
|
+
async execute(client: ViemClient, context: PriorityFeeStrategyContext): Promise<PriorityFeeStrategyResult> {
|
|
113
|
+
const { isBlobTx, logger } = context;
|
|
114
|
+
|
|
115
|
+
// Fire all RPC calls in parallel
|
|
116
|
+
const [latestBlockResult, blobBaseFeeResult, networkEstimateResult, pendingBlockResult, feeHistoryResult] =
|
|
117
|
+
await Promise.allSettled([
|
|
118
|
+
client.getBlock({ blockTag: 'latest' }),
|
|
119
|
+
isBlobTx ? client.getBlobBaseFee() : Promise.resolve(undefined),
|
|
120
|
+
client.estimateMaxPriorityFeePerGas().catch(() => 0n),
|
|
121
|
+
client.getBlock({ blockTag: 'pending', includeTransactions: true }).catch(() => null),
|
|
122
|
+
isBlobTx
|
|
123
|
+
? getBlobPriorityFeeHistory(client, HISTORICAL_BLOCK_COUNT, [75])
|
|
124
|
+
: client
|
|
125
|
+
.getFeeHistory({
|
|
126
|
+
blockCount: HISTORICAL_BLOCK_COUNT,
|
|
127
|
+
rewardPercentiles: [75],
|
|
128
|
+
blockTag: 'latest',
|
|
129
|
+
})
|
|
130
|
+
.catch(() => null),
|
|
131
|
+
]);
|
|
132
|
+
|
|
133
|
+
// Extract latest block (required)
|
|
134
|
+
if (latestBlockResult.status === 'rejected') {
|
|
135
|
+
throw new Error(`Failed to get latest block: ${latestBlockResult.reason}`);
|
|
136
|
+
}
|
|
137
|
+
const latestBlock = latestBlockResult.value;
|
|
138
|
+
|
|
139
|
+
// Extract blob base fee (only for blob txs)
|
|
140
|
+
let blobBaseFee: bigint | undefined;
|
|
141
|
+
if (isBlobTx) {
|
|
142
|
+
if (blobBaseFeeResult.status === 'fulfilled' && typeof blobBaseFeeResult.value === 'bigint') {
|
|
143
|
+
blobBaseFee = blobBaseFeeResult.value;
|
|
144
|
+
} else {
|
|
145
|
+
logger?.warn('Failed to get L1 blob base fee');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
144
148
|
|
|
145
|
-
// Extract network estimate
|
|
149
|
+
// Extract network estimate
|
|
146
150
|
const networkEstimate =
|
|
147
|
-
|
|
148
|
-
?
|
|
151
|
+
networkEstimateResult.status === 'fulfilled' && typeof networkEstimateResult.value === 'bigint'
|
|
152
|
+
? networkEstimateResult.value
|
|
149
153
|
: 0n;
|
|
150
154
|
|
|
151
155
|
let competitiveFee = networkEstimate;
|
|
@@ -153,8 +157,8 @@ export const P75BlobTxsOnlyPriorityFeeStrategy: PriorityFeeStrategy<P75AllTxsStr
|
|
|
153
157
|
networkEstimateGwei: formatGwei(networkEstimate),
|
|
154
158
|
};
|
|
155
159
|
|
|
156
|
-
// Extract pending block
|
|
157
|
-
const pendingBlock =
|
|
160
|
+
// Extract pending block
|
|
161
|
+
const pendingBlock = pendingBlockResult.status === 'fulfilled' ? pendingBlockResult.value : null;
|
|
158
162
|
|
|
159
163
|
// Analyze pending block transactions
|
|
160
164
|
if (pendingBlock?.transactions && pendingBlock.transactions.length > 0) {
|
|
@@ -163,14 +167,12 @@ export const P75BlobTxsOnlyPriorityFeeStrategy: PriorityFeeStrategy<P75AllTxsStr
|
|
|
163
167
|
if (typeof tx === 'string') {
|
|
164
168
|
return 0n;
|
|
165
169
|
}
|
|
166
|
-
if (
|
|
170
|
+
if (isBlobTx) {
|
|
167
171
|
if (!isBlobTransaction(tx)) {
|
|
168
172
|
return 0n;
|
|
169
173
|
}
|
|
170
174
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return fee;
|
|
175
|
+
return tx.maxPriorityFeePerGas || 0n;
|
|
174
176
|
})
|
|
175
177
|
.filter((fee: bigint) => fee > 0n);
|
|
176
178
|
|
|
@@ -191,8 +193,8 @@ export const P75BlobTxsOnlyPriorityFeeStrategy: PriorityFeeStrategy<P75AllTxsStr
|
|
|
191
193
|
}
|
|
192
194
|
}
|
|
193
195
|
|
|
194
|
-
// Extract fee history
|
|
195
|
-
const feeHistory =
|
|
196
|
+
// Extract fee history
|
|
197
|
+
const feeHistory = feeHistoryResult.status === 'fulfilled' ? feeHistoryResult.value : null;
|
|
196
198
|
|
|
197
199
|
// Analyze fee history
|
|
198
200
|
if (feeHistory?.reward && feeHistory.reward.length > 0) {
|
|
@@ -205,7 +207,7 @@ export const P75BlobTxsOnlyPriorityFeeStrategy: PriorityFeeStrategy<P75AllTxsStr
|
|
|
205
207
|
|
|
206
208
|
// Debug: Log suspicious fees from history
|
|
207
209
|
if (medianHistoricalFee > 100n * WEI_CONST) {
|
|
208
|
-
logger?.
|
|
210
|
+
logger?.debug('Suspicious high fee in history', {
|
|
209
211
|
historicalMedian: formatGwei(medianHistoricalFee),
|
|
210
212
|
allP75Fees: percentile75Fees.map(f => formatGwei(f)),
|
|
211
213
|
});
|
|
@@ -235,6 +237,8 @@ export const P75BlobTxsOnlyPriorityFeeStrategy: PriorityFeeStrategy<P75AllTxsStr
|
|
|
235
237
|
|
|
236
238
|
return {
|
|
237
239
|
priorityFee: competitiveFee,
|
|
240
|
+
latestBlock,
|
|
241
|
+
blobBaseFee,
|
|
238
242
|
debugInfo,
|
|
239
243
|
};
|
|
240
244
|
},
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Logger } from '@aztec/foundation/log';
|
|
2
2
|
|
|
3
|
+
import type { Block } from 'viem';
|
|
4
|
+
|
|
3
5
|
import type { ViemClient } from '../../types.js';
|
|
4
6
|
import type { L1TxUtilsConfig } from '../config.js';
|
|
5
7
|
|
|
@@ -14,12 +16,16 @@ export const HISTORICAL_BLOCK_COUNT = 5;
|
|
|
14
16
|
export interface PriorityFeeStrategyResult {
|
|
15
17
|
/** The calculated priority fee in wei */
|
|
16
18
|
priorityFee: bigint;
|
|
19
|
+
/** The latest block (fetched as part of the strategy) */
|
|
20
|
+
latestBlock: Block;
|
|
21
|
+
/** The blob base fee (only present for blob transactions) */
|
|
22
|
+
blobBaseFee?: bigint;
|
|
17
23
|
/** Optional debug info about how the fee was calculated */
|
|
18
24
|
debugInfo?: Record<string, string | number>;
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
/**
|
|
22
|
-
* Context passed to the strategy
|
|
28
|
+
* Context passed to the strategy function
|
|
23
29
|
*/
|
|
24
30
|
export interface PriorityFeeStrategyContext {
|
|
25
31
|
/** Gas configuration */
|
|
@@ -32,57 +38,19 @@ export interface PriorityFeeStrategyContext {
|
|
|
32
38
|
|
|
33
39
|
/**
|
|
34
40
|
* A strategy for calculating the priority fee for L1 transactions.
|
|
35
|
-
*
|
|
36
|
-
*
|
|
41
|
+
* The function handles all RPC calls and returns
|
|
42
|
+
* the priority fee, along with any block data needed by the caller.
|
|
37
43
|
*/
|
|
38
|
-
export
|
|
44
|
+
export type PriorityFeeStrategy = {
|
|
39
45
|
/** Human-readable name for logging */
|
|
40
46
|
name: string;
|
|
41
47
|
/** Unique identifier for metrics */
|
|
42
48
|
id: string;
|
|
43
49
|
/**
|
|
44
|
-
*
|
|
45
|
-
* These will be run in parallel with Promise.allSettled.
|
|
50
|
+
* Calculate the priority fee.
|
|
46
51
|
* @param client - The viem client to use for RPC calls
|
|
47
|
-
* @returns An object of promises keyed by name
|
|
48
|
-
*/
|
|
49
|
-
getRequiredPromises(client: ViemClient, opts: Partial<PriorityFeeStrategyContext>): TPromises;
|
|
50
|
-
/**
|
|
51
|
-
* Calculate the priority fee based on the settled promise results.
|
|
52
|
-
* @param results - The settled results of the promises from getRequiredPromises
|
|
53
52
|
* @param context - Contains gas config, whether it's a blob tx, and logger
|
|
54
|
-
* @returns The calculated priority fee result
|
|
53
|
+
* @returns The calculated priority fee result including block data
|
|
55
54
|
*/
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
context: PriorityFeeStrategyContext,
|
|
59
|
-
): PriorityFeeStrategyResult;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Helper function to execute a strategy's promises and calculate the result.
|
|
64
|
-
* This can be used by both L1FeeAnalyzer and ReadOnlyL1TxUtils.
|
|
65
|
-
* @param strategy - The strategy to execute
|
|
66
|
-
* @param client - The viem client to use for RPC calls
|
|
67
|
-
* @param context - The context for calculation
|
|
68
|
-
* @returns The strategy result
|
|
69
|
-
*/
|
|
70
|
-
export async function executeStrategy<TPromises extends Record<string, Promise<any>>>(
|
|
71
|
-
strategy: PriorityFeeStrategy<TPromises>,
|
|
72
|
-
client: ViemClient,
|
|
73
|
-
context: PriorityFeeStrategyContext,
|
|
74
|
-
): Promise<PriorityFeeStrategyResult> {
|
|
75
|
-
const promises = strategy.getRequiredPromises(client, { isBlobTx: context.isBlobTx });
|
|
76
|
-
const keys = Object.keys(promises) as Array<keyof TPromises>;
|
|
77
|
-
const promiseArray = keys.map(k => promises[k]);
|
|
78
|
-
|
|
79
|
-
const settledResults = await Promise.allSettled(promiseArray);
|
|
80
|
-
|
|
81
|
-
// Reconstruct the results object with the same keys, preserving the type mapping
|
|
82
|
-
const results = {} as { [K in keyof TPromises]: PromiseSettledResult<Awaited<TPromises[K]>> };
|
|
83
|
-
keys.forEach((key, index) => {
|
|
84
|
-
results[key] = settledResults[index] as PromiseSettledResult<Awaited<TPromises[typeof key]>>;
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
return strategy.calculate(results, context);
|
|
88
|
-
}
|
|
55
|
+
execute: (client: ViemClient, context: PriorityFeeStrategyContext) => Promise<PriorityFeeStrategyResult>;
|
|
56
|
+
};
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
DEFAULT_PRIORITY_FEE_STRATEGIES,
|
|
14
14
|
type PriorityFeeStrategy,
|
|
15
15
|
type PriorityFeeStrategyContext,
|
|
16
|
-
executeStrategy,
|
|
17
16
|
} from './fee-strategies/index.js';
|
|
18
17
|
import type { L1BlobInputs, L1TxRequest } from './types.js';
|
|
19
18
|
|
|
@@ -262,7 +261,7 @@ export class L1FeeAnalyzer {
|
|
|
262
261
|
|
|
263
262
|
/**
|
|
264
263
|
* Executes all configured strategies and returns their results.
|
|
265
|
-
* Each strategy
|
|
264
|
+
* Each strategy handles its own RPC calls internally.
|
|
266
265
|
* @param isBlobTx - Whether this is a blob transaction
|
|
267
266
|
* @returns Array of strategy results
|
|
268
267
|
*/
|
|
@@ -276,7 +275,7 @@ export class L1FeeAnalyzer {
|
|
|
276
275
|
|
|
277
276
|
for (const strategy of this.strategies) {
|
|
278
277
|
try {
|
|
279
|
-
const result = await
|
|
278
|
+
const result = await strategy.execute(this.client, context);
|
|
280
279
|
|
|
281
280
|
results.push({
|
|
282
281
|
strategyId: strategy.id,
|
|
@@ -27,7 +27,7 @@ import { jsonRpc } from 'viem/nonce';
|
|
|
27
27
|
import type { ViemClient } from '../types.js';
|
|
28
28
|
import { formatViemError } from '../utils.js';
|
|
29
29
|
import { type L1TxUtilsConfig, l1TxUtilsConfigMappings } from './config.js';
|
|
30
|
-
import {
|
|
30
|
+
import { MAX_L1_TX_LIMIT } from './constants.js';
|
|
31
31
|
import type { IL1TxMetrics, IL1TxStore } from './interfaces.js';
|
|
32
32
|
import { ReadOnlyL1TxUtils } from './readonly_l1_tx_utils.js';
|
|
33
33
|
import {
|
|
@@ -207,7 +207,7 @@ export class L1TxUtils extends ReadOnlyL1TxUtils {
|
|
|
207
207
|
|
|
208
208
|
let gasLimit: bigint;
|
|
209
209
|
if (this.debugMaxGasLimit) {
|
|
210
|
-
gasLimit =
|
|
210
|
+
gasLimit = MAX_L1_TX_LIMIT;
|
|
211
211
|
} else if (gasConfig.gasLimit) {
|
|
212
212
|
gasLimit = gasConfig.gasLimit;
|
|
213
213
|
} else {
|
|
@@ -283,7 +283,7 @@ export class L1TxUtils extends ReadOnlyL1TxUtils {
|
|
|
283
283
|
return { txHash, state: l1TxState };
|
|
284
284
|
} catch (err: any) {
|
|
285
285
|
const viemError = formatViemError(err, request.abi);
|
|
286
|
-
this.logger.error(`Failed to send L1 transaction`, viemError, {
|
|
286
|
+
this.logger.error(`Failed to send L1 transaction: ${viemError.message}`, viemError, {
|
|
287
287
|
request: pick(request, 'to', 'value'),
|
|
288
288
|
});
|
|
289
289
|
throw viemError;
|
|
@@ -631,12 +631,12 @@ export class L1TxUtils extends ReadOnlyL1TxUtils {
|
|
|
631
631
|
from: request.from ?? this.getSenderAddress().toString(),
|
|
632
632
|
maxFeePerGas: gasPrice.maxFeePerGas,
|
|
633
633
|
maxPriorityFeePerGas: gasPrice.maxPriorityFeePerGas,
|
|
634
|
-
gas: request.gas ??
|
|
634
|
+
gas: request.gas ?? MAX_L1_TX_LIMIT,
|
|
635
635
|
};
|
|
636
636
|
|
|
637
637
|
if (!request.gas && !gasConfig.ignoreBlockGasLimit) {
|
|
638
|
-
//
|
|
639
|
-
blockOverrides.gasLimit =
|
|
638
|
+
// MAX_L1_TX_LIMIT is set as call.gas, ensure block gasLimit is sufficient
|
|
639
|
+
blockOverrides.gasLimit = MAX_L1_TX_LIMIT;
|
|
640
640
|
}
|
|
641
641
|
|
|
642
642
|
return this._simulate(call, blockOverrides, stateOverrides, gasConfig, abi);
|
|
@@ -27,7 +27,7 @@ import type { ViemClient } from '../types.js';
|
|
|
27
27
|
import { type L1TxUtilsConfig, defaultL1TxUtilsConfig, l1TxUtilsConfigMappings } from './config.js';
|
|
28
28
|
import {
|
|
29
29
|
BLOCK_TIME_MS,
|
|
30
|
-
|
|
30
|
+
MAX_L1_TX_LIMIT,
|
|
31
31
|
MIN_BLOB_REPLACEMENT_BUMP_PERCENTAGE,
|
|
32
32
|
MIN_REPLACEMENT_BUMP_PERCENTAGE,
|
|
33
33
|
WEI_CONST,
|
|
@@ -84,63 +84,31 @@ export class ReadOnlyL1TxUtils {
|
|
|
84
84
|
): Promise<GasPrice> {
|
|
85
85
|
const gasConfig = merge(this.config, gasConfigOverrides);
|
|
86
86
|
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
// Execute strategy - it handles all RPC calls internally and returns everything we need
|
|
88
|
+
const strategyResult = await retry(
|
|
89
|
+
() =>
|
|
90
|
+
CurrentStrategy.execute(this.client, {
|
|
91
|
+
gasConfig,
|
|
92
|
+
isBlobTx,
|
|
93
|
+
logger: this.logger,
|
|
94
|
+
}),
|
|
95
|
+
'Executing priority fee strategy',
|
|
96
|
+
makeBackoff(times(2, () => 0)),
|
|
97
|
+
this.logger,
|
|
98
|
+
true,
|
|
92
99
|
);
|
|
93
100
|
|
|
94
|
-
|
|
95
|
-
if (isBlobTx) {
|
|
96
|
-
blobBaseFeePromise = this.tryTwice(() => this.client.getBlobBaseFee(), 'Getting blob base fee');
|
|
97
|
-
}
|
|
101
|
+
const { latestBlock, blobBaseFee, priorityFee: strategyPriorityFee } = strategyResult;
|
|
98
102
|
|
|
99
|
-
//
|
|
100
|
-
const
|
|
101
|
-
const strategyPromiseKeys = [];
|
|
102
|
-
const strategyPromisesArr = [];
|
|
103
|
-
for (const [key, promise] of Object.entries(strategyPromises)) {
|
|
104
|
-
strategyPromiseKeys.push(key);
|
|
105
|
-
strategyPromisesArr.push(this.tryTwice(() => promise, `Getting strategy data for ${key}`));
|
|
106
|
-
}
|
|
103
|
+
// Extract base fee from latest block
|
|
104
|
+
const baseFee = latestBlock.baseFeePerGas ?? 0n;
|
|
107
105
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
blobBaseFeePromise ?? Promise.resolve(0n),
|
|
111
|
-
...strategyPromisesArr,
|
|
112
|
-
]);
|
|
113
|
-
|
|
114
|
-
// Extract results
|
|
115
|
-
const baseFee =
|
|
116
|
-
latestBlockResult.status === 'fulfilled' &&
|
|
117
|
-
typeof latestBlockResult.value === 'object' &&
|
|
118
|
-
latestBlockResult.value.baseFeePerGas
|
|
119
|
-
? latestBlockResult.value.baseFeePerGas
|
|
120
|
-
: 0n;
|
|
121
|
-
|
|
122
|
-
// Get blob base fee if available
|
|
123
|
-
let blobBaseFee = 0n;
|
|
124
|
-
if (isBlobTx && blobBaseFeeResult.status === 'fulfilled' && typeof blobBaseFeeResult.value === 'bigint') {
|
|
125
|
-
blobBaseFee = blobBaseFeeResult.value;
|
|
126
|
-
} else if (isBlobTx) {
|
|
106
|
+
// Handle blob base fee
|
|
107
|
+
if (isBlobTx && blobBaseFee === undefined) {
|
|
127
108
|
this.logger?.warn('Failed to get L1 blob base fee', attempt);
|
|
128
109
|
}
|
|
129
110
|
|
|
130
|
-
let priorityFee
|
|
131
|
-
// Get competitive priority fee using strategy
|
|
132
|
-
// Reconstruct the results object with the same keys as the promises
|
|
133
|
-
const resultsObject: Record<string, PromiseSettledResult<unknown>> = {};
|
|
134
|
-
strategyPromiseKeys.forEach((key, index) => {
|
|
135
|
-
resultsObject[key] = strategyResults[index];
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
const result = CurrentStrategy.calculate(resultsObject as any, {
|
|
139
|
-
gasConfig,
|
|
140
|
-
isBlobTx,
|
|
141
|
-
logger: this.logger,
|
|
142
|
-
});
|
|
143
|
-
priorityFee = result.priorityFee;
|
|
111
|
+
let priorityFee = strategyPriorityFee;
|
|
144
112
|
|
|
145
113
|
// Apply minimum priority fee floor if configured
|
|
146
114
|
if (gasConfig.minimumPriorityFeePerGas) {
|
|
@@ -156,7 +124,7 @@ export class ReadOnlyL1TxUtils {
|
|
|
156
124
|
}
|
|
157
125
|
let maxFeePerGas = baseFee;
|
|
158
126
|
|
|
159
|
-
let maxFeePerBlobGas = blobBaseFee;
|
|
127
|
+
let maxFeePerBlobGas = blobBaseFee ?? 0n;
|
|
160
128
|
|
|
161
129
|
// Bump base fee so it's valid for next blocks if it stalls
|
|
162
130
|
const numBlocks = Math.ceil(gasConfig.stallTimeMs! / BLOCK_TIME_MS);
|
|
@@ -250,7 +218,7 @@ export class ReadOnlyL1TxUtils {
|
|
|
250
218
|
baseFee: formatGwei(baseFee),
|
|
251
219
|
maxFeePerGas: formatGwei(maxFeePerGas),
|
|
252
220
|
maxPriorityFeePerGas: formatGwei(maxPriorityFeePerGas),
|
|
253
|
-
blobBaseFee: formatGwei(blobBaseFee),
|
|
221
|
+
blobBaseFee: formatGwei(blobBaseFee ?? 0n),
|
|
254
222
|
maxFeePerBlobGas: formatGwei(maxFeePerBlobGas),
|
|
255
223
|
},
|
|
256
224
|
);
|
|
@@ -281,7 +249,7 @@ export class ReadOnlyL1TxUtils {
|
|
|
281
249
|
...request,
|
|
282
250
|
..._blobInputs,
|
|
283
251
|
maxFeePerBlobGas: gasPrice.maxFeePerBlobGas!,
|
|
284
|
-
gas:
|
|
252
|
+
gas: MAX_L1_TX_LIMIT,
|
|
285
253
|
blockTag: 'latest',
|
|
286
254
|
});
|
|
287
255
|
|
|
@@ -290,7 +258,7 @@ export class ReadOnlyL1TxUtils {
|
|
|
290
258
|
initialEstimate = await this.client.estimateGas({
|
|
291
259
|
account,
|
|
292
260
|
...request,
|
|
293
|
-
gas:
|
|
261
|
+
gas: MAX_L1_TX_LIMIT,
|
|
294
262
|
blockTag: 'latest',
|
|
295
263
|
});
|
|
296
264
|
this.logger?.trace(`Estimated gas for non-blob tx: ${initialEstimate}`);
|
|
@@ -448,11 +416,4 @@ export class ReadOnlyL1TxUtils {
|
|
|
448
416
|
});
|
|
449
417
|
return bumpedGasLimit;
|
|
450
418
|
}
|
|
451
|
-
|
|
452
|
-
/**
|
|
453
|
-
* Helper function to retry RPC calls twice
|
|
454
|
-
*/
|
|
455
|
-
private tryTwice<T>(fn: () => Promise<T>, description: string): Promise<T> {
|
|
456
|
-
return retry<T>(fn, description, makeBackoff(times(2, () => 0)), this.logger, true);
|
|
457
|
-
}
|
|
458
419
|
}
|
package/src/publisher_manager.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { pick } from '@aztec/foundation/collection';
|
|
2
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
3
3
|
|
|
4
4
|
import { L1TxUtils, TxUtilsState } from './l1_tx_utils/index.js';
|
|
5
5
|
|
|
@@ -28,13 +28,15 @@ const busyStates: TxUtilsState[] = [
|
|
|
28
28
|
export type PublisherFilter<UtilsType extends L1TxUtils> = (utils: UtilsType) => boolean;
|
|
29
29
|
|
|
30
30
|
export class PublisherManager<UtilsType extends L1TxUtils = L1TxUtils> {
|
|
31
|
-
private log
|
|
31
|
+
private log: Logger;
|
|
32
32
|
private config: { publisherAllowInvalidStates?: boolean };
|
|
33
33
|
|
|
34
34
|
constructor(
|
|
35
35
|
private publishers: UtilsType[],
|
|
36
36
|
config: { publisherAllowInvalidStates?: boolean },
|
|
37
|
+
bindings?: LoggerBindings,
|
|
37
38
|
) {
|
|
39
|
+
this.log = createLogger('publisher:manager', bindings);
|
|
38
40
|
this.log.info(`PublisherManager initialized with ${publishers.length} publishers.`);
|
|
39
41
|
this.publishers = publishers;
|
|
40
42
|
this.config = pick(config, 'publisherAllowInvalidStates');
|
package/src/queries.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
2
|
|
|
3
|
-
import type
|
|
3
|
+
import { DefaultL1ContractsConfig, type L1ContractsConfig } from './config.js';
|
|
4
4
|
import { ReadOnlyGovernanceContract } from './contracts/governance.js';
|
|
5
5
|
import { GovernanceProposerContract } from './contracts/governance_proposer.js';
|
|
6
|
+
import { InboxContract } from './contracts/inbox.js';
|
|
6
7
|
import { RollupContract } from './contracts/rollup.js';
|
|
7
8
|
import type { ViemPublicClient } from './types.js';
|
|
8
9
|
|
|
@@ -25,6 +26,8 @@ export async function getL1ContractsConfig(
|
|
|
25
26
|
const rollup = new RollupContract(publicClient, rollupAddress.toString());
|
|
26
27
|
const slasherProposer = await rollup.getSlashingProposer();
|
|
27
28
|
const slasher = await rollup.getSlasherContract();
|
|
29
|
+
const rollupAddresses = await rollup.getRollupAddresses();
|
|
30
|
+
const inboxContract = new InboxContract(publicClient, rollupAddresses.inboxAddress.toString());
|
|
28
31
|
|
|
29
32
|
const [
|
|
30
33
|
l1StartBlock,
|
|
@@ -35,6 +38,7 @@ export async function getL1ContractsConfig(
|
|
|
35
38
|
aztecTargetCommitteeSize,
|
|
36
39
|
lagInEpochsForValidatorSet,
|
|
37
40
|
lagInEpochsForRandao,
|
|
41
|
+
inboxLag,
|
|
38
42
|
activationThreshold,
|
|
39
43
|
ejectionThreshold,
|
|
40
44
|
localEjectionThreshold,
|
|
@@ -62,6 +66,7 @@ export async function getL1ContractsConfig(
|
|
|
62
66
|
rollup.getTargetCommitteeSize(),
|
|
63
67
|
rollup.getLagInEpochsForValidatorSet(),
|
|
64
68
|
rollup.getLagInEpochsForRandao(),
|
|
69
|
+
inboxContract.getLag(),
|
|
65
70
|
rollup.getActivationThreshold(),
|
|
66
71
|
rollup.getEjectionThreshold(),
|
|
67
72
|
rollup.getLocalEjectionThreshold(),
|
|
@@ -91,13 +96,15 @@ export async function getL1ContractsConfig(
|
|
|
91
96
|
aztecTargetCommitteeSize: Number(aztecTargetCommitteeSize),
|
|
92
97
|
lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
|
|
93
98
|
lagInEpochsForRandao: Number(lagInEpochsForRandao),
|
|
99
|
+
inboxLag: Number(inboxLag),
|
|
94
100
|
governanceProposerQuorum: Number(governanceProposerQuorum),
|
|
95
101
|
governanceProposerRoundSize: Number(governanceProposerRoundSize),
|
|
102
|
+
governanceVotingDuration: DefaultL1ContractsConfig.governanceVotingDuration,
|
|
96
103
|
activationThreshold,
|
|
97
104
|
ejectionThreshold,
|
|
98
105
|
localEjectionThreshold,
|
|
99
106
|
slashingQuorum: Number(slashingQuorum),
|
|
100
|
-
slashingRoundSizeInEpochs: Number(slashingRoundSize / aztecEpochDuration),
|
|
107
|
+
slashingRoundSizeInEpochs: Number(Number(slashingRoundSize) / aztecEpochDuration),
|
|
101
108
|
slashingLifetimeInRounds: Number(slashingLifetimeInRounds),
|
|
102
109
|
slashingExecutionDelayInRounds: Number(slashingExecutionDelayInRounds),
|
|
103
110
|
slashingVetoer,
|
|
@@ -105,12 +112,13 @@ export async function getL1ContractsConfig(
|
|
|
105
112
|
manaTarget,
|
|
106
113
|
provingCostPerMana: provingCostPerMana,
|
|
107
114
|
rollupVersion: Number(rollupVersion),
|
|
108
|
-
genesisArchiveTreeRoot,
|
|
115
|
+
genesisArchiveTreeRoot: genesisArchiveTreeRoot.toString(),
|
|
109
116
|
exitDelaySeconds: Number(exitDelay),
|
|
110
117
|
slasherFlavor: slasherProposer?.type ?? 'tally',
|
|
111
118
|
slashingOffsetInRounds: Number(slashingOffsetInRounds),
|
|
112
119
|
slashAmountSmall: slashingAmounts[0],
|
|
113
120
|
slashAmountMedium: slashingAmounts[1],
|
|
114
121
|
slashAmountLarge: slashingAmounts[2],
|
|
122
|
+
initialEthPerFeeAsset: DefaultL1ContractsConfig.initialEthPerFeeAsset,
|
|
115
123
|
};
|
|
116
124
|
}
|
|
@@ -156,7 +156,7 @@ export class ChainMonitor extends EventEmitter<ChainMonitorEventMap> {
|
|
|
156
156
|
let committee: EthAddress[] | undefined;
|
|
157
157
|
if (l2Epoch !== this.l2EpochNumber) {
|
|
158
158
|
this.l2EpochNumber = l2Epoch;
|
|
159
|
-
committee =
|
|
159
|
+
committee = await this.rollup.getCurrentEpochCommittee();
|
|
160
160
|
this.emit('l2-epoch', { l2EpochNumber: l2Epoch, timestamp, committee });
|
|
161
161
|
msg += ` starting new epoch ${this.l2EpochNumber} `;
|
|
162
162
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RollupContract } from '@aztec/ethereum/contracts';
|
|
1
|
+
import { OutboxContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
2
2
|
import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
3
3
|
import type { ViemPublicClient } from '@aztec/ethereum/types';
|
|
4
4
|
import { CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
@@ -56,6 +56,15 @@ export class RollupCheatCodes {
|
|
|
56
56
|
return SlotNumber.fromBigInt(await this.rollup.read.getSlotAt([ts]));
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/** Returns the number of seconds until the start of the given slot based on L1 block timestamp. */
|
|
60
|
+
public async getSecondsUntilSlot(slot: SlotNumber): Promise<number> {
|
|
61
|
+
const [currentTimestamp, targetTimestamp] = await Promise.all([
|
|
62
|
+
this.client.getBlock().then(b => BigInt(b.timestamp)),
|
|
63
|
+
this.rollup.read.getTimestampForSlot([BigInt(slot)]),
|
|
64
|
+
]);
|
|
65
|
+
return Math.max(0, Number(targetTimestamp - currentTimestamp));
|
|
66
|
+
}
|
|
67
|
+
|
|
59
68
|
/** Returns the current epoch */
|
|
60
69
|
public async getEpoch(): Promise<EpochNumber> {
|
|
61
70
|
const slotNumber = await this.getSlot();
|
|
@@ -124,7 +133,7 @@ export class RollupCheatCodes {
|
|
|
124
133
|
} = {},
|
|
125
134
|
) {
|
|
126
135
|
const { epochDuration: slotsInEpoch } = await this.getConfig();
|
|
127
|
-
const slotNumber = SlotNumber(epoch * Number(slotsInEpoch));
|
|
136
|
+
const slotNumber = SlotNumber(Number(epoch) * Number(slotsInEpoch));
|
|
128
137
|
const timestamp = (await this.rollup.read.getTimestampForSlot([BigInt(slotNumber)])) + BigInt(opts.offset ?? 0);
|
|
129
138
|
try {
|
|
130
139
|
await this.ethCheatCodes.warp(Number(timestamp), { ...opts, silent: true, resetBlockInterval: true });
|
|
@@ -176,7 +185,7 @@ export class RollupCheatCodes {
|
|
|
176
185
|
* Marks the specified checkpoint (or latest if none) as proven
|
|
177
186
|
* @param maybeCheckpointNumber - The checkpoint number to mark as proven (defaults to latest pending)
|
|
178
187
|
*/
|
|
179
|
-
public markAsProven(maybeCheckpointNumber?:
|
|
188
|
+
public markAsProven(maybeCheckpointNumber?: CheckpointNumber) {
|
|
180
189
|
return this.ethCheatCodes.execWithPausedAnvil(async () => {
|
|
181
190
|
const tipsBefore = await this.getTips();
|
|
182
191
|
const { pending, proven } = tipsBefore;
|
|
@@ -250,6 +259,15 @@ export class RollupCheatCodes {
|
|
|
250
259
|
});
|
|
251
260
|
}
|
|
252
261
|
|
|
262
|
+
public insertOutbox(epoch: EpochNumber, outHash: bigint) {
|
|
263
|
+
return this.ethCheatCodes.execWithPausedAnvil(async () => {
|
|
264
|
+
const outboxAddress = await this.rollup.read.getOutbox();
|
|
265
|
+
const epochRootSlot = OutboxContract.getEpochRootStorageSlot(epoch);
|
|
266
|
+
await this.ethCheatCodes.store(EthAddress.fromString(outboxAddress), epochRootSlot, outHash);
|
|
267
|
+
this.logger.warn(`Advanced outbox to epoch ${epoch} with out hash ${outHash}`);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
253
271
|
/**
|
|
254
272
|
* Executes an action impersonated as the owner of the Rollup contract.
|
|
255
273
|
* @param action - The action to execute
|
package/src/test/start_anvil.ts
CHANGED
|
@@ -33,7 +33,7 @@ export async function startAnvil(
|
|
|
33
33
|
const anvil = createAnvil({
|
|
34
34
|
anvilBinary,
|
|
35
35
|
host: '127.0.0.1',
|
|
36
|
-
port: opts.port ?? 8545,
|
|
36
|
+
port: opts.port ?? (process.env.ANVIL_PORT ? parseInt(process.env.ANVIL_PORT) : 8545),
|
|
37
37
|
blockTime: opts.l1BlockTime,
|
|
38
38
|
stopTimeout: 1000,
|
|
39
39
|
accounts: opts.accounts ?? 20,
|