@aztec/ethereum 3.0.3 → 4.0.0-devnet.1-patch.0
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/client.js +6 -2
- 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_base.d.ts +2 -1
- package/dest/contracts/empire_base.d.ts.map +1 -1
- package/dest/contracts/empire_slashing_proposer.d.ts +2 -1
- package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/empire_slashing_proposer.js +22 -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 +2 -1
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +395 -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 +162 -81
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +691 -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 +87 -19
- 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 +4964 -1573
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/l1_contract_addresses.d.ts +1 -1
- package/dest/l1_contract_addresses.d.ts.map +1 -1
- package/dest/l1_contract_addresses.js +3 -3
- package/dest/l1_tx_utils/constants.d.ts +8 -2
- package/dest/l1_tx_utils/constants.d.ts.map +1 -1
- package/dest/l1_tx_utils/constants.js +27 -2
- package/dest/l1_tx_utils/fee-strategies/index.d.ts +10 -0
- package/dest/l1_tx_utils/fee-strategies/index.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/index.js +12 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts +8 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +129 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts +23 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +191 -0
- package/dest/l1_tx_utils/fee-strategies/types.d.ts +51 -0
- package/dest/l1_tx_utils/fee-strategies/types.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/types.js +3 -0
- package/dest/l1_tx_utils/index.d.ts +3 -1
- package/dest/l1_tx_utils/index.d.ts.map +1 -1
- package/dest/l1_tx_utils/index.js +2 -0
- package/dest/l1_tx_utils/l1_fee_analyzer.d.ts +233 -0
- package/dest/l1_tx_utils/l1_fee_analyzer.d.ts.map +1 -0
- package/dest/l1_tx_utils/l1_fee_analyzer.js +506 -0
- package/dest/l1_tx_utils/l1_tx_utils.js +6 -6
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +4 -15
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/readonly_l1_tx_utils.js +35 -143
- 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/eth_cheat_codes.js +3 -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 +22 -3
- package/dest/test/start_anvil.js +1 -1
- package/dest/test/tx_delayer.js +1 -1
- package/dest/utils.d.ts +15 -2
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +64 -0
- package/package.json +9 -7
- package/src/client.ts +2 -2
- package/src/config.ts +62 -53
- package/src/contracts/README.md +157 -0
- package/src/contracts/empire_base.ts +1 -1
- package/src/contracts/empire_slashing_proposer.ts +22 -28
- package/src/contracts/fee_asset_handler.ts +10 -7
- package/src/contracts/governance.ts +10 -1
- package/src/contracts/governance_proposer.ts +10 -2
- 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 +364 -100
- package/src/contracts/tally_slashing_proposer.ts +5 -1
- package/src/deploy_aztec_l1_contracts.ts +94 -18
- package/src/generated/l1-contracts-defaults.ts +32 -0
- package/src/l1_contract_addresses.ts +22 -20
- package/src/l1_tx_utils/constants.ts +13 -2
- package/src/l1_tx_utils/fee-strategies/index.ts +22 -0
- package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +163 -0
- package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +245 -0
- package/src/l1_tx_utils/fee-strategies/types.ts +56 -0
- package/src/l1_tx_utils/index.ts +2 -0
- package/src/l1_tx_utils/l1_fee_analyzer.ts +803 -0
- package/src/l1_tx_utils/l1_tx_utils.ts +6 -6
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +48 -186
- package/src/publisher_manager.ts +4 -2
- package/src/queries.ts +11 -3
- package/src/test/chain_monitor.ts +1 -1
- package/src/test/eth_cheat_codes.ts +1 -1
- package/src/test/rollup_cheat_codes.ts +22 -4
- package/src/test/start_anvil.ts +1 -1
- package/src/test/tx_delayer.ts +1 -1
- package/src/utils.ts +82 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { L1TxRequest } from '@aztec/ethereum/l1-tx-utils';
|
|
2
2
|
import type { ViemClient } from '@aztec/ethereum/types';
|
|
3
|
-
import { tryExtractEvent } from '@aztec/ethereum/utils';
|
|
3
|
+
import { mergeAbis, tryExtractEvent } from '@aztec/ethereum/utils';
|
|
4
4
|
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
5
5
|
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
6
6
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
7
7
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
8
8
|
import { hexToBuffer } from '@aztec/foundation/string';
|
|
9
|
+
import { SlasherAbi } from '@aztec/l1-artifacts/SlasherAbi';
|
|
9
10
|
import { TallySlashingProposerAbi } from '@aztec/l1-artifacts/TallySlashingProposerAbi';
|
|
10
11
|
|
|
11
12
|
import {
|
|
@@ -160,6 +161,7 @@ export class TallySlashingProposerContract {
|
|
|
160
161
|
|
|
161
162
|
return {
|
|
162
163
|
to: this.contract.address,
|
|
164
|
+
abi: TallySlashingProposerAbi,
|
|
163
165
|
data: encodeFunctionData({
|
|
164
166
|
abi: TallySlashingProposerAbi,
|
|
165
167
|
functionName: 'vote',
|
|
@@ -207,6 +209,7 @@ export class TallySlashingProposerContract {
|
|
|
207
209
|
public buildVoteRequestWithSignature(votes: Hex, signature: { v: number; r: Hex; s: Hex }): L1TxRequest {
|
|
208
210
|
return {
|
|
209
211
|
to: this.contract.address,
|
|
212
|
+
abi: TallySlashingProposerAbi,
|
|
210
213
|
data: encodeFunctionData({
|
|
211
214
|
abi: TallySlashingProposerAbi,
|
|
212
215
|
functionName: 'vote',
|
|
@@ -224,6 +227,7 @@ export class TallySlashingProposerContract {
|
|
|
224
227
|
public buildExecuteRoundRequest(round: bigint, committees: EthAddress[][]): L1TxRequest {
|
|
225
228
|
return {
|
|
226
229
|
to: this.contract.address,
|
|
230
|
+
abi: mergeAbis([TallySlashingProposerAbi, SlasherAbi]),
|
|
227
231
|
data: encodeFunctionData({
|
|
228
232
|
abi: TallySlashingProposerAbi,
|
|
229
233
|
functionName: 'executeRound',
|
|
@@ -10,10 +10,12 @@ import { fileURLToPath } from '@aztec/foundation/url';
|
|
|
10
10
|
import { bn254 } from '@noble/curves/bn254';
|
|
11
11
|
import type { Abi, Narrow } from 'abitype';
|
|
12
12
|
import { spawn } from 'child_process';
|
|
13
|
-
import {
|
|
13
|
+
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs';
|
|
14
|
+
import { tmpdir } from 'os';
|
|
15
|
+
import { dirname, join, resolve } from 'path';
|
|
14
16
|
import readline from 'readline';
|
|
15
17
|
import type { Hex } from 'viem';
|
|
16
|
-
import {
|
|
18
|
+
import { mainnet, sepolia } from 'viem/chains';
|
|
17
19
|
|
|
18
20
|
import { createEthereumChain, isAnvilTestChain } from './chain.js';
|
|
19
21
|
import { createExtendedL1Client } from './client.js';
|
|
@@ -107,17 +109,80 @@ export interface ValidatorJson {
|
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
/**
|
|
110
|
-
* Gets the path to the l1-contracts directory.
|
|
112
|
+
* Gets the path to the l1-contracts foundry artifacts directory.
|
|
113
|
+
* These are copied from l1-contracts to yarn-project/l1-artifacts/l1-contracts
|
|
114
|
+
* during build to make yarn-project self-contained.
|
|
111
115
|
*/
|
|
112
116
|
export function getL1ContractsPath(): string {
|
|
113
|
-
// Try to find l1-contracts relative to this file
|
|
114
117
|
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const l1ContractsPath = resolve(currentDir, '..', '..', '..', 'l1-contracts');
|
|
118
|
+
// Go up from yarn-project/ethereum/dest to yarn-project, then to l1-artifacts/l1-contracts
|
|
119
|
+
const l1ContractsPath = resolve(currentDir, '..', '..', 'l1-artifacts', 'l1-contracts');
|
|
118
120
|
return l1ContractsPath;
|
|
119
121
|
}
|
|
120
122
|
|
|
123
|
+
// Cached deployment directory
|
|
124
|
+
let preparedDeployDir: string | undefined;
|
|
125
|
+
|
|
126
|
+
function cleanupDeployDir() {
|
|
127
|
+
if (preparedDeployDir) {
|
|
128
|
+
try {
|
|
129
|
+
rmSync(preparedDeployDir, { recursive: true, force: true });
|
|
130
|
+
} catch {
|
|
131
|
+
// ignore cleanup errors
|
|
132
|
+
}
|
|
133
|
+
preparedDeployDir = undefined;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Prepares a temp directory for forge deployment.
|
|
139
|
+
* Copies all artifacts with preserved timestamps (required for forge cache validity).
|
|
140
|
+
* A fresh broadcast/ directory is created for deployment outputs.
|
|
141
|
+
*/
|
|
142
|
+
export function prepareL1ContractsForDeployment(): string {
|
|
143
|
+
if (preparedDeployDir && existsSync(preparedDeployDir)) {
|
|
144
|
+
logger.verbose(`Using cached deployment directory: ${preparedDeployDir}`);
|
|
145
|
+
return preparedDeployDir;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const basePath = getL1ContractsPath();
|
|
149
|
+
logger.verbose(`Preparing L1 contracts from: ${basePath}`);
|
|
150
|
+
const tempDir = mkdtempSync(join(tmpdir(), '.foundry-deploy-'));
|
|
151
|
+
logger.verbose(`Created temp directory for deployment: ${tempDir}`);
|
|
152
|
+
preparedDeployDir = tempDir;
|
|
153
|
+
process.on('exit', cleanupDeployDir);
|
|
154
|
+
|
|
155
|
+
// Copy all dirs with preserved timestamps (required for forge cache validity)
|
|
156
|
+
const copyOpts = { recursive: true, preserveTimestamps: true };
|
|
157
|
+
cpSync(join(basePath, 'out'), join(tempDir, 'out'), copyOpts);
|
|
158
|
+
cpSync(join(basePath, 'lib'), join(tempDir, 'lib'), copyOpts);
|
|
159
|
+
cpSync(join(basePath, 'cache'), join(tempDir, 'cache'), copyOpts);
|
|
160
|
+
cpSync(join(basePath, 'src'), join(tempDir, 'src'), copyOpts);
|
|
161
|
+
cpSync(join(basePath, 'script'), join(tempDir, 'script'), copyOpts);
|
|
162
|
+
cpSync(join(basePath, 'generated'), join(tempDir, 'generated'), copyOpts);
|
|
163
|
+
// Kludge: copy test/ to appease forge cache which references test/shouting.t.sol
|
|
164
|
+
cpSync(join(basePath, 'test'), join(tempDir, 'test'), copyOpts);
|
|
165
|
+
cpSync(join(basePath, 'foundry.lock'), join(tempDir, 'foundry.lock'));
|
|
166
|
+
|
|
167
|
+
// Update foundry.toml to use absolute path to solc binary (avoids copying to noexec tmpfs)
|
|
168
|
+
const foundryTomlPath = join(basePath, 'foundry.toml');
|
|
169
|
+
let foundryToml = readFileSync(foundryTomlPath, 'utf-8');
|
|
170
|
+
const solcPathMatch = foundryToml.match(/solc\s*=\s*"\.\/solc-([^"]+)"/);
|
|
171
|
+
// Did we find a hardcoded solc path that we need to make absolute?
|
|
172
|
+
// This code path happens in CI currently as we bundle solc there to avoid race conditions when
|
|
173
|
+
// downloading solc.
|
|
174
|
+
if (solcPathMatch) {
|
|
175
|
+
const solcVersion = solcPathMatch[1];
|
|
176
|
+
const absoluteSolcPath = join(basePath, `solc-${solcVersion}`);
|
|
177
|
+
foundryToml = foundryToml.replace(/solc\s*=\s*"\.\/solc-[^"]+"/, `solc = "${absoluteSolcPath}"`);
|
|
178
|
+
logger.verbose(`Updated solc path in foundry.toml to: ${absoluteSolcPath}`);
|
|
179
|
+
}
|
|
180
|
+
writeFileSync(join(tempDir, 'foundry.toml'), foundryToml);
|
|
181
|
+
|
|
182
|
+
mkdirSync(join(tempDir, 'broadcast'));
|
|
183
|
+
return tempDir;
|
|
184
|
+
}
|
|
185
|
+
|
|
121
186
|
/**
|
|
122
187
|
* Computes the validator data for passing to Solidity.
|
|
123
188
|
* Only computes the G2 public key (which requires scalar multiplication on G2, not available in EVM).
|
|
@@ -211,7 +276,6 @@ export async function deployAztecL1Contracts(
|
|
|
211
276
|
'Initial validator funding requires minting tokens, which is not possible with an external token.',
|
|
212
277
|
);
|
|
213
278
|
}
|
|
214
|
-
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
215
279
|
const chain = createEthereumChain([rpcUrl], chainId);
|
|
216
280
|
|
|
217
281
|
const l1Client = createExtendedL1Client([rpcUrl], privateKey, chain.chainInfo);
|
|
@@ -240,17 +304,26 @@ export async function deployAztecL1Contracts(
|
|
|
240
304
|
}
|
|
241
305
|
}
|
|
242
306
|
|
|
243
|
-
//
|
|
244
|
-
const l1ContractsPath =
|
|
307
|
+
// Use foundry-artifacts from l1-artifacts package
|
|
308
|
+
const l1ContractsPath = prepareL1ContractsForDeployment();
|
|
245
309
|
|
|
246
310
|
const FORGE_SCRIPT = 'script/deploy/DeployAztecL1Contracts.s.sol';
|
|
247
311
|
await maybeForgeForceProductionBuild(l1ContractsPath, FORGE_SCRIPT, chainId);
|
|
248
312
|
|
|
249
|
-
|
|
313
|
+
// Verify contracts on Etherscan when on mainnet/sepolia and ETHERSCAN_API_KEY is available.
|
|
314
|
+
const isVerifiableChain = chainId === mainnet.id || chainId === sepolia.id;
|
|
315
|
+
const shouldVerify = isVerifiableChain && !!process.env.ETHERSCAN_API_KEY;
|
|
316
|
+
|
|
317
|
+
if (isVerifiableChain && !process.env.ETHERSCAN_API_KEY) {
|
|
318
|
+
logger.warn(
|
|
319
|
+
`Deploying to chain ${chainId} (${chainId === mainnet.id ? 'mainnet' : 'sepolia'}) without ETHERSCAN_API_KEY. ` +
|
|
320
|
+
`Contracts will NOT be verified on Etherscan. Set ETHERSCAN_API_KEY environment variable to enable verification.`,
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
250
324
|
// From heuristic testing. More caused issues with anvil.
|
|
251
|
-
const MAGIC_ANVIL_BATCH_SIZE =
|
|
325
|
+
const MAGIC_ANVIL_BATCH_SIZE = 8;
|
|
252
326
|
// Anvil seems to stall with unbounded batch size. Otherwise no max batch size is desirable.
|
|
253
|
-
// On sepolia and mainnet, we verify on etherscan (if etherscan API key is in env)
|
|
254
327
|
const forgeArgs = [
|
|
255
328
|
'script',
|
|
256
329
|
FORGE_SCRIPT,
|
|
@@ -261,7 +334,8 @@ export async function deployAztecL1Contracts(
|
|
|
261
334
|
'--rpc-url',
|
|
262
335
|
rpcUrl,
|
|
263
336
|
'--broadcast',
|
|
264
|
-
|
|
337
|
+
'--batch-size',
|
|
338
|
+
MAGIC_ANVIL_BATCH_SIZE.toString(),
|
|
265
339
|
...(shouldVerify ? ['--verify'] : []),
|
|
266
340
|
];
|
|
267
341
|
const forgeEnv = {
|
|
@@ -438,6 +512,7 @@ export function getDeployAztecL1ContractsEnvVars(args: DeployAztecL1ContractsArg
|
|
|
438
512
|
AZTEC_EJECTION_THRESHOLD: args.ejectionThreshold?.toString(),
|
|
439
513
|
AZTEC_GOVERNANCE_PROPOSER_ROUND_SIZE: args.governanceProposerRoundSize?.toString(),
|
|
440
514
|
AZTEC_GOVERNANCE_PROPOSER_QUORUM: args.governanceProposerQuorum?.toString(),
|
|
515
|
+
AZTEC_GOVERNANCE_VOTING_DURATION: args.governanceVotingDuration?.toString(),
|
|
441
516
|
ZKPASSPORT_DOMAIN: args.zkPassportArgs?.zkPassportDomain,
|
|
442
517
|
ZKPASSPORT_SCOPE: args.zkPassportArgs?.zkPassportScope,
|
|
443
518
|
} as const;
|
|
@@ -468,14 +543,17 @@ export function getDeployRollupForUpgradeEnvVars(
|
|
|
468
543
|
AZTEC_TARGET_COMMITTEE_SIZE: args.aztecTargetCommitteeSize.toString(),
|
|
469
544
|
AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET: args.lagInEpochsForValidatorSet.toString(),
|
|
470
545
|
AZTEC_LAG_IN_EPOCHS_FOR_RANDAO: args.lagInEpochsForRandao.toString(),
|
|
546
|
+
AZTEC_INBOX_LAG: args.inboxLag?.toString(),
|
|
471
547
|
AZTEC_PROOF_SUBMISSION_EPOCHS: args.aztecProofSubmissionEpochs.toString(),
|
|
472
548
|
AZTEC_LOCAL_EJECTION_THRESHOLD: args.localEjectionThreshold.toString(),
|
|
473
549
|
AZTEC_SLASHING_LIFETIME_IN_ROUNDS: args.slashingLifetimeInRounds.toString(),
|
|
550
|
+
AZTEC_SLASHING_EXECUTION_DELAY_IN_ROUNDS: args.slashingExecutionDelayInRounds.toString(),
|
|
474
551
|
AZTEC_SLASHING_VETOER: args.slashingVetoer.toString(),
|
|
475
552
|
AZTEC_SLASHING_DISABLE_DURATION: args.slashingDisableDuration.toString(),
|
|
476
553
|
AZTEC_MANA_TARGET: args.manaTarget.toString(),
|
|
477
554
|
AZTEC_EXIT_DELAY_SECONDS: args.exitDelaySeconds.toString(),
|
|
478
555
|
AZTEC_PROVING_COST_PER_MANA: args.provingCostPerMana.toString(),
|
|
556
|
+
AZTEC_INITIAL_ETH_PER_FEE_ASSET: args.initialEthPerFeeAsset.toString(),
|
|
479
557
|
AZTEC_SLASHER_FLAVOR: args.slasherFlavor,
|
|
480
558
|
AZTEC_SLASHING_ROUND_SIZE_IN_EPOCHS: args.slashingRoundSizeInEpochs.toString(),
|
|
481
559
|
AZTEC_SLASHING_QUORUM: args.slashingQuorum?.toString(),
|
|
@@ -503,10 +581,8 @@ export const deployRollupForUpgrade = async (
|
|
|
503
581
|
| 'zkPassportArgs'
|
|
504
582
|
>,
|
|
505
583
|
) => {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
// Relative location of l1-contracts in monorepo or docker image.
|
|
509
|
-
const l1ContractsPath = resolve(currentDir, '..', '..', '..', 'l1-contracts');
|
|
584
|
+
// Use foundry-artifacts from l1-artifacts package
|
|
585
|
+
const l1ContractsPath = prepareL1ContractsForDeployment();
|
|
510
586
|
|
|
511
587
|
const FORGE_SCRIPT = 'script/deploy/DeployRollupForUpgrade.s.sol';
|
|
512
588
|
await maybeForgeForceProductionBuild(l1ContractsPath, FORGE_SCRIPT, chainId);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Auto-generated from spartan/environments/network-defaults.yml
|
|
2
|
+
// Do not edit manually - run yarn generate to regenerate
|
|
3
|
+
|
|
4
|
+
/** Default L1 contracts configuration values from network-defaults.yml */
|
|
5
|
+
export const l1ContractsDefaultEnv = {
|
|
6
|
+
ETHEREUM_SLOT_DURATION: 12,
|
|
7
|
+
AZTEC_SLOT_DURATION: 36,
|
|
8
|
+
AZTEC_EPOCH_DURATION: 32,
|
|
9
|
+
AZTEC_TARGET_COMMITTEE_SIZE: 48,
|
|
10
|
+
AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET: 2,
|
|
11
|
+
AZTEC_LAG_IN_EPOCHS_FOR_RANDAO: 2,
|
|
12
|
+
AZTEC_ACTIVATION_THRESHOLD: 100000000000000000000,
|
|
13
|
+
AZTEC_EJECTION_THRESHOLD: 50000000000000000000,
|
|
14
|
+
AZTEC_LOCAL_EJECTION_THRESHOLD: 98000000000000000000,
|
|
15
|
+
AZTEC_EXIT_DELAY_SECONDS: 172800,
|
|
16
|
+
AZTEC_INBOX_LAG: 1,
|
|
17
|
+
AZTEC_PROOF_SUBMISSION_EPOCHS: 1,
|
|
18
|
+
AZTEC_MANA_TARGET: 100000000,
|
|
19
|
+
AZTEC_PROVING_COST_PER_MANA: 100,
|
|
20
|
+
AZTEC_INITIAL_ETH_PER_FEE_ASSET: 10000000,
|
|
21
|
+
AZTEC_SLASHER_FLAVOR: 'tally',
|
|
22
|
+
AZTEC_SLASHING_ROUND_SIZE_IN_EPOCHS: 4,
|
|
23
|
+
AZTEC_SLASHING_LIFETIME_IN_ROUNDS: 5,
|
|
24
|
+
AZTEC_SLASHING_EXECUTION_DELAY_IN_ROUNDS: 0,
|
|
25
|
+
AZTEC_SLASHING_OFFSET_IN_ROUNDS: 2,
|
|
26
|
+
AZTEC_SLASHING_VETOER: '0x0000000000000000000000000000000000000000',
|
|
27
|
+
AZTEC_SLASHING_DISABLE_DURATION: 432000,
|
|
28
|
+
AZTEC_SLASH_AMOUNT_SMALL: 10000000000000000000,
|
|
29
|
+
AZTEC_SLASH_AMOUNT_MEDIUM: 20000000000000000000,
|
|
30
|
+
AZTEC_SLASH_AMOUNT_LARGE: 50000000000000000000,
|
|
31
|
+
AZTEC_GOVERNANCE_PROPOSER_ROUND_SIZE: 300,
|
|
32
|
+
} as const;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ConfigMappingsType } from '@aztec/foundation/config';
|
|
2
2
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
-
import {
|
|
3
|
+
import { schemas, zodFor } from '@aztec/foundation/schemas';
|
|
4
4
|
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
|
|
@@ -35,25 +35,27 @@ export type L1ContractAddresses = {
|
|
|
35
35
|
dateGatedRelayerAddress?: EthAddress | undefined;
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
export const L1ContractAddressesSchema =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
38
|
+
export const L1ContractAddressesSchema = zodFor<L1ContractAddresses>()(
|
|
39
|
+
z.object({
|
|
40
|
+
rollupAddress: schemas.EthAddress,
|
|
41
|
+
registryAddress: schemas.EthAddress,
|
|
42
|
+
inboxAddress: schemas.EthAddress,
|
|
43
|
+
outboxAddress: schemas.EthAddress,
|
|
44
|
+
feeJuiceAddress: schemas.EthAddress,
|
|
45
|
+
stakingAssetAddress: schemas.EthAddress,
|
|
46
|
+
feeJuicePortalAddress: schemas.EthAddress,
|
|
47
|
+
coinIssuerAddress: schemas.EthAddress,
|
|
48
|
+
rewardDistributorAddress: schemas.EthAddress,
|
|
49
|
+
governanceProposerAddress: schemas.EthAddress,
|
|
50
|
+
governanceAddress: schemas.EthAddress,
|
|
51
|
+
slashFactoryAddress: schemas.EthAddress.optional(),
|
|
52
|
+
feeAssetHandlerAddress: schemas.EthAddress.optional(),
|
|
53
|
+
stakingAssetHandlerAddress: schemas.EthAddress.optional(),
|
|
54
|
+
zkPassportVerifierAddress: schemas.EthAddress.optional(),
|
|
55
|
+
gseAddress: schemas.EthAddress.optional(),
|
|
56
|
+
dateGatedRelayerAddress: schemas.EthAddress.optional(),
|
|
57
|
+
}),
|
|
58
|
+
);
|
|
57
59
|
|
|
58
60
|
const parseEnv = (val: string) => EthAddress.fromString(val);
|
|
59
61
|
|
|
@@ -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
|
-
//
|
|
7
|
-
export const
|
|
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
|
+
];
|
|
@@ -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
|
+
};
|