@aztec/l1-artifacts 0.0.1-commit.8227e42 → 0.0.1-commit.85d7d01

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.
@@ -1 +1 @@
1
- {"id":"09862803192e8bf5","source_id_to_path":{"0":"generated/HonkVerifier.sol","1":"lib/circuits/src/solidity/src/Constants.sol","2":"lib/circuits/src/solidity/src/DateUtils.sol","3":"lib/circuits/src/solidity/src/IProofVerifier.sol","4":"lib/circuits/src/solidity/src/IRootRegistry.sol","5":"lib/circuits/src/solidity/src/InputsExtractor.sol","6":"lib/circuits/src/solidity/src/StringUtils.sol","7":"lib/circuits/src/solidity/src/Types.sol","8":"lib/circuits/src/solidity/src/ZKPassportHelper.sol","9":"lib/circuits/src/solidity/src/ZKPassportRootVerifier.sol","10":"lib/circuits/src/solidity/src/ZKPassportSubVerifier.sol","11":"lib/forge-std/src/Base.sol","12":"lib/forge-std/src/Script.sol","13":"lib/forge-std/src/StdAssertions.sol","14":"lib/forge-std/src/StdChains.sol","15":"lib/forge-std/src/StdCheats.sol","16":"lib/forge-std/src/StdError.sol","17":"lib/forge-std/src/StdInvariant.sol","18":"lib/forge-std/src/StdJson.sol","19":"lib/forge-std/src/StdMath.sol","20":"lib/forge-std/src/StdStorage.sol","21":"lib/forge-std/src/StdStyle.sol","22":"lib/forge-std/src/StdToml.sol","23":"lib/forge-std/src/StdUtils.sol","24":"lib/forge-std/src/Test.sol","25":"lib/forge-std/src/Vm.sol","26":"lib/forge-std/src/console.sol","27":"lib/forge-std/src/console2.sol","28":"lib/forge-std/src/interfaces/IERC165.sol","29":"lib/forge-std/src/interfaces/IERC20.sol","30":"lib/forge-std/src/interfaces/IERC721.sol","31":"lib/forge-std/src/interfaces/IMulticall3.sol","32":"lib/forge-std/src/mocks/MockERC20.sol","33":"lib/forge-std/src/mocks/MockERC721.sol","34":"lib/forge-std/src/safeconsole.sol","35":"lib/openzeppelin-contracts/contracts/access/Ownable.sol","36":"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol","37":"lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol","38":"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol","39":"lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol","40":"lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol","41":"lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol","42":"lib/openzeppelin-contracts/contracts/proxy/Clones.sol","43":"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol","44":"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol","45":"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol","46":"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol","47":"lib/openzeppelin-contracts/contracts/utils/Address.sol","48":"lib/openzeppelin-contracts/contracts/utils/Context.sol","49":"lib/openzeppelin-contracts/contracts/utils/Create2.sol","50":"lib/openzeppelin-contracts/contracts/utils/Errors.sol","51":"lib/openzeppelin-contracts/contracts/utils/Panic.sol","52":"lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol","53":"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol","54":"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol","55":"lib/openzeppelin-contracts/contracts/utils/Strings.sol","56":"lib/openzeppelin-contracts/contracts/utils/TransientSlot.sol","57":"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol","58":"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol","59":"lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol","60":"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol","61":"lib/openzeppelin-contracts/contracts/utils/math/Math.sol","62":"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol","63":"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol","64":"lib/openzeppelin-contracts/contracts/utils/structs/BitMaps.sol","65":"lib/openzeppelin-contracts/contracts/utils/structs/Checkpoints.sol","66":"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol","67":"script/deploy/DeployAztecL1Contracts.s.sol","68":"script/deploy/DeployRollupForUpgrade.s.sol","69":"script/deploy/DeployRollupLib.sol","70":"script/deploy/DeploymentConfiguration.sol","71":"script/deploy/RollupConfiguration.sol","72":"src/core/Rollup.sol","73":"src/core/RollupCore.sol","74":"src/core/interfaces/IEscapeHatch.sol","75":"src/core/interfaces/IFeeJuicePortal.sol","76":"src/core/interfaces/IInstance.sol","77":"src/core/interfaces/IRollup.sol","78":"src/core/interfaces/ISlasher.sol","79":"src/core/interfaces/IStaking.sol","80":"src/core/interfaces/IValidatorSelection.sol","81":"src/core/interfaces/IVerifier.sol","82":"src/core/interfaces/messagebridge/IInbox.sol","83":"src/core/interfaces/messagebridge/IOutbox.sol","84":"src/core/libraries/ConstantsGen.sol","85":"src/core/libraries/DataStructures.sol","86":"src/core/libraries/Errors.sol","87":"src/core/libraries/HatchMath.sol","88":"src/core/libraries/SlashPayloadLib.sol","89":"src/core/libraries/SlashRoundLib.sol","90":"src/core/libraries/StakingQueue.sol","91":"src/core/libraries/TimeLib.sol","92":"src/core/libraries/compressed-data/CheckpointLog.sol","93":"src/core/libraries/compressed-data/StakingQueueConfig.sol","94":"src/core/libraries/compressed-data/Tips.sol","95":"src/core/libraries/compressed-data/fees/FeeConfig.sol","96":"src/core/libraries/compressed-data/fees/FeeStructs.sol","97":"src/core/libraries/crypto/FrontierLib.sol","98":"src/core/libraries/crypto/Hash.sol","99":"src/core/libraries/crypto/MerkleLib.sol","100":"src/core/libraries/crypto/SampleLib.sol","101":"src/core/libraries/rollup/AttestationLib.sol","102":"src/core/libraries/rollup/BlobLib.sol","103":"src/core/libraries/rollup/EmpireSlasherDeploymentExtLib.sol","104":"src/core/libraries/rollup/EpochProofLib.sol","105":"src/core/libraries/rollup/FeeLib.sol","106":"src/core/libraries/rollup/InvalidateLib.sol","107":"src/core/libraries/rollup/ProposeLib.sol","108":"src/core/libraries/rollup/ProposedHeaderLib.sol","109":"src/core/libraries/rollup/RewardExtLib.sol","110":"src/core/libraries/rollup/RewardLib.sol","111":"src/core/libraries/rollup/RollupOperationsExtLib.sol","112":"src/core/libraries/rollup/STFLib.sol","113":"src/core/libraries/rollup/StakingLib.sol","114":"src/core/libraries/rollup/TallySlasherDeploymentExtLib.sol","115":"src/core/libraries/rollup/ValidatorOperationsExtLib.sol","116":"src/core/libraries/rollup/ValidatorSelectionLib.sol","117":"src/core/messagebridge/FeeJuicePortal.sol","118":"src/core/messagebridge/Inbox.sol","119":"src/core/messagebridge/Outbox.sol","120":"src/core/reward-boost/RewardBooster.sol","121":"src/core/slashing/EmpireSlashingProposer.sol","122":"src/core/slashing/Slasher.sol","123":"src/core/slashing/TallySlashingProposer.sol","124":"src/governance/Bn254LibWrapper.sol","125":"src/governance/CoinIssuer.sol","126":"src/governance/GSE.sol","127":"src/governance/GSEPayload.sol","128":"src/governance/Governance.sol","129":"src/governance/Registry.sol","130":"src/governance/RewardDistributor.sol","131":"src/governance/interfaces/IBn254LibWrapper.sol","132":"src/governance/interfaces/ICoinIssuer.sol","133":"src/governance/interfaces/IEmpire.sol","134":"src/governance/interfaces/IGovernance.sol","135":"src/governance/interfaces/IGovernanceProposer.sol","136":"src/governance/interfaces/IPayload.sol","137":"src/governance/interfaces/IProposerPayload.sol","138":"src/governance/interfaces/IRegistry.sol","139":"src/governance/interfaces/IRewardDistributor.sol","140":"src/governance/libraries/AddressSnapshotLib.sol","141":"src/governance/libraries/CheckpointedUintLib.sol","142":"src/governance/libraries/ConfigurationLib.sol","143":"src/governance/libraries/DepositDelegationLib.sol","144":"src/governance/libraries/Errors.sol","145":"src/governance/libraries/ProposalLib.sol","146":"src/governance/libraries/compressed-data/Ballot.sol","147":"src/governance/libraries/compressed-data/Configuration.sol","148":"src/governance/libraries/compressed-data/Proposal.sol","149":"src/governance/proposer/EmpireBase.sol","150":"src/governance/proposer/GovernanceProposer.sol","151":"src/mock/FeeAssetHandler.sol","152":"src/mock/MockVerifier.sol","153":"src/mock/MultiAdder.sol","154":"src/mock/StakingAssetHandler.sol","155":"src/mock/TestERC20.sol","156":"src/mock/libraries/BlobLib.sol","157":"src/mock/staking_asset_handler/MockZKPassportVerifier.sol","158":"src/periphery/DateGatedRelayer.sol","159":"src/periphery/RegisterNewRollupVersionPayload.sol","160":"src/periphery/SlashFactory.sol","161":"src/periphery/SlashPayload.sol","162":"src/periphery/SlashPayloadCloneable.sol","163":"src/periphery/interfaces/IDateGatedRelayer.sol","164":"src/periphery/interfaces/ISlashFactory.sol","165":"src/shared/interfaces/IMintableERC20.sol","166":"src/shared/libraries/BN254Lib.sol","167":"src/shared/libraries/CompressedTimeMath.sol","168":"src/shared/libraries/SignatureLib.sol","169":"src/shared/libraries/TimeMath.sol","170":"test/script/DeployAztecL1Contracts.t.sol","171":"test/script/DeployRollupForUpgrade.t.sol","172":"test/shouting.t.sol"},"language":"Solidity"}
1
+ {"id":"829c69e12cc2d6eb","source_id_to_path":{"0":"generated/HonkVerifier.sol","1":"lib/circuits/src/solidity/src/Constants.sol","2":"lib/circuits/src/solidity/src/DateUtils.sol","3":"lib/circuits/src/solidity/src/IProofVerifier.sol","4":"lib/circuits/src/solidity/src/IRootRegistry.sol","5":"lib/circuits/src/solidity/src/InputsExtractor.sol","6":"lib/circuits/src/solidity/src/StringUtils.sol","7":"lib/circuits/src/solidity/src/Types.sol","8":"lib/circuits/src/solidity/src/ZKPassportHelper.sol","9":"lib/circuits/src/solidity/src/ZKPassportRootVerifier.sol","10":"lib/circuits/src/solidity/src/ZKPassportSubVerifier.sol","11":"lib/forge-std/src/Base.sol","12":"lib/forge-std/src/Script.sol","13":"lib/forge-std/src/StdAssertions.sol","14":"lib/forge-std/src/StdChains.sol","15":"lib/forge-std/src/StdCheats.sol","16":"lib/forge-std/src/StdError.sol","17":"lib/forge-std/src/StdInvariant.sol","18":"lib/forge-std/src/StdJson.sol","19":"lib/forge-std/src/StdMath.sol","20":"lib/forge-std/src/StdStorage.sol","21":"lib/forge-std/src/StdStyle.sol","22":"lib/forge-std/src/StdToml.sol","23":"lib/forge-std/src/StdUtils.sol","24":"lib/forge-std/src/Test.sol","25":"lib/forge-std/src/Vm.sol","26":"lib/forge-std/src/console.sol","27":"lib/forge-std/src/console2.sol","28":"lib/forge-std/src/interfaces/IERC165.sol","29":"lib/forge-std/src/interfaces/IERC20.sol","30":"lib/forge-std/src/interfaces/IERC721.sol","31":"lib/forge-std/src/interfaces/IMulticall3.sol","32":"lib/forge-std/src/mocks/MockERC20.sol","33":"lib/forge-std/src/mocks/MockERC721.sol","34":"lib/forge-std/src/safeconsole.sol","35":"lib/openzeppelin-contracts/contracts/access/Ownable.sol","36":"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol","37":"lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol","38":"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol","39":"lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol","40":"lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol","41":"lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol","42":"lib/openzeppelin-contracts/contracts/proxy/Clones.sol","43":"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol","44":"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol","45":"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol","46":"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol","47":"lib/openzeppelin-contracts/contracts/utils/Address.sol","48":"lib/openzeppelin-contracts/contracts/utils/Context.sol","49":"lib/openzeppelin-contracts/contracts/utils/Create2.sol","50":"lib/openzeppelin-contracts/contracts/utils/Errors.sol","51":"lib/openzeppelin-contracts/contracts/utils/Panic.sol","52":"lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol","53":"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol","54":"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol","55":"lib/openzeppelin-contracts/contracts/utils/Strings.sol","56":"lib/openzeppelin-contracts/contracts/utils/TransientSlot.sol","57":"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol","58":"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol","59":"lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol","60":"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol","61":"lib/openzeppelin-contracts/contracts/utils/math/Math.sol","62":"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol","63":"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol","64":"lib/openzeppelin-contracts/contracts/utils/structs/BitMaps.sol","65":"lib/openzeppelin-contracts/contracts/utils/structs/Checkpoints.sol","66":"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol","67":"script/deploy/DeployAztecL1Contracts.s.sol","68":"script/deploy/DeployRollupForUpgrade.s.sol","69":"script/deploy/DeployRollupLib.sol","70":"script/deploy/DeploymentConfiguration.sol","71":"script/deploy/RollupConfiguration.sol","72":"src/core/Rollup.sol","73":"src/core/RollupCore.sol","74":"src/core/interfaces/IEscapeHatch.sol","75":"src/core/interfaces/IFeeJuicePortal.sol","76":"src/core/interfaces/IInstance.sol","77":"src/core/interfaces/IRollup.sol","78":"src/core/interfaces/ISlasher.sol","79":"src/core/interfaces/IStaking.sol","80":"src/core/interfaces/IValidatorSelection.sol","81":"src/core/interfaces/IVerifier.sol","82":"src/core/interfaces/messagebridge/IInbox.sol","83":"src/core/interfaces/messagebridge/IOutbox.sol","84":"src/core/libraries/ConstantsGen.sol","85":"src/core/libraries/DataStructures.sol","86":"src/core/libraries/Errors.sol","87":"src/core/libraries/HatchMath.sol","88":"src/core/libraries/SlashPayloadLib.sol","89":"src/core/libraries/SlashRoundLib.sol","90":"src/core/libraries/StakingQueue.sol","91":"src/core/libraries/TimeLib.sol","92":"src/core/libraries/compressed-data/CheckpointLog.sol","93":"src/core/libraries/compressed-data/StakingQueueConfig.sol","94":"src/core/libraries/compressed-data/Tips.sol","95":"src/core/libraries/compressed-data/fees/FeeConfig.sol","96":"src/core/libraries/compressed-data/fees/FeeStructs.sol","97":"src/core/libraries/crypto/FrontierLib.sol","98":"src/core/libraries/crypto/Hash.sol","99":"src/core/libraries/crypto/MerkleLib.sol","100":"src/core/libraries/crypto/SampleLib.sol","101":"src/core/libraries/rollup/AttestationLib.sol","102":"src/core/libraries/rollup/BlobLib.sol","103":"src/core/libraries/rollup/EmpireSlasherDeploymentExtLib.sol","104":"src/core/libraries/rollup/EpochProofLib.sol","105":"src/core/libraries/rollup/FeeLib.sol","106":"src/core/libraries/rollup/InvalidateLib.sol","107":"src/core/libraries/rollup/ProposeLib.sol","108":"src/core/libraries/rollup/ProposedHeaderLib.sol","109":"src/core/libraries/rollup/RewardExtLib.sol","110":"src/core/libraries/rollup/RewardLib.sol","111":"src/core/libraries/rollup/RollupOperationsExtLib.sol","112":"src/core/libraries/rollup/STFLib.sol","113":"src/core/libraries/rollup/StakingLib.sol","114":"src/core/libraries/rollup/TallySlasherDeploymentExtLib.sol","115":"src/core/libraries/rollup/ValidatorOperationsExtLib.sol","116":"src/core/libraries/rollup/ValidatorSelectionLib.sol","117":"src/core/messagebridge/FeeJuicePortal.sol","118":"src/core/messagebridge/Inbox.sol","119":"src/core/messagebridge/Outbox.sol","120":"src/core/reward-boost/RewardBooster.sol","121":"src/core/slashing/EmpireSlashingProposer.sol","122":"src/core/slashing/Slasher.sol","123":"src/core/slashing/TallySlashingProposer.sol","124":"src/governance/Bn254LibWrapper.sol","125":"src/governance/CoinIssuer.sol","126":"src/governance/GSE.sol","127":"src/governance/GSEPayload.sol","128":"src/governance/Governance.sol","129":"src/governance/Registry.sol","130":"src/governance/RewardDistributor.sol","131":"src/governance/interfaces/IBn254LibWrapper.sol","132":"src/governance/interfaces/ICoinIssuer.sol","133":"src/governance/interfaces/IEmpire.sol","134":"src/governance/interfaces/IGovernance.sol","135":"src/governance/interfaces/IGovernanceProposer.sol","136":"src/governance/interfaces/IPayload.sol","137":"src/governance/interfaces/IProposerPayload.sol","138":"src/governance/interfaces/IRegistry.sol","139":"src/governance/interfaces/IRewardDistributor.sol","140":"src/governance/libraries/AddressSnapshotLib.sol","141":"src/governance/libraries/CheckpointedUintLib.sol","142":"src/governance/libraries/ConfigurationLib.sol","143":"src/governance/libraries/DepositDelegationLib.sol","144":"src/governance/libraries/Errors.sol","145":"src/governance/libraries/ProposalLib.sol","146":"src/governance/libraries/compressed-data/Ballot.sol","147":"src/governance/libraries/compressed-data/Configuration.sol","148":"src/governance/libraries/compressed-data/Proposal.sol","149":"src/governance/proposer/EmpireBase.sol","150":"src/governance/proposer/GovernanceProposer.sol","151":"src/mock/FeeAssetHandler.sol","152":"src/mock/MockVerifier.sol","153":"src/mock/MultiAdder.sol","154":"src/mock/StakingAssetHandler.sol","155":"src/mock/TestERC20.sol","156":"src/mock/libraries/BlobLib.sol","157":"src/mock/staking_asset_handler/MockZKPassportVerifier.sol","158":"src/periphery/DateGatedRelayer.sol","159":"src/periphery/RegisterNewRollupVersionPayload.sol","160":"src/periphery/SlashFactory.sol","161":"src/periphery/SlashPayload.sol","162":"src/periphery/SlashPayloadCloneable.sol","163":"src/periphery/interfaces/IDateGatedRelayer.sol","164":"src/periphery/interfaces/ISlashFactory.sol","165":"src/shared/interfaces/IMintableERC20.sol","166":"src/shared/libraries/BN254Lib.sol","167":"src/shared/libraries/CompressedTimeMath.sol","168":"src/shared/libraries/SignatureLib.sol","169":"src/shared/libraries/TimeMath.sol","170":"test/script/DeployAztecL1Contracts.t.sol","171":"test/script/DeployRollupForUpgrade.t.sol","172":"test/shouting.t.sol"},"language":"Solidity"}
@@ -143,7 +143,7 @@ contract DeploymentConfiguration is IDeploymentConfiguration, Test {
143
143
  }),
144
144
  votingDelay: Timestamp.wrap(3 * 24 * 60 * 60),
145
145
  votingDuration: Timestamp.wrap(7 * 24 * 60 * 60),
146
- executionDelay: Timestamp.wrap(7 * 24 * 60 * 60),
146
+ executionDelay: Timestamp.wrap(30 * 24 * 60 * 60),
147
147
  gracePeriod: Timestamp.wrap(7 * 24 * 60 * 60),
148
148
  quorum: 0.2e18,
149
149
  requiredYeaMargin: 0.33e18,
@@ -71,7 +71,7 @@ contract RollupConfiguration is IRollupConfiguration, Test {
71
71
  uint16 sequencerBps;
72
72
  uint96 checkpointReward;
73
73
  sequencerBps = 7000;
74
- checkpointReward = 400e18;
74
+ checkpointReward = 500e18;
75
75
 
76
76
  return RewardConfig({
77
77
  rewardDistributor: _rewardDistributor,
@@ -1,327 +1,73 @@
1
1
  #!/usr/bin/env node
2
- // Note: this would be .ts but Node.js refuses to load .ts from node_modules.
3
-
4
- // forge_broadcast.js - Reliable forge script broadcast with retry and timeout.
5
- //
6
- // Wraps `forge script` with:
7
- // 1. --batch-size 8 to prevent forge broadcast hangs (forge bug with large RPC batches)
8
- // 2. External timeout (forge's --timeout is unreliable for broadcast hangs)
9
- // 3. Retry with --resume on real chains, or full retry from scratch on anvil
10
- //
11
- // Anvil's auto-miner has a race condition where batched transactions can get stranded
12
- // in the mempool — they arrive after the auto-miner already triggered for the batch,
13
- // and sit waiting for the next trigger that never comes. Neither evm_mine nor --resume
14
- // can recover these stuck transactions. Interval mining (--block-time) avoids this issue.
15
- //
16
- // On anvil, we work around this by clearing broadcast artifacts and retrying from scratch.
17
- // On real chains (where this anvil-specific bug doesn't apply), we use --resume.
2
+ // forge_broadcast.js Run `forge script --broadcast` safely on anvil.
18
3
  //
19
- // Usage:
20
- // ./scripts/forge_broadcast.js <forge script args...>
4
+ // Bug: anvil's auto-miner races with batched transactions. When a batch is sent,
5
+ // anvil mines a block for the first tx but the rest arrive after the auto-mine
6
+ // trigger fired, leaving them stranded or dropped. Temporarily switching to 1s
7
+ // interval mining for the duration of the broadcast avoids both variants.
21
8
  //
22
- // Pass the same args you'd pass to `forge script`, WITHOUT --broadcast or --batch-size.
23
- // The wrapper adds those automatically.
9
+ // Only activates when anvil is in automine mode.
24
10
  //
25
- // Example:
26
- // ./scripts/forge_broadcast.js script/deploy/Deploy.s.sol:Deploy \
27
- // --rpc-url "$RPC_URL" --private-key "$KEY" -vvv
28
- //
29
- // Environment variables:
30
- // FORGE_BROADCAST_TIMEOUT - Override timeout per attempt in seconds (auto-detected from chain ID)
31
- // FORGE_BROADCAST_MAX_RETRIES - Max retries after initial attempt (default: 3)
32
- //
33
- // Uses only Node.js built-ins (no external dependencies).
11
+ // Usage: ./scripts/forge_broadcast.js <forge script args...>
12
+ // (without --broadcast or --batch-size — added automatically)
34
13
 
35
14
  import { spawn } from "node:child_process";
36
- import { rmSync, writeSync } from "node:fs";
37
-
38
- // Chain IDs for timeout selection.
39
- const MAINNET_CHAIN_ID = 1;
40
- const SEPOLIA_CHAIN_ID = 11155111;
41
-
42
- // Timeout per attempt: 300s for mainnet/sepolia (real chains are slow), 50s for everything else.
43
- // FORGE_BROADCAST_TIMEOUT env var overrides the auto-detected value.
44
- function getDefaultTimeout(chainId) {
45
- if (chainId === MAINNET_CHAIN_ID || chainId === SEPOLIA_CHAIN_ID) return 300;
46
- return 50;
47
- }
48
-
49
- const MAX_RETRIES = parseInt(
50
- process.env.FORGE_BROADCAST_MAX_RETRIES ?? "3",
51
- 10,
52
- );
53
-
54
- if (!Number.isSafeInteger(MAX_RETRIES)) {
55
- process.stderr.write(`MAX_RETRIES is not a valid integer.\n`);
56
- process.exit(1);
57
- }
58
-
59
- // Batch size of 8 prevents forge from hanging during broadcast.
60
- // See: https://github.com/foundry-rs/foundry/issues/6796
61
- const BATCH_SIZE = 8;
62
- const KILL_GRACE = 15_000;
63
- // Exit code indicating a timeout, matching the `timeout` coreutil convention.
64
- const EXIT_TIMEOUT = 124;
65
- // Delay before retry to let pending transactions settle in the mempool.
66
- const RETRY_DELAY = 10_000;
15
+ import { writeSync } from "node:fs";
67
16
 
68
- function log(msg) {
69
- process.stderr.write(`[forge_broadcast] ${msg}\n`);
70
- }
71
-
72
- function sleep(ms) {
73
- return new Promise((resolve) => setTimeout(resolve, ms));
74
- }
75
-
76
- /** Extract --rpc-url value from forge args. */
77
- function extractRpcUrl(args) {
78
- for (let i = 0; i < args.length - 1; i++) {
79
- if (args[i] === "--rpc-url") return args[i + 1];
80
- }
81
- return undefined;
82
- }
83
-
84
- /** Strip --verify from args, returning the filtered args and whether --verify was present. */
85
- function extractVerifyFlag(args) {
86
- const filtered = args.filter((a) => a !== "--verify");
87
- return { args: filtered, verify: filtered.length !== args.length };
88
- }
17
+ const log = (msg) => process.stderr.write(`[forge_broadcast] ${msg}\n`);
89
18
 
90
- const RPC_TIMEOUT = 10_000;
91
-
92
- /** JSON-RPC call using fetch. Rejects on JSON-RPC errors and timeouts. */
93
- async function rpcCall(rpcUrl, method, params) {
94
- const body = JSON.stringify({ jsonrpc: "2.0", id: 1, method, params });
95
- const res = await fetch(rpcUrl, {
19
+ async function rpc(url, method, params = []) {
20
+ const res = await fetch(url, {
96
21
  method: "POST",
97
22
  headers: { "Content-Type": "application/json" },
98
- body,
99
- signal: AbortSignal.timeout(RPC_TIMEOUT),
23
+ body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
24
+ signal: AbortSignal.timeout(10_000),
100
25
  });
101
- if (!res.ok) {
102
- throw new Error(`RPC HTTP ${res.status} for ${method}`);
103
- }
104
- const data = await res.text();
105
- let parsed;
106
- try {
107
- parsed = JSON.parse(data);
108
- } catch {
109
- throw new Error(`Bad RPC response for ${method}: ${data.slice(0, 200)}`);
110
- }
111
- if (parsed.error) {
112
- throw new Error(`RPC error for ${method}: ${JSON.stringify(parsed.error)}`);
113
- }
114
- return parsed.result;
115
- }
116
-
117
- /** Detect if the RPC endpoint is an anvil dev node via web3_clientVersion. */
118
- async function detectAnvil(rpcUrl) {
119
- try {
120
- const version = await rpcCall(rpcUrl, "web3_clientVersion", []);
121
- return version.toLowerCase().includes("anvil");
122
- } catch {
123
- return false;
124
- }
26
+ const json = await res.json();
27
+ if (json.error) throw new Error(json.error.message);
28
+ return json.result;
125
29
  }
126
30
 
127
- /** Get the chain ID from the RPC endpoint. */
128
- async function getChainId(rpcUrl) {
129
- try {
130
- const result = await rpcCall(rpcUrl, "eth_chainId", []);
131
- return parseInt(result, 16);
132
- } catch {
133
- return undefined;
134
- }
31
+ function extractArg(args, flag) {
32
+ const i = args.indexOf(flag);
33
+ return i >= 0 && i < args.length - 1 ? args[i + 1] : undefined;
135
34
  }
136
35
 
137
- function runForge(args, timeoutSecs) {
138
- return new Promise((resolve) => {
139
- const proc = spawn(
140
- "forge",
141
- ["script", ...args, "--broadcast", "--batch-size", String(BATCH_SIZE)],
142
- {
143
- stdio: ["ignore", "pipe", "inherit"], // buffer stdout, pass stderr through
144
- },
145
- );
36
+ const args = process.argv.slice(2);
37
+ const rpcUrl = extractArg(args, "--rpc-url");
146
38
 
147
- const stdout = [];
148
- proc.stdout.on("data", (chunk) => stdout.push(chunk));
39
+ const [isAnvil, isAutomine] = rpcUrl
40
+ ? await Promise.all([
41
+ rpc(rpcUrl, "web3_clientVersion").then((v) => v.toLowerCase().includes("anvil")).catch(() => false),
42
+ rpc(rpcUrl, "anvil_getAutomine").catch(() => false),
43
+ ])
44
+ : [false, false];
149
45
 
150
- let timedOut = false;
151
- let settled = false;
152
- let killTimer;
153
-
154
- const timer = setTimeout(() => {
155
- timedOut = true;
156
- proc.kill("SIGTERM");
157
- killTimer = setTimeout(() => proc.kill("SIGKILL"), KILL_GRACE);
158
- }, timeoutSecs * 1000);
159
-
160
- const finish = (code) => {
161
- if (settled) return;
162
- settled = true;
163
- clearTimeout(timer);
164
- clearTimeout(killTimer);
165
- resolve({ exitCode: timedOut ? EXIT_TIMEOUT : code, stdout });
166
- };
167
-
168
- proc.on("error", () => finish(1));
169
- proc.on("close", (code) => finish(code ?? 1));
170
- });
46
+ if (isAnvil && isAutomine) {
47
+ await rpc(rpcUrl, "evm_setAutomine", [false]);
48
+ await rpc(rpcUrl, "evm_setIntervalMining", [1]);
171
49
  }
172
50
 
173
- // Main
51
+ const proc = spawn("forge", ["script", ...args, "--broadcast", "--batch-size", "8"], {
52
+ stdio: ["ignore", "pipe", "inherit"],
53
+ });
174
54
 
175
- // Strip --verify from args so it doesn't run during broadcast attempts. Verification
176
- // happens after all receipts are collected (foundry-rs/foundry crates/script/src/lib.rs:333-338)
177
- // and forge exits non-zero if ANY verification fails (crates/script/src/verify.rs), even when
178
- // all transactions landed. We run verification as a separate step after broadcast succeeds.
179
- const { args: forgeArgs, verify: wantsVerify } = extractVerifyFlag(
180
- process.argv.slice(2),
181
- );
182
- const rpcUrl = extractRpcUrl(forgeArgs);
183
-
184
- // Query chain info from RPC at startup.
185
- const chainId = rpcUrl ? await getChainId(rpcUrl) : undefined;
186
- const TIMEOUT = process.env.FORGE_BROADCAST_TIMEOUT
187
- ? parseInt(process.env.FORGE_BROADCAST_TIMEOUT, 10)
188
- : getDefaultTimeout(chainId);
189
-
190
- if (!Number.isSafeInteger(TIMEOUT)) {
191
- process.stderr.write(`FORGE_BROADCAST_TIMEOUT is not a valid integer.\n`);
192
- process.exit(1);
193
- }
55
+ const stdout = [];
56
+ proc.stdout.on("data", (chunk) => stdout.push(chunk));
194
57
 
195
- log(
196
- `chain_id=${chainId ?? "unknown"}, timeout=${TIMEOUT}s, max_retries=${MAX_RETRIES}, batch_size=${BATCH_SIZE}${wantsVerify ? ", verify=true (after broadcast)" : ""}`,
197
- );
58
+ const exitCode = await new Promise((resolve) => {
59
+ proc.on("error", () => resolve(1));
60
+ proc.on("close", (code) => resolve(code ?? 1));
61
+ });
198
62
 
199
- // Detect anvil once at startup. On anvil, retries reset the chain and start from scratch
200
- // instead of using --resume, because anvil's auto-miner can strand transactions in the
201
- // mempool in an unrecoverable state (neither evm_mine nor --resume can flush them).
202
- const isAnvil = rpcUrl ? await detectAnvil(rpcUrl) : false;
203
- if (isAnvil) {
204
- log("Detected anvil — retries will reset chain instead of using --resume.");
205
- }
206
-
207
- /**
208
- * Run contract verification via `forge script --resume --verify --broadcast` (no timeout).
209
- * Verification uses broadcast artifacts + re-compilation — it doesn't need simulation data.
210
- * See: foundry-rs/foundry crates/script/src/build.rs (CompiledState::resume) and
211
- * crates/script/src/verify.rs (verify_contracts).
212
- * Failure is logged but doesn't affect the exit code — transactions already landed.
213
- */
214
- async function runVerification(args) {
215
- log("Running contract verification (no timeout)...");
216
- const verifyResult = await new Promise((resolve) => {
217
- const proc = spawn(
218
- "forge",
219
- ["script", ...args, "--broadcast", "--resume", "--verify"],
220
- {
221
- stdio: ["ignore", "inherit", "inherit"],
222
- },
223
- );
224
- let settled = false;
225
- proc.on("error", () => {
226
- if (!settled) {
227
- settled = true;
228
- resolve(1);
229
- }
230
- });
231
- proc.on("close", (code) => {
232
- if (!settled) {
233
- settled = true;
234
- resolve(code ?? 1);
235
- }
236
- });
237
- });
238
- if (verifyResult === 0) {
239
- log("Contract verification succeeded.");
240
- } else {
241
- log(
242
- `Contract verification failed (exit ${verifyResult}). Transactions are on-chain; verify manually if needed.`,
243
- );
244
- }
245
- }
246
-
247
- /** Write buffered stdout to fd 1 (synchronous) and exit. */
248
- function emitAndExit(result, code) {
249
- const data = Buffer.concat(result.stdout);
250
- if (data.length > 0) {
251
- writeSync(1, data);
252
- }
253
- process.exit(code);
254
- }
255
-
256
- /** Run verification if requested, then emit stdout and exit. */
257
- async function verifyAndExit(result) {
258
- if (wantsVerify) {
259
- await runVerification(forgeArgs);
260
- }
261
- emitAndExit(result, 0);
262
- }
263
-
264
- // Attempt 1: initial broadcast
265
- log(`Attempt 1/${MAX_RETRIES + 1}: broadcasting...`);
266
- let result = await runForge(forgeArgs, TIMEOUT);
267
-
268
- if (result.exitCode === 0) {
269
- log("Broadcast succeeded on first attempt.");
270
- await verifyAndExit(result);
271
- }
272
-
273
- log(
274
- `Attempt 1 ${result.exitCode === EXIT_TIMEOUT ? `timed out after ${TIMEOUT}s` : `failed (exit ${result.exitCode})`}.`,
275
- );
276
-
277
- for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
278
- log(`Waiting ${RETRY_DELAY / 1000}s before retry...`);
279
- await sleep(RETRY_DELAY);
280
-
281
- if (isAnvil) {
282
- // On anvil: retry from scratch instead of --resume.
283
- //
284
- // Anvil's auto-miner has a race condition where batched transactions can arrive
285
- // after the auto-miner already triggered, stranding them in the mempool. --resume
286
- // just waits for these same stuck transactions and hangs again. A fresh retry
287
- // re-simulates from current chain state and re-sends, which works because:
288
- // - Forge computes new nonces from on-chain state
289
- // - New transactions replace any stuck ones with the same nonce
290
- // - The race condition is intermittent (~0.04%), so retries almost always succeed
291
- rmSync("broadcast", { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
292
-
293
- log(
294
- `Attempt ${attempt + 1}/${MAX_RETRIES + 1}: retrying from scratch (anvil)...`,
295
- );
296
- result = await runForge(forgeArgs, TIMEOUT);
297
- } else {
298
- // On real chains: use --resume to pick up unmined transactions.
299
- // --resume re-reads broadcast artifacts and resubmits unmined transactions.
300
- // NOTE: --resume skips simulation, so console.log output (e.g. JSON deploy results)
301
- // is only produced on the first attempt. We keep the first attempt's stdout (`result`)
302
- // and only check the exit code from the --resume attempt.
303
- log(`Attempt ${attempt + 1}/${MAX_RETRIES + 1}: --resume`);
304
- const resumeResult = await runForge([...forgeArgs, "--resume"], TIMEOUT);
305
-
306
- if (resumeResult.exitCode === 0) {
307
- log(`Broadcast succeeded on attempt ${attempt + 1}.`);
308
- // Emit the first attempt's stdout which has the JSON simulation output.
309
- await verifyAndExit(result);
310
- }
311
- log(
312
- `Attempt ${attempt + 1} ${resumeResult.exitCode === EXIT_TIMEOUT ? `timed out after ${TIMEOUT}s` : `failed (exit ${resumeResult.exitCode})`}.`,
313
- );
314
- continue;
315
- }
316
-
317
- if (result.exitCode === 0) {
318
- log(`Broadcast succeeded on attempt ${attempt + 1}.`);
319
- await verifyAndExit(result);
320
- }
321
- log(
322
- `Attempt ${attempt + 1} ${result.exitCode === EXIT_TIMEOUT ? `timed out after ${TIMEOUT}s` : `failed (exit ${result.exitCode})`}.`,
323
- );
63
+ if (isAnvil && isAutomine) {
64
+ try {
65
+ await rpc(rpcUrl, "evm_setIntervalMining", [0]);
66
+ await rpc(rpcUrl, "evm_setAutomine", [true]);
67
+ } catch {}
324
68
  }
325
69
 
326
- log(`All ${MAX_RETRIES + 1} attempts failed.`);
327
- emitAndExit(result, result.exitCode);
70
+ log(exitCode === 0 ? "Broadcast succeeded." : `Broadcast failed (exit ${exitCode}).`);
71
+ const data = Buffer.concat(stdout);
72
+ if (data.length > 0) writeSync(1, data);
73
+ process.exit(exitCode);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/l1-artifacts",
3
- "version": "0.0.1-commit.8227e42",
3
+ "version": "0.0.1-commit.85d7d01",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./*": "./dest/*.js",