@aztec/ethereum 0.0.1-commit.e6bd8901 → 0.0.1-commit.ec7ac5448
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 -7
- package/dest/config.d.ts +8 -6
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +15 -11
- 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 +3 -1
- package/dest/contracts/empire_base.d.ts.map +1 -1
- package/dest/contracts/fee_asset_handler.d.ts +1 -1
- package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
- package/dest/contracts/fee_asset_handler.js +2 -0
- 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 +1 -1
- package/dest/contracts/governance.d.ts.map +1 -1
- package/dest/contracts/governance.js +5 -3
- package/dest/contracts/governance_proposer.d.ts +3 -1
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +13 -1
- package/dest/contracts/inbox.d.ts +3 -3
- package/dest/contracts/inbox.d.ts.map +1 -1
- package/dest/contracts/inbox.js +5 -6
- package/dest/contracts/index.d.ts +4 -3
- package/dest/contracts/index.d.ts.map +1 -1
- package/dest/contracts/index.js +3 -2
- 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/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 +45 -20
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +218 -52
- package/dest/contracts/{tally_slashing_proposer.d.ts → slashing_proposer.d.ts} +3 -4
- 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 +4 -8
- package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_aztec_l1_contracts.js +39 -26
- package/dest/deploy_l1_contract.js +3 -3
- package/dest/generated/l1-contracts-defaults.d.ts +2 -2
- package/dest/generated/l1-contracts-defaults.js +2 -2
- package/dest/l1_artifacts.d.ts +9382 -15156
- 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 +0 -6
- package/dest/l1_reader.d.ts +3 -1
- package/dest/l1_reader.d.ts.map +1 -1
- package/dest/l1_reader.js +6 -1
- package/dest/l1_tx_utils/config.d.ts +7 -1
- package/dest/l1_tx_utils/config.d.ts.map +1 -1
- package/dest/l1_tx_utils/config.js +14 -1
- package/dest/l1_tx_utils/constants.d.ts +1 -1
- package/dest/l1_tx_utils/constants.js +2 -2
- package/dest/l1_tx_utils/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/p75_competitive.js +1 -1
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +1 -1
- package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +15 -15
- package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +9 -15
- package/dest/l1_tx_utils/index-blobs.d.ts +3 -3
- package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -1
- package/dest/l1_tx_utils/index-blobs.js +2 -2
- package/dest/l1_tx_utils/index.d.ts +2 -1
- package/dest/l1_tx_utils/index.d.ts.map +1 -1
- package/dest/l1_tx_utils/index.js +1 -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 +81 -57
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +1 -1
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/readonly_l1_tx_utils.js +11 -7
- 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 +62 -34
- 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.js +3 -3
- package/dest/test/chain_monitor.d.ts +22 -3
- package/dest/test/chain_monitor.d.ts.map +1 -1
- package/dest/test/chain_monitor.js +33 -2
- package/dest/test/eth_cheat_codes.d.ts +6 -4
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +6 -4
- 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 +7 -1
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +18 -1
- package/dest/test/start_anvil.d.ts +23 -3
- 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/utils.d.ts +2 -1
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +62 -12
- package/package.json +5 -7
- package/src/client.ts +10 -2
- package/src/config.ts +24 -15
- package/src/contracts/chain_state_override.ts +147 -0
- package/src/contracts/empire_base.ts +2 -0
- package/src/contracts/fee_asset_handler.ts +2 -0
- package/src/contracts/fee_asset_price_oracle.ts +280 -0
- package/src/contracts/governance.ts +5 -3
- package/src/contracts/governance_proposer.ts +10 -1
- package/src/contracts/inbox.ts +4 -4
- package/src/contracts/index.ts +3 -2
- package/src/contracts/multicall.ts +70 -3
- package/src/contracts/registry.ts +31 -1
- package/src/contracts/rollup.ts +242 -51
- package/src/contracts/{tally_slashing_proposer.ts → slashing_proposer.ts} +16 -14
- package/src/deploy_aztec_l1_contracts.ts +61 -34
- package/src/deploy_l1_contract.ts +3 -3
- package/src/generated/l1-contracts-defaults.ts +2 -2
- package/src/l1_artifacts.ts +12 -35
- package/src/l1_contract_addresses.ts +0 -7
- package/src/l1_reader.ts +13 -1
- package/src/l1_tx_utils/config.ts +20 -0
- package/src/l1_tx_utils/constants.ts +2 -2
- package/src/l1_tx_utils/factory.ts +31 -31
- package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +1 -1
- package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +1 -1
- package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +43 -54
- package/src/l1_tx_utils/index-blobs.ts +2 -2
- package/src/l1_tx_utils/index.ts +1 -0
- package/src/l1_tx_utils/l1_tx_utils.ts +74 -36
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +11 -7
- package/src/{test → l1_tx_utils}/tx_delayer.ts +78 -50
- package/src/publisher_manager.ts +107 -10
- package/src/queries.ts +3 -3
- package/src/test/chain_monitor.ts +60 -3
- package/src/test/eth_cheat_codes.ts +6 -4
- package/src/test/index.ts +0 -2
- package/src/test/rollup_cheat_codes.ts +20 -1
- package/src/test/start_anvil.ts +177 -29
- package/src/test/upgrade_utils.ts +2 -2
- package/src/utils.ts +70 -14
- package/dest/contracts/empire_slashing_proposer.d.ts +0 -67
- package/dest/contracts/empire_slashing_proposer.d.ts.map +0 -1
- package/dest/contracts/empire_slashing_proposer.js +0 -209
- package/dest/contracts/tally_slashing_proposer.d.ts.map +0 -1
- 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 -270
- 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
|
@@ -4,6 +4,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
4
4
|
import { memoize } from '@aztec/foundation/decorators';
|
|
5
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
6
|
import type { ViemSignature } from '@aztec/foundation/eth-signature';
|
|
7
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
7
8
|
import { makeBackoff, retry } from '@aztec/foundation/retry';
|
|
8
9
|
import { EscapeHatchAbi } from '@aztec/l1-artifacts/EscapeHatchAbi';
|
|
9
10
|
import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
|
|
@@ -16,6 +17,7 @@ import {
|
|
|
16
17
|
type Hex,
|
|
17
18
|
type StateOverride,
|
|
18
19
|
type WatchContractEventReturnType,
|
|
20
|
+
encodeAbiParameters,
|
|
19
21
|
encodeFunctionData,
|
|
20
22
|
getContract,
|
|
21
23
|
hexToBigInt,
|
|
@@ -29,11 +31,10 @@ import type { L1ReaderConfig } from '../l1_reader.js';
|
|
|
29
31
|
import type { L1TxRequest, L1TxUtils } from '../l1_tx_utils/index.js';
|
|
30
32
|
import type { ViemClient } from '../types.js';
|
|
31
33
|
import { formatViemError } from '../utils.js';
|
|
32
|
-
import { EmpireSlashingProposerContract } from './empire_slashing_proposer.js';
|
|
33
34
|
import { GSEContract } from './gse.js';
|
|
34
35
|
import type { L1EventLog } from './log.js';
|
|
35
36
|
import { SlasherContract } from './slasher_contract.js';
|
|
36
|
-
import {
|
|
37
|
+
import { SlashingProposerContract } from './slashing_proposer.js';
|
|
37
38
|
import { checkBlockTag } from './utils.js';
|
|
38
39
|
|
|
39
40
|
export type ViemCommitteeAttestation = {
|
|
@@ -55,7 +56,6 @@ export type L1RollupContractAddresses = Pick<
|
|
|
55
56
|
| 'feeJuiceAddress'
|
|
56
57
|
| 'stakingAssetAddress'
|
|
57
58
|
| 'rewardDistributorAddress'
|
|
58
|
-
| 'slashFactoryAddress'
|
|
59
59
|
| 'gseAddress'
|
|
60
60
|
>;
|
|
61
61
|
|
|
@@ -85,12 +85,6 @@ export type ViemGasFees = {
|
|
|
85
85
|
feePerL2Gas: bigint;
|
|
86
86
|
};
|
|
87
87
|
|
|
88
|
-
export enum SlashingProposerType {
|
|
89
|
-
None = 0,
|
|
90
|
-
Tally = 1,
|
|
91
|
-
Empire = 2,
|
|
92
|
-
}
|
|
93
|
-
|
|
94
88
|
/**
|
|
95
89
|
* Status of a validator/attester in the staking system.
|
|
96
90
|
* Matches the Status enum in StakingLib.sol
|
|
@@ -134,6 +128,14 @@ export type L1FeeData = {
|
|
|
134
128
|
blobFee: bigint;
|
|
135
129
|
};
|
|
136
130
|
|
|
131
|
+
/** Components of the minimum fee per mana, as returned by the L1 rollup contract. */
|
|
132
|
+
export type ManaMinFeeComponents = {
|
|
133
|
+
sequencerCost: bigint;
|
|
134
|
+
proverCost: bigint;
|
|
135
|
+
congestionCost: bigint;
|
|
136
|
+
congestionMultiplier: bigint;
|
|
137
|
+
};
|
|
138
|
+
|
|
137
139
|
/**
|
|
138
140
|
* Reward configuration for the rollup
|
|
139
141
|
*/
|
|
@@ -193,10 +195,10 @@ export type CheckpointProposedArgs = {
|
|
|
193
195
|
checkpointNumber: CheckpointNumber;
|
|
194
196
|
archive: Fr;
|
|
195
197
|
versionedBlobHashes: Buffer[];
|
|
196
|
-
/** Hash of attestations
|
|
197
|
-
attestationsHash
|
|
198
|
-
/** Digest of the payload
|
|
199
|
-
payloadDigest
|
|
198
|
+
/** Hash of attestations emitted in the CheckpointProposed event. */
|
|
199
|
+
attestationsHash: Buffer32;
|
|
200
|
+
/** Digest of the payload emitted in the CheckpointProposed event. */
|
|
201
|
+
payloadDigest: Buffer32;
|
|
200
202
|
};
|
|
201
203
|
|
|
202
204
|
/** Log type for CheckpointProposed events. */
|
|
@@ -204,6 +206,7 @@ export type CheckpointProposedLog = L1EventLog<CheckpointProposedArgs>;
|
|
|
204
206
|
|
|
205
207
|
export class RollupContract {
|
|
206
208
|
private readonly rollup: GetContractReturnType<typeof RollupAbi, ViemClient>;
|
|
209
|
+
private readonly logger = createLogger('ethereum:rollup');
|
|
207
210
|
|
|
208
211
|
private static cachedStfStorageSlot: Hex | undefined;
|
|
209
212
|
private cachedEscapeHatch?: {
|
|
@@ -259,34 +262,18 @@ export class RollupContract {
|
|
|
259
262
|
return this.rollup;
|
|
260
263
|
}
|
|
261
264
|
|
|
262
|
-
public async getSlashingProposer(): Promise<
|
|
263
|
-
EmpireSlashingProposerContract | TallySlashingProposerContract | undefined
|
|
264
|
-
> {
|
|
265
|
+
public async getSlashingProposer(): Promise<SlashingProposerContract | undefined> {
|
|
265
266
|
const slasher = await this.getSlasherContract();
|
|
266
267
|
if (!slasher) {
|
|
267
268
|
return undefined;
|
|
268
269
|
}
|
|
269
270
|
|
|
270
271
|
const proposerAddress = await slasher.getProposer();
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
type: 'function',
|
|
274
|
-
name: 'SLASHING_PROPOSER_TYPE',
|
|
275
|
-
inputs: [],
|
|
276
|
-
outputs: [{ name: '', type: 'uint8', internalType: 'enum SlasherFlavor' }],
|
|
277
|
-
stateMutability: 'view',
|
|
278
|
-
},
|
|
279
|
-
] as const;
|
|
280
|
-
|
|
281
|
-
const proposer = getContract({ address: proposerAddress.toString(), abi: proposerAbi, client: this.client });
|
|
282
|
-
const proposerType = await proposer.read.SLASHING_PROPOSER_TYPE();
|
|
283
|
-
if (proposerType === SlashingProposerType.Tally.valueOf()) {
|
|
284
|
-
return new TallySlashingProposerContract(this.client, proposerAddress);
|
|
285
|
-
} else if (proposerType === SlashingProposerType.Empire.valueOf()) {
|
|
286
|
-
return new EmpireSlashingProposerContract(this.client, proposerAddress);
|
|
287
|
-
} else {
|
|
288
|
-
throw new Error(`Unknown slashing proposer type: ${proposerType}`);
|
|
272
|
+
if (proposerAddress.isZero()) {
|
|
273
|
+
return undefined;
|
|
289
274
|
}
|
|
275
|
+
|
|
276
|
+
return new SlashingProposerContract(this.client, proposerAddress);
|
|
290
277
|
}
|
|
291
278
|
|
|
292
279
|
@memoize
|
|
@@ -379,6 +366,20 @@ export class RollupContract {
|
|
|
379
366
|
return Fr.fromString(await this.rollup.read.archiveAt([0n]));
|
|
380
367
|
}
|
|
381
368
|
|
|
369
|
+
@memoize
|
|
370
|
+
async getVkTreeRoot(): Promise<Fr> {
|
|
371
|
+
const slot = BigInt(RollupContract.stfStorageSlot) + 3n;
|
|
372
|
+
const value = await this.client.getStorageAt({ address: this.address, slot: `0x${slot.toString(16)}` });
|
|
373
|
+
return Fr.fromString(value ?? '0x0');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
@memoize
|
|
377
|
+
async getProtocolContractsHash(): Promise<Fr> {
|
|
378
|
+
const slot = BigInt(RollupContract.stfStorageSlot) + 4n;
|
|
379
|
+
const value = await this.client.getStorageAt({ address: this.address, slot: `0x${slot.toString(16)}` });
|
|
380
|
+
return Fr.fromString(value ?? '0x0');
|
|
381
|
+
}
|
|
382
|
+
|
|
382
383
|
/**
|
|
383
384
|
* Returns rollup constants used for epoch queries.
|
|
384
385
|
* Return type is `L1RollupConstants` which is defined in stdlib,
|
|
@@ -391,13 +392,25 @@ export class RollupContract {
|
|
|
391
392
|
slotDuration: number;
|
|
392
393
|
epochDuration: number;
|
|
393
394
|
proofSubmissionEpochs: number;
|
|
395
|
+
targetCommitteeSize: number;
|
|
396
|
+
rollupManaLimit: number;
|
|
394
397
|
}> {
|
|
395
|
-
const [
|
|
398
|
+
const [
|
|
399
|
+
l1StartBlock,
|
|
400
|
+
l1GenesisTime,
|
|
401
|
+
slotDuration,
|
|
402
|
+
epochDuration,
|
|
403
|
+
proofSubmissionEpochs,
|
|
404
|
+
targetCommitteeSize,
|
|
405
|
+
rollupManaLimit,
|
|
406
|
+
] = await Promise.all([
|
|
396
407
|
this.getL1StartBlock(),
|
|
397
408
|
this.getL1GenesisTime(),
|
|
398
409
|
this.getSlotDuration(),
|
|
399
410
|
this.getEpochDuration(),
|
|
400
411
|
this.getProofSubmissionEpochs(),
|
|
412
|
+
this.getTargetCommitteeSize(),
|
|
413
|
+
this.getManaLimit(),
|
|
401
414
|
]);
|
|
402
415
|
return {
|
|
403
416
|
l1StartBlock,
|
|
@@ -405,6 +418,8 @@ export class RollupContract {
|
|
|
405
418
|
slotDuration,
|
|
406
419
|
epochDuration: Number(epochDuration),
|
|
407
420
|
proofSubmissionEpochs: Number(proofSubmissionEpochs),
|
|
421
|
+
targetCommitteeSize,
|
|
422
|
+
rollupManaLimit: Number(rollupManaLimit),
|
|
408
423
|
};
|
|
409
424
|
}
|
|
410
425
|
|
|
@@ -459,7 +474,11 @@ export class RollupContract {
|
|
|
459
474
|
|
|
460
475
|
const [isOpen] = await escapeHatch.read.isHatchOpen([BigInt(epoch)]);
|
|
461
476
|
return isOpen;
|
|
462
|
-
} catch {
|
|
477
|
+
} catch (err) {
|
|
478
|
+
this.logger.warn('isEscapeHatchOpen failed (treating as closed); RPC or contract error may cause liveness risk', {
|
|
479
|
+
epoch: Number(epoch),
|
|
480
|
+
error: err,
|
|
481
|
+
});
|
|
463
482
|
return false;
|
|
464
483
|
}
|
|
465
484
|
}
|
|
@@ -499,8 +518,9 @@ export class RollupContract {
|
|
|
499
518
|
return CheckpointNumber.fromBigInt(await this.rollup.read.getPendingCheckpointNumber());
|
|
500
519
|
}
|
|
501
520
|
|
|
502
|
-
async getProvenCheckpointNumber(): Promise<CheckpointNumber> {
|
|
503
|
-
|
|
521
|
+
async getProvenCheckpointNumber(options?: { blockNumber?: bigint }): Promise<CheckpointNumber> {
|
|
522
|
+
await checkBlockTag(options?.blockNumber, this.client);
|
|
523
|
+
return CheckpointNumber.fromBigInt(await this.rollup.read.getProvenCheckpointNumber(options));
|
|
504
524
|
}
|
|
505
525
|
|
|
506
526
|
async getSlotNumber(): Promise<SlotNumber> {
|
|
@@ -741,14 +761,13 @@ export class RollupContract {
|
|
|
741
761
|
* timestamp of the next L1 block
|
|
742
762
|
* @throws otherwise
|
|
743
763
|
*/
|
|
744
|
-
public async
|
|
764
|
+
public async canProposeAt(
|
|
745
765
|
archive: Buffer,
|
|
746
766
|
account: `0x${string}` | Account,
|
|
747
|
-
|
|
748
|
-
|
|
767
|
+
timestamp: bigint,
|
|
768
|
+
stateOverride: StateOverride = [],
|
|
749
769
|
): Promise<{ slot: SlotNumber; checkpointNumber: CheckpointNumber; timeOfNextL1Slot: bigint }> {
|
|
750
|
-
const
|
|
751
|
-
const timeOfNextL1Slot = latestBlock.timestamp + BigInt(slotDuration);
|
|
770
|
+
const timeOfNextL1Slot = timestamp;
|
|
752
771
|
const who = typeof account === 'string' ? account : account.address;
|
|
753
772
|
|
|
754
773
|
try {
|
|
@@ -760,7 +779,7 @@ export class RollupContract {
|
|
|
760
779
|
functionName: 'canProposeAtTime',
|
|
761
780
|
args: [timeOfNextL1Slot, `0x${archive.toString('hex')}`, who],
|
|
762
781
|
account,
|
|
763
|
-
stateOverride
|
|
782
|
+
stateOverride,
|
|
764
783
|
});
|
|
765
784
|
|
|
766
785
|
return {
|
|
@@ -796,6 +815,151 @@ export class RollupContract {
|
|
|
796
815
|
];
|
|
797
816
|
}
|
|
798
817
|
|
|
818
|
+
/**
|
|
819
|
+
* Returns a state override that sets tempCheckpointLogs[checkpointNumber].feeHeader to the compressed fee header.
|
|
820
|
+
* Used when simulating a propose call where the parent checkpoint hasn't landed on L1 yet (pipelining).
|
|
821
|
+
*/
|
|
822
|
+
public async makeFeeHeaderOverride(checkpointNumber: CheckpointNumber, feeHeader: FeeHeader): Promise<StateOverride> {
|
|
823
|
+
const { epochDuration, proofSubmissionEpochs } = await this.getRollupConstants();
|
|
824
|
+
const roundaboutSize = BigInt(epochDuration * (proofSubmissionEpochs + 1) + 1);
|
|
825
|
+
const circularIndex = BigInt(checkpointNumber) % roundaboutSize;
|
|
826
|
+
|
|
827
|
+
// tempCheckpointLogs is at offset 2 in RollupStore
|
|
828
|
+
const tempCheckpointLogsMappingBase = hexToBigInt(RollupContract.stfStorageSlot) + 2n;
|
|
829
|
+
|
|
830
|
+
// Solidity mapping slot: keccak256(abi.encode(key, baseSlot))
|
|
831
|
+
const structBaseSlot = hexToBigInt(
|
|
832
|
+
keccak256(
|
|
833
|
+
encodeAbiParameters([{ type: 'uint256' }, { type: 'uint256' }], [circularIndex, tempCheckpointLogsMappingBase]),
|
|
834
|
+
),
|
|
835
|
+
);
|
|
836
|
+
|
|
837
|
+
// feeHeader is the 7th field (offset 6) in CompressedTempCheckpointLog
|
|
838
|
+
const feeHeaderSlot = structBaseSlot + 6n;
|
|
839
|
+
const compressed = RollupContract.compressFeeHeader(feeHeader);
|
|
840
|
+
|
|
841
|
+
return [
|
|
842
|
+
{
|
|
843
|
+
address: this.address,
|
|
844
|
+
stateDiff: [
|
|
845
|
+
{
|
|
846
|
+
slot: `0x${feeHeaderSlot.toString(16).padStart(64, '0')}`,
|
|
847
|
+
value: `0x${compressed.toString(16).padStart(64, '0')}`,
|
|
848
|
+
},
|
|
849
|
+
],
|
|
850
|
+
},
|
|
851
|
+
];
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* Returns a state override that sets archives[checkpointNumber] to the given archive value.
|
|
856
|
+
* Used when simulating a canProposeAtTime call where the local archive differs from L1
|
|
857
|
+
* (e.g. pipelining where the parent checkpoint hasn't landed on L1 yet).
|
|
858
|
+
*/
|
|
859
|
+
public makeArchiveOverride(checkpointNumber: CheckpointNumber, archive: Fr): StateOverride {
|
|
860
|
+
const archivesMappingBase = hexToBigInt(RollupContract.stfStorageSlot) + 1n;
|
|
861
|
+
const archiveSlot = hexToBigInt(
|
|
862
|
+
keccak256(
|
|
863
|
+
encodeAbiParameters(
|
|
864
|
+
[{ type: 'uint256' }, { type: 'uint256' }],
|
|
865
|
+
[BigInt(checkpointNumber), archivesMappingBase],
|
|
866
|
+
),
|
|
867
|
+
),
|
|
868
|
+
);
|
|
869
|
+
return [
|
|
870
|
+
{
|
|
871
|
+
address: this.address,
|
|
872
|
+
stateDiff: [
|
|
873
|
+
{
|
|
874
|
+
slot: `0x${archiveSlot.toString(16).padStart(64, '0')}`,
|
|
875
|
+
value: archive.toString(),
|
|
876
|
+
},
|
|
877
|
+
],
|
|
878
|
+
},
|
|
879
|
+
];
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/** Merges multiple StateOverride arrays, combining stateDiff entries for the same address. */
|
|
883
|
+
public static mergeStateOverrides(...overrides: StateOverride[]): StateOverride {
|
|
884
|
+
type StateDiffEntry = { slot: `0x${string}`; value: `0x${string}` };
|
|
885
|
+
const byAddress = new Map<string, { address: `0x${string}`; balance?: bigint; stateDiff: StateDiffEntry[] }>();
|
|
886
|
+
for (const override of overrides) {
|
|
887
|
+
for (const entry of override) {
|
|
888
|
+
const key = entry.address.toLowerCase();
|
|
889
|
+
const existing = byAddress.get(key);
|
|
890
|
+
if (existing) {
|
|
891
|
+
existing.stateDiff.push(...(entry.stateDiff ?? []));
|
|
892
|
+
if (entry.balance !== undefined) {
|
|
893
|
+
existing.balance = entry.balance;
|
|
894
|
+
}
|
|
895
|
+
} else {
|
|
896
|
+
byAddress.set(key, {
|
|
897
|
+
address: entry.address,
|
|
898
|
+
balance: entry.balance,
|
|
899
|
+
stateDiff: [...(entry.stateDiff ?? [])],
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
return [...byAddress.values()];
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/** Compresses a FeeHeader into a uint256 matching FeeHeaderLib.compress() in FeeStructs.sol. */
|
|
908
|
+
public static compressFeeHeader(feeHeader: FeeHeader): bigint {
|
|
909
|
+
const MASK_48_BITS = (1n << 48n) - 1n;
|
|
910
|
+
const MASK_64_BITS = (1n << 64n) - 1n;
|
|
911
|
+
const MASK_63_BITS = (1n << 63n) - 1n;
|
|
912
|
+
|
|
913
|
+
let value = BigInt(feeHeader.manaUsed) & ((1n << 32n) - 1n); // bits [0:31]
|
|
914
|
+
value |= (feeHeader.excessMana < MASK_48_BITS ? feeHeader.excessMana : MASK_48_BITS) << 32n; // bits [32:79]
|
|
915
|
+
value |= (BigInt(feeHeader.ethPerFeeAsset) & MASK_48_BITS) << 80n; // bits [80:127]
|
|
916
|
+
value |= (feeHeader.congestionCost < MASK_64_BITS ? feeHeader.congestionCost : MASK_64_BITS) << 128n; // bits [128:191]
|
|
917
|
+
value |= (feeHeader.proverCost < MASK_63_BITS ? feeHeader.proverCost : MASK_63_BITS) << 192n; // bits [192:254]
|
|
918
|
+
value |= 1n << 255n; // preheat flag
|
|
919
|
+
return value;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/** Computes the fee header for a child checkpoint given parent fee header and child data.
|
|
923
|
+
* Must stay in sync with Solidity FeeLib.sol (computeNewEthPerFeeAsset, clampedAdd). */
|
|
924
|
+
public static computeChildFeeHeader(
|
|
925
|
+
parentFeeHeader: FeeHeader,
|
|
926
|
+
childManaUsed: bigint,
|
|
927
|
+
feeAssetPriceModifier: bigint,
|
|
928
|
+
manaTarget: bigint,
|
|
929
|
+
): FeeHeader {
|
|
930
|
+
const MIN_ETH_PER_FEE_ASSET = 100n;
|
|
931
|
+
const MAX_ETH_PER_FEE_ASSET = 100_000_000_000_000n; // 1e14, matches FeeLib.sol
|
|
932
|
+
|
|
933
|
+
// excessMana = clampedAdd(parent.excessMana + parent.manaUsed, -manaTarget)
|
|
934
|
+
const sum = parentFeeHeader.excessMana + parentFeeHeader.manaUsed;
|
|
935
|
+
const excessMana = sum > manaTarget ? sum - manaTarget : 0n;
|
|
936
|
+
|
|
937
|
+
// ethPerFeeAsset = computeNewEthPerFeeAsset(max(parent.ethPerFeeAsset, MIN), modifier)
|
|
938
|
+
const parentPrice =
|
|
939
|
+
parentFeeHeader.ethPerFeeAsset > MIN_ETH_PER_FEE_ASSET ? parentFeeHeader.ethPerFeeAsset : MIN_ETH_PER_FEE_ASSET;
|
|
940
|
+
let newPrice: bigint;
|
|
941
|
+
if (feeAssetPriceModifier >= 0n) {
|
|
942
|
+
newPrice = (parentPrice * (10_000n + feeAssetPriceModifier)) / 10_000n;
|
|
943
|
+
} else {
|
|
944
|
+
const absMod = -feeAssetPriceModifier;
|
|
945
|
+
newPrice = (parentPrice * (10_000n - absMod)) / 10_000n;
|
|
946
|
+
}
|
|
947
|
+
if (newPrice < MIN_ETH_PER_FEE_ASSET) {
|
|
948
|
+
newPrice = MIN_ETH_PER_FEE_ASSET;
|
|
949
|
+
}
|
|
950
|
+
if (newPrice > MAX_ETH_PER_FEE_ASSET) {
|
|
951
|
+
newPrice = MAX_ETH_PER_FEE_ASSET;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
return {
|
|
955
|
+
excessMana,
|
|
956
|
+
manaUsed: childManaUsed,
|
|
957
|
+
ethPerFeeAsset: newPrice,
|
|
958
|
+
congestionCost: 0n,
|
|
959
|
+
proverCost: 0n,
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
|
|
799
963
|
/** Creates a request to Rollup#invalidateBadAttestation to be simulated or sent */
|
|
800
964
|
public buildInvalidateBadAttestationRequest(
|
|
801
965
|
checkpointNumber: CheckpointNumber,
|
|
@@ -805,6 +969,7 @@ export class RollupContract {
|
|
|
805
969
|
): L1TxRequest {
|
|
806
970
|
return {
|
|
807
971
|
to: this.address,
|
|
972
|
+
abi: RollupAbi,
|
|
808
973
|
data: encodeFunctionData({
|
|
809
974
|
abi: RollupAbi,
|
|
810
975
|
functionName: 'invalidateBadAttestation',
|
|
@@ -826,6 +991,7 @@ export class RollupContract {
|
|
|
826
991
|
): L1TxRequest {
|
|
827
992
|
return {
|
|
828
993
|
to: this.address,
|
|
994
|
+
abi: RollupAbi,
|
|
829
995
|
data: encodeFunctionData({
|
|
830
996
|
abi: RollupAbi,
|
|
831
997
|
functionName: 'invalidateInsufficientAttestations',
|
|
@@ -842,8 +1008,18 @@ export class RollupContract {
|
|
|
842
1008
|
return this.rollup.read.getHasSubmitted([BigInt(epochNumber), BigInt(numberOfCheckpointsInEpoch), prover]);
|
|
843
1009
|
}
|
|
844
1010
|
|
|
845
|
-
getManaMinFeeAt(timestamp: bigint, inFeeAsset: boolean): Promise<bigint> {
|
|
846
|
-
return this.rollup.read.getManaMinFeeAt([timestamp, inFeeAsset]);
|
|
1011
|
+
getManaMinFeeAt(timestamp: bigint, inFeeAsset: boolean, stateOverride?: StateOverride): Promise<bigint> {
|
|
1012
|
+
return this.rollup.read.getManaMinFeeAt([timestamp, inFeeAsset], { stateOverride });
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
async getManaMinFeeComponentsAt(timestamp: bigint, inFeeAsset: boolean): Promise<ManaMinFeeComponents> {
|
|
1016
|
+
const result = await this.rollup.read.getManaMinFeeComponentsAt([timestamp, inFeeAsset]);
|
|
1017
|
+
return {
|
|
1018
|
+
sequencerCost: result.sequencerCost,
|
|
1019
|
+
proverCost: result.proverCost,
|
|
1020
|
+
congestionCost: result.congestionCost,
|
|
1021
|
+
congestionMultiplier: result.congestionMultiplier,
|
|
1022
|
+
};
|
|
847
1023
|
}
|
|
848
1024
|
|
|
849
1025
|
async getSlotAt(timestamp: bigint): Promise<SlotNumber> {
|
|
@@ -889,11 +1065,10 @@ export class RollupContract {
|
|
|
889
1065
|
return this.rollup.read.getSpecificProverRewardsForEpoch([epoch, prover]);
|
|
890
1066
|
}
|
|
891
1067
|
|
|
892
|
-
async getAttesters(): Promise<EthAddress[]> {
|
|
1068
|
+
async getAttesters(timestamp?: bigint): Promise<EthAddress[]> {
|
|
893
1069
|
const attesterSize = await this.getActiveAttesterCount();
|
|
894
1070
|
const gse = new GSEContract(this.client, await this.getGSE());
|
|
895
|
-
const ts = (await this.client.getBlock()).timestamp;
|
|
896
|
-
|
|
1071
|
+
const ts = timestamp ?? (await this.client.getBlock()).timestamp;
|
|
897
1072
|
const indices = Array.from({ length: attesterSize }, (_, i) => BigInt(i));
|
|
898
1073
|
const chunks = chunk(indices, 1000);
|
|
899
1074
|
|
|
@@ -959,6 +1134,7 @@ export class RollupContract {
|
|
|
959
1134
|
setupEpoch(l1TxUtils: L1TxUtils) {
|
|
960
1135
|
return l1TxUtils.sendAndMonitorTransaction({
|
|
961
1136
|
to: this.address,
|
|
1137
|
+
abi: RollupAbi,
|
|
962
1138
|
data: encodeFunctionData({
|
|
963
1139
|
abi: RollupAbi,
|
|
964
1140
|
functionName: 'setupEpoch',
|
|
@@ -970,6 +1146,7 @@ export class RollupContract {
|
|
|
970
1146
|
vote(l1TxUtils: L1TxUtils, proposalId: bigint) {
|
|
971
1147
|
return l1TxUtils.sendAndMonitorTransaction({
|
|
972
1148
|
to: this.address,
|
|
1149
|
+
abi: RollupAbi,
|
|
973
1150
|
data: encodeFunctionData({
|
|
974
1151
|
abi: RollupAbi,
|
|
975
1152
|
functionName: 'vote',
|
|
@@ -1052,8 +1229,22 @@ export class RollupContract {
|
|
|
1052
1229
|
checkpointNumber: CheckpointNumber.fromBigInt(log.args.checkpointNumber!),
|
|
1053
1230
|
archive: Fr.fromString(log.args.archive!),
|
|
1054
1231
|
versionedBlobHashes: log.args.versionedBlobHashes!.map(h => Buffer.from(h.slice(2), 'hex')),
|
|
1055
|
-
attestationsHash:
|
|
1056
|
-
|
|
1232
|
+
attestationsHash: (() => {
|
|
1233
|
+
if (!log.args.attestationsHash) {
|
|
1234
|
+
throw new Error(
|
|
1235
|
+
`CheckpointProposed event missing attestationsHash for checkpoint ${log.args.checkpointNumber}`,
|
|
1236
|
+
);
|
|
1237
|
+
}
|
|
1238
|
+
return Buffer32.fromString(log.args.attestationsHash);
|
|
1239
|
+
})(),
|
|
1240
|
+
payloadDigest: (() => {
|
|
1241
|
+
if (!log.args.payloadDigest) {
|
|
1242
|
+
throw new Error(
|
|
1243
|
+
`CheckpointProposed event missing payloadDigest for checkpoint ${log.args.checkpointNumber}`,
|
|
1244
|
+
);
|
|
1245
|
+
}
|
|
1246
|
+
return Buffer32.fromString(log.args.payloadDigest);
|
|
1247
|
+
})(),
|
|
1057
1248
|
},
|
|
1058
1249
|
}));
|
|
1059
1250
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { L1TxRequest } from '@aztec/ethereum/l1-tx-utils';
|
|
2
2
|
import type { ViemClient } from '@aztec/ethereum/types';
|
|
3
|
-
import { tryExtractEvent } from '@aztec/ethereum/utils';
|
|
3
|
+
import { mergeAbis, tryExtractEvent } from '@aztec/ethereum/utils';
|
|
4
4
|
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
5
5
|
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
6
6
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
7
7
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
8
8
|
import { hexToBuffer } from '@aztec/foundation/string';
|
|
9
|
-
import {
|
|
9
|
+
import { SlasherAbi } from '@aztec/l1-artifacts/SlasherAbi';
|
|
10
|
+
import { SlashingProposerAbi } from '@aztec/l1-artifacts/SlashingProposerAbi';
|
|
10
11
|
|
|
11
12
|
import {
|
|
12
13
|
type GetContractReturnType,
|
|
@@ -18,13 +19,11 @@ import {
|
|
|
18
19
|
} from 'viem';
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
|
-
* Wrapper around the
|
|
22
|
+
* Wrapper around the SlashingProposer contract that provides
|
|
22
23
|
* a TypeScript interface for interacting with the consensus-based slashing system.
|
|
23
24
|
*/
|
|
24
|
-
export class
|
|
25
|
-
private readonly contract: GetContractReturnType<typeof
|
|
26
|
-
|
|
27
|
-
public readonly type = 'tally' as const;
|
|
25
|
+
export class SlashingProposerContract {
|
|
26
|
+
private readonly contract: GetContractReturnType<typeof SlashingProposerAbi, ViemClient>;
|
|
28
27
|
|
|
29
28
|
constructor(
|
|
30
29
|
public readonly client: ViemClient,
|
|
@@ -32,7 +31,7 @@ export class TallySlashingProposerContract {
|
|
|
32
31
|
) {
|
|
33
32
|
this.contract = getContract({
|
|
34
33
|
address: typeof address === 'string' ? address : address.toString(),
|
|
35
|
-
abi:
|
|
34
|
+
abi: SlashingProposerAbi,
|
|
36
35
|
client,
|
|
37
36
|
});
|
|
38
37
|
}
|
|
@@ -135,12 +134,12 @@ export class TallySlashingProposerContract {
|
|
|
135
134
|
|
|
136
135
|
/** Tries to extract a VoteCast event from the given logs. */
|
|
137
136
|
public tryExtractVoteCastEvent(logs: Log[]) {
|
|
138
|
-
return tryExtractEvent(logs, this.address.toString(),
|
|
137
|
+
return tryExtractEvent(logs, this.address.toString(), SlashingProposerAbi, 'VoteCast');
|
|
139
138
|
}
|
|
140
139
|
|
|
141
140
|
/** Tries to extract a RoundExecuted event from the given logs. */
|
|
142
141
|
public tryExtractRoundExecutedEvent(logs: Log[]) {
|
|
143
|
-
return tryExtractEvent(logs, this.address.toString(),
|
|
142
|
+
return tryExtractEvent(logs, this.address.toString(), SlashingProposerAbi, 'RoundExecuted');
|
|
144
143
|
}
|
|
145
144
|
|
|
146
145
|
/**
|
|
@@ -160,8 +159,9 @@ export class TallySlashingProposerContract {
|
|
|
160
159
|
|
|
161
160
|
return {
|
|
162
161
|
to: this.contract.address,
|
|
162
|
+
abi: SlashingProposerAbi,
|
|
163
163
|
data: encodeFunctionData({
|
|
164
|
-
abi:
|
|
164
|
+
abi: SlashingProposerAbi,
|
|
165
165
|
functionName: 'vote',
|
|
166
166
|
args: [votes, signature.toViemSignature()],
|
|
167
167
|
}),
|
|
@@ -171,7 +171,7 @@ export class TallySlashingProposerContract {
|
|
|
171
171
|
/** Returns the typed data definition to EIP712-sign for voting */
|
|
172
172
|
public buildVoteTypedData(votes: Hex, slot: SlotNumber): TypedDataDefinition {
|
|
173
173
|
const domain = {
|
|
174
|
-
name: '
|
|
174
|
+
name: 'SlashingProposer',
|
|
175
175
|
version: '1',
|
|
176
176
|
chainId: this.client.chain.id,
|
|
177
177
|
verifyingContract: this.contract.address,
|
|
@@ -207,8 +207,9 @@ export class TallySlashingProposerContract {
|
|
|
207
207
|
public buildVoteRequestWithSignature(votes: Hex, signature: { v: number; r: Hex; s: Hex }): L1TxRequest {
|
|
208
208
|
return {
|
|
209
209
|
to: this.contract.address,
|
|
210
|
+
abi: SlashingProposerAbi,
|
|
210
211
|
data: encodeFunctionData({
|
|
211
|
-
abi:
|
|
212
|
+
abi: SlashingProposerAbi,
|
|
212
213
|
functionName: 'vote',
|
|
213
214
|
args: [votes, signature],
|
|
214
215
|
}),
|
|
@@ -224,8 +225,9 @@ export class TallySlashingProposerContract {
|
|
|
224
225
|
public buildExecuteRoundRequest(round: bigint, committees: EthAddress[][]): L1TxRequest {
|
|
225
226
|
return {
|
|
226
227
|
to: this.contract.address,
|
|
228
|
+
abi: mergeAbis([SlashingProposerAbi, SlasherAbi]),
|
|
227
229
|
data: encodeFunctionData({
|
|
228
|
-
abi:
|
|
230
|
+
abi: SlashingProposerAbi,
|
|
229
231
|
functionName: 'executeRound',
|
|
230
232
|
args: [round, committees.map(c => c.map(addr => addr.toString()))],
|
|
231
233
|
}),
|