@aztec/ethereum 0.0.0-test.0 → 0.0.1-commit.21caa21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/account.d.ts +2 -0
- package/dest/account.d.ts.map +1 -0
- package/dest/account.js +4 -0
- package/dest/chain.d.ts +1 -1
- package/dest/client.d.ts +6 -4
- package/dest/client.d.ts.map +1 -1
- package/dest/client.js +16 -2
- package/dest/config.d.ts +111 -17
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +462 -22
- package/dest/constants.d.ts +1 -1
- package/dest/contracts/empire_base.d.ts +24 -8
- package/dest/contracts/empire_base.d.ts.map +1 -1
- package/dest/contracts/empire_base.js +75 -2
- package/dest/contracts/empire_slashing_proposer.d.ts +66 -0
- package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -0
- package/dest/contracts/empire_slashing_proposer.js +200 -0
- package/dest/contracts/errors.d.ts +7 -0
- package/dest/contracts/errors.d.ts.map +1 -0
- package/dest/contracts/errors.js +12 -0
- package/dest/contracts/fee_asset_handler.d.ts +19 -0
- package/dest/contracts/fee_asset_handler.d.ts.map +1 -0
- package/dest/contracts/fee_asset_handler.js +57 -0
- package/dest/contracts/fee_juice.d.ts +6 -7
- package/dest/contracts/fee_juice.d.ts.map +1 -1
- package/dest/contracts/fee_juice.js +27 -20
- package/dest/contracts/governance.d.ts +43 -32
- package/dest/contracts/governance.d.ts.map +1 -1
- package/dest/contracts/governance.js +87 -84
- package/dest/contracts/governance_proposer.d.ts +16 -13
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +37 -17
- package/dest/contracts/gse.d.ts +32 -0
- package/dest/contracts/gse.d.ts.map +1 -0
- package/dest/contracts/gse.js +72 -0
- package/dest/contracts/inbox.d.ts +26 -0
- package/dest/contracts/inbox.d.ts.map +1 -0
- package/dest/contracts/inbox.js +45 -0
- package/dest/contracts/index.d.ts +9 -3
- package/dest/contracts/index.d.ts.map +1 -1
- package/dest/contracts/index.js +8 -2
- package/dest/contracts/multicall.d.ts +21 -0
- package/dest/contracts/multicall.d.ts.map +1 -0
- package/dest/contracts/multicall.js +156 -0
- package/dest/contracts/registry.d.ts +10 -5
- package/dest/contracts/registry.d.ts.map +1 -1
- package/dest/contracts/registry.js +44 -16
- package/dest/contracts/rollup.d.ts +204 -40
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +529 -79
- package/dest/contracts/slasher_contract.d.ts +44 -0
- package/dest/contracts/slasher_contract.d.ts.map +1 -0
- package/dest/contracts/slasher_contract.js +75 -0
- package/dest/contracts/tally_slashing_proposer.d.ts +139 -0
- package/dest/contracts/tally_slashing_proposer.d.ts.map +1 -0
- package/dest/contracts/tally_slashing_proposer.js +313 -0
- package/dest/contracts/utils.d.ts +3 -0
- package/dest/contracts/utils.d.ts.map +1 -0
- package/dest/contracts/utils.js +11 -0
- package/dest/deploy_l1_contracts.d.ts +577 -21114
- package/dest/deploy_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_l1_contracts.js +1225 -421
- package/dest/eth-signer/eth-signer.d.ts +21 -0
- package/dest/eth-signer/eth-signer.d.ts.map +1 -0
- package/dest/eth-signer/eth-signer.js +5 -0
- package/dest/eth-signer/index.d.ts +2 -0
- package/dest/eth-signer/index.d.ts.map +1 -0
- package/dest/eth-signer/index.js +1 -0
- package/dest/index.d.ts +7 -3
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +6 -2
- package/dest/l1_artifacts.d.ts +77344 -0
- package/dest/l1_artifacts.d.ts.map +1 -0
- package/dest/l1_artifacts.js +166 -0
- package/dest/l1_contract_addresses.d.ts +24 -4
- package/dest/l1_contract_addresses.d.ts.map +1 -1
- package/dest/l1_contract_addresses.js +22 -18
- package/dest/l1_reader.d.ts +2 -2
- package/dest/l1_reader.d.ts.map +1 -1
- package/dest/l1_reader.js +8 -8
- package/dest/l1_tx_utils/config.d.ts +59 -0
- package/dest/l1_tx_utils/config.d.ts.map +1 -0
- package/dest/l1_tx_utils/config.js +82 -0
- package/dest/l1_tx_utils/constants.d.ts +6 -0
- package/dest/l1_tx_utils/constants.d.ts.map +1 -0
- package/dest/l1_tx_utils/constants.js +14 -0
- package/dest/l1_tx_utils/factory.d.ts +24 -0
- package/dest/l1_tx_utils/factory.d.ts.map +1 -0
- package/dest/l1_tx_utils/factory.js +12 -0
- package/dest/l1_tx_utils/index.d.ts +10 -0
- package/dest/l1_tx_utils/index.d.ts.map +1 -0
- package/dest/l1_tx_utils/index.js +10 -0
- package/dest/l1_tx_utils/interfaces.d.ts +76 -0
- package/dest/l1_tx_utils/interfaces.d.ts.map +1 -0
- package/dest/l1_tx_utils/interfaces.js +4 -0
- package/dest/l1_tx_utils/l1_tx_utils.d.ts +94 -0
- package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/l1_tx_utils.js +610 -0
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +26 -0
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +1 -0
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +26 -0
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +94 -0
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/readonly_l1_tx_utils.js +430 -0
- package/dest/l1_tx_utils/signer.d.ts +4 -0
- package/dest/l1_tx_utils/signer.d.ts.map +1 -0
- package/dest/l1_tx_utils/signer.js +16 -0
- package/dest/l1_tx_utils/types.d.ts +67 -0
- package/dest/l1_tx_utils/types.d.ts.map +1 -0
- package/dest/l1_tx_utils/types.js +26 -0
- package/dest/l1_tx_utils/utils.d.ts +4 -0
- package/dest/l1_tx_utils/utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/utils.js +14 -0
- package/dest/l1_types.d.ts +6 -0
- package/dest/l1_types.d.ts.map +1 -0
- package/dest/l1_types.js +1 -0
- package/dest/publisher_manager.d.ts +15 -0
- package/dest/publisher_manager.d.ts.map +1 -0
- package/dest/publisher_manager.js +88 -0
- package/dest/queries.d.ts +4 -2
- package/dest/queries.d.ts.map +1 -1
- package/dest/queries.js +53 -12
- package/dest/test/chain_monitor.d.ts +73 -0
- package/dest/test/chain_monitor.d.ts.map +1 -0
- package/dest/test/chain_monitor.js +215 -0
- package/dest/test/delayed_tx_utils.d.ts +8 -3
- package/dest/test/delayed_tx_utils.d.ts.map +1 -1
- package/dest/test/delayed_tx_utils.js +13 -6
- package/dest/test/eth_cheat_codes.d.ts +217 -0
- package/dest/test/eth_cheat_codes.d.ts.map +1 -0
- package/dest/test/eth_cheat_codes.js +558 -0
- package/dest/test/eth_cheat_codes_with_state.d.ts +2 -2
- package/dest/test/eth_cheat_codes_with_state.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes_with_state.js +1 -1
- package/dest/test/index.d.ts +4 -1
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +3 -0
- package/dest/test/rollup_cheat_codes.d.ts +87 -0
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -0
- package/dest/test/rollup_cheat_codes.js +266 -0
- package/dest/test/start_anvil.d.ts +7 -1
- package/dest/test/start_anvil.d.ts.map +1 -1
- package/dest/test/start_anvil.js +16 -7
- package/dest/test/tx_delayer.d.ts +18 -7
- package/dest/test/tx_delayer.d.ts.map +1 -1
- package/dest/test/tx_delayer.js +95 -19
- package/dest/test/upgrade_utils.d.ts +6 -5
- package/dest/test/upgrade_utils.d.ts.map +1 -1
- package/dest/test/upgrade_utils.js +23 -16
- package/dest/types.d.ts +7 -8
- package/dest/types.d.ts.map +1 -1
- package/dest/types.js +3 -1
- package/dest/utils.d.ts +2 -1
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +43 -88
- package/dest/zkPassportVerifierAddress.d.ts +15 -0
- package/dest/zkPassportVerifierAddress.d.ts.map +1 -0
- package/dest/zkPassportVerifierAddress.js +11 -0
- package/package.json +28 -19
- package/src/account.ts +5 -0
- package/src/client.ts +42 -4
- package/src/config.ts +592 -31
- package/src/contracts/empire_base.ts +77 -7
- package/src/contracts/empire_slashing_proposer.ts +265 -0
- package/src/contracts/errors.ts +13 -0
- package/src/contracts/fee_asset_handler.ts +63 -0
- package/src/contracts/fee_juice.ts +29 -15
- package/src/contracts/governance.ts +80 -77
- package/src/contracts/governance_proposer.ts +66 -24
- package/src/contracts/gse.ts +88 -0
- package/src/contracts/inbox.ts +63 -0
- package/src/contracts/index.ts +8 -2
- package/src/contracts/multicall.ts +155 -0
- package/src/contracts/registry.ts +51 -26
- package/src/contracts/rollup.ts +596 -74
- package/src/contracts/slasher_contract.ts +89 -0
- package/src/contracts/tally_slashing_proposer.ts +316 -0
- package/src/contracts/utils.ts +14 -0
- package/src/deploy_l1_contracts.ts +1459 -538
- package/src/eth-signer/eth-signer.ts +25 -0
- package/src/eth-signer/index.ts +1 -0
- package/src/index.ts +6 -2
- package/src/l1_artifacts.ts +254 -0
- package/src/l1_contract_addresses.ts +32 -19
- package/src/l1_reader.ts +9 -9
- package/src/l1_tx_utils/README.md +177 -0
- package/src/l1_tx_utils/config.ts +143 -0
- package/src/l1_tx_utils/constants.ts +18 -0
- package/src/l1_tx_utils/factory.ts +64 -0
- package/src/l1_tx_utils/index.ts +12 -0
- package/src/l1_tx_utils/interfaces.ts +86 -0
- package/src/l1_tx_utils/l1_tx_utils.ts +718 -0
- package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +77 -0
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +558 -0
- package/src/l1_tx_utils/signer.ts +28 -0
- package/src/l1_tx_utils/types.ts +85 -0
- package/src/l1_tx_utils/utils.ts +16 -0
- package/src/l1_types.ts +6 -0
- package/src/publisher_manager.ts +106 -0
- package/src/queries.ts +73 -15
- package/src/test/chain_monitor.ts +243 -0
- package/src/test/delayed_tx_utils.ts +34 -6
- package/src/test/eth_cheat_codes.ts +588 -0
- package/src/test/eth_cheat_codes_with_state.ts +1 -1
- package/src/test/index.ts +3 -0
- package/src/test/rollup_cheat_codes.ts +307 -0
- package/src/test/start_anvil.ts +22 -5
- package/src/test/tx_delayer.ts +127 -26
- package/src/test/upgrade_utils.ts +30 -21
- package/src/types.ts +10 -8
- package/src/utils.ts +49 -90
- package/src/zkPassportVerifierAddress.ts +15 -0
- package/dest/contracts/forwarder.d.ts +0 -24
- package/dest/contracts/forwarder.d.ts.map +0 -1
- package/dest/contracts/forwarder.js +0 -101
- package/dest/contracts/slashing_proposer.d.ts +0 -21
- package/dest/contracts/slashing_proposer.d.ts.map +0 -1
- package/dest/contracts/slashing_proposer.js +0 -47
- package/dest/eth_cheat_codes.d.ts +0 -147
- package/dest/eth_cheat_codes.d.ts.map +0 -1
- package/dest/eth_cheat_codes.js +0 -303
- package/dest/l1_tx_utils.d.ts +0 -192
- package/dest/l1_tx_utils.d.ts.map +0 -1
- package/dest/l1_tx_utils.js +0 -641
- package/dest/l1_tx_utils_with_blobs.d.ts +0 -12
- package/dest/l1_tx_utils_with_blobs.d.ts.map +0 -1
- package/dest/l1_tx_utils_with_blobs.js +0 -64
- package/src/contracts/forwarder.ts +0 -132
- package/src/contracts/slashing_proposer.ts +0 -51
- package/src/eth_cheat_codes.ts +0 -314
- package/src/l1_tx_utils.ts +0 -847
- package/src/l1_tx_utils_with_blobs.ts +0 -86
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
import { toBigIntBE, toHex } from '@aztec/foundation/bigint-buffer';
|
|
2
|
+
import { keccak256 } from '@aztec/foundation/crypto';
|
|
3
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
|
+
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
5
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
6
|
+
import { pluralize } from '@aztec/foundation/string';
|
|
7
|
+
import type { DateProvider, TestDateProvider } from '@aztec/foundation/timer';
|
|
8
|
+
|
|
9
|
+
import { type Chain, type Hex, type Transaction, createPublicClient, fallback, hexToNumber, http } from 'viem';
|
|
10
|
+
import { foundry } from 'viem/chains';
|
|
11
|
+
|
|
12
|
+
import type { ViemPublicClient } from '../types.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A class that provides utility functions for interacting with ethereum (L1).
|
|
16
|
+
*/
|
|
17
|
+
export class EthCheatCodes {
|
|
18
|
+
public readonly publicClient: ViemPublicClient;
|
|
19
|
+
constructor(
|
|
20
|
+
/**
|
|
21
|
+
* The RPC URL to use for interacting with the chain
|
|
22
|
+
*/
|
|
23
|
+
public rpcUrls: string[],
|
|
24
|
+
/**
|
|
25
|
+
* The date provider to use for time operations
|
|
26
|
+
*/
|
|
27
|
+
public dateProvider: DateProvider | TestDateProvider,
|
|
28
|
+
/**
|
|
29
|
+
* The logger to use for the eth cheatcodes
|
|
30
|
+
*/
|
|
31
|
+
public logger = createLogger('ethereum:cheat_codes'),
|
|
32
|
+
/**
|
|
33
|
+
* The chain configuration provided to Anvil
|
|
34
|
+
*/
|
|
35
|
+
public chain: Chain = foundry,
|
|
36
|
+
) {
|
|
37
|
+
this.publicClient = createPublicClient({
|
|
38
|
+
transport: fallback(this.rpcUrls.map(url => http(url))),
|
|
39
|
+
chain: chain,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public rpcCall(method: string, params: any[]) {
|
|
44
|
+
this.logger.debug(`Calling ${method} with params: ${jsonStringify(params)} on ${this.rpcUrls.join(', ')}`);
|
|
45
|
+
return this.doRpcCall(method, params);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private async doRpcCall(method: string, params: any[]) {
|
|
49
|
+
return (await this.publicClient.transport.request({
|
|
50
|
+
method,
|
|
51
|
+
params,
|
|
52
|
+
})) as any;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get the auto mine status of the underlying chain
|
|
57
|
+
* @returns True if automine is on, false otherwise
|
|
58
|
+
*/
|
|
59
|
+
public async isAutoMining(): Promise<boolean> {
|
|
60
|
+
try {
|
|
61
|
+
const res = await this.doRpcCall('anvil_getAutomine', []);
|
|
62
|
+
return res;
|
|
63
|
+
} catch (err) {
|
|
64
|
+
this.logger.error(`Calling "anvil_getAutomine" failed with:`, err);
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get the current blocknumber
|
|
71
|
+
* @returns The current block number
|
|
72
|
+
*/
|
|
73
|
+
public async blockNumber(): Promise<number> {
|
|
74
|
+
const res = await this.doRpcCall('eth_blockNumber', []);
|
|
75
|
+
return parseInt(res, 16);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get the current chainId
|
|
80
|
+
* @returns The current chainId
|
|
81
|
+
*/
|
|
82
|
+
public async chainId(): Promise<number> {
|
|
83
|
+
const res = await this.doRpcCall('eth_chainId', []);
|
|
84
|
+
return parseInt(res, 16);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get the current timestamp
|
|
89
|
+
* @returns The current timestamp
|
|
90
|
+
*/
|
|
91
|
+
public async timestamp(): Promise<number> {
|
|
92
|
+
const res = await this.doRpcCall('eth_getBlockByNumber', ['latest', true]);
|
|
93
|
+
return parseInt(res.timestamp, 16);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Advance the chain by a number of blocks
|
|
98
|
+
* @param numberOfBlocks - The number of blocks to mine
|
|
99
|
+
*/
|
|
100
|
+
public async mine(numberOfBlocks: number | bigint = 1): Promise<void> {
|
|
101
|
+
await this.doMine(Number(numberOfBlocks));
|
|
102
|
+
this.logger.warn(`Mined ${numberOfBlocks} L1 blocks`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private async doMine(numberOfBlocks = 1): Promise<void> {
|
|
106
|
+
try {
|
|
107
|
+
await this.doRpcCall('hardhat_mine', [numberOfBlocks]);
|
|
108
|
+
} catch (err) {
|
|
109
|
+
throw new Error(`Error mining: ${err}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Mines a single block with evm_mine
|
|
115
|
+
*/
|
|
116
|
+
public async evmMine(): Promise<void> {
|
|
117
|
+
try {
|
|
118
|
+
await this.doRpcCall('evm_mine', []);
|
|
119
|
+
this.logger.warn(`Mined 1 L1 block with evm_mine`);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
throw new Error(`Error mining: ${err}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Set the balance of an account
|
|
127
|
+
* @param account - The account to set the balance for
|
|
128
|
+
* @param balance - The balance to set
|
|
129
|
+
*/
|
|
130
|
+
public async setBalance(account: EthAddress | Hex, balance: bigint): Promise<void> {
|
|
131
|
+
try {
|
|
132
|
+
await this.rpcCall('anvil_setBalance', [account.toString(), toHex(balance)]);
|
|
133
|
+
} catch (err) {
|
|
134
|
+
throw new Error(`Error setting balance for ${account}: ${err}`);
|
|
135
|
+
}
|
|
136
|
+
this.logger.warn(`Set balance for ${account} to ${balance}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public async getBalance(account: EthAddress | Hex): Promise<bigint> {
|
|
140
|
+
const res = await this.doRpcCall('eth_getBalance', [account.toString(), 'latest']);
|
|
141
|
+
return BigInt(res);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Set the interval between successive blocks (block time). This does NOT enable interval mining.
|
|
146
|
+
* @param interval - The interval to use between blocks
|
|
147
|
+
*/
|
|
148
|
+
public async setBlockInterval(interval: number): Promise<void> {
|
|
149
|
+
try {
|
|
150
|
+
await this.rpcCall('anvil_setBlockTimestampInterval', [interval]);
|
|
151
|
+
} catch (err) {
|
|
152
|
+
throw new Error(`Error setting block interval: ${err}`);
|
|
153
|
+
}
|
|
154
|
+
this.logger.warn(`Set L1 block interval to ${interval}`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Set the next block base fee per gas
|
|
159
|
+
* @param baseFee - The base fee to set
|
|
160
|
+
*/
|
|
161
|
+
public async setNextBlockBaseFeePerGas(baseFee: bigint | number): Promise<void> {
|
|
162
|
+
try {
|
|
163
|
+
await this.rpcCall('anvil_setNextBlockBaseFeePerGas', [baseFee.toString()]);
|
|
164
|
+
} catch (err) {
|
|
165
|
+
throw new Error(`Error setting next block base fee per gas: ${err}`);
|
|
166
|
+
}
|
|
167
|
+
this.logger.warn(`Set L1 next block base fee per gas to ${baseFee}`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get interval mining if set.
|
|
172
|
+
* @param seconds - The interval to use between blocks
|
|
173
|
+
*/
|
|
174
|
+
public getIntervalMining(): Promise<number | null> {
|
|
175
|
+
try {
|
|
176
|
+
return this.doRpcCall('anvil_getIntervalMining', []);
|
|
177
|
+
} catch (err) {
|
|
178
|
+
throw new Error(`Error getting interval mining: ${err}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Enable interval mining at the given interval (block time)
|
|
184
|
+
* @param seconds - The interval to use between blocks
|
|
185
|
+
*/
|
|
186
|
+
public async setIntervalMining(seconds: number, opts: { silent?: boolean } = {}): Promise<void> {
|
|
187
|
+
try {
|
|
188
|
+
await this.rpcCall('anvil_setIntervalMining', [seconds]);
|
|
189
|
+
} catch (err) {
|
|
190
|
+
throw new Error(`Error setting interval mining: ${err}`);
|
|
191
|
+
}
|
|
192
|
+
if (!opts.silent) {
|
|
193
|
+
this.logger.warn(`Set L1 interval mining to ${seconds} seconds`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Set the automine status of the underlying anvil chain
|
|
199
|
+
* @param automine - The automine status to set
|
|
200
|
+
*/
|
|
201
|
+
public async setAutomine(automine: boolean, opts: { silent?: boolean } = {}): Promise<void> {
|
|
202
|
+
try {
|
|
203
|
+
await this.rpcCall('anvil_setAutomine', [automine]);
|
|
204
|
+
} catch (err) {
|
|
205
|
+
throw new Error(`Error setting automine: ${err}`);
|
|
206
|
+
}
|
|
207
|
+
if (!opts.silent) {
|
|
208
|
+
this.logger.warn(`Set L1 automine to ${automine}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Drop a transaction from the mempool
|
|
214
|
+
* @param txHash - The transaction hash
|
|
215
|
+
*/
|
|
216
|
+
public async dropTransaction(txHash: Hex): Promise<void> {
|
|
217
|
+
try {
|
|
218
|
+
await this.rpcCall('anvil_dropTransaction', [txHash]);
|
|
219
|
+
} catch (err) {
|
|
220
|
+
throw new Error(`Error dropping transaction: ${err}`);
|
|
221
|
+
}
|
|
222
|
+
this.logger.warn(`Dropped transaction ${txHash}`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Set the next block timestamp
|
|
227
|
+
* @param timestamp - The timestamp to set the next block to
|
|
228
|
+
*/
|
|
229
|
+
public async setNextBlockTimestamp(timestamp: number | Date): Promise<void> {
|
|
230
|
+
try {
|
|
231
|
+
await this.rpcCall('evm_setNextBlockTimestamp', [
|
|
232
|
+
timestamp instanceof Date ? Math.floor(timestamp.getTime() / 1000) : timestamp,
|
|
233
|
+
]);
|
|
234
|
+
} catch (err: any) {
|
|
235
|
+
throw new Error(`Error setting next block timestamp: ${err.message}`);
|
|
236
|
+
}
|
|
237
|
+
this.logger.warn(`Set L1 next block timestamp to ${timestamp}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Set the next block timestamp and mines the block.
|
|
242
|
+
* Optionally resets interval mining so the next block is mined in `blockInterval` seconds from now.
|
|
243
|
+
* Always updates the injected date provider to follow L1 time.
|
|
244
|
+
* @param timestamp - The timestamp to set the next block to
|
|
245
|
+
*/
|
|
246
|
+
public async warp(
|
|
247
|
+
timestamp: number | bigint,
|
|
248
|
+
opts: { silent?: boolean; resetBlockInterval?: boolean } = {},
|
|
249
|
+
): Promise<void> {
|
|
250
|
+
let blockInterval: number | null = null;
|
|
251
|
+
try {
|
|
252
|
+
// Load current block interval and disable it
|
|
253
|
+
if (opts.resetBlockInterval) {
|
|
254
|
+
blockInterval = await this.getIntervalMining();
|
|
255
|
+
if (blockInterval !== null) {
|
|
256
|
+
await this.setIntervalMining(0, { silent: true });
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Set the timestamp of the next block to be mined
|
|
260
|
+
await this.rpcCall('evm_setNextBlockTimestamp', [Number(timestamp)]);
|
|
261
|
+
// And mine a block so the timestamp goes into effect now
|
|
262
|
+
await this.doMine();
|
|
263
|
+
// Update the injected date provider so it follows L1 time
|
|
264
|
+
if ('setTime' in this.dateProvider) {
|
|
265
|
+
this.dateProvider.setTime(Number(timestamp) * 1000);
|
|
266
|
+
}
|
|
267
|
+
} catch (err) {
|
|
268
|
+
throw new Error(`Error warping: ${err}`);
|
|
269
|
+
} finally {
|
|
270
|
+
// Restore interval mining so the next block is mined in `blockInterval` seconds from this one
|
|
271
|
+
if (opts.resetBlockInterval && blockInterval !== null && blockInterval > 0) {
|
|
272
|
+
await this.setIntervalMining(blockInterval, { silent: true });
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (!opts.silent) {
|
|
276
|
+
this.logger.warn(`Warped L1 timestamp to ${timestamp}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Load the value at a storage slot of a contract address on eth
|
|
282
|
+
* @param contract - The contract address
|
|
283
|
+
* @param slot - The storage slot
|
|
284
|
+
* @returns - The value at the storage slot
|
|
285
|
+
*/
|
|
286
|
+
public async load(contract: EthAddress, slot: bigint): Promise<bigint> {
|
|
287
|
+
const res = await this.rpcCall('eth_getStorageAt', [contract.toString(), toHex(slot), 'latest']);
|
|
288
|
+
return BigInt(res);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Set the value at a storage slot of a contract address on eth
|
|
293
|
+
* @param contract - The contract address
|
|
294
|
+
* @param slot - The storage slot
|
|
295
|
+
* @param value - The value to set the storage slot to
|
|
296
|
+
*/
|
|
297
|
+
public async store(
|
|
298
|
+
contract: EthAddress,
|
|
299
|
+
slot: bigint,
|
|
300
|
+
value: bigint,
|
|
301
|
+
opts: { silent?: boolean } = {},
|
|
302
|
+
): Promise<void> {
|
|
303
|
+
// for the rpc call, we need to change value to be a 32 byte hex string.
|
|
304
|
+
try {
|
|
305
|
+
await this.rpcCall('hardhat_setStorageAt', [contract.toString(), toHex(slot), toHex(value, true)]);
|
|
306
|
+
} catch (err) {
|
|
307
|
+
throw new Error(`Error setting storage for contract ${contract} at ${slot}: ${err}`);
|
|
308
|
+
}
|
|
309
|
+
if (!opts.silent) {
|
|
310
|
+
this.logger.warn(`Set L1 storage for contract ${contract} at ${slot} to ${value}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Computes the slot value for a given map and key.
|
|
316
|
+
* @param baseSlot - The base slot of the map (specified in Aztec.nr contract)
|
|
317
|
+
* @param key - The key to lookup in the map
|
|
318
|
+
* @returns The storage slot of the value in the map
|
|
319
|
+
*/
|
|
320
|
+
public keccak256(baseSlot: bigint, key: bigint): bigint {
|
|
321
|
+
// abi encode (removing the 0x) - concat key and baseSlot (both padded to 32 bytes)
|
|
322
|
+
const abiEncoded = toHex(key, true).substring(2) + toHex(baseSlot, true).substring(2);
|
|
323
|
+
return toBigIntBE(keccak256(Buffer.from(abiEncoded, 'hex')));
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Send transactions impersonating an externally owned account or contract.
|
|
328
|
+
* @param who - The address to impersonate
|
|
329
|
+
*/
|
|
330
|
+
public async startImpersonating(who: EthAddress | Hex): Promise<void> {
|
|
331
|
+
try {
|
|
332
|
+
// Since the `who` impersonated will sometimes be a contract without funds, we fund it if needed.
|
|
333
|
+
if ((await this.getBalance(who)) === 0n) {
|
|
334
|
+
await this.setBalance(who, 10n * 10n ** 18n);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
await this.rpcCall('hardhat_impersonateAccount', [who.toString()]);
|
|
338
|
+
} catch (err) {
|
|
339
|
+
throw new Error(`Error impersonating ${who}: ${err}`);
|
|
340
|
+
}
|
|
341
|
+
this.logger.warn(`Impersonating ${who}`);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Stop impersonating an account that you are currently impersonating.
|
|
346
|
+
* @param who - The address to stop impersonating
|
|
347
|
+
*/
|
|
348
|
+
public async stopImpersonating(who: EthAddress | Hex): Promise<void> {
|
|
349
|
+
try {
|
|
350
|
+
await this.rpcCall('hardhat_stopImpersonatingAccount', [who.toString()]);
|
|
351
|
+
} catch (err) {
|
|
352
|
+
throw new Error(`Error when stopping the impersonation of ${who}: ${err}`);
|
|
353
|
+
}
|
|
354
|
+
this.logger.warn(`Stopped impersonating ${who}`);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Set the bytecode for a contract
|
|
359
|
+
* @param contract - The contract address
|
|
360
|
+
* @param bytecode - The bytecode to set
|
|
361
|
+
*/
|
|
362
|
+
public async etch(contract: EthAddress, bytecode: `0x${string}`): Promise<void> {
|
|
363
|
+
try {
|
|
364
|
+
await this.rpcCall('hardhat_setCode', [contract.toString(), bytecode]);
|
|
365
|
+
} catch (err) {
|
|
366
|
+
throw new Error(`Error setting bytecode for ${contract}: ${err}`);
|
|
367
|
+
}
|
|
368
|
+
this.logger.warn(`Set bytecode for ${contract} to ${bytecode}`);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Get the bytecode for a contract
|
|
373
|
+
* @param contract - The contract address
|
|
374
|
+
* @returns The bytecode for the contract
|
|
375
|
+
*/
|
|
376
|
+
public async getBytecode(contract: EthAddress): Promise<`0x${string}`> {
|
|
377
|
+
return await this.doRpcCall('eth_getCode', [contract.toString(), 'latest']);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Get the raw transaction object for a given transaction hash
|
|
382
|
+
* @param txHash - The transaction hash
|
|
383
|
+
* @returns The raw transaction
|
|
384
|
+
*/
|
|
385
|
+
public async getRawTransaction(txHash: Hex): Promise<`0x${string}`> {
|
|
386
|
+
return await this.doRpcCall('debug_getRawTransaction', [txHash]);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Get the trace for a given transaction hash
|
|
391
|
+
* @param txHash - The transaction hash
|
|
392
|
+
* @returns The trace
|
|
393
|
+
*/
|
|
394
|
+
public async debugTraceTransaction(txHash: Hex): Promise<any> {
|
|
395
|
+
return await this.doRpcCall('debug_traceTransaction', [txHash]);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Triggers a reorg of the given depth, removing those blocks from the chain.
|
|
400
|
+
* @param depth - The depth of the reorg
|
|
401
|
+
*/
|
|
402
|
+
public reorg(depth: number): Promise<void> {
|
|
403
|
+
return this.execWithPausedAnvil(() => {
|
|
404
|
+
return this.rpcCall('anvil_rollback', [depth]);
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Causes Anvil to reorg until the given block number is the new tip
|
|
410
|
+
* @param blockNumber - The block number that's going to be the new tip
|
|
411
|
+
*/
|
|
412
|
+
public reorgTo(blockNumber: number): Promise<void> {
|
|
413
|
+
if (blockNumber <= 0) {
|
|
414
|
+
throw new Error(`Can't reorg to block before genesis: ${blockNumber}`);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return this.execWithPausedAnvil(async () => {
|
|
418
|
+
const currentTip = await this.publicClient.getBlockNumber();
|
|
419
|
+
if (currentTip < BigInt(blockNumber)) {
|
|
420
|
+
this.logger.warn(
|
|
421
|
+
`Can't call anvil_rollback, chain tip is behind target block: ${currentTip} < ${BigInt(blockNumber)}`,
|
|
422
|
+
);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const depth = Number(currentTip - BigInt(blockNumber) + 1n);
|
|
427
|
+
await this.rpcCall('anvil_rollback', [depth]);
|
|
428
|
+
this.logger.warn(`Reorged L1 chain to block number ${blockNumber} (depth ${depth})`);
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Triggers a reorg of the given depth, optionally replacing it with new blocks.
|
|
434
|
+
* The resulting block height will be the same as the original chain.
|
|
435
|
+
* @param depth - The depth of the reorg
|
|
436
|
+
* @param newBlocks - The blocks to replace the old ones with, each represented as a list of txs.
|
|
437
|
+
*/
|
|
438
|
+
public async reorgWithReplacement(
|
|
439
|
+
depth: number,
|
|
440
|
+
newBlocks: (Hex | { to: EthAddress | Hex; input?: Hex; from?: EthAddress | Hex; value?: number | bigint })[][] = [],
|
|
441
|
+
): Promise<void> {
|
|
442
|
+
this.logger.verbose(`Preparing L1 reorg with depth ${depth}`);
|
|
443
|
+
try {
|
|
444
|
+
await this.rpcCall('anvil_reorg', [
|
|
445
|
+
depth,
|
|
446
|
+
newBlocks.flatMap((txs, index) => txs.map(tx => [typeof tx === 'string' ? tx : { value: 0, ...tx }, index])),
|
|
447
|
+
]);
|
|
448
|
+
} catch (err) {
|
|
449
|
+
throw new Error(`Error reorging: ${err}`);
|
|
450
|
+
}
|
|
451
|
+
this.logger.warn(`Reorged L1 chain with depth ${depth} and ${newBlocks.length} new blocks`, { depth, newBlocks });
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
public traceTransaction(txHash: Hex): Promise<any> {
|
|
455
|
+
return this.doRpcCall('trace_transaction', [txHash]);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
public async getTxPoolStatus(): Promise<{ pending: number; queued: number }> {
|
|
459
|
+
const { pending, queued } = await this.doRpcCall('txpool_status', []);
|
|
460
|
+
return { pending: hexToNumber(pending), queued: hexToNumber(queued) };
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
public async getTxPoolContents(): Promise<TxPoolTransaction[]> {
|
|
464
|
+
const txpoolContent = await this.doRpcCall('txpool_content', []);
|
|
465
|
+
return mapTxPoolContent(txpoolContent);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Mines an empty block by temporarily removing all pending transactions from the mempool,
|
|
470
|
+
* mining a block, and then re-adding the transactions back to the pool.
|
|
471
|
+
*/
|
|
472
|
+
public async mineEmptyBlock(blockCount: number = 1): Promise<void> {
|
|
473
|
+
await this.execWithPausedAnvil(async () => {
|
|
474
|
+
// Get all pending and queued transactions from the pool
|
|
475
|
+
const txs = await this.getTxPoolContents();
|
|
476
|
+
|
|
477
|
+
this.logger.debug(`Found ${txs.length} transactions in pool`);
|
|
478
|
+
|
|
479
|
+
// Get raw transactions before dropping them
|
|
480
|
+
const rawTxs: Hex[] = [];
|
|
481
|
+
for (const tx of txs) {
|
|
482
|
+
try {
|
|
483
|
+
const rawTx = await this.doRpcCall('debug_getRawTransaction', [tx.hash]);
|
|
484
|
+
if (rawTx) {
|
|
485
|
+
rawTxs.push(rawTx);
|
|
486
|
+
this.logger.debug(`Got raw tx for ${tx.hash}`);
|
|
487
|
+
} else {
|
|
488
|
+
this.logger.warn(`No raw tx found for ${tx.hash}`);
|
|
489
|
+
}
|
|
490
|
+
} catch {
|
|
491
|
+
this.logger.warn(`Failed to get raw transaction for ${tx.hash}`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
this.logger.debug(`Retrieved ${rawTxs.length} raw transactions`);
|
|
496
|
+
|
|
497
|
+
// Drop all transactions from the mempool
|
|
498
|
+
await this.doRpcCall('anvil_dropAllTransactions', []);
|
|
499
|
+
|
|
500
|
+
// Mine an empty block
|
|
501
|
+
await this.doMine(blockCount);
|
|
502
|
+
|
|
503
|
+
// Re-add the transactions to the pool
|
|
504
|
+
for (const rawTx of rawTxs) {
|
|
505
|
+
try {
|
|
506
|
+
const txHash = await this.doRpcCall('eth_sendRawTransaction', [rawTx]);
|
|
507
|
+
this.logger.debug(`Re-added transaction ${txHash}`);
|
|
508
|
+
} catch (err) {
|
|
509
|
+
this.logger.warn(`Failed to re-add transaction: ${err}`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (rawTxs.length !== txs.length) {
|
|
514
|
+
this.logger.warn(`Failed to add all txs back: had ${txs.length} but re-added ${rawTxs.length}`);
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
this.logger.warn(`Mined ${blockCount} empty L1 ${pluralize('block', blockCount)}`);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
public async execWithPausedAnvil<T>(fn: () => Promise<T>): Promise<T> {
|
|
522
|
+
const [blockInterval, wasAutoMining] = await Promise.all([this.getIntervalMining(), this.isAutoMining()]);
|
|
523
|
+
try {
|
|
524
|
+
if (blockInterval !== null) {
|
|
525
|
+
await this.setIntervalMining(0, { silent: true });
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (wasAutoMining) {
|
|
529
|
+
await this.setAutomine(false, { silent: true });
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
return await fn();
|
|
533
|
+
} finally {
|
|
534
|
+
try {
|
|
535
|
+
// restore automine if necessary
|
|
536
|
+
if (wasAutoMining) {
|
|
537
|
+
await this.setAutomine(true, { silent: true });
|
|
538
|
+
}
|
|
539
|
+
} catch (err) {
|
|
540
|
+
this.logger.warn(`Failed to reenable automining: ${err}`);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
try {
|
|
544
|
+
// restore automine if necessary
|
|
545
|
+
if (blockInterval !== null) {
|
|
546
|
+
await this.setIntervalMining(blockInterval, { silent: true });
|
|
547
|
+
}
|
|
548
|
+
} catch (err) {
|
|
549
|
+
this.logger.warn(`Failed to reenable interval mining: ${err}`);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
public async syncDateProvider() {
|
|
555
|
+
const timestamp = await this.timestamp();
|
|
556
|
+
if ('setTime' in this.dateProvider) {
|
|
557
|
+
this.dateProvider.setTime(timestamp * 1000);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
type TxPoolState = 'pending' | 'queued';
|
|
563
|
+
|
|
564
|
+
interface TxPoolContent {
|
|
565
|
+
pending: Record<Hex, Record<string, Transaction>>;
|
|
566
|
+
queued: Record<Hex, Record<string, Transaction>>;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
export type TxPoolTransaction = Transaction & {
|
|
570
|
+
poolState: TxPoolState;
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
function mapTxPoolContent(content: TxPoolContent): TxPoolTransaction[] {
|
|
574
|
+
const result: TxPoolTransaction[] = [];
|
|
575
|
+
|
|
576
|
+
const processPool = (pool: Record<Hex, Record<string, Transaction>>, poolState: TxPoolState) => {
|
|
577
|
+
for (const txsByNonce of Object.values(pool)) {
|
|
578
|
+
for (const tx of Object.values(txsByNonce)) {
|
|
579
|
+
result.push({ ...tx, poolState });
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
processPool(content.pending, 'pending');
|
|
585
|
+
processPool(content.queued, 'queued');
|
|
586
|
+
|
|
587
|
+
return result;
|
|
588
|
+
}
|
package/src/test/index.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export * from './delayed_tx_utils.js';
|
|
2
|
+
export * from './eth_cheat_codes.js';
|
|
2
3
|
export * from './eth_cheat_codes_with_state.js';
|
|
3
4
|
export * from './start_anvil.js';
|
|
4
5
|
export * from './tx_delayer.js';
|
|
5
6
|
export * from './upgrade_utils.js';
|
|
7
|
+
export * from './chain_monitor.js';
|
|
8
|
+
export * from './rollup_cheat_codes.js';
|