@aztec/ethereum 0.0.1-commit.9b94fc1 → 0.0.1-commit.9badcec54
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.d.ts +10 -2
- package/dest/client.d.ts.map +1 -1
- package/dest/client.js +13 -3
- package/dest/config.d.ts +26 -73
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +64 -387
- package/dest/contracts/chain_state_override.d.ts +38 -0
- package/dest/contracts/chain_state_override.d.ts.map +1 -0
- package/dest/contracts/chain_state_override.js +100 -0
- package/dest/contracts/empire_base.d.ts +4 -1
- package/dest/contracts/empire_base.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 +101 -0
- package/dest/contracts/fee_asset_price_oracle.d.ts.map +1 -0
- package/dest/contracts/fee_asset_price_oracle.js +651 -0
- package/dest/contracts/governance.d.ts +3 -1
- package/dest/contracts/governance.d.ts.map +1 -1
- package/dest/contracts/governance.js +14 -4
- package/dest/contracts/governance_proposer.d.ts +4 -1
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +404 -9
- package/dest/contracts/inbox.d.ts +24 -3
- package/dest/contracts/inbox.d.ts.map +1 -1
- package/dest/contracts/inbox.js +35 -1
- 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 +51 -2
- package/dest/contracts/multicall.d.ts.map +1 -1
- package/dest/contracts/multicall.js +87 -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/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 +251 -107
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +991 -188
- package/dest/contracts/{tally_slashing_proposer.d.ts → slashing_proposer.d.ts} +5 -5
- package/dest/contracts/slashing_proposer.d.ts.map +1 -0
- package/dest/contracts/{tally_slashing_proposer.js → slashing_proposer.js} +18 -13
- package/dest/deploy_aztec_l1_contracts.d.ts +256 -0
- package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -0
- package/dest/deploy_aztec_l1_contracts.js +411 -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/forwarder_proxy.d.ts +32 -0
- package/dest/forwarder_proxy.d.ts.map +1 -0
- package/dest/forwarder_proxy.js +93 -0
- 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 +14182 -17121
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/l1_artifacts.js +9 -24
- package/dest/l1_contract_addresses.d.ts +1 -5
- package/dest/l1_contract_addresses.d.ts.map +1 -1
- package/dest/l1_contract_addresses.js +3 -9
- package/dest/l1_reader.d.ts +5 -1
- package/dest/l1_reader.d.ts.map +1 -1
- package/dest/l1_reader.js +12 -1
- package/dest/l1_tx_utils/config.d.ts +9 -3
- package/dest/l1_tx_utils/config.d.ts.map +1 -1
- package/dest/l1_tx_utils/config.js +31 -4
- 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 +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.d.ts +20 -7
- package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/l1_tx_utils.js +98 -61
- 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 +61 -164
- package/dest/l1_tx_utils/tx_delayer.d.ts +56 -0
- package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -0
- package/dest/{test → l1_tx_utils}/tx_delayer.js +65 -36
- package/dest/publisher_manager.d.ts +21 -6
- package/dest/publisher_manager.d.ts.map +1 -1
- package/dest/publisher_manager.js +81 -7
- package/dest/queries.d.ts +2 -2
- package/dest/queries.d.ts.map +1 -1
- package/dest/queries.js +15 -7
- package/dest/test/chain_monitor.d.ts +35 -14
- package/dest/test/chain_monitor.d.ts.map +1 -1
- package/dest/test/chain_monitor.js +40 -11
- package/dest/test/eth_cheat_codes.d.ts +18 -4
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +10 -6
- package/dest/test/index.d.ts +1 -3
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +0 -2
- package/dest/test/rollup_cheat_codes.d.ts +13 -6
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +41 -7
- package/dest/test/start_anvil.d.ts +24 -2
- package/dest/test/start_anvil.d.ts.map +1 -1
- package/dest/test/start_anvil.js +143 -29
- 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 +16 -3
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +80 -12
- package/package.json +33 -16
- package/src/client.ts +10 -2
- package/src/config.ts +82 -468
- package/src/contracts/README.md +157 -0
- package/src/contracts/chain_state_override.ts +147 -0
- package/src/contracts/empire_base.ts +3 -1
- package/src/contracts/fee_asset_handler.ts +10 -7
- package/src/contracts/fee_asset_price_oracle.ts +280 -0
- package/src/contracts/governance.ts +13 -4
- package/src/contracts/governance_proposer.ts +16 -2
- package/src/contracts/inbox.ts +55 -3
- package/src/contracts/index.ts +5 -2
- package/src/contracts/log.ts +13 -0
- package/src/contracts/multicall.ts +70 -3
- package/src/contracts/outbox.ts +98 -0
- package/src/contracts/registry.ts +31 -1
- package/src/contracts/rollup.ts +689 -149
- package/src/contracts/{tally_slashing_proposer.ts → slashing_proposer.ts} +18 -14
- package/src/deploy_aztec_l1_contracts.ts +646 -0
- package/src/deploy_l1_contract.ts +362 -0
- package/src/forwarder_proxy.ts +108 -0
- package/src/generated/l1-contracts-defaults.ts +32 -0
- package/src/l1_artifacts.ts +12 -35
- package/src/l1_contract_addresses.ts +21 -26
- package/src/l1_reader.ts +21 -1
- package/src/l1_tx_utils/config.ts +44 -6
- 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 +803 -0
- package/src/l1_tx_utils/l1_tx_utils.ts +98 -40
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +75 -210
- package/src/{test → l1_tx_utils}/tx_delayer.ts +82 -52
- package/src/publisher_manager.ts +107 -10
- package/src/queries.ts +14 -6
- package/src/test/chain_monitor.ts +77 -18
- package/src/test/eth_cheat_codes.ts +8 -6
- package/src/test/index.ts +0 -2
- package/src/test/rollup_cheat_codes.ts +43 -10
- package/src/test/start_anvil.ts +178 -28
- package/src/test/upgrade_utils.ts +2 -2
- package/src/types.ts +62 -0
- package/src/utils.ts +100 -15
- package/dest/contracts/empire_slashing_proposer.d.ts +0 -66
- package/dest/contracts/empire_slashing_proposer.d.ts.map +0 -1
- package/dest/contracts/empire_slashing_proposer.js +0 -200
- package/dest/contracts/tally_slashing_proposer.d.ts.map +0 -1
- package/dest/deploy_l1_contracts.d.ts +0 -673
- package/dest/deploy_l1_contracts.d.ts.map +0 -1
- package/dest/deploy_l1_contracts.js +0 -1491
- 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 -265
- package/src/deploy_l1_contracts.ts +0 -1869
- 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
package/src/contracts/rollup.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
1
|
+
import { CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
3
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
4
|
import { memoize } from '@aztec/foundation/decorators';
|
|
3
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
6
|
import type { ViemSignature } from '@aztec/foundation/eth-signature';
|
|
7
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
8
|
+
import { makeBackoff, retry } from '@aztec/foundation/retry';
|
|
9
|
+
import { EscapeHatchAbi } from '@aztec/l1-artifacts/EscapeHatchAbi';
|
|
5
10
|
import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
|
|
6
11
|
import { RollupStorage } from '@aztec/l1-artifacts/RollupStorage';
|
|
7
12
|
|
|
@@ -12,6 +17,7 @@ import {
|
|
|
12
17
|
type Hex,
|
|
13
18
|
type StateOverride,
|
|
14
19
|
type WatchContractEventReturnType,
|
|
20
|
+
encodeAbiParameters,
|
|
15
21
|
encodeFunctionData,
|
|
16
22
|
getContract,
|
|
17
23
|
hexToBigInt,
|
|
@@ -19,16 +25,16 @@ import {
|
|
|
19
25
|
} from 'viem';
|
|
20
26
|
|
|
21
27
|
import { getPublicClient } from '../client.js';
|
|
22
|
-
import type {
|
|
28
|
+
import type { DeployAztecL1ContractsReturnType } from '../deploy_aztec_l1_contracts.js';
|
|
23
29
|
import type { L1ContractAddresses } from '../l1_contract_addresses.js';
|
|
24
30
|
import type { L1ReaderConfig } from '../l1_reader.js';
|
|
25
31
|
import type { L1TxRequest, L1TxUtils } from '../l1_tx_utils/index.js';
|
|
26
32
|
import type { ViemClient } from '../types.js';
|
|
27
33
|
import { formatViemError } from '../utils.js';
|
|
28
|
-
import { EmpireSlashingProposerContract } from './empire_slashing_proposer.js';
|
|
29
34
|
import { GSEContract } from './gse.js';
|
|
35
|
+
import type { L1EventLog } from './log.js';
|
|
30
36
|
import { SlasherContract } from './slasher_contract.js';
|
|
31
|
-
import {
|
|
37
|
+
import { SlashingProposerContract } from './slashing_proposer.js';
|
|
32
38
|
import { checkBlockTag } from './utils.js';
|
|
33
39
|
|
|
34
40
|
export type ViemCommitteeAttestation = {
|
|
@@ -50,20 +56,22 @@ export type L1RollupContractAddresses = Pick<
|
|
|
50
56
|
| 'feeJuiceAddress'
|
|
51
57
|
| 'stakingAssetAddress'
|
|
52
58
|
| 'rewardDistributorAddress'
|
|
53
|
-
| 'slashFactoryAddress'
|
|
54
59
|
| 'gseAddress'
|
|
55
60
|
>;
|
|
56
61
|
|
|
57
62
|
export type EpochProofPublicInputArgs = {
|
|
58
63
|
previousArchive: `0x${string}`;
|
|
59
64
|
endArchive: `0x${string}`;
|
|
65
|
+
outHash: `0x${string}`;
|
|
60
66
|
proverId: `0x${string}`;
|
|
61
67
|
};
|
|
62
68
|
|
|
63
69
|
export type ViemHeader = {
|
|
64
70
|
lastArchiveRoot: `0x${string}`;
|
|
65
71
|
blockHeadersHash: `0x${string}`;
|
|
66
|
-
|
|
72
|
+
blobsHash: `0x${string}`;
|
|
73
|
+
inHash: `0x${string}`;
|
|
74
|
+
outHash: `0x${string}`;
|
|
67
75
|
slotNumber: bigint;
|
|
68
76
|
timestamp: bigint;
|
|
69
77
|
coinbase: `0x${string}`;
|
|
@@ -72,27 +80,150 @@ export type ViemHeader = {
|
|
|
72
80
|
totalManaUsed: bigint;
|
|
73
81
|
};
|
|
74
82
|
|
|
75
|
-
export type ViemContentCommitment = {
|
|
76
|
-
blobsHash: `0x${string}`;
|
|
77
|
-
inHash: `0x${string}`;
|
|
78
|
-
outHash: `0x${string}`;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
83
|
export type ViemGasFees = {
|
|
82
84
|
feePerDaGas: bigint;
|
|
83
85
|
feePerL2Gas: bigint;
|
|
84
86
|
};
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Status of a validator/attester in the staking system.
|
|
90
|
+
* Matches the Status enum in StakingLib.sol
|
|
91
|
+
*/
|
|
92
|
+
export enum AttesterStatus {
|
|
93
|
+
NONE = 0,
|
|
94
|
+
VALIDATING = 1,
|
|
95
|
+
ZOMBIE = 2,
|
|
96
|
+
EXITING = 3,
|
|
90
97
|
}
|
|
91
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Fee header data for a checkpoint
|
|
101
|
+
*/
|
|
102
|
+
export type FeeHeader = {
|
|
103
|
+
excessMana: bigint;
|
|
104
|
+
manaUsed: bigint;
|
|
105
|
+
ethPerFeeAsset: bigint;
|
|
106
|
+
congestionCost: bigint;
|
|
107
|
+
proverCost: bigint;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Checkpoint log data returned from the rollup contract
|
|
112
|
+
*/
|
|
113
|
+
export type CheckpointLog = {
|
|
114
|
+
archive: Fr;
|
|
115
|
+
headerHash: Buffer32;
|
|
116
|
+
blobCommitmentsHash: Buffer32;
|
|
117
|
+
attestationsHash: Buffer32;
|
|
118
|
+
payloadDigest: Buffer32;
|
|
119
|
+
slotNumber: SlotNumber;
|
|
120
|
+
feeHeader: FeeHeader;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* L1 fee data (base fee and blob fee)
|
|
125
|
+
*/
|
|
126
|
+
export type L1FeeData = {
|
|
127
|
+
baseFee: bigint;
|
|
128
|
+
blobFee: bigint;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/** Field offsets within the CompressedTempCheckpointLog struct in Solidity storage. */
|
|
132
|
+
export enum TempCheckpointLogField {
|
|
133
|
+
HeaderHash = 0,
|
|
134
|
+
BlobCommitmentsHash = 1,
|
|
135
|
+
OutHash = 2,
|
|
136
|
+
AttestationsHash = 3,
|
|
137
|
+
PayloadDigest = 4,
|
|
138
|
+
SlotNumber = 5,
|
|
139
|
+
FeeHeader = 6,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Components of the minimum fee per mana, as returned by the L1 rollup contract. */
|
|
143
|
+
export type ManaMinFeeComponents = {
|
|
144
|
+
sequencerCost: bigint;
|
|
145
|
+
proverCost: bigint;
|
|
146
|
+
congestionCost: bigint;
|
|
147
|
+
congestionMultiplier: bigint;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Reward configuration for the rollup
|
|
152
|
+
*/
|
|
153
|
+
export type RewardConfig = {
|
|
154
|
+
rewardDistributor: EthAddress;
|
|
155
|
+
sequencerBps: bigint;
|
|
156
|
+
booster: EthAddress;
|
|
157
|
+
checkpointReward: bigint;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Exit information for a validator
|
|
162
|
+
*/
|
|
163
|
+
export type Exit = {
|
|
164
|
+
withdrawalId: bigint;
|
|
165
|
+
amount: bigint;
|
|
166
|
+
exitableAt: bigint;
|
|
167
|
+
recipientOrWithdrawer: EthAddress;
|
|
168
|
+
isRecipient: boolean;
|
|
169
|
+
exists: boolean;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Attester configuration including public key and withdrawer
|
|
174
|
+
*/
|
|
175
|
+
export type AttesterConfig = {
|
|
176
|
+
publicKey: {
|
|
177
|
+
x: bigint;
|
|
178
|
+
y: bigint;
|
|
179
|
+
};
|
|
180
|
+
withdrawer: EthAddress;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Complete view of an attester's state
|
|
185
|
+
*/
|
|
186
|
+
export type AttesterView = {
|
|
187
|
+
status: AttesterStatus;
|
|
188
|
+
effectiveBalance: bigint;
|
|
189
|
+
exit: Exit;
|
|
190
|
+
config: AttesterConfig;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Return for a status call
|
|
195
|
+
*/
|
|
196
|
+
export type RollupStatusResponse = {
|
|
197
|
+
provenCheckpointNumber: CheckpointNumber;
|
|
198
|
+
provenArchive: Fr;
|
|
199
|
+
pendingCheckpointNumber: CheckpointNumber;
|
|
200
|
+
pendingArchive: Fr;
|
|
201
|
+
archiveOfMyCheckpoint: Fr;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
/** Arguments for the CheckpointProposed event. */
|
|
205
|
+
export type CheckpointProposedArgs = {
|
|
206
|
+
checkpointNumber: CheckpointNumber;
|
|
207
|
+
archive: Fr;
|
|
208
|
+
versionedBlobHashes: Buffer[];
|
|
209
|
+
/** Hash of attestations emitted in the CheckpointProposed event. */
|
|
210
|
+
attestationsHash: Buffer32;
|
|
211
|
+
/** Digest of the payload emitted in the CheckpointProposed event. */
|
|
212
|
+
payloadDigest: Buffer32;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/** Log type for CheckpointProposed events. */
|
|
216
|
+
export type CheckpointProposedLog = L1EventLog<CheckpointProposedArgs>;
|
|
217
|
+
|
|
92
218
|
export class RollupContract {
|
|
93
219
|
private readonly rollup: GetContractReturnType<typeof RollupAbi, ViemClient>;
|
|
220
|
+
private readonly logger = createLogger('ethereum:rollup');
|
|
94
221
|
|
|
95
222
|
private static cachedStfStorageSlot: Hex | undefined;
|
|
223
|
+
private cachedEscapeHatch?: {
|
|
224
|
+
address: EthAddress;
|
|
225
|
+
contract: GetContractReturnType<typeof EscapeHatchAbi, ViemClient>;
|
|
226
|
+
};
|
|
96
227
|
|
|
97
228
|
static get checkBlobStorageSlot(): bigint {
|
|
98
229
|
const asString = RollupStorage.find(storage => storage.label === 'checkBlob')?.slot;
|
|
@@ -106,7 +237,7 @@ export class RollupContract {
|
|
|
106
237
|
return (RollupContract.cachedStfStorageSlot ??= keccak256(Buffer.from('aztec.stf.storage', 'utf-8')));
|
|
107
238
|
}
|
|
108
239
|
|
|
109
|
-
static getFromL1ContractsValues(deployL1ContractsValues:
|
|
240
|
+
static getFromL1ContractsValues(deployL1ContractsValues: DeployAztecL1ContractsReturnType) {
|
|
110
241
|
const {
|
|
111
242
|
l1Client,
|
|
112
243
|
l1ContractAddresses: { rollupAddress },
|
|
@@ -130,8 +261,8 @@ export class RollupContract {
|
|
|
130
261
|
this.rollup = getContract({ address, abi: RollupAbi, client });
|
|
131
262
|
}
|
|
132
263
|
|
|
133
|
-
getGSE() {
|
|
134
|
-
return this.rollup.read.getGSE();
|
|
264
|
+
async getGSE(): Promise<EthAddress> {
|
|
265
|
+
return EthAddress.fromString(await this.rollup.read.getGSE());
|
|
135
266
|
}
|
|
136
267
|
|
|
137
268
|
public get address() {
|
|
@@ -142,54 +273,38 @@ export class RollupContract {
|
|
|
142
273
|
return this.rollup;
|
|
143
274
|
}
|
|
144
275
|
|
|
145
|
-
public async getSlashingProposer(): Promise<
|
|
146
|
-
EmpireSlashingProposerContract | TallySlashingProposerContract | undefined
|
|
147
|
-
> {
|
|
276
|
+
public async getSlashingProposer(): Promise<SlashingProposerContract | undefined> {
|
|
148
277
|
const slasher = await this.getSlasherContract();
|
|
149
278
|
if (!slasher) {
|
|
150
279
|
return undefined;
|
|
151
280
|
}
|
|
152
281
|
|
|
153
282
|
const proposerAddress = await slasher.getProposer();
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
type: 'function',
|
|
157
|
-
name: 'SLASHING_PROPOSER_TYPE',
|
|
158
|
-
inputs: [],
|
|
159
|
-
outputs: [{ name: '', type: 'uint8', internalType: 'enum SlasherFlavor' }],
|
|
160
|
-
stateMutability: 'view',
|
|
161
|
-
},
|
|
162
|
-
] as const;
|
|
163
|
-
|
|
164
|
-
const proposer = getContract({ address: proposerAddress.toString(), abi: proposerAbi, client: this.client });
|
|
165
|
-
const proposerType = await proposer.read.SLASHING_PROPOSER_TYPE();
|
|
166
|
-
if (proposerType === SlashingProposerType.Tally.valueOf()) {
|
|
167
|
-
return new TallySlashingProposerContract(this.client, proposerAddress);
|
|
168
|
-
} else if (proposerType === SlashingProposerType.Empire.valueOf()) {
|
|
169
|
-
return new EmpireSlashingProposerContract(this.client, proposerAddress);
|
|
170
|
-
} else {
|
|
171
|
-
throw new Error(`Unknown slashing proposer type: ${proposerType}`);
|
|
283
|
+
if (proposerAddress.isZero()) {
|
|
284
|
+
return undefined;
|
|
172
285
|
}
|
|
286
|
+
|
|
287
|
+
return new SlashingProposerContract(this.client, proposerAddress);
|
|
173
288
|
}
|
|
174
289
|
|
|
175
290
|
@memoize
|
|
176
|
-
getL1StartBlock() {
|
|
291
|
+
getL1StartBlock(): Promise<bigint> {
|
|
177
292
|
return this.rollup.read.L1_BLOCK_AT_GENESIS();
|
|
178
293
|
}
|
|
179
294
|
|
|
180
295
|
@memoize
|
|
181
|
-
getL1GenesisTime() {
|
|
296
|
+
getL1GenesisTime(): Promise<bigint> {
|
|
182
297
|
return this.rollup.read.getGenesisTime();
|
|
183
298
|
}
|
|
184
299
|
|
|
185
300
|
@memoize
|
|
186
|
-
getProofSubmissionEpochs() {
|
|
187
|
-
return this.rollup.read.getProofSubmissionEpochs();
|
|
301
|
+
async getProofSubmissionEpochs(): Promise<number> {
|
|
302
|
+
return Number(await this.rollup.read.getProofSubmissionEpochs());
|
|
188
303
|
}
|
|
189
304
|
|
|
190
305
|
@memoize
|
|
191
|
-
getEpochDuration() {
|
|
192
|
-
return this.rollup.read.getEpochDuration();
|
|
306
|
+
async getEpochDuration(): Promise<number> {
|
|
307
|
+
return Number(await this.rollup.read.getEpochDuration());
|
|
193
308
|
}
|
|
194
309
|
|
|
195
310
|
@memoize
|
|
@@ -198,68 +313,82 @@ export class RollupContract {
|
|
|
198
313
|
}
|
|
199
314
|
|
|
200
315
|
@memoize
|
|
201
|
-
getTargetCommitteeSize() {
|
|
202
|
-
return this.rollup.read.getTargetCommitteeSize();
|
|
316
|
+
async getTargetCommitteeSize(): Promise<number> {
|
|
317
|
+
return Number(await this.rollup.read.getTargetCommitteeSize());
|
|
203
318
|
}
|
|
204
319
|
|
|
205
320
|
@memoize
|
|
206
|
-
getEjectionThreshold() {
|
|
321
|
+
getEjectionThreshold(): Promise<bigint> {
|
|
207
322
|
return this.rollup.read.getEjectionThreshold();
|
|
208
323
|
}
|
|
209
324
|
|
|
210
325
|
@memoize
|
|
211
|
-
getLocalEjectionThreshold() {
|
|
326
|
+
getLocalEjectionThreshold(): Promise<bigint> {
|
|
212
327
|
return this.rollup.read.getLocalEjectionThreshold();
|
|
213
328
|
}
|
|
214
329
|
|
|
215
330
|
@memoize
|
|
216
|
-
getLagInEpochsForValidatorSet() {
|
|
217
|
-
return this.rollup.read.getLagInEpochsForValidatorSet();
|
|
331
|
+
async getLagInEpochsForValidatorSet(): Promise<number> {
|
|
332
|
+
return Number(await this.rollup.read.getLagInEpochsForValidatorSet());
|
|
218
333
|
}
|
|
219
334
|
|
|
220
335
|
@memoize
|
|
221
|
-
getLagInEpochsForRandao() {
|
|
222
|
-
return this.rollup.read.getLagInEpochsForRandao();
|
|
336
|
+
async getLagInEpochsForRandao(): Promise<number> {
|
|
337
|
+
return Number(await this.rollup.read.getLagInEpochsForRandao());
|
|
223
338
|
}
|
|
224
339
|
|
|
225
340
|
@memoize
|
|
226
|
-
getActivationThreshold() {
|
|
341
|
+
getActivationThreshold(): Promise<bigint> {
|
|
227
342
|
return this.rollup.read.getActivationThreshold();
|
|
228
343
|
}
|
|
229
344
|
|
|
230
345
|
@memoize
|
|
231
|
-
getExitDelay() {
|
|
232
|
-
return this.rollup.read.getExitDelay();
|
|
346
|
+
async getExitDelay(): Promise<number> {
|
|
347
|
+
return Number(await this.rollup.read.getExitDelay());
|
|
233
348
|
}
|
|
234
349
|
|
|
235
350
|
@memoize
|
|
236
|
-
getManaTarget() {
|
|
351
|
+
getManaTarget(): Promise<bigint> {
|
|
237
352
|
return this.rollup.read.getManaTarget();
|
|
238
353
|
}
|
|
239
354
|
|
|
240
355
|
@memoize
|
|
241
|
-
getProvingCostPerMana() {
|
|
356
|
+
getProvingCostPerMana(): Promise<bigint> {
|
|
242
357
|
return this.rollup.read.getProvingCostPerManaInEth();
|
|
243
358
|
}
|
|
244
359
|
|
|
245
360
|
@memoize
|
|
246
|
-
getProvingCostPerManaInFeeAsset() {
|
|
361
|
+
getProvingCostPerManaInFeeAsset(): Promise<bigint> {
|
|
247
362
|
return this.rollup.read.getProvingCostPerManaInFeeAsset();
|
|
248
363
|
}
|
|
249
364
|
|
|
250
365
|
@memoize
|
|
251
|
-
getManaLimit() {
|
|
366
|
+
getManaLimit(): Promise<bigint> {
|
|
252
367
|
return this.rollup.read.getManaLimit();
|
|
253
368
|
}
|
|
254
369
|
|
|
255
370
|
@memoize
|
|
256
|
-
getVersion() {
|
|
371
|
+
getVersion(): Promise<bigint> {
|
|
257
372
|
return this.rollup.read.getVersion();
|
|
258
373
|
}
|
|
259
374
|
|
|
260
375
|
@memoize
|
|
261
|
-
async getGenesisArchiveTreeRoot(): Promise
|
|
262
|
-
return await this.rollup.read.archiveAt([0n]);
|
|
376
|
+
async getGenesisArchiveTreeRoot(): Promise<Fr> {
|
|
377
|
+
return Fr.fromString(await this.rollup.read.archiveAt([0n]));
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
@memoize
|
|
381
|
+
async getVkTreeRoot(): Promise<Fr> {
|
|
382
|
+
const slot = BigInt(RollupContract.stfStorageSlot) + 3n;
|
|
383
|
+
const value = await this.client.getStorageAt({ address: this.address, slot: `0x${slot.toString(16)}` });
|
|
384
|
+
return Fr.fromString(value ?? '0x0');
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
@memoize
|
|
388
|
+
async getProtocolContractsHash(): Promise<Fr> {
|
|
389
|
+
const slot = BigInt(RollupContract.stfStorageSlot) + 4n;
|
|
390
|
+
const value = await this.client.getStorageAt({ address: this.address, slot: `0x${slot.toString(16)}` });
|
|
391
|
+
return Fr.fromString(value ?? '0x0');
|
|
263
392
|
}
|
|
264
393
|
|
|
265
394
|
/**
|
|
@@ -274,13 +403,25 @@ export class RollupContract {
|
|
|
274
403
|
slotDuration: number;
|
|
275
404
|
epochDuration: number;
|
|
276
405
|
proofSubmissionEpochs: number;
|
|
406
|
+
targetCommitteeSize: number;
|
|
407
|
+
rollupManaLimit: number;
|
|
277
408
|
}> {
|
|
278
|
-
const [
|
|
409
|
+
const [
|
|
410
|
+
l1StartBlock,
|
|
411
|
+
l1GenesisTime,
|
|
412
|
+
slotDuration,
|
|
413
|
+
epochDuration,
|
|
414
|
+
proofSubmissionEpochs,
|
|
415
|
+
targetCommitteeSize,
|
|
416
|
+
rollupManaLimit,
|
|
417
|
+
] = await Promise.all([
|
|
279
418
|
this.getL1StartBlock(),
|
|
280
419
|
this.getL1GenesisTime(),
|
|
281
420
|
this.getSlotDuration(),
|
|
282
421
|
this.getEpochDuration(),
|
|
283
422
|
this.getProofSubmissionEpochs(),
|
|
423
|
+
this.getTargetCommitteeSize(),
|
|
424
|
+
this.getManaLimit(),
|
|
284
425
|
]);
|
|
285
426
|
return {
|
|
286
427
|
l1StartBlock,
|
|
@@ -288,30 +429,88 @@ export class RollupContract {
|
|
|
288
429
|
slotDuration,
|
|
289
430
|
epochDuration: Number(epochDuration),
|
|
290
431
|
proofSubmissionEpochs: Number(proofSubmissionEpochs),
|
|
432
|
+
targetCommitteeSize,
|
|
433
|
+
rollupManaLimit: Number(rollupManaLimit),
|
|
291
434
|
};
|
|
292
435
|
}
|
|
293
436
|
|
|
294
|
-
getSlasherAddress() {
|
|
295
|
-
return this.rollup.read.getSlasher();
|
|
437
|
+
async getSlasherAddress(): Promise<EthAddress> {
|
|
438
|
+
return EthAddress.fromString(await this.rollup.read.getSlasher());
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Returns the configured escape hatch contract address, or zero if disabled.
|
|
443
|
+
*/
|
|
444
|
+
async getEscapeHatchAddress(): Promise<EthAddress> {
|
|
445
|
+
return EthAddress.fromString(await this.rollup.read.getEscapeHatch());
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
private async getEscapeHatchContract(): Promise<
|
|
449
|
+
GetContractReturnType<typeof EscapeHatchAbi, ViemClient> | undefined
|
|
450
|
+
> {
|
|
451
|
+
const escapeHatchAddress = await this.getEscapeHatchAddress();
|
|
452
|
+
if (escapeHatchAddress.isZero()) {
|
|
453
|
+
return undefined;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Cache the viem contract wrapper since it will be used frequently.
|
|
457
|
+
if (!this.cachedEscapeHatch || !this.cachedEscapeHatch.address.equals(escapeHatchAddress)) {
|
|
458
|
+
this.cachedEscapeHatch = {
|
|
459
|
+
address: escapeHatchAddress,
|
|
460
|
+
contract: getContract({
|
|
461
|
+
address: escapeHatchAddress.toString(),
|
|
462
|
+
abi: EscapeHatchAbi,
|
|
463
|
+
client: this.client,
|
|
464
|
+
}),
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return this.cachedEscapeHatch.contract;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Returns whether the escape hatch is open for the given epoch.
|
|
473
|
+
* If escape hatch is not configured, returns false.
|
|
474
|
+
*
|
|
475
|
+
* This function is intentionally defensive: any failure to query the escape hatch
|
|
476
|
+
* (RPC issues, transient errors, etc.) is treated as "closed" to avoid callers
|
|
477
|
+
* needing to sprinkle try/catch everywhere.
|
|
478
|
+
*/
|
|
479
|
+
async isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean> {
|
|
480
|
+
try {
|
|
481
|
+
const escapeHatch = await this.getEscapeHatchContract();
|
|
482
|
+
if (!escapeHatch) {
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const [isOpen] = await escapeHatch.read.isHatchOpen([BigInt(epoch)]);
|
|
487
|
+
return isOpen;
|
|
488
|
+
} catch (err) {
|
|
489
|
+
this.logger.warn('isEscapeHatchOpen failed (treating as closed); RPC or contract error may cause liveness risk', {
|
|
490
|
+
epoch: Number(epoch),
|
|
491
|
+
error: err,
|
|
492
|
+
});
|
|
493
|
+
return false;
|
|
494
|
+
}
|
|
296
495
|
}
|
|
297
496
|
|
|
298
497
|
/**
|
|
299
498
|
* Returns a SlasherContract instance for interacting with the slasher contract.
|
|
300
499
|
*/
|
|
301
500
|
async getSlasherContract(): Promise<SlasherContract | undefined> {
|
|
302
|
-
const slasherAddress =
|
|
501
|
+
const slasherAddress = await this.getSlasherAddress();
|
|
303
502
|
if (slasherAddress.isZero()) {
|
|
304
503
|
return undefined;
|
|
305
504
|
}
|
|
306
505
|
return new SlasherContract(this.client, slasherAddress);
|
|
307
506
|
}
|
|
308
507
|
|
|
309
|
-
getOwner() {
|
|
310
|
-
return this.rollup.read.owner();
|
|
508
|
+
async getOwner(): Promise<EthAddress> {
|
|
509
|
+
return EthAddress.fromString(await this.rollup.read.owner());
|
|
311
510
|
}
|
|
312
511
|
|
|
313
|
-
getActiveAttesterCount() {
|
|
314
|
-
return this.rollup.read.getActiveAttesterCount();
|
|
512
|
+
async getActiveAttesterCount(): Promise<number> {
|
|
513
|
+
return Number(await this.rollup.read.getActiveAttesterCount());
|
|
315
514
|
}
|
|
316
515
|
|
|
317
516
|
public async getSlashingProposerAddress() {
|
|
@@ -322,31 +521,50 @@ export class RollupContract {
|
|
|
322
521
|
return await slasher.getProposer();
|
|
323
522
|
}
|
|
324
523
|
|
|
325
|
-
getCheckpointReward() {
|
|
524
|
+
getCheckpointReward(): Promise<bigint> {
|
|
326
525
|
return this.rollup.read.getCheckpointReward();
|
|
327
526
|
}
|
|
328
527
|
|
|
329
|
-
getCheckpointNumber() {
|
|
330
|
-
|
|
528
|
+
async getCheckpointNumber(options?: { blockNumber?: bigint }): Promise<CheckpointNumber> {
|
|
529
|
+
await checkBlockTag(options?.blockNumber, this.client);
|
|
530
|
+
return CheckpointNumber.fromBigInt(await this.rollup.read.getPendingCheckpointNumber(options));
|
|
331
531
|
}
|
|
332
532
|
|
|
333
|
-
getProvenCheckpointNumber() {
|
|
334
|
-
|
|
533
|
+
async getProvenCheckpointNumber(options?: { blockNumber?: bigint }): Promise<CheckpointNumber> {
|
|
534
|
+
await checkBlockTag(options?.blockNumber, this.client);
|
|
535
|
+
return CheckpointNumber.fromBigInt(await this.rollup.read.getProvenCheckpointNumber(options));
|
|
335
536
|
}
|
|
336
537
|
|
|
337
|
-
async getSlotNumber(): Promise<SlotNumber> {
|
|
338
|
-
|
|
538
|
+
async getSlotNumber(options?: { blockNumber?: bigint }): Promise<SlotNumber> {
|
|
539
|
+
await checkBlockTag(options?.blockNumber, this.client);
|
|
540
|
+
return SlotNumber.fromBigInt(await this.rollup.read.getCurrentSlot(options));
|
|
339
541
|
}
|
|
340
542
|
|
|
341
|
-
getL1FeesAt(timestamp: bigint) {
|
|
342
|
-
|
|
543
|
+
async getL1FeesAt(timestamp: bigint, options?: { blockNumber?: bigint }): Promise<L1FeeData> {
|
|
544
|
+
await checkBlockTag(options?.blockNumber, this.client);
|
|
545
|
+
const result = await this.rollup.read.getL1FeesAt([timestamp], options);
|
|
546
|
+
return {
|
|
547
|
+
baseFee: result.baseFee,
|
|
548
|
+
blobFee: result.blobFee,
|
|
549
|
+
};
|
|
343
550
|
}
|
|
344
551
|
|
|
345
|
-
|
|
346
|
-
|
|
552
|
+
async getFeeHeader(checkpointNumber: bigint): Promise<FeeHeader> {
|
|
553
|
+
const result = await this.rollup.read.getFeeHeader([checkpointNumber]);
|
|
554
|
+
return {
|
|
555
|
+
excessMana: result.excessMana,
|
|
556
|
+
manaUsed: result.manaUsed,
|
|
557
|
+
ethPerFeeAsset: result.ethPerFeeAsset,
|
|
558
|
+
congestionCost: result.congestionCost,
|
|
559
|
+
proverCost: result.proverCost,
|
|
560
|
+
};
|
|
347
561
|
}
|
|
348
562
|
|
|
349
|
-
|
|
563
|
+
getEthPerFeeAsset(): Promise<bigint> {
|
|
564
|
+
return this.rollup.read.getEthPerFeeAsset();
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
async getCommitteeAt(timestamp: bigint): Promise<EthAddress[] | undefined> {
|
|
350
568
|
const { result } = await this.client
|
|
351
569
|
.simulateContract({
|
|
352
570
|
address: this.address,
|
|
@@ -361,22 +579,22 @@ export class RollupContract {
|
|
|
361
579
|
throw e;
|
|
362
580
|
});
|
|
363
581
|
|
|
364
|
-
return result;
|
|
582
|
+
return result ? result.map(addr => EthAddress.fromString(addr)) : undefined;
|
|
365
583
|
}
|
|
366
584
|
|
|
367
|
-
getSampleSeedAt(timestamp: bigint) {
|
|
368
|
-
return this.rollup.read.getSampleSeedAt([timestamp]);
|
|
585
|
+
async getSampleSeedAt(timestamp: bigint): Promise<Buffer32> {
|
|
586
|
+
return Buffer32.fromBigInt(await this.rollup.read.getSampleSeedAt([timestamp]));
|
|
369
587
|
}
|
|
370
588
|
|
|
371
|
-
getCurrentSampleSeed() {
|
|
372
|
-
return this.rollup.read.getCurrentSampleSeed();
|
|
589
|
+
async getCurrentSampleSeed(): Promise<Buffer32> {
|
|
590
|
+
return Buffer32.fromBigInt(await this.rollup.read.getCurrentSampleSeed());
|
|
373
591
|
}
|
|
374
592
|
|
|
375
593
|
async getCurrentEpoch(): Promise<EpochNumber> {
|
|
376
594
|
return EpochNumber.fromBigInt(await this.rollup.read.getCurrentEpoch());
|
|
377
595
|
}
|
|
378
596
|
|
|
379
|
-
async getCurrentEpochCommittee(): Promise<
|
|
597
|
+
async getCurrentEpochCommittee(): Promise<EthAddress[] | undefined> {
|
|
380
598
|
const { result } = await this.client
|
|
381
599
|
.simulateContract({
|
|
382
600
|
address: this.address,
|
|
@@ -391,10 +609,10 @@ export class RollupContract {
|
|
|
391
609
|
throw e;
|
|
392
610
|
});
|
|
393
611
|
|
|
394
|
-
return result;
|
|
612
|
+
return result ? result.map(addr => EthAddress.fromString(addr)) : undefined;
|
|
395
613
|
}
|
|
396
614
|
|
|
397
|
-
async getCurrentProposer() {
|
|
615
|
+
async getCurrentProposer(): Promise<EthAddress> {
|
|
398
616
|
const { result } = await this.client.simulateContract({
|
|
399
617
|
address: this.address,
|
|
400
618
|
abi: RollupAbi,
|
|
@@ -402,10 +620,10 @@ export class RollupContract {
|
|
|
402
620
|
args: [],
|
|
403
621
|
});
|
|
404
622
|
|
|
405
|
-
return result;
|
|
623
|
+
return EthAddress.fromString(result);
|
|
406
624
|
}
|
|
407
625
|
|
|
408
|
-
async getProposerAt(timestamp: bigint) {
|
|
626
|
+
async getProposerAt(timestamp: bigint): Promise<EthAddress> {
|
|
409
627
|
const { result } = await this.client.simulateContract({
|
|
410
628
|
address: this.address,
|
|
411
629
|
abi: RollupAbi,
|
|
@@ -413,27 +631,86 @@ export class RollupContract {
|
|
|
413
631
|
args: [timestamp],
|
|
414
632
|
});
|
|
415
633
|
|
|
416
|
-
return result;
|
|
634
|
+
return EthAddress.fromString(result);
|
|
417
635
|
}
|
|
418
636
|
|
|
419
|
-
getCheckpoint(checkpointNumber: bigint
|
|
420
|
-
|
|
637
|
+
async getCheckpoint(checkpointNumber: CheckpointNumber, options?: { blockNumber?: bigint }): Promise<CheckpointLog> {
|
|
638
|
+
await checkBlockTag(options?.blockNumber, this.client);
|
|
639
|
+
const result = await this.rollup.read.getCheckpoint([BigInt(checkpointNumber)], options);
|
|
640
|
+
return {
|
|
641
|
+
archive: Fr.fromString(result.archive),
|
|
642
|
+
headerHash: Buffer32.fromString(result.headerHash),
|
|
643
|
+
blobCommitmentsHash: Buffer32.fromString(result.blobCommitmentsHash),
|
|
644
|
+
attestationsHash: Buffer32.fromString(result.attestationsHash),
|
|
645
|
+
payloadDigest: Buffer32.fromString(result.payloadDigest),
|
|
646
|
+
slotNumber: SlotNumber.fromBigInt(result.slotNumber),
|
|
647
|
+
feeHeader: {
|
|
648
|
+
excessMana: result.feeHeader.excessMana,
|
|
649
|
+
manaUsed: result.feeHeader.manaUsed,
|
|
650
|
+
ethPerFeeAsset: result.feeHeader.ethPerFeeAsset,
|
|
651
|
+
congestionCost: result.feeHeader.congestionCost,
|
|
652
|
+
proverCost: result.feeHeader.proverCost,
|
|
653
|
+
},
|
|
654
|
+
};
|
|
421
655
|
}
|
|
422
656
|
|
|
423
|
-
|
|
424
|
-
|
|
657
|
+
/** Returns the pending checkpoint from the rollup contract */
|
|
658
|
+
getPendingCheckpoint() {
|
|
659
|
+
// We retry because of race conditions during prunes: we may get a pending checkpoint number which is immediately
|
|
660
|
+
// reorged out due to a prune happening, causing the subsequent getCheckpoint call to fail. So we try again in that case.
|
|
661
|
+
return retry(
|
|
662
|
+
async () => {
|
|
663
|
+
const pendingCheckpointNumber = await this.getCheckpointNumber();
|
|
664
|
+
const pendingCheckpoint = await this.getCheckpoint(pendingCheckpointNumber);
|
|
665
|
+
return pendingCheckpoint;
|
|
666
|
+
},
|
|
667
|
+
'getting pending checkpoint',
|
|
668
|
+
makeBackoff([0.5, 0.5, 0.5]),
|
|
669
|
+
);
|
|
425
670
|
}
|
|
426
671
|
|
|
427
|
-
|
|
672
|
+
/**
|
|
673
|
+
* Returns the effective pending checkpoint, accounting for potential prunes.
|
|
674
|
+
* When a prune can happen, the L1 contract uses the proven checkpoint instead of the pending one.
|
|
675
|
+
* This mirrors the behavior of getEffectivePendingCheckpointNumber in STFLib.sol.
|
|
676
|
+
* @param atTimestamp - The timestamp to evaluate pruneability at. Defaults to the current L1 block timestamp.
|
|
677
|
+
* @param options - Optional L1 block number to pin the queries to.
|
|
678
|
+
*/
|
|
679
|
+
getEffectivePendingCheckpoint(atTimestamp?: bigint, options?: { blockNumber?: bigint }) {
|
|
680
|
+
return retry(
|
|
681
|
+
async () => {
|
|
682
|
+
const timestamp = atTimestamp ?? (await this.client.getBlock()).timestamp;
|
|
683
|
+
const canPrune = await this.canPruneAtTime(timestamp, options);
|
|
684
|
+
if (canPrune) {
|
|
685
|
+
const provenCheckpointNumber = await this.getProvenCheckpointNumber(options);
|
|
686
|
+
return await this.getCheckpoint(provenCheckpointNumber, options);
|
|
687
|
+
}
|
|
688
|
+
const pendingCheckpointNumber = await this.getCheckpointNumber(options);
|
|
689
|
+
return await this.getCheckpoint(pendingCheckpointNumber, options);
|
|
690
|
+
},
|
|
691
|
+
'getting effective pending checkpoint',
|
|
692
|
+
makeBackoff([0.5, 0.5, 0.5]),
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
async getTips(): Promise<{ pending: CheckpointNumber; proven: CheckpointNumber }> {
|
|
697
|
+
const { pending, proven } = await this.rollup.read.getTips();
|
|
698
|
+
return {
|
|
699
|
+
pending: CheckpointNumber.fromBigInt(pending),
|
|
700
|
+
proven: CheckpointNumber.fromBigInt(proven),
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
getTimestampForSlot(slot: SlotNumber): Promise<bigint> {
|
|
428
705
|
return this.rollup.read.getTimestampForSlot([BigInt(slot)]);
|
|
429
706
|
}
|
|
430
707
|
|
|
431
|
-
getEntryQueueLength() {
|
|
432
|
-
return this.rollup.read.getEntryQueueLength();
|
|
708
|
+
async getEntryQueueLength(): Promise<number> {
|
|
709
|
+
return Number(await this.rollup.read.getEntryQueueLength());
|
|
433
710
|
}
|
|
434
711
|
|
|
435
|
-
getAvailableValidatorFlushes() {
|
|
436
|
-
return this.rollup.read.getAvailableValidatorFlushes();
|
|
712
|
+
async getAvailableValidatorFlushes(): Promise<number> {
|
|
713
|
+
return Number(await this.rollup.read.getAvailableValidatorFlushes());
|
|
437
714
|
}
|
|
438
715
|
|
|
439
716
|
async getNextFlushableEpoch(): Promise<EpochNumber> {
|
|
@@ -444,7 +721,7 @@ export class RollupContract {
|
|
|
444
721
|
return EpochNumber.fromBigInt(await this.rollup.read.getCurrentEpoch());
|
|
445
722
|
}
|
|
446
723
|
|
|
447
|
-
async getEpochNumberForCheckpoint(checkpointNumber:
|
|
724
|
+
async getEpochNumberForCheckpoint(checkpointNumber: CheckpointNumber): Promise<EpochNumber> {
|
|
448
725
|
return EpochNumber.fromBigInt(await this.rollup.read.getEpochForCheckpoint([BigInt(checkpointNumber)]));
|
|
449
726
|
}
|
|
450
727
|
|
|
@@ -489,10 +766,11 @@ export class RollupContract {
|
|
|
489
766
|
return EpochNumber.fromBigInt(await this.rollup.read.getEpochAtSlot([BigInt(slotNumber)]));
|
|
490
767
|
}
|
|
491
768
|
|
|
492
|
-
getEpochProofPublicInputs(
|
|
769
|
+
async getEpochProofPublicInputs(
|
|
493
770
|
args: readonly [bigint, bigint, EpochProofPublicInputArgs, readonly `0x${string}`[], `0x${string}`],
|
|
494
|
-
) {
|
|
495
|
-
|
|
771
|
+
): Promise<Fr[]> {
|
|
772
|
+
const result = await this.rollup.read.getEpochProofPublicInputs(args);
|
|
773
|
+
return result.map(Fr.fromString);
|
|
496
774
|
}
|
|
497
775
|
|
|
498
776
|
public async validateHeader(
|
|
@@ -533,14 +811,13 @@ export class RollupContract {
|
|
|
533
811
|
* timestamp of the next L1 block
|
|
534
812
|
* @throws otherwise
|
|
535
813
|
*/
|
|
536
|
-
public async
|
|
814
|
+
public async canProposeAt(
|
|
537
815
|
archive: Buffer,
|
|
538
816
|
account: `0x${string}` | Account,
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
): Promise<{ slot: SlotNumber; checkpointNumber:
|
|
542
|
-
const
|
|
543
|
-
const timeOfNextL1Slot = latestBlock.timestamp + BigInt(slotDuration);
|
|
817
|
+
timestamp: bigint,
|
|
818
|
+
stateOverride: StateOverride = [],
|
|
819
|
+
): Promise<{ slot: SlotNumber; checkpointNumber: CheckpointNumber; timeOfNextL1Slot: bigint }> {
|
|
820
|
+
const timeOfNextL1Slot = timestamp;
|
|
544
821
|
const who = typeof account === 'string' ? account : account.address;
|
|
545
822
|
|
|
546
823
|
try {
|
|
@@ -552,10 +829,14 @@ export class RollupContract {
|
|
|
552
829
|
functionName: 'canProposeAtTime',
|
|
553
830
|
args: [timeOfNextL1Slot, `0x${archive.toString('hex')}`, who],
|
|
554
831
|
account,
|
|
555
|
-
stateOverride
|
|
832
|
+
stateOverride,
|
|
556
833
|
});
|
|
557
834
|
|
|
558
|
-
return {
|
|
835
|
+
return {
|
|
836
|
+
slot: SlotNumber.fromBigInt(slot),
|
|
837
|
+
checkpointNumber: CheckpointNumber.fromBigInt(checkpointNumber),
|
|
838
|
+
timeOfNextL1Slot,
|
|
839
|
+
};
|
|
559
840
|
} catch (err: unknown) {
|
|
560
841
|
throw formatViemError(err);
|
|
561
842
|
}
|
|
@@ -567,7 +848,7 @@ export class RollupContract {
|
|
|
567
848
|
* stored in the same slot. If the argument is undefined, it returns an empty override.
|
|
568
849
|
*/
|
|
569
850
|
public async makePendingCheckpointNumberOverride(
|
|
570
|
-
forcePendingCheckpointNumber:
|
|
851
|
+
forcePendingCheckpointNumber: CheckpointNumber | undefined,
|
|
571
852
|
): Promise<StateOverride> {
|
|
572
853
|
if (forcePendingCheckpointNumber === undefined) {
|
|
573
854
|
return [];
|
|
@@ -584,15 +865,161 @@ export class RollupContract {
|
|
|
584
865
|
];
|
|
585
866
|
}
|
|
586
867
|
|
|
868
|
+
/**
|
|
869
|
+
* Returns a state override that sets tempCheckpointLogs[checkpointNumber].feeHeader to the compressed fee header.
|
|
870
|
+
* Used when simulating a propose call where the parent checkpoint hasn't landed on L1 yet (pipelining).
|
|
871
|
+
*/
|
|
872
|
+
public async makeFeeHeaderOverride(checkpointNumber: CheckpointNumber, feeHeader: FeeHeader): Promise<StateOverride> {
|
|
873
|
+
const { epochDuration, proofSubmissionEpochs } = await this.getRollupConstants();
|
|
874
|
+
const roundaboutSize = BigInt(epochDuration * (proofSubmissionEpochs + 1) + 1);
|
|
875
|
+
const circularIndex = BigInt(checkpointNumber) % roundaboutSize;
|
|
876
|
+
|
|
877
|
+
// tempCheckpointLogs is at offset 2 in RollupStore
|
|
878
|
+
const tempCheckpointLogsMappingBase = hexToBigInt(RollupContract.stfStorageSlot) + 2n;
|
|
879
|
+
|
|
880
|
+
// Solidity mapping slot: keccak256(abi.encode(key, baseSlot))
|
|
881
|
+
const structBaseSlot = hexToBigInt(
|
|
882
|
+
keccak256(
|
|
883
|
+
encodeAbiParameters([{ type: 'uint256' }, { type: 'uint256' }], [circularIndex, tempCheckpointLogsMappingBase]),
|
|
884
|
+
),
|
|
885
|
+
);
|
|
886
|
+
|
|
887
|
+
// feeHeader is the 7th field (offset 6) in CompressedTempCheckpointLog
|
|
888
|
+
const feeHeaderSlot = structBaseSlot + 6n;
|
|
889
|
+
const compressed = RollupContract.compressFeeHeader(feeHeader);
|
|
890
|
+
|
|
891
|
+
return [
|
|
892
|
+
{
|
|
893
|
+
address: this.address,
|
|
894
|
+
stateDiff: [
|
|
895
|
+
{
|
|
896
|
+
slot: `0x${feeHeaderSlot.toString(16).padStart(64, '0')}`,
|
|
897
|
+
value: `0x${compressed.toString(16).padStart(64, '0')}`,
|
|
898
|
+
},
|
|
899
|
+
],
|
|
900
|
+
},
|
|
901
|
+
];
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
/**
|
|
905
|
+
* Returns a state override that sets archives[checkpointNumber] to the given archive value.
|
|
906
|
+
* Used when simulating a canProposeAtTime call where the local archive differs from L1
|
|
907
|
+
* (e.g. pipelining where the parent checkpoint hasn't landed on L1 yet).
|
|
908
|
+
*/
|
|
909
|
+
public makeArchiveOverride(checkpointNumber: CheckpointNumber, archive: Fr): StateOverride {
|
|
910
|
+
const archivesMappingBase = hexToBigInt(RollupContract.stfStorageSlot) + 1n;
|
|
911
|
+
const archiveSlot = hexToBigInt(
|
|
912
|
+
keccak256(
|
|
913
|
+
encodeAbiParameters(
|
|
914
|
+
[{ type: 'uint256' }, { type: 'uint256' }],
|
|
915
|
+
[BigInt(checkpointNumber), archivesMappingBase],
|
|
916
|
+
),
|
|
917
|
+
),
|
|
918
|
+
);
|
|
919
|
+
return [
|
|
920
|
+
{
|
|
921
|
+
address: this.address,
|
|
922
|
+
stateDiff: [
|
|
923
|
+
{
|
|
924
|
+
slot: `0x${archiveSlot.toString(16).padStart(64, '0')}`,
|
|
925
|
+
value: archive.toString(),
|
|
926
|
+
},
|
|
927
|
+
],
|
|
928
|
+
},
|
|
929
|
+
];
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
/** Merges multiple StateOverride arrays, combining stateDiff entries for the same address. */
|
|
933
|
+
public static mergeStateOverrides(...overrides: StateOverride[]): StateOverride {
|
|
934
|
+
type StateDiffEntry = { slot: `0x${string}`; value: `0x${string}` };
|
|
935
|
+
const byAddress = new Map<string, { address: `0x${string}`; balance?: bigint; stateDiff: StateDiffEntry[] }>();
|
|
936
|
+
for (const override of overrides) {
|
|
937
|
+
for (const entry of override) {
|
|
938
|
+
const key = entry.address.toLowerCase();
|
|
939
|
+
const existing = byAddress.get(key);
|
|
940
|
+
if (existing) {
|
|
941
|
+
existing.stateDiff.push(...(entry.stateDiff ?? []));
|
|
942
|
+
if (entry.balance !== undefined) {
|
|
943
|
+
existing.balance = entry.balance;
|
|
944
|
+
}
|
|
945
|
+
} else {
|
|
946
|
+
byAddress.set(key, {
|
|
947
|
+
address: entry.address,
|
|
948
|
+
balance: entry.balance,
|
|
949
|
+
stateDiff: [...(entry.stateDiff ?? [])],
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
return [...byAddress.values()];
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
/** Compresses a FeeHeader into a uint256 matching FeeHeaderLib.compress() in FeeStructs.sol. */
|
|
958
|
+
public static compressFeeHeader(feeHeader: FeeHeader): bigint {
|
|
959
|
+
const MASK_48_BITS = (1n << 48n) - 1n;
|
|
960
|
+
const MASK_64_BITS = (1n << 64n) - 1n;
|
|
961
|
+
const MASK_63_BITS = (1n << 63n) - 1n;
|
|
962
|
+
|
|
963
|
+
let value = BigInt(feeHeader.manaUsed) & ((1n << 32n) - 1n); // bits [0:31]
|
|
964
|
+
value |= (feeHeader.excessMana < MASK_48_BITS ? feeHeader.excessMana : MASK_48_BITS) << 32n; // bits [32:79]
|
|
965
|
+
value |= (BigInt(feeHeader.ethPerFeeAsset) & MASK_48_BITS) << 80n; // bits [80:127]
|
|
966
|
+
value |= (feeHeader.congestionCost < MASK_64_BITS ? feeHeader.congestionCost : MASK_64_BITS) << 128n; // bits [128:191]
|
|
967
|
+
value |= (feeHeader.proverCost < MASK_63_BITS ? feeHeader.proverCost : MASK_63_BITS) << 192n; // bits [192:254]
|
|
968
|
+
value |= 1n << 255n; // preheat flag
|
|
969
|
+
return value;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/** Computes the fee header for a child checkpoint given parent fee header and child data.
|
|
973
|
+
* Must stay in sync with Solidity FeeLib.sol (computeNewEthPerFeeAsset, clampedAdd). */
|
|
974
|
+
public static computeChildFeeHeader(
|
|
975
|
+
parentFeeHeader: FeeHeader,
|
|
976
|
+
childManaUsed: bigint,
|
|
977
|
+
feeAssetPriceModifier: bigint,
|
|
978
|
+
manaTarget: bigint,
|
|
979
|
+
): FeeHeader {
|
|
980
|
+
const MIN_ETH_PER_FEE_ASSET = 100n;
|
|
981
|
+
const MAX_ETH_PER_FEE_ASSET = 100_000_000_000_000n; // 1e14, matches FeeLib.sol
|
|
982
|
+
|
|
983
|
+
// excessMana = clampedAdd(parent.excessMana + parent.manaUsed, -manaTarget)
|
|
984
|
+
const sum = parentFeeHeader.excessMana + parentFeeHeader.manaUsed;
|
|
985
|
+
const excessMana = sum > manaTarget ? sum - manaTarget : 0n;
|
|
986
|
+
|
|
987
|
+
// ethPerFeeAsset = computeNewEthPerFeeAsset(max(parent.ethPerFeeAsset, MIN), modifier)
|
|
988
|
+
const parentPrice =
|
|
989
|
+
parentFeeHeader.ethPerFeeAsset > MIN_ETH_PER_FEE_ASSET ? parentFeeHeader.ethPerFeeAsset : MIN_ETH_PER_FEE_ASSET;
|
|
990
|
+
let newPrice: bigint;
|
|
991
|
+
if (feeAssetPriceModifier >= 0n) {
|
|
992
|
+
newPrice = (parentPrice * (10_000n + feeAssetPriceModifier)) / 10_000n;
|
|
993
|
+
} else {
|
|
994
|
+
const absMod = -feeAssetPriceModifier;
|
|
995
|
+
newPrice = (parentPrice * (10_000n - absMod)) / 10_000n;
|
|
996
|
+
}
|
|
997
|
+
if (newPrice < MIN_ETH_PER_FEE_ASSET) {
|
|
998
|
+
newPrice = MIN_ETH_PER_FEE_ASSET;
|
|
999
|
+
}
|
|
1000
|
+
if (newPrice > MAX_ETH_PER_FEE_ASSET) {
|
|
1001
|
+
newPrice = MAX_ETH_PER_FEE_ASSET;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
return {
|
|
1005
|
+
excessMana,
|
|
1006
|
+
manaUsed: childManaUsed,
|
|
1007
|
+
ethPerFeeAsset: newPrice,
|
|
1008
|
+
congestionCost: 0n,
|
|
1009
|
+
proverCost: 0n,
|
|
1010
|
+
};
|
|
1011
|
+
}
|
|
1012
|
+
|
|
587
1013
|
/** Creates a request to Rollup#invalidateBadAttestation to be simulated or sent */
|
|
588
1014
|
public buildInvalidateBadAttestationRequest(
|
|
589
|
-
checkpointNumber:
|
|
1015
|
+
checkpointNumber: CheckpointNumber,
|
|
590
1016
|
attestationsAndSigners: ViemCommitteeAttestations,
|
|
591
1017
|
committee: EthAddress[],
|
|
592
1018
|
invalidIndex: number,
|
|
593
1019
|
): L1TxRequest {
|
|
594
1020
|
return {
|
|
595
1021
|
to: this.address,
|
|
1022
|
+
abi: RollupAbi,
|
|
596
1023
|
data: encodeFunctionData({
|
|
597
1024
|
abi: RollupAbi,
|
|
598
1025
|
functionName: 'invalidateBadAttestation',
|
|
@@ -608,12 +1035,13 @@ export class RollupContract {
|
|
|
608
1035
|
|
|
609
1036
|
/** Creates a request to Rollup#invalidateInsufficientAttestations to be simulated or sent */
|
|
610
1037
|
public buildInvalidateInsufficientAttestationsRequest(
|
|
611
|
-
checkpointNumber:
|
|
1038
|
+
checkpointNumber: CheckpointNumber,
|
|
612
1039
|
attestationsAndSigners: ViemCommitteeAttestations,
|
|
613
1040
|
committee: EthAddress[],
|
|
614
1041
|
): L1TxRequest {
|
|
615
1042
|
return {
|
|
616
1043
|
to: this.address,
|
|
1044
|
+
abi: RollupAbi,
|
|
617
1045
|
data: encodeFunctionData({
|
|
618
1046
|
abi: RollupAbi,
|
|
619
1047
|
functionName: 'invalidateInsufficientAttestations',
|
|
@@ -630,90 +1058,133 @@ export class RollupContract {
|
|
|
630
1058
|
return this.rollup.read.getHasSubmitted([BigInt(epochNumber), BigInt(numberOfCheckpointsInEpoch), prover]);
|
|
631
1059
|
}
|
|
632
1060
|
|
|
633
|
-
|
|
634
|
-
return this.rollup.read.
|
|
1061
|
+
getManaMinFeeAt(timestamp: bigint, inFeeAsset: boolean, stateOverride?: StateOverride): Promise<bigint> {
|
|
1062
|
+
return this.rollup.read.getManaMinFeeAt([timestamp, inFeeAsset], { stateOverride });
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
async getManaMinFeeComponentsAt(timestamp: bigint, inFeeAsset: boolean): Promise<ManaMinFeeComponents> {
|
|
1066
|
+
const result = await this.rollup.read.getManaMinFeeComponentsAt([timestamp, inFeeAsset]);
|
|
1067
|
+
return {
|
|
1068
|
+
sequencerCost: result.sequencerCost,
|
|
1069
|
+
proverCost: result.proverCost,
|
|
1070
|
+
congestionCost: result.congestionCost,
|
|
1071
|
+
congestionMultiplier: result.congestionMultiplier,
|
|
1072
|
+
};
|
|
635
1073
|
}
|
|
636
1074
|
|
|
637
1075
|
async getSlotAt(timestamp: bigint): Promise<SlotNumber> {
|
|
638
1076
|
return SlotNumber.fromBigInt(await this.rollup.read.getSlotAt([timestamp]));
|
|
639
1077
|
}
|
|
640
1078
|
|
|
641
|
-
async status(checkpointNumber:
|
|
1079
|
+
async status(checkpointNumber: CheckpointNumber, options?: { blockNumber?: bigint }): Promise<RollupStatusResponse> {
|
|
642
1080
|
await checkBlockTag(options?.blockNumber, this.client);
|
|
643
|
-
|
|
1081
|
+
const result = await this.rollup.read.status([BigInt(checkpointNumber)], options);
|
|
1082
|
+
return {
|
|
1083
|
+
provenCheckpointNumber: CheckpointNumber.fromBigInt(result[0]),
|
|
1084
|
+
provenArchive: Fr.fromString(result[1]),
|
|
1085
|
+
pendingCheckpointNumber: CheckpointNumber.fromBigInt(result[2]),
|
|
1086
|
+
pendingArchive: Fr.fromString(result[3]),
|
|
1087
|
+
archiveOfMyCheckpoint: Fr.fromString(result[4]),
|
|
1088
|
+
};
|
|
644
1089
|
}
|
|
645
1090
|
|
|
646
|
-
async canPruneAtTime(timestamp: bigint, options?: { blockNumber?: bigint }) {
|
|
1091
|
+
async canPruneAtTime(timestamp: bigint, options?: { blockNumber?: bigint }): Promise<boolean> {
|
|
647
1092
|
await checkBlockTag(options?.blockNumber, this.client);
|
|
648
1093
|
return this.rollup.read.canPruneAtTime([timestamp], options);
|
|
649
1094
|
}
|
|
650
1095
|
|
|
651
|
-
archive() {
|
|
652
|
-
return this.rollup.read.archive();
|
|
1096
|
+
async archive(): Promise<Fr> {
|
|
1097
|
+
return Fr.fromString(await this.rollup.read.archive());
|
|
653
1098
|
}
|
|
654
1099
|
|
|
655
|
-
archiveAt(checkpointNumber:
|
|
656
|
-
return this.rollup.read.archiveAt([checkpointNumber]);
|
|
1100
|
+
async archiveAt(checkpointNumber: CheckpointNumber): Promise<Fr> {
|
|
1101
|
+
return Fr.fromString(await this.rollup.read.archiveAt([BigInt(checkpointNumber)]));
|
|
657
1102
|
}
|
|
658
1103
|
|
|
659
|
-
getSequencerRewards(address: Hex | EthAddress) {
|
|
1104
|
+
getSequencerRewards(address: Hex | EthAddress): Promise<bigint> {
|
|
660
1105
|
if (address instanceof EthAddress) {
|
|
661
1106
|
address = address.toString();
|
|
662
1107
|
}
|
|
663
1108
|
return this.rollup.read.getSequencerRewards([address]);
|
|
664
1109
|
}
|
|
665
1110
|
|
|
666
|
-
getSpecificProverRewardsForEpoch(epoch: bigint, prover: Hex | EthAddress) {
|
|
1111
|
+
getSpecificProverRewardsForEpoch(epoch: bigint, prover: Hex | EthAddress): Promise<bigint> {
|
|
667
1112
|
if (prover instanceof EthAddress) {
|
|
668
1113
|
prover = prover.toString();
|
|
669
1114
|
}
|
|
670
1115
|
return this.rollup.read.getSpecificProverRewardsForEpoch([epoch, prover]);
|
|
671
1116
|
}
|
|
672
1117
|
|
|
673
|
-
async getAttesters() {
|
|
1118
|
+
async getAttesters(timestamp?: bigint): Promise<EthAddress[]> {
|
|
674
1119
|
const attesterSize = await this.getActiveAttesterCount();
|
|
675
1120
|
const gse = new GSEContract(this.client, await this.getGSE());
|
|
676
|
-
const ts = (await this.client.getBlock()).timestamp;
|
|
677
|
-
|
|
678
|
-
const indices = Array.from({ length: Number(attesterSize) }, (_, i) => BigInt(i));
|
|
1121
|
+
const ts = timestamp ?? (await this.client.getBlock()).timestamp;
|
|
1122
|
+
const indices = Array.from({ length: attesterSize }, (_, i) => BigInt(i));
|
|
679
1123
|
const chunks = chunk(indices, 1000);
|
|
680
1124
|
|
|
681
|
-
|
|
1125
|
+
const results = await Promise.all(chunks.map(chunk => gse.getAttestersFromIndicesAtTime(this.address, ts, chunk)));
|
|
1126
|
+
return results.flat().map(addr => EthAddress.fromString(addr));
|
|
682
1127
|
}
|
|
683
1128
|
|
|
684
|
-
getAttesterView(address: Hex | EthAddress) {
|
|
1129
|
+
async getAttesterView(address: Hex | EthAddress): Promise<AttesterView> {
|
|
685
1130
|
if (address instanceof EthAddress) {
|
|
686
1131
|
address = address.toString();
|
|
687
1132
|
}
|
|
688
|
-
|
|
1133
|
+
const result = await this.rollup.read.getAttesterView([address]);
|
|
1134
|
+
return {
|
|
1135
|
+
status: result.status as AttesterStatus,
|
|
1136
|
+
effectiveBalance: result.effectiveBalance,
|
|
1137
|
+
exit: {
|
|
1138
|
+
withdrawalId: result.exit.withdrawalId,
|
|
1139
|
+
amount: result.exit.amount,
|
|
1140
|
+
exitableAt: result.exit.exitableAt,
|
|
1141
|
+
recipientOrWithdrawer: EthAddress.fromString(result.exit.recipientOrWithdrawer),
|
|
1142
|
+
isRecipient: result.exit.isRecipient,
|
|
1143
|
+
exists: result.exit.exists,
|
|
1144
|
+
},
|
|
1145
|
+
config: {
|
|
1146
|
+
publicKey: {
|
|
1147
|
+
x: result.config.publicKey.x,
|
|
1148
|
+
y: result.config.publicKey.y,
|
|
1149
|
+
},
|
|
1150
|
+
withdrawer: EthAddress.fromString(result.config.withdrawer),
|
|
1151
|
+
},
|
|
1152
|
+
};
|
|
689
1153
|
}
|
|
690
1154
|
|
|
691
|
-
getStatus(address: Hex | EthAddress) {
|
|
1155
|
+
async getStatus(address: Hex | EthAddress): Promise<AttesterStatus> {
|
|
692
1156
|
if (address instanceof EthAddress) {
|
|
693
1157
|
address = address.toString();
|
|
694
1158
|
}
|
|
695
|
-
return this.rollup.read.getStatus([address]);
|
|
1159
|
+
return (await this.rollup.read.getStatus([address])) as AttesterStatus;
|
|
696
1160
|
}
|
|
697
1161
|
|
|
698
|
-
getBlobCommitmentsHash(checkpointNumber:
|
|
699
|
-
return this.rollup.read.getBlobCommitmentsHash([checkpointNumber]);
|
|
1162
|
+
async getBlobCommitmentsHash(checkpointNumber: CheckpointNumber): Promise<Buffer32> {
|
|
1163
|
+
return Buffer32.fromString(await this.rollup.read.getBlobCommitmentsHash([BigInt(checkpointNumber)]));
|
|
700
1164
|
}
|
|
701
1165
|
|
|
702
|
-
getCurrentBlobCommitmentsHash() {
|
|
703
|
-
return this.rollup.read.getCurrentBlobCommitmentsHash();
|
|
1166
|
+
async getCurrentBlobCommitmentsHash(): Promise<Buffer32> {
|
|
1167
|
+
return Buffer32.fromString(await this.rollup.read.getCurrentBlobCommitmentsHash());
|
|
704
1168
|
}
|
|
705
1169
|
|
|
706
|
-
getStakingAsset() {
|
|
707
|
-
return this.rollup.read.getStakingAsset();
|
|
1170
|
+
async getStakingAsset(): Promise<EthAddress> {
|
|
1171
|
+
return EthAddress.fromString(await this.rollup.read.getStakingAsset());
|
|
708
1172
|
}
|
|
709
1173
|
|
|
710
|
-
getRewardConfig() {
|
|
711
|
-
|
|
1174
|
+
async getRewardConfig(): Promise<RewardConfig> {
|
|
1175
|
+
const result = await this.rollup.read.getRewardConfig();
|
|
1176
|
+
return {
|
|
1177
|
+
rewardDistributor: EthAddress.fromString(result.rewardDistributor),
|
|
1178
|
+
sequencerBps: BigInt(result.sequencerBps),
|
|
1179
|
+
booster: EthAddress.fromString(result.booster),
|
|
1180
|
+
checkpointReward: result.checkpointReward,
|
|
1181
|
+
};
|
|
712
1182
|
}
|
|
713
1183
|
|
|
714
1184
|
setupEpoch(l1TxUtils: L1TxUtils) {
|
|
715
1185
|
return l1TxUtils.sendAndMonitorTransaction({
|
|
716
1186
|
to: this.address,
|
|
1187
|
+
abi: RollupAbi,
|
|
717
1188
|
data: encodeFunctionData({
|
|
718
1189
|
abi: RollupAbi,
|
|
719
1190
|
functionName: 'setupEpoch',
|
|
@@ -725,6 +1196,7 @@ export class RollupContract {
|
|
|
725
1196
|
vote(l1TxUtils: L1TxUtils, proposalId: bigint) {
|
|
726
1197
|
return l1TxUtils.sendAndMonitorTransaction({
|
|
727
1198
|
to: this.address,
|
|
1199
|
+
abi: RollupAbi,
|
|
728
1200
|
data: encodeFunctionData({
|
|
729
1201
|
abi: RollupAbi,
|
|
730
1202
|
functionName: 'vote',
|
|
@@ -752,7 +1224,7 @@ export class RollupContract {
|
|
|
752
1224
|
}
|
|
753
1225
|
|
|
754
1226
|
public listenToCheckpointInvalidated(
|
|
755
|
-
callback: (args: { checkpointNumber:
|
|
1227
|
+
callback: (args: { checkpointNumber: CheckpointNumber }) => unknown,
|
|
756
1228
|
): WatchContractEventReturnType {
|
|
757
1229
|
return this.rollup.watchEvent.CheckpointInvalidated(
|
|
758
1230
|
{},
|
|
@@ -761,7 +1233,7 @@ export class RollupContract {
|
|
|
761
1233
|
for (const log of logs) {
|
|
762
1234
|
const args = log.args;
|
|
763
1235
|
if (args.checkpointNumber !== undefined) {
|
|
764
|
-
callback({ checkpointNumber: args.checkpointNumber });
|
|
1236
|
+
callback({ checkpointNumber: CheckpointNumber.fromBigInt(args.checkpointNumber) });
|
|
765
1237
|
}
|
|
766
1238
|
}
|
|
767
1239
|
},
|
|
@@ -793,4 +1265,72 @@ export class RollupContract {
|
|
|
793
1265
|
},
|
|
794
1266
|
);
|
|
795
1267
|
}
|
|
1268
|
+
|
|
1269
|
+
/** Fetches CheckpointProposed events within the given block range. */
|
|
1270
|
+
async getCheckpointProposedEvents(fromBlock: bigint, toBlock: bigint): Promise<CheckpointProposedLog[]> {
|
|
1271
|
+
const logs = await this.rollup.getEvents.CheckpointProposed({}, { fromBlock, toBlock });
|
|
1272
|
+
return logs
|
|
1273
|
+
.filter(log => log.blockNumber! >= fromBlock && log.blockNumber! <= toBlock)
|
|
1274
|
+
.map(log => ({
|
|
1275
|
+
l1BlockNumber: log.blockNumber!,
|
|
1276
|
+
l1BlockHash: Buffer32.fromString(log.blockHash!),
|
|
1277
|
+
l1TransactionHash: log.transactionHash!,
|
|
1278
|
+
args: {
|
|
1279
|
+
checkpointNumber: CheckpointNumber.fromBigInt(log.args.checkpointNumber!),
|
|
1280
|
+
archive: Fr.fromString(log.args.archive!),
|
|
1281
|
+
versionedBlobHashes: log.args.versionedBlobHashes!.map(h => Buffer.from(h.slice(2), 'hex')),
|
|
1282
|
+
attestationsHash: (() => {
|
|
1283
|
+
if (!log.args.attestationsHash) {
|
|
1284
|
+
throw new Error(
|
|
1285
|
+
`CheckpointProposed event missing attestationsHash for checkpoint ${log.args.checkpointNumber}`,
|
|
1286
|
+
);
|
|
1287
|
+
}
|
|
1288
|
+
return Buffer32.fromString(log.args.attestationsHash);
|
|
1289
|
+
})(),
|
|
1290
|
+
payloadDigest: (() => {
|
|
1291
|
+
if (!log.args.payloadDigest) {
|
|
1292
|
+
throw new Error(
|
|
1293
|
+
`CheckpointProposed event missing payloadDigest for checkpoint ${log.args.checkpointNumber}`,
|
|
1294
|
+
);
|
|
1295
|
+
}
|
|
1296
|
+
return Buffer32.fromString(log.args.payloadDigest);
|
|
1297
|
+
})(),
|
|
1298
|
+
},
|
|
1299
|
+
}));
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
/** Packs pending and proven checkpoint numbers into the chain tips storage format. */
|
|
1303
|
+
static packChainTips(pendingCheckpointNumber: bigint, provenCheckpointNumber: bigint): bigint {
|
|
1304
|
+
return (pendingCheckpointNumber << 128n) | (provenCheckpointNumber & ((1n << 128n) - 1n));
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
/** Storage slot for the chain tips (offset 0 within the STF storage struct). */
|
|
1308
|
+
static get chainTipsStorageSlot(): bigint {
|
|
1309
|
+
return BigInt(RollupContract.stfStorageSlot);
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
/**
|
|
1313
|
+
* Computes the storage slot for a field within a tempCheckpointLog entry.
|
|
1314
|
+
* @param checkpointNumber - The checkpoint number
|
|
1315
|
+
* @param field - The field within the CompressedTempCheckpointLog struct
|
|
1316
|
+
*/
|
|
1317
|
+
async getTempCheckpointLogStorageSlot(
|
|
1318
|
+
checkpointNumber: CheckpointNumber,
|
|
1319
|
+
field: TempCheckpointLogField,
|
|
1320
|
+
): Promise<bigint> {
|
|
1321
|
+
const fieldOffset = BigInt(field);
|
|
1322
|
+
const [epochDuration, proofSubmissionEpochs] = await Promise.all([
|
|
1323
|
+
this.getEpochDuration(),
|
|
1324
|
+
this.getProofSubmissionEpochs(),
|
|
1325
|
+
]);
|
|
1326
|
+
const roundaboutSize = BigInt(epochDuration) * (BigInt(proofSubmissionEpochs) + 1n) + 1n;
|
|
1327
|
+
const tempCheckpointLogsBase = BigInt(RollupContract.stfStorageSlot) + 2n;
|
|
1328
|
+
const circularIndex = BigInt(checkpointNumber) % roundaboutSize;
|
|
1329
|
+
const entryBase = BigInt(
|
|
1330
|
+
keccak256(
|
|
1331
|
+
encodeAbiParameters([{ type: 'uint256' }, { type: 'uint256' }], [circularIndex, tempCheckpointLogsBase]),
|
|
1332
|
+
),
|
|
1333
|
+
);
|
|
1334
|
+
return entryBase + fieldOffset;
|
|
1335
|
+
}
|
|
796
1336
|
}
|