@aztec/ethereum 0.0.1-commit.b655e406 → 0.0.1-commit.b8a057fa
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/account.d.ts +1 -1
- package/dest/chain.d.ts +1 -1
- package/dest/client.d.ts +25 -3
- package/dest/client.d.ts.map +1 -1
- package/dest/client.js +60 -4
- package/dest/config.d.ts +48 -73
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +120 -386
- package/dest/constants.d.ts +1 -1
- package/dest/contracts/chain_state_override.d.ts +78 -0
- package/dest/contracts/chain_state_override.d.ts.map +1 -0
- package/dest/contracts/chain_state_override.js +137 -0
- package/dest/contracts/empire_base.d.ts +7 -5
- package/dest/contracts/empire_base.d.ts.map +1 -1
- package/dest/contracts/empire_base.js +1 -1
- package/dest/contracts/errors.d.ts +1 -1
- package/dest/contracts/errors.d.ts.map +1 -1
- 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/fee_asset_price_oracle.d.ts +105 -0
- package/dest/contracts/fee_asset_price_oracle.d.ts.map +1 -0
- package/dest/contracts/fee_asset_price_oracle.js +656 -0
- package/dest/contracts/fee_juice.d.ts +1 -1
- package/dest/contracts/fee_juice.d.ts.map +1 -1
- package/dest/contracts/governance.d.ts +113 -36
- package/dest/contracts/governance.d.ts.map +1 -1
- package/dest/contracts/governance.js +207 -16
- package/dest/contracts/governance_proposer.d.ts +38 -4
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +455 -12
- package/dest/contracts/gse.d.ts +4 -2
- package/dest/contracts/gse.d.ts.map +1 -1
- package/dest/contracts/gse.js +2 -2
- package/dest/contracts/inbox.d.ts +24 -3
- package/dest/contracts/inbox.d.ts.map +1 -1
- package/dest/contracts/inbox.js +42 -2
- package/dest/contracts/index.d.ts +6 -3
- package/dest/contracts/index.d.ts.map +1 -1
- package/dest/contracts/index.js +5 -2
- 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 +130 -13
- package/dest/contracts/multicall.d.ts.map +1 -1
- package/dest/contracts/multicall.js +203 -93
- package/dest/contracts/outbox.d.ts +64 -0
- package/dest/contracts/outbox.d.ts.map +1 -0
- package/dest/contracts/outbox.js +113 -0
- package/dest/contracts/registry.d.ts +3 -1
- package/dest/contracts/registry.d.ts.map +1 -1
- package/dest/contracts/registry.js +30 -1
- package/dest/contracts/rollup.d.ts +5591 -131
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +1125 -232
- package/dest/contracts/slasher_contract.d.ts +1 -1
- package/dest/contracts/slasher_contract.d.ts.map +1 -1
- package/dest/contracts/{tally_slashing_proposer.d.ts → slashing_proposer.d.ts} +11 -10
- package/dest/contracts/slashing_proposer.d.ts.map +1 -0
- package/dest/contracts/{tally_slashing_proposer.js → slashing_proposer.js} +21 -16
- package/dest/contracts/utils.d.ts +1 -1
- package/dest/deploy_aztec_l1_contracts.d.ts +267 -0
- package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -0
- package/dest/deploy_aztec_l1_contracts.js +417 -0
- package/dest/deploy_l1_contract.d.ts +68 -0
- package/dest/deploy_l1_contract.d.ts.map +1 -0
- package/dest/deploy_l1_contract.js +312 -0
- package/dest/eth-signer/eth-signer.d.ts +1 -1
- package/dest/eth-signer/index.d.ts +1 -1
- package/dest/forwarder_proxy.d.ts +32 -0
- package/dest/forwarder_proxy.d.ts.map +1 -0
- package/dest/forwarder_proxy.js +93 -0
- package/dest/l1_artifacts.d.ts +21007 -16779
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/l1_artifacts.js +9 -24
- package/dest/l1_contract_addresses.d.ts +61 -65
- package/dest/l1_contract_addresses.d.ts.map +1 -1
- package/dest/l1_contract_addresses.js +99 -80
- package/dest/l1_reader.d.ts +7 -5
- package/dest/l1_reader.d.ts.map +1 -1
- package/dest/l1_reader.js +15 -7
- package/dest/l1_tx_utils/config.d.ts +11 -5
- package/dest/l1_tx_utils/config.d.ts.map +1 -1
- package/dest/l1_tx_utils/config.js +46 -10
- 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/factory.d.ts +18 -10
- package/dest/l1_tx_utils/factory.d.ts.map +1 -1
- package/dest/l1_tx_utils/factory.js +17 -7
- 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/forwarder_l1_tx_utils.d.ts +41 -0
- package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +42 -0
- package/dest/l1_tx_utils/index-blobs.d.ts +3 -0
- package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -0
- package/dest/l1_tx_utils/index-blobs.js +2 -0
- package/dest/l1_tx_utils/index.d.ts +4 -1
- package/dest/l1_tx_utils/index.d.ts.map +1 -1
- package/dest/l1_tx_utils/index.js +3 -0
- package/dest/l1_tx_utils/interfaces.d.ts +2 -2
- package/dest/l1_tx_utils/interfaces.d.ts.map +1 -1
- package/dest/l1_tx_utils/l1_fee_analyzer.d.ts +252 -0
- package/dest/l1_tx_utils/l1_fee_analyzer.d.ts.map +1 -0
- package/dest/l1_tx_utils/l1_fee_analyzer.js +568 -0
- package/dest/l1_tx_utils/l1_tx_utils.d.ts +26 -8
- package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/l1_tx_utils.js +202 -92
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +19 -30
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/readonly_l1_tx_utils.js +65 -168
- package/dest/l1_tx_utils/signer.d.ts +1 -1
- package/dest/l1_tx_utils/tx_delayer.d.ts +58 -0
- package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -0
- package/dest/{test → l1_tx_utils}/tx_delayer.js +70 -39
- package/dest/l1_tx_utils/types.d.ts +27 -1
- package/dest/l1_tx_utils/types.d.ts.map +1 -1
- package/dest/l1_tx_utils/types.js +10 -0
- package/dest/l1_tx_utils/utils.d.ts +1 -1
- package/dest/l1_types.d.ts +1 -1
- package/dest/publisher_manager.d.ts +34 -7
- package/dest/publisher_manager.d.ts.map +1 -1
- package/dest/publisher_manager.js +119 -8
- package/dest/queries.d.ts +14 -3
- package/dest/queries.d.ts.map +1 -1
- package/dest/queries.js +84 -9
- package/dest/test/blob_kzg_warmup.d.ts +19 -0
- package/dest/test/blob_kzg_warmup.d.ts.map +1 -0
- package/dest/test/blob_kzg_warmup.js +64 -0
- package/dest/test/chain_monitor.d.ts +80 -26
- package/dest/test/chain_monitor.d.ts.map +1 -1
- package/dest/test/chain_monitor.js +137 -39
- package/dest/test/eth_cheat_codes.d.ts +47 -8
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +100 -44
- package/dest/test/eth_cheat_codes_with_state.d.ts +1 -1
- package/dest/test/eth_cheat_codes_with_state.d.ts.map +1 -1
- package/dest/test/index.d.ts +2 -3
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +1 -2
- package/dest/test/rollup_cheat_codes.d.ts +75 -14
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +145 -42
- package/dest/test/start_anvil.d.ts +25 -2
- package/dest/test/start_anvil.d.ts.map +1 -1
- package/dest/test/start_anvil.js +143 -28
- package/dest/test/upgrade_utils.d.ts +1 -1
- package/dest/test/upgrade_utils.js +2 -2
- package/dest/types.d.ts +57 -2
- package/dest/types.d.ts.map +1 -1
- package/dest/utils.d.ts +24 -4
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +112 -16
- package/dest/zkPassportVerifierAddress.d.ts +1 -1
- package/package.json +34 -17
- package/src/client.ts +66 -2
- package/src/config.ts +162 -470
- package/src/contracts/README.md +157 -0
- package/src/contracts/chain_state_override.ts +200 -0
- package/src/contracts/empire_base.ts +6 -5
- package/src/contracts/fee_asset_handler.ts +10 -7
- package/src/contracts/fee_asset_price_oracle.ts +285 -0
- package/src/contracts/governance.ts +279 -13
- package/src/contracts/governance_proposer.ts +74 -7
- package/src/contracts/gse.ts +7 -2
- package/src/contracts/inbox.ts +64 -4
- package/src/contracts/index.ts +5 -2
- package/src/contracts/log.ts +13 -0
- package/src/contracts/multicall.ts +247 -103
- package/src/contracts/outbox.ts +132 -0
- package/src/contracts/registry.ts +31 -1
- package/src/contracts/rollup.ts +830 -194
- package/src/contracts/{tally_slashing_proposer.ts → slashing_proposer.ts} +26 -21
- package/src/deploy_aztec_l1_contracts.ts +652 -0
- package/src/deploy_l1_contract.ts +362 -0
- package/src/forwarder_proxy.ts +108 -0
- package/src/l1_artifacts.ts +12 -35
- package/src/l1_contract_addresses.ts +120 -92
- package/src/l1_reader.ts +25 -10
- package/src/l1_tx_utils/config.ts +55 -14
- package/src/l1_tx_utils/constants.ts +13 -2
- package/src/l1_tx_utils/factory.ts +31 -31
- 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/forwarder_l1_tx_utils.ts +108 -0
- package/src/l1_tx_utils/index-blobs.ts +2 -0
- package/src/l1_tx_utils/index.ts +3 -0
- package/src/l1_tx_utils/interfaces.ts +1 -1
- package/src/l1_tx_utils/l1_fee_analyzer.ts +875 -0
- package/src/l1_tx_utils/l1_tx_utils.ts +194 -72
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +79 -214
- package/src/{test → l1_tx_utils}/tx_delayer.ts +97 -58
- package/src/l1_tx_utils/types.ts +32 -0
- package/src/publisher_manager.ts +145 -12
- package/src/queries.ts +93 -10
- package/src/test/blob_kzg_warmup.ts +65 -0
- package/src/test/chain_monitor.ts +198 -51
- package/src/test/eth_cheat_codes.ts +91 -48
- package/src/test/index.ts +1 -2
- package/src/test/rollup_cheat_codes.ts +174 -45
- package/src/test/start_anvil.ts +179 -27
- package/src/test/upgrade_utils.ts +2 -2
- package/src/types.ts +62 -0
- package/src/utils.ts +128 -19
- package/dest/contracts/empire_slashing_proposer.d.ts +0 -65
- package/dest/contracts/empire_slashing_proposer.d.ts.map +0 -1
- package/dest/contracts/empire_slashing_proposer.js +0 -194
- package/dest/contracts/tally_slashing_proposer.d.ts.map +0 -1
- package/dest/deploy_l1_contracts.d.ts +0 -226
- package/dest/deploy_l1_contracts.d.ts.map +0 -1
- package/dest/deploy_l1_contracts.js +0 -1473
- package/dest/index.d.ts +0 -18
- package/dest/index.d.ts.map +0 -1
- package/dest/index.js +0 -17
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +0 -26
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +0 -1
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +0 -26
- package/dest/test/delayed_tx_utils.d.ts +0 -13
- package/dest/test/delayed_tx_utils.d.ts.map +0 -1
- package/dest/test/delayed_tx_utils.js +0 -28
- package/dest/test/tx_delayer.d.ts +0 -36
- package/dest/test/tx_delayer.d.ts.map +0 -1
- package/src/contracts/empire_slashing_proposer.ts +0 -259
- package/src/deploy_l1_contracts.ts +0 -1849
- package/src/index.ts +0 -17
- package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +0 -77
- package/src/test/delayed_tx_utils.ts +0 -52
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { RollupContract } from '@aztec/ethereum';
|
|
1
|
+
import { OutboxContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
2
|
+
import { CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
5
|
+
import { retryUntil } from '@aztec/foundation/retry';
|
|
4
6
|
import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
|
|
5
|
-
import { createPublicClient, fallback, getContract, hexToBigInt, http } from 'viem';
|
|
6
|
-
import { foundry } from 'viem/chains';
|
|
7
|
+
import { createPublicClient, fallback, getContract, hexToBigInt, http, keccak256 } from 'viem';
|
|
7
8
|
import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
8
9
|
/** Cheat codes for the L1 rollup contract. */ export class RollupCheatCodes {
|
|
9
10
|
ethCheatCodes;
|
|
@@ -14,8 +15,10 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
14
15
|
this.ethCheatCodes = ethCheatCodes;
|
|
15
16
|
this.logger = createLogger('aztecjs:cheat_codes');
|
|
16
17
|
this.client = createPublicClient({
|
|
17
|
-
chain:
|
|
18
|
-
transport: fallback(ethCheatCodes.rpcUrls.map((url)=>http(url
|
|
18
|
+
chain: ethCheatCodes.chain,
|
|
19
|
+
transport: fallback(ethCheatCodes.rpcUrls.map((url)=>http(url, {
|
|
20
|
+
batch: false
|
|
21
|
+
})))
|
|
19
22
|
});
|
|
20
23
|
this.rollup = getContract({
|
|
21
24
|
abi: RollupAbi,
|
|
@@ -29,39 +32,56 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
29
32
|
}
|
|
30
33
|
/** Returns the current slot */ async getSlot() {
|
|
31
34
|
const ts = BigInt((await this.client.getBlock()).timestamp);
|
|
32
|
-
return
|
|
33
|
-
|
|
35
|
+
return this.getSlotAt(ts);
|
|
36
|
+
}
|
|
37
|
+
/** Returns the slot number at a given timestamp. */ async getSlotAt(timestamp) {
|
|
38
|
+
return SlotNumber.fromBigInt(await this.rollup.read.getSlotAt([
|
|
39
|
+
timestamp
|
|
40
|
+
]));
|
|
41
|
+
}
|
|
42
|
+
/** Returns the timestamp for the start of a given slot. */ async getTimestampForSlot(slot) {
|
|
43
|
+
return await this.rollup.read.getTimestampForSlot([
|
|
44
|
+
BigInt(slot)
|
|
45
|
+
]);
|
|
46
|
+
}
|
|
47
|
+
/** Returns the number of seconds until the start of the given slot based on L1 block timestamp. */ async getSecondsUntilSlot(slot) {
|
|
48
|
+
const [currentTimestamp, targetTimestamp] = await Promise.all([
|
|
49
|
+
this.client.getBlock().then((b)=>BigInt(b.timestamp)),
|
|
50
|
+
this.rollup.read.getTimestampForSlot([
|
|
51
|
+
BigInt(slot)
|
|
52
|
+
])
|
|
34
53
|
]);
|
|
54
|
+
return Math.max(0, Number(targetTimestamp - currentTimestamp));
|
|
35
55
|
}
|
|
36
56
|
/** Returns the current epoch */ async getEpoch() {
|
|
37
57
|
const slotNumber = await this.getSlot();
|
|
38
|
-
return await this.rollup.read.getEpochAtSlot([
|
|
39
|
-
slotNumber
|
|
40
|
-
]);
|
|
58
|
+
return EpochNumber.fromBigInt(await this.rollup.read.getEpochAtSlot([
|
|
59
|
+
BigInt(slotNumber)
|
|
60
|
+
]));
|
|
41
61
|
}
|
|
42
62
|
/**
|
|
43
63
|
* Returns the pending and proven chain tips
|
|
44
64
|
* @returns The pending and proven chain tips
|
|
45
65
|
*/ async getTips() {
|
|
46
|
-
const
|
|
66
|
+
const { pending, proven } = await this.rollup.read.getTips();
|
|
47
67
|
return {
|
|
48
|
-
pending:
|
|
49
|
-
proven:
|
|
68
|
+
pending: CheckpointNumber.fromBigInt(pending),
|
|
69
|
+
proven: CheckpointNumber.fromBigInt(proven)
|
|
50
70
|
};
|
|
51
71
|
}
|
|
52
72
|
/**
|
|
53
73
|
* Logs the current state of the rollup contract.
|
|
54
74
|
*/ async debugRollup() {
|
|
55
75
|
const rollup = new RollupContract(this.client, this.rollup.address);
|
|
56
|
-
const pendingNum = await rollup.
|
|
57
|
-
const provenNum = await rollup.
|
|
76
|
+
const pendingNum = await rollup.getCheckpointNumber();
|
|
77
|
+
const provenNum = await rollup.getProvenCheckpointNumber();
|
|
58
78
|
const validators = await rollup.getAttesters();
|
|
59
79
|
const committee = await rollup.getCurrentEpochCommittee();
|
|
60
80
|
const archive = await rollup.archive();
|
|
61
81
|
const slot = await this.getSlot();
|
|
62
82
|
const epochNum = await rollup.getEpochNumberForSlotNumber(slot);
|
|
63
|
-
this.logger.info(`Pending
|
|
64
|
-
this.logger.info(`Proven
|
|
83
|
+
this.logger.info(`Pending checkpoint num: ${pendingNum}`);
|
|
84
|
+
this.logger.info(`Proven checkpoint num: ${provenNum}`);
|
|
65
85
|
this.logger.info(`Validators: ${validators.map((v)=>v.toString()).join(', ')}`);
|
|
66
86
|
this.logger.info(`Committee: ${committee?.map((v)=>v.toString()).join(', ')}`);
|
|
67
87
|
this.logger.info(`Archive: ${archive}`);
|
|
@@ -75,7 +95,7 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
75
95
|
]);
|
|
76
96
|
return {
|
|
77
97
|
epochDuration,
|
|
78
|
-
slotDuration
|
|
98
|
+
slotDuration: Number(slotDuration)
|
|
79
99
|
};
|
|
80
100
|
}
|
|
81
101
|
/**
|
|
@@ -84,8 +104,9 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
84
104
|
* @param opts - Options
|
|
85
105
|
*/ async advanceToEpoch(epoch, opts = {}) {
|
|
86
106
|
const { epochDuration: slotsInEpoch } = await this.getConfig();
|
|
107
|
+
const slotNumber = SlotNumber(Number(epoch) * Number(slotsInEpoch));
|
|
87
108
|
const timestamp = await this.rollup.read.getTimestampForSlot([
|
|
88
|
-
BigInt(
|
|
109
|
+
BigInt(slotNumber)
|
|
89
110
|
]) + BigInt(opts.offset ?? 0);
|
|
90
111
|
try {
|
|
91
112
|
await this.ethCheatCodes.warp(Number(timestamp), {
|
|
@@ -93,7 +114,10 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
93
114
|
silent: true,
|
|
94
115
|
resetBlockInterval: true
|
|
95
116
|
});
|
|
96
|
-
this.logger.warn(`Warped to epoch ${epoch}
|
|
117
|
+
this.logger.warn(`Warped to epoch ${epoch}`, {
|
|
118
|
+
offset: opts.offset,
|
|
119
|
+
timestamp
|
|
120
|
+
});
|
|
97
121
|
} catch (err) {
|
|
98
122
|
this.logger.warn(`Warp to epoch ${epoch} failed: ${err}`);
|
|
99
123
|
}
|
|
@@ -102,8 +126,8 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
102
126
|
/** Warps time in L1 until the next epoch */ async advanceToNextEpoch() {
|
|
103
127
|
const slot = await this.getSlot();
|
|
104
128
|
const { epochDuration, slotDuration } = await this.getConfig();
|
|
105
|
-
const slotsUntilNextEpoch = epochDuration - slot % epochDuration + 1n;
|
|
106
|
-
const timeToNextEpoch = slotsUntilNextEpoch * slotDuration;
|
|
129
|
+
const slotsUntilNextEpoch = epochDuration - BigInt(slot) % epochDuration + 1n;
|
|
130
|
+
const timeToNextEpoch = slotsUntilNextEpoch * BigInt(slotDuration);
|
|
107
131
|
const l1Timestamp = BigInt((await this.client.getBlock()).timestamp);
|
|
108
132
|
await this.ethCheatCodes.warp(Number(l1Timestamp + timeToNextEpoch), {
|
|
109
133
|
silent: true,
|
|
@@ -113,26 +137,47 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
113
137
|
}
|
|
114
138
|
/** Warps time in L1 until the beginning of the next slot. */ async advanceToNextSlot() {
|
|
115
139
|
const currentSlot = await this.getSlot();
|
|
140
|
+
const nextSlot = SlotNumber(currentSlot + 1);
|
|
116
141
|
const timestamp = await this.rollup.read.getTimestampForSlot([
|
|
117
|
-
|
|
142
|
+
BigInt(nextSlot)
|
|
118
143
|
]);
|
|
119
144
|
await this.ethCheatCodes.warp(Number(timestamp), {
|
|
120
145
|
silent: true,
|
|
121
146
|
resetBlockInterval: true
|
|
122
147
|
});
|
|
123
|
-
this.logger.warn(`Advanced to slot ${
|
|
148
|
+
this.logger.warn(`Advanced to slot ${nextSlot}`);
|
|
124
149
|
return [
|
|
125
150
|
timestamp,
|
|
126
|
-
|
|
151
|
+
nextSlot
|
|
127
152
|
];
|
|
128
153
|
}
|
|
129
154
|
/**
|
|
155
|
+
* Warps L1 time to the start of an explicit absolute slot. Unlike `advanceSlots(N)` which is
|
|
156
|
+
* relative to the current L1 timestamp at call time and therefore races with real-time
|
|
157
|
+
* progression between query and warp, this lands at the slot regardless of latency.
|
|
158
|
+
*
|
|
159
|
+
* Throws if the requested slot is in the past relative to current L1 time (anvil cannot
|
|
160
|
+
* rewind).
|
|
161
|
+
*/ async advanceToSlot(slot) {
|
|
162
|
+
const timestamp = await this.rollup.read.getTimestampForSlot([
|
|
163
|
+
BigInt(slot)
|
|
164
|
+
]);
|
|
165
|
+
await this.ethCheatCodes.warp(Number(timestamp), {
|
|
166
|
+
silent: true,
|
|
167
|
+
resetBlockInterval: true
|
|
168
|
+
});
|
|
169
|
+
this.logger.warn(`Advanced to slot ${slot}`, {
|
|
170
|
+
timestamp
|
|
171
|
+
});
|
|
172
|
+
return timestamp;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
130
175
|
* Warps time in L1 equivalent to however many slots.
|
|
131
176
|
* @param howMany - The number of slots to advance.
|
|
132
177
|
*/ async advanceSlots(howMany) {
|
|
133
178
|
const l1Timestamp = (await this.client.getBlock()).timestamp;
|
|
134
|
-
const slotDuration = await this.rollup.read.getSlotDuration();
|
|
135
|
-
const timeToWarp = BigInt(howMany) * slotDuration;
|
|
179
|
+
const slotDuration = Number(await this.rollup.read.getSlotDuration());
|
|
180
|
+
const timeToWarp = BigInt(howMany) * BigInt(slotDuration);
|
|
136
181
|
await this.ethCheatCodes.warp(l1Timestamp + timeToWarp, {
|
|
137
182
|
silent: true,
|
|
138
183
|
resetBlockInterval: true
|
|
@@ -144,36 +189,62 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
144
189
|
this.logger.warn(`Advanced ${howMany} slots up to slot ${slot} in epoch ${epoch}`);
|
|
145
190
|
}
|
|
146
191
|
/**
|
|
147
|
-
* Marks the specified
|
|
148
|
-
* @param
|
|
149
|
-
*/ markAsProven(
|
|
192
|
+
* Marks the specified checkpoint (or latest if none) as proven
|
|
193
|
+
* @param maybeCheckpointNumber - The checkpoint number to mark as proven (defaults to latest pending)
|
|
194
|
+
*/ markAsProven(maybeCheckpointNumber) {
|
|
150
195
|
return this.ethCheatCodes.execWithPausedAnvil(async ()=>{
|
|
151
196
|
const tipsBefore = await this.getTips();
|
|
152
197
|
const { pending, proven } = tipsBefore;
|
|
153
|
-
let
|
|
154
|
-
if (
|
|
155
|
-
|
|
198
|
+
let checkpointNumber = maybeCheckpointNumber;
|
|
199
|
+
if (checkpointNumber === undefined || checkpointNumber > pending) {
|
|
200
|
+
checkpointNumber = pending;
|
|
156
201
|
}
|
|
157
|
-
if (
|
|
158
|
-
this.logger.debug(`
|
|
202
|
+
if (checkpointNumber <= proven) {
|
|
203
|
+
this.logger.debug(`Checkpoint ${checkpointNumber} is already proven`);
|
|
159
204
|
return;
|
|
160
205
|
}
|
|
161
206
|
// @note @LHerskind this is heavily dependent on the storage layout and size of values
|
|
162
207
|
// The rollupStore is a struct and if the size of elements or the struct changes, this can break
|
|
163
|
-
const
|
|
208
|
+
const provenCheckpointNumberSlot = hexToBigInt(RollupContract.stfStorageSlot);
|
|
164
209
|
// Need to pack it as a single 32 byte word
|
|
165
|
-
const newValue = BigInt(tipsBefore.pending) << 128n | BigInt(
|
|
166
|
-
await this.ethCheatCodes.store(EthAddress.fromString(this.rollup.address),
|
|
210
|
+
const newValue = BigInt(tipsBefore.pending) << 128n | BigInt(checkpointNumber);
|
|
211
|
+
await this.ethCheatCodes.store(EthAddress.fromString(this.rollup.address), provenCheckpointNumberSlot, newValue);
|
|
167
212
|
const tipsAfter = await this.getTips();
|
|
168
213
|
if (tipsAfter.pending < tipsAfter.proven) {
|
|
169
|
-
throw new Error('Overwrote pending tip to a
|
|
214
|
+
throw new Error('Overwrote pending tip to a checkpoint in the past');
|
|
170
215
|
}
|
|
171
216
|
this.logger.info(`Proven tip moved: ${tipsBefore.proven} -> ${tipsAfter.proven}. Pending tip: ${tipsAfter.pending}.`);
|
|
172
217
|
});
|
|
173
218
|
}
|
|
174
219
|
/**
|
|
220
|
+
* Polls the rollup until its current epoch reaches `epoch`. Unlike {@link advanceToEpoch} this does
|
|
221
|
+
* not warp the L1 clock; it only waits for the chain to reach `epoch` through external activity.
|
|
222
|
+
*/ async waitForEpoch(epoch, opts = {}) {
|
|
223
|
+
await retryUntil(async ()=>await this.getEpoch() >= epoch || undefined, `rollup epoch >= ${epoch}`, opts.timeout ?? 60, opts.interval ?? 1);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Polls the rollup until its current slot reaches `slot`. Unlike {@link advanceToSlot} this does not
|
|
227
|
+
* warp the L1 clock; it only waits for the chain to reach `slot` through external activity.
|
|
228
|
+
*/ async waitForSlot(slot, opts = {}) {
|
|
229
|
+
await retryUntil(async ()=>await this.getSlot() >= slot || undefined, `rollup slot >= ${slot}`, opts.timeout ?? 60, opts.interval ?? 1);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Polls the rollup until its pending checkpoint settles below `checkpoint` on a freshly mined, non-zero
|
|
233
|
+
* checkpoint, and returns that new pending checkpoint number. Reads the L1 rollup contract directly
|
|
234
|
+
* rather than a node, since a rollback lands on L1 first.
|
|
235
|
+
*
|
|
236
|
+
* A prune can momentarily drop the pending checkpoint to 0 before the post-deadline propose mines its
|
|
237
|
+
* replacement, so a caller detecting a rollback wants the new lower checkpoint, not that transient
|
|
238
|
+
* empty state — hence the non-zero guard.
|
|
239
|
+
*/ async waitForCheckpointBelow(checkpoint, opts = {}) {
|
|
240
|
+
return await retryUntil(async ()=>{
|
|
241
|
+
const { pending } = await this.getTips();
|
|
242
|
+
return pending > 0 && pending < checkpoint ? pending : undefined;
|
|
243
|
+
}, `rollup checkpoint in (0, ${checkpoint})`, opts.timeout ?? 60, opts.interval ?? 1);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
175
246
|
* Overrides the inProgress field of the Inbox contract state
|
|
176
|
-
* @param howMuch - How many
|
|
247
|
+
* @param howMuch - How many checkpoints to move it forward
|
|
177
248
|
*/ advanceInboxInProgress(howMuch) {
|
|
178
249
|
return this.ethCheatCodes.execWithPausedAnvil(async ()=>{
|
|
179
250
|
// Storage slot 2 contains the InboxState struct
|
|
@@ -204,6 +275,14 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
204
275
|
return newInProgress;
|
|
205
276
|
});
|
|
206
277
|
}
|
|
278
|
+
insertOutbox(epoch, numCheckpointsInEpoch, outHash) {
|
|
279
|
+
return this.ethCheatCodes.execWithPausedAnvil(async ()=>{
|
|
280
|
+
const outboxAddress = await this.rollup.read.getOutbox();
|
|
281
|
+
const epochRootSlot = OutboxContract.getEpochRootStorageSlot(epoch, numCheckpointsInEpoch);
|
|
282
|
+
await this.ethCheatCodes.store(EthAddress.fromString(outboxAddress), epochRootSlot, outHash);
|
|
283
|
+
this.logger.warn(`Advanced outbox to epoch ${epoch} numCheckpointsInEpoch ${numCheckpointsInEpoch} with out hash ${outHash}`);
|
|
284
|
+
});
|
|
285
|
+
}
|
|
207
286
|
/**
|
|
208
287
|
* Executes an action impersonated as the owner of the Rollup contract.
|
|
209
288
|
* @param action - The action to execute
|
|
@@ -248,7 +327,8 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
248
327
|
await this.setProvingCostPerMana(newCost);
|
|
249
328
|
}
|
|
250
329
|
/**
|
|
251
|
-
* Directly updates proving cost per mana.
|
|
330
|
+
* Directly updates proving cost per mana. Throws if the on-chain tx reverts
|
|
331
|
+
* (e.g. rate-limit cooldown, step cap, or floor) instead of silently succeeding.
|
|
252
332
|
* @param ethValue - The new proving cost per mana in ETH
|
|
253
333
|
*/ async setProvingCostPerMana(ethValue) {
|
|
254
334
|
await this.asOwner(async (account, rollup)=>{
|
|
@@ -259,10 +339,33 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
259
339
|
chain: this.client.chain,
|
|
260
340
|
gasLimit: 1000000n
|
|
261
341
|
});
|
|
262
|
-
await this.client.waitForTransactionReceipt({
|
|
342
|
+
const receipt = await this.client.waitForTransactionReceipt({
|
|
263
343
|
hash
|
|
264
344
|
});
|
|
345
|
+
if (receipt.status !== 'success') {
|
|
346
|
+
throw new Error(`setProvingCostPerMana(${ethValue}) reverted on L1 (tx ${hash}). ` + `Likely FeeLib rate-limit (30-day cooldown or 1.5x step cap); ` + `use clearProvingCostCooldown() between successive updates.`);
|
|
347
|
+
}
|
|
265
348
|
this.logger.warn(`Updated proving cost per mana to ${ethValue}`);
|
|
266
349
|
});
|
|
267
350
|
}
|
|
351
|
+
/**
|
|
352
|
+
* Resets the 30-day proving-cost update cooldown enforced by FeeLib.updateProvingCostPerMana
|
|
353
|
+
* by zeroing `FeeStore.provingCostLastUpdate` directly in contract storage. Use between
|
|
354
|
+
* successive setProvingCostPerMana / bumpProvingCostPerMana calls so the later update can
|
|
355
|
+
* land instead of reverting. Does not touch L1 time, so PXE/tx-expiration state stays intact.
|
|
356
|
+
*
|
|
357
|
+
* @note This is tightly coupled to the `FeeStore` layout in
|
|
358
|
+
* l1-contracts/src/core/libraries/rollup/FeeLib.sol:
|
|
359
|
+
* slot + 0: CompressedFeeConfig config (uint256)
|
|
360
|
+
* slot + 1: L1GasOracleValues l1GasOracleValues (14+14+4 bytes, packed)
|
|
361
|
+
* slot + 2: uint64 provingCostLastUpdate (only member — zeroing the slot is safe)
|
|
362
|
+
* If the struct layout changes, update the offset below.
|
|
363
|
+
*/ async clearProvingCostCooldown() {
|
|
364
|
+
const feeStoreBaseSlot = hexToBigInt(keccak256(Buffer.from('aztec.fee.storage', 'utf-8')));
|
|
365
|
+
const provingCostLastUpdateSlot = feeStoreBaseSlot + 2n;
|
|
366
|
+
await this.ethCheatCodes.store(EthAddress.fromString(this.rollup.address), provingCostLastUpdateSlot, 0n, {
|
|
367
|
+
silent: true
|
|
368
|
+
});
|
|
369
|
+
this.logger.warn(`Cleared proving-cost update cooldown`);
|
|
370
|
+
}
|
|
268
371
|
}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { TestDateProvider } from '@aztec/foundation/timer';
|
|
2
|
+
/** Minimal interface matching the @viem/anvil Anvil shape used by callers. */
|
|
3
|
+
export interface Anvil {
|
|
4
|
+
readonly port: number;
|
|
5
|
+
readonly host: string;
|
|
6
|
+
readonly status: 'listening' | 'idle';
|
|
7
|
+
stop(): Promise<void>;
|
|
8
|
+
}
|
|
2
9
|
/**
|
|
3
10
|
* Ensures there's a running Anvil instance and returns the RPC URL.
|
|
4
11
|
*/
|
|
@@ -8,10 +15,26 @@ export declare function startAnvil(opts?: {
|
|
|
8
15
|
log?: boolean;
|
|
9
16
|
captureMethodCalls?: boolean;
|
|
10
17
|
accounts?: number;
|
|
18
|
+
chainId?: number;
|
|
19
|
+
/** The hardfork to use (e.g. 'cancun', 'latest'). */
|
|
20
|
+
hardfork?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Number of slots per epoch used by anvil to compute the 'finalized' and 'safe' block tags.
|
|
23
|
+
* Anvil reports `finalized = latest - slotsInAnEpoch * 2`.
|
|
24
|
+
* Defaults to 1 so the finalized block advances immediately, making tests that check
|
|
25
|
+
* L1-finality-based logic work without needing hundreds of mined blocks.
|
|
26
|
+
*/
|
|
27
|
+
slotsInAnEpoch?: number;
|
|
28
|
+
/**
|
|
29
|
+
* If provided, the date provider will be synced to anvil's block time on every mined block.
|
|
30
|
+
* This keeps the dateProvider in lockstep with anvil's chain time, avoiding drift between
|
|
31
|
+
* the wall clock and the L1 chain when computing L1 slot timestamps.
|
|
32
|
+
*/
|
|
33
|
+
dateProvider?: TestDateProvider;
|
|
11
34
|
}): Promise<{
|
|
12
35
|
anvil: Anvil;
|
|
13
36
|
methodCalls?: string[];
|
|
14
37
|
rpcUrl: string;
|
|
15
38
|
stop: () => Promise<void>;
|
|
16
39
|
}>;
|
|
17
|
-
//# sourceMappingURL=
|
|
40
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnRfYW52aWwuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L3N0YXJ0X2FudmlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFNaEUsOEVBQThFO0FBQzlFLE1BQU0sV0FBVyxLQUFLO0lBQ3BCLFFBQVEsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ3RCLFFBQVEsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ3RCLFFBQVEsQ0FBQyxNQUFNLEVBQUUsV0FBVyxHQUFHLE1BQU0sQ0FBQztJQUN0QyxJQUFJLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0NBQ3ZCO0FBRUQ7O0dBRUc7QUFDSCx3QkFBc0IsVUFBVSxDQUM5QixJQUFJLEdBQUU7SUFDSixJQUFJLENBQUMsRUFBRSxNQUFNLENBQUM7SUFDZCxXQUFXLENBQUMsRUFBRSxNQUFNLENBQUM7SUFDckIsR0FBRyxDQUFDLEVBQUUsT0FBTyxDQUFDO0lBQ2Qsa0JBQWtCLENBQUMsRUFBRSxPQUFPLENBQUM7SUFDN0IsUUFBUSxDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ2xCLE9BQU8sQ0FBQyxFQUFFLE1BQU0sQ0FBQztJQUNqQixxREFBcUQ7SUFDckQsUUFBUSxDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ2xCOzs7OztPQUtHO0lBQ0gsY0FBYyxDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ3hCOzs7O09BSUc7SUFDSCxZQUFZLENBQUMsRUFBRSxnQkFBZ0IsQ0FBQztDQUM1QixHQUNMLE9BQU8sQ0FBQztJQUFFLEtBQUssRUFBRSxLQUFLLENBQUM7SUFBQyxXQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQztJQUFDLE1BQU0sRUFBRSxNQUFNLENBQUM7SUFBQyxJQUFJLEVBQUUsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUE7Q0FBRSxDQUFDLENBK0g5RiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start_anvil.d.ts","sourceRoot":"","sources":["../../src/test/start_anvil.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"start_anvil.d.ts","sourceRoot":"","sources":["../../src/test/start_anvil.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAMhE,8EAA8E;AAC9E,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC;IACtC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,IAAI,GAAE;IACJ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,YAAY,CAAC,EAAE,gBAAgB,CAAC;CAC5B,GACL,OAAO,CAAC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CA+H9F"}
|
package/dest/test/start_anvil.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
2
|
import { makeBackoff, retry } from '@aztec/foundation/retry';
|
|
3
3
|
import { fileURLToPath } from '@aztec/foundation/url';
|
|
4
|
-
import {
|
|
4
|
+
import { spawn } from 'child_process';
|
|
5
5
|
import { dirname, resolve } from 'path';
|
|
6
6
|
/**
|
|
7
7
|
* Ensures there's a running Anvil instance and returns the RPC URL.
|
|
@@ -9,46 +9,161 @@ import { dirname, resolve } from 'path';
|
|
|
9
9
|
const anvilBinary = resolve(dirname(fileURLToPath(import.meta.url)), '../../', 'scripts/anvil_kill_wrapper.sh');
|
|
10
10
|
const logger = opts.log ? createLogger('ethereum:anvil') : undefined;
|
|
11
11
|
const methodCalls = opts.captureMethodCalls ? [] : undefined;
|
|
12
|
-
let
|
|
13
|
-
// Start anvil.
|
|
14
|
-
// We go via a wrapper script to ensure if the parent dies, anvil dies.
|
|
12
|
+
let detectedPort;
|
|
15
13
|
const anvil = await retry(async ()=>{
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
host
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
accounts
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
const port = opts.port ?? (process.env.ANVIL_PORT ? parseInt(process.env.ANVIL_PORT) : 8545);
|
|
15
|
+
const args = [
|
|
16
|
+
'--host',
|
|
17
|
+
'127.0.0.1',
|
|
18
|
+
'--port',
|
|
19
|
+
String(port),
|
|
20
|
+
'--accounts',
|
|
21
|
+
String(opts.accounts ?? 20),
|
|
22
|
+
'--gas-limit',
|
|
23
|
+
String(45_000_000),
|
|
24
|
+
'--chain-id',
|
|
25
|
+
String(opts.chainId ?? 31337)
|
|
26
|
+
];
|
|
27
|
+
if (opts.l1BlockTime !== undefined) {
|
|
28
|
+
args.push('--block-time', String(opts.l1BlockTime));
|
|
29
|
+
}
|
|
30
|
+
if (opts.hardfork !== undefined) {
|
|
31
|
+
args.push('--hardfork', opts.hardfork);
|
|
32
|
+
}
|
|
33
|
+
args.push('--slots-in-an-epoch', String(opts.slotsInAnEpoch ?? 1));
|
|
34
|
+
const child = spawn(anvilBinary, args, {
|
|
35
|
+
stdio: [
|
|
36
|
+
'ignore',
|
|
37
|
+
'pipe',
|
|
38
|
+
'pipe'
|
|
39
|
+
],
|
|
40
|
+
env: {
|
|
41
|
+
...process.env,
|
|
42
|
+
RAYON_NUM_THREADS: '1'
|
|
31
43
|
}
|
|
32
44
|
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
// Wait for "Listening on" or an early exit.
|
|
46
|
+
await new Promise((resolve, reject)=>{
|
|
47
|
+
let stderr = '';
|
|
48
|
+
const onStdout = (data)=>{
|
|
49
|
+
const text = data.toString();
|
|
50
|
+
logger?.debug(text.trim());
|
|
51
|
+
methodCalls?.push(...text.match(/eth_[^\s]+/g) || []);
|
|
52
|
+
if (detectedPort === undefined && text.includes('Listening on')) {
|
|
53
|
+
const match = text.match(/Listening on ([^:]+):(\d+)/);
|
|
54
|
+
if (match) {
|
|
55
|
+
detectedPort = parseInt(match[2]);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (detectedPort !== undefined) {
|
|
59
|
+
child.stdout?.removeListener('data', onStdout);
|
|
60
|
+
child.stderr?.removeListener('data', onStderr);
|
|
61
|
+
child.removeListener('close', onClose);
|
|
62
|
+
resolve();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const onStderr = (data)=>{
|
|
66
|
+
stderr += data.toString();
|
|
67
|
+
logger?.debug(data.toString().trim());
|
|
68
|
+
};
|
|
69
|
+
const onClose = (code)=>{
|
|
70
|
+
child.stdout?.removeListener('data', onStdout);
|
|
71
|
+
child.stderr?.removeListener('data', onStderr);
|
|
72
|
+
reject(new Error(`Anvil exited with code ${code} before listening. stderr: ${stderr}`));
|
|
73
|
+
};
|
|
74
|
+
child.stdout?.on('data', onStdout);
|
|
75
|
+
child.stderr?.on('data', onStderr);
|
|
76
|
+
child.once('close', onClose);
|
|
77
|
+
});
|
|
78
|
+
// Continue piping for logging, method-call capture, and/or dateProvider sync after startup.
|
|
79
|
+
if (logger || opts.captureMethodCalls || opts.dateProvider) {
|
|
80
|
+
child.stdout?.on('data', (data)=>{
|
|
81
|
+
const text = data.toString();
|
|
82
|
+
logger?.debug(text.trim());
|
|
83
|
+
methodCalls?.push(...text.match(/eth_[^\s]+/g) || []);
|
|
84
|
+
if (opts.dateProvider) {
|
|
85
|
+
syncDateProviderFromAnvilOutput(text, opts.dateProvider);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
child.stderr?.on('data', (data)=>{
|
|
89
|
+
logger?.debug(data.toString().trim());
|
|
90
|
+
});
|
|
91
|
+
} else {
|
|
92
|
+
// Consume streams so the child process doesn't block on full pipe buffers.
|
|
93
|
+
child.stdout?.resume();
|
|
94
|
+
child.stderr?.resume();
|
|
36
95
|
}
|
|
37
|
-
return
|
|
96
|
+
return child;
|
|
38
97
|
}, 'Start anvil', makeBackoff([
|
|
39
98
|
5,
|
|
40
99
|
5,
|
|
41
100
|
5
|
|
42
101
|
]));
|
|
43
|
-
if (!
|
|
102
|
+
if (!detectedPort) {
|
|
44
103
|
throw new Error('Failed to start anvil');
|
|
45
104
|
}
|
|
46
|
-
|
|
47
|
-
|
|
105
|
+
const port = detectedPort;
|
|
106
|
+
let status = 'listening';
|
|
107
|
+
anvil.once('close', ()=>{
|
|
108
|
+
status = 'idle';
|
|
109
|
+
});
|
|
110
|
+
const stop = async ()=>{
|
|
111
|
+
if (status === 'idle') {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
await killChild(anvil);
|
|
115
|
+
};
|
|
116
|
+
const anvilObj = {
|
|
117
|
+
port,
|
|
118
|
+
host: '127.0.0.1',
|
|
119
|
+
get status () {
|
|
120
|
+
return status;
|
|
121
|
+
},
|
|
122
|
+
stop
|
|
123
|
+
};
|
|
48
124
|
return {
|
|
49
|
-
anvil,
|
|
125
|
+
anvil: anvilObj,
|
|
50
126
|
methodCalls,
|
|
51
|
-
stop
|
|
127
|
+
stop,
|
|
52
128
|
rpcUrl: `http://127.0.0.1:${port}`
|
|
53
129
|
};
|
|
54
130
|
}
|
|
131
|
+
/** Extracts block time from anvil stdout and syncs the dateProvider. */ function syncDateProviderFromAnvilOutput(text, dateProvider) {
|
|
132
|
+
// Anvil logs mined blocks as:
|
|
133
|
+
// Block Time: "Fri, 20 Mar 2026 02:10:46 +0000"
|
|
134
|
+
const match = text.match(/Block Time:\s*"([^"]+)"/);
|
|
135
|
+
if (match) {
|
|
136
|
+
const blockTimeMs = new Date(match[1]).getTime();
|
|
137
|
+
if (!isNaN(blockTimeMs)) {
|
|
138
|
+
dateProvider.setTime(blockTimeMs);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** Send SIGTERM, wait up to 5 s, then SIGKILL. All timers are always cleared. */ function killChild(child) {
|
|
143
|
+
return new Promise((resolve)=>{
|
|
144
|
+
if (child.exitCode !== null || child.killed) {
|
|
145
|
+
child.stdout?.destroy();
|
|
146
|
+
child.stderr?.destroy();
|
|
147
|
+
resolve();
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
let killTimer;
|
|
151
|
+
const onClose = ()=>{
|
|
152
|
+
if (killTimer !== undefined) {
|
|
153
|
+
clearTimeout(killTimer);
|
|
154
|
+
}
|
|
155
|
+
// Destroy stdio streams so their PipeWrap handles don't keep the event loop alive.
|
|
156
|
+
child.stdout?.destroy();
|
|
157
|
+
child.stderr?.destroy();
|
|
158
|
+
resolve();
|
|
159
|
+
};
|
|
160
|
+
child.once('close', onClose);
|
|
161
|
+
child.kill('SIGTERM');
|
|
162
|
+
killTimer = setTimeout(()=>{
|
|
163
|
+
killTimer = undefined;
|
|
164
|
+
child.kill('SIGKILL');
|
|
165
|
+
}, 5000);
|
|
166
|
+
// Ensure the timer does not prevent Node from exiting.
|
|
167
|
+
killTimer.unref();
|
|
168
|
+
});
|
|
169
|
+
}
|
|
@@ -9,4 +9,4 @@ export declare function createGovernanceProposal(payloadAddress: `0x${string}`,
|
|
|
9
9
|
voteAmount: bigint;
|
|
10
10
|
proposalId: bigint;
|
|
11
11
|
}>;
|
|
12
|
-
//# sourceMappingURL=
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBncmFkZV91dGlscy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3QvdXBncmFkZV91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUVwRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFHbEUsT0FBTyxFQUFFLEtBQUsscUJBQXFCLEVBQUUsS0FBSyxpQkFBaUIsRUFBZSxNQUFNLE1BQU0sQ0FBQztBQUd2RixPQUFPLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRXZFLE9BQU8sS0FBSyxFQUFFLHdCQUF3QixFQUFFLGdCQUFnQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRzlFLHdCQUFzQix5QkFBeUIsQ0FDN0MsVUFBVSxFQUFFLE1BQU0sRUFDbEIsVUFBVSxFQUFFLHFCQUFxQixDQUFDLE9BQU8sYUFBYSxFQUFFLGdCQUFnQixDQUFDLEVBQ3pFLFVBQVUsRUFBRSxNQUFNLEVBQ2xCLFVBQVUsRUFBRSxpQkFBaUIsRUFDN0IsUUFBUSxFQUFFLHdCQUF3QixFQUNsQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQ2pCLE1BQU0sRUFBRSxNQUFNLGlCQW1DZjtBQUVELHdCQUFzQix3QkFBd0IsQ0FDNUMsY0FBYyxFQUFFLEtBQUssTUFBTSxFQUFFLEVBQzdCLFNBQVMsRUFBRSxtQkFBbUIsRUFDOUIsVUFBVSxFQUFFLGlCQUFpQixFQUM3QixZQUFZLEVBQUUsZ0JBQWdCLEVBQzlCLE1BQU0sRUFBRSxNQUFNLEdBQ2IsT0FBTyxDQUFDO0lBQ1QsVUFBVSxFQUFFLHFCQUFxQixDQUFDLE9BQU8sYUFBYSxFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFDMUUsVUFBVSxFQUFFLE1BQU0sQ0FBQztJQUNuQixVQUFVLEVBQUUsTUFBTSxDQUFDO0NBQ3BCLENBQUMsQ0F5Q0QifQ==
|
|
@@ -3,13 +3,13 @@ import { GovernanceAbi } from '@aztec/l1-artifacts/GovernanceAbi';
|
|
|
3
3
|
import { TestERC20Abi as StakingAssetAbi } from '@aztec/l1-artifacts/TestERC20Abi';
|
|
4
4
|
import { getContract } from 'viem';
|
|
5
5
|
import { extractProposalIdFromLogs } from '../contracts/governance.js';
|
|
6
|
-
import {
|
|
6
|
+
import { createL1TxUtils } from '../l1_tx_utils/index.js';
|
|
7
7
|
import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
8
8
|
export async function executeGovernanceProposal(proposalId, governance, voteAmount, privateKey, l1Client, rpcUrls, logger) {
|
|
9
9
|
const proposal = await governance.read.getProposal([
|
|
10
10
|
proposalId
|
|
11
11
|
]);
|
|
12
|
-
const l1TxUtils =
|
|
12
|
+
const l1TxUtils = createL1TxUtils(l1Client);
|
|
13
13
|
const waitL1Block = async ()=>{
|
|
14
14
|
await l1TxUtils.sendAndMonitorTransaction({
|
|
15
15
|
to: l1Client.account.address,
|