@aztec-labs/ethereum 6.0.0-rc.3 → 6.0.0
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/blob_tx.d.ts +24 -0
- package/dest/blob_tx.d.ts.map +1 -0
- package/dest/blob_tx.js +94 -0
- package/dest/bn254/hash_to_point.d.ts +32 -0
- package/dest/bn254/hash_to_point.d.ts.map +1 -0
- package/dest/bn254/hash_to_point.js +80 -0
- package/dest/bn254/index.d.ts +3 -0
- package/dest/bn254/index.d.ts.map +1 -0
- package/dest/bn254/index.js +2 -0
- package/dest/bn254/proof_of_possession_gas.d.ts +29 -0
- package/dest/bn254/proof_of_possession_gas.d.ts.map +1 -0
- package/dest/bn254/proof_of_possession_gas.js +24 -0
- package/dest/client.d.ts +1 -1
- package/dest/client.d.ts.map +1 -1
- package/dest/client.js +5 -3
- package/dest/contracts/errors.d.ts +10 -3
- package/dest/contracts/errors.d.ts.map +1 -1
- package/dest/contracts/errors.js +10 -4
- package/dest/contracts/inbox.d.ts +1 -1
- package/dest/contracts/inbox.d.ts.map +1 -1
- package/dest/contracts/inbox.js +2 -0
- package/dest/contracts/log.d.ts +7 -1
- package/dest/contracts/log.d.ts.map +1 -1
- package/dest/contracts/log.js +6 -0
- package/dest/contracts/rollup.d.ts +32 -4
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +63 -7
- package/dest/deploy_aztec_l1_contracts.d.ts +16 -1
- package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_aztec_l1_contracts.js +201 -65
- package/dest/foundry_binary.d.ts +1 -1
- package/dest/foundry_binary.d.ts.map +1 -1
- package/dest/foundry_binary.js +2 -1
- package/dest/l1_tx_utils/amsterdam.d.ts +1 -1
- package/dest/l1_tx_utils/amsterdam.d.ts.map +1 -1
- package/dest/l1_tx_utils/amsterdam.js +4 -1
- package/dest/l1_tx_utils/constants.d.ts +2 -1
- package/dest/l1_tx_utils/constants.d.ts.map +1 -1
- package/dest/l1_tx_utils/constants.js +3 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts +1 -1
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts.map +1 -1
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +6 -1
- 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 +21 -1
- package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/l1_tx_utils.js +71 -5
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +8 -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 +1 -1
- package/dest/l1_tx_utils/send_cost.d.ts +15 -0
- package/dest/l1_tx_utils/send_cost.d.ts.map +1 -0
- package/dest/l1_tx_utils/send_cost.js +10 -0
- package/dest/l1_tx_utils/signer.d.ts +2 -2
- package/dest/l1_tx_utils/signer.d.ts.map +1 -1
- package/dest/l1_tx_utils/signer.js +2 -2
- package/dest/l1_tx_utils/tx_delayer.d.ts +1 -1
- package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -1
- package/dest/l1_tx_utils/tx_delayer.js +8 -26
- package/dest/publisher_manager.d.ts +127 -13
- package/dest/publisher_manager.d.ts.map +1 -1
- package/dest/publisher_manager.js +320 -79
- package/dest/test/anvil_hardfork.d.ts +42 -0
- package/dest/test/anvil_hardfork.d.ts.map +1 -0
- package/dest/test/anvil_hardfork.js +107 -0
- package/dest/test/eth_cheat_codes.d.ts +30 -5
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +283 -101
- package/dest/test/index.d.ts +3 -1
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +2 -0
- package/dest/test/l1_hardfork.d.ts +43 -0
- package/dest/test/l1_hardfork.d.ts.map +1 -0
- package/dest/test/l1_hardfork.js +51 -0
- package/dest/test/recording_rpc_server.d.ts +1 -1
- package/dest/test/recording_rpc_server.d.ts.map +1 -1
- package/dest/test/recording_rpc_server.js +1 -0
- package/dest/test/rollup_cheat_codes.d.ts +1 -1
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +7 -7
- package/dest/test/start_anvil.d.ts +14 -2
- package/dest/test/start_anvil.d.ts.map +1 -1
- package/dest/test/start_anvil.js +28 -11
- package/package.json +13 -11
- package/src/blob_tx.ts +118 -0
- package/src/bn254/hash_to_point.ts +95 -0
- package/src/bn254/index.ts +2 -0
- package/src/bn254/proof_of_possession_gas.ts +54 -0
- package/src/client.ts +6 -3
- package/src/contracts/errors.ts +12 -4
- package/src/contracts/inbox.ts +4 -0
- package/src/contracts/log.ts +12 -0
- package/src/contracts/rollup.ts +63 -6
- package/src/deploy_aztec_l1_contracts.ts +238 -63
- package/src/foundry_binary.ts +2 -1
- package/src/l1_tx_utils/amsterdam.ts +4 -1
- package/src/l1_tx_utils/constants.ts +4 -0
- package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +11 -1
- package/src/l1_tx_utils/index.ts +1 -0
- package/src/l1_tx_utils/l1_tx_utils.ts +72 -5
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +1 -1
- package/src/l1_tx_utils/send_cost.ts +21 -0
- package/src/l1_tx_utils/signer.ts +3 -2
- package/src/l1_tx_utils/tx_delayer.ts +8 -37
- package/src/publisher_manager.ts +458 -83
- package/src/test/anvil_hardfork.ts +95 -0
- package/src/test/eth_cheat_codes.ts +306 -81
- package/src/test/fixtures/sepolia_blob_tx.json +10 -0
- package/src/test/index.ts +2 -0
- package/src/test/l1_hardfork.ts +71 -0
- package/src/test/recording_rpc_server.ts +1 -0
- package/src/test/rollup_cheat_codes.ts +9 -9
- package/src/test/start_anvil.ts +41 -13
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { SlotNumber } from '@aztec-labs/foundation/branded-types';
|
|
2
2
|
import { getActiveNetworkName } from '@aztec-labs/foundation/config';
|
|
3
|
+
import { getEnv } from '@aztec-labs/foundation/config/env';
|
|
3
4
|
import { EthAddress } from '@aztec-labs/foundation/eth-address';
|
|
4
5
|
import { jsonStringify } from '@aztec-labs/foundation/json-rpc';
|
|
5
6
|
import { createLogger } from '@aztec-labs/foundation/log';
|
|
6
7
|
import { promiseWithResolvers } from '@aztec-labs/foundation/promise';
|
|
8
|
+
import { parse as parseToml } from '@iarna/toml';
|
|
7
9
|
import { bn254 } from '@noble/curves/bn254';
|
|
8
|
-
import { spawn } from 'child_process';
|
|
9
|
-
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs';
|
|
10
|
+
import { execFileSync, spawn } from 'child_process';
|
|
11
|
+
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, statSync, utimesSync, writeFileSync } from 'fs';
|
|
10
12
|
import { createRequire } from 'node:module';
|
|
11
13
|
import { tmpdir } from 'os';
|
|
12
|
-
import { basename, dirname, join, resolve } from 'path';
|
|
14
|
+
import { basename, dirname, isAbsolute, join, resolve } from 'path';
|
|
13
15
|
import readline from 'readline';
|
|
14
16
|
import { mainnet, sepolia } from 'viem/chains';
|
|
15
17
|
import { createEthereumChain, isAnvilTestChain } from './chain.js';
|
|
@@ -22,16 +24,56 @@ import { isAmsterdamBlock } from './l1_tx_utils/amsterdam.js';
|
|
|
22
24
|
const logger = createLogger('ethereum:deploy_aztec_l1_contracts');
|
|
23
25
|
const require = createRequire(import.meta.url);
|
|
24
26
|
const JSON_DEPLOY_RESULT_PREFIX = 'JSON DEPLOY RESULT:';
|
|
27
|
+
/**
|
|
28
|
+
* Extends a broadcast deadline for a `--slow` broadcast, which waits for each transaction's receipt before sending the
|
|
29
|
+
* next, so on a chain that mines on an interval it needs at least one block per transaction.
|
|
30
|
+
*/ export function getSlowBroadcastTimeout(timeout, txCount) {
|
|
31
|
+
return timeout === undefined ? undefined : timeout + txCount * SLOW_BROADCAST_ALLOWANCE_PER_TX_MS;
|
|
32
|
+
}
|
|
33
|
+
/** One mainnet slot per transaction, which also covers the slowest anvil block intervals the tests use. */ const SLOW_BROADCAST_ALLOWANCE_PER_TX_MS = 12_000;
|
|
34
|
+
/** Returns the broadcast deadline, with an optional environment override in milliseconds. */ export function getForgeBroadcastTimeout(chainId, value = getEnv().FORGE_BROADCAST_TIMEOUT_MS) {
|
|
35
|
+
if (value === undefined || value === '') {
|
|
36
|
+
return isAnvilTestChain(chainId) ? 120_000 : undefined;
|
|
37
|
+
}
|
|
38
|
+
const timeout = Number(value);
|
|
39
|
+
if (!Number.isSafeInteger(timeout) || timeout < 0 || timeout > 2_147_483_647) {
|
|
40
|
+
throw new Error('FORGE_BROADCAST_TIMEOUT_MS must be an integer between 0 and 2147483647');
|
|
41
|
+
}
|
|
42
|
+
return timeout === 0 ? undefined : timeout;
|
|
43
|
+
}
|
|
44
|
+
/** Returns Forge broadcast flags for the target chain and artifact EVM version. */ export function getForgeBroadcastArgs(l1ContractsPath, chainId) {
|
|
45
|
+
const broadcastArgs = [
|
|
46
|
+
'--broadcast',
|
|
47
|
+
'--disable-external-identification'
|
|
48
|
+
];
|
|
49
|
+
if (chainId !== sepolia.id) {
|
|
50
|
+
return broadcastArgs;
|
|
51
|
+
}
|
|
52
|
+
const foundryToml = readFileSync(join(l1ContractsPath, 'foundry.toml'), 'utf-8');
|
|
53
|
+
const profile = parseToml(foundryToml).profile;
|
|
54
|
+
const defaultProfile = typeof profile === 'object' && 'default' in profile ? profile.default : undefined;
|
|
55
|
+
const evmVersion = defaultProfile && typeof defaultProfile === 'object' && 'evm_version' in defaultProfile ? defaultProfile.evm_version : undefined;
|
|
56
|
+
if (typeof evmVersion !== 'string' || !evmVersion) {
|
|
57
|
+
throw new Error('L1 deployment artifacts do not specify an EVM version');
|
|
58
|
+
}
|
|
59
|
+
// Plan with the artifact's EVM target; --skip-simulation makes Forge estimate each send through RPC.
|
|
60
|
+
return [
|
|
61
|
+
...broadcastArgs,
|
|
62
|
+
'--hardfork',
|
|
63
|
+
evmVersion,
|
|
64
|
+
'--skip-simulation'
|
|
65
|
+
];
|
|
66
|
+
}
|
|
25
67
|
/**
|
|
26
68
|
* Runs a process and parses JSON deploy results from stdout.
|
|
27
69
|
* Lines starting with JSON_DEPLOY_RESULT_PREFIX are parsed and returned.
|
|
28
70
|
* All other stdout goes to logger.info, stderr goes to logger.warn.
|
|
29
|
-
*/ function runProcess(command, args, env, cwd) {
|
|
71
|
+
*/ export function runProcess(command, args, env, cwd, timeoutMs) {
|
|
30
72
|
const { promise, resolve, reject } = promiseWithResolvers();
|
|
31
73
|
const proc = spawn(command, args, {
|
|
32
74
|
cwd,
|
|
33
75
|
env: {
|
|
34
|
-
...
|
|
76
|
+
...getEnv(),
|
|
35
77
|
...env
|
|
36
78
|
},
|
|
37
79
|
stdio: [
|
|
@@ -43,6 +85,23 @@ const JSON_DEPLOY_RESULT_PREFIX = 'JSON DEPLOY RESULT:';
|
|
|
43
85
|
let result;
|
|
44
86
|
let parseError;
|
|
45
87
|
let settled = false;
|
|
88
|
+
let timedOut = false;
|
|
89
|
+
let killTimer;
|
|
90
|
+
const timeoutTimer = timeoutMs ? setTimeout(()=>{
|
|
91
|
+
timedOut = true;
|
|
92
|
+
proc.kill('SIGTERM');
|
|
93
|
+
killTimer = setTimeout(()=>proc.kill('SIGKILL'), 1000);
|
|
94
|
+
}, timeoutMs) : undefined;
|
|
95
|
+
const clearTimers = ()=>{
|
|
96
|
+
clearTimeout(timeoutTimer);
|
|
97
|
+
clearTimeout(killTimer);
|
|
98
|
+
};
|
|
99
|
+
const rejectProcess = (error)=>{
|
|
100
|
+
if (preparedDeployDirs.delete(cwd)) {
|
|
101
|
+
error.message += `; deployment artifacts preserved at ${cwd}. Transactions may already have been broadcast.`;
|
|
102
|
+
}
|
|
103
|
+
reject(error);
|
|
104
|
+
};
|
|
46
105
|
readline.createInterface({
|
|
47
106
|
input: proc.stdout
|
|
48
107
|
}).on('line', (line)=>{
|
|
@@ -66,17 +125,23 @@ const JSON_DEPLOY_RESULT_PREFIX = 'JSON DEPLOY RESULT:';
|
|
|
66
125
|
return;
|
|
67
126
|
}
|
|
68
127
|
settled = true;
|
|
69
|
-
|
|
128
|
+
clearTimers();
|
|
129
|
+
rejectProcess(new Error(`Failed to spawn ${command}: ${error.message}`));
|
|
70
130
|
});
|
|
71
|
-
proc.on('close', (code)=>{
|
|
131
|
+
proc.on('close', (code, signal)=>{
|
|
72
132
|
if (settled) {
|
|
73
133
|
return;
|
|
74
134
|
}
|
|
75
135
|
settled = true;
|
|
76
|
-
|
|
77
|
-
|
|
136
|
+
clearTimers();
|
|
137
|
+
if (timedOut) {
|
|
138
|
+
rejectProcess(new Error(`${command} timed out after ${timeoutMs}ms (signal ${signal ?? 'none'})`));
|
|
139
|
+
} else if (signal) {
|
|
140
|
+
rejectProcess(new Error(`${command} terminated by signal ${signal}`));
|
|
141
|
+
} else if (code !== 0) {
|
|
142
|
+
rejectProcess(new Error(`${command} exited with code ${code}`));
|
|
78
143
|
} else if (parseError) {
|
|
79
|
-
|
|
144
|
+
rejectProcess(parseError);
|
|
80
145
|
} else {
|
|
81
146
|
resolve(result);
|
|
82
147
|
}
|
|
@@ -110,6 +175,9 @@ const JSON_DEPLOY_RESULT_PREFIX = 'JSON DEPLOY RESULT:';
|
|
|
110
175
|
const verifyArgs = args.verify ? [
|
|
111
176
|
'--verify'
|
|
112
177
|
] : [];
|
|
178
|
+
const chainId = await l1Client.getChainId();
|
|
179
|
+
const broadcastArgs = getForgeBroadcastArgs(l1ContractsPath, chainId);
|
|
180
|
+
const timeout = getForgeBroadcastTimeout(chainId);
|
|
113
181
|
const latestBlock = await l1Client.request({
|
|
114
182
|
method: 'eth_getBlockByNumber',
|
|
115
183
|
params: [
|
|
@@ -117,47 +185,59 @@ const JSON_DEPLOY_RESULT_PREFIX = 'JSON DEPLOY RESULT:';
|
|
|
117
185
|
false
|
|
118
186
|
]
|
|
119
187
|
});
|
|
188
|
+
let result;
|
|
120
189
|
if (!latestBlock || !isAmsterdamBlock(latestBlock)) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
...baseArgs.slice(1),
|
|
190
|
+
result = await runProcess(forgeBin, [
|
|
191
|
+
...baseArgs,
|
|
192
|
+
...broadcastArgs,
|
|
125
193
|
...verifyArgs
|
|
126
|
-
],
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
194
|
+
], env, l1ContractsPath, timeout);
|
|
195
|
+
} else {
|
|
196
|
+
logger.info(`Dry-running ${script} to plan Glamsterdam gas limits`);
|
|
197
|
+
result = await runProcess(forgeBin, [
|
|
198
|
+
...baseArgs,
|
|
199
|
+
...broadcastArgs.filter((arg)=>arg !== '--broadcast' && arg !== '--skip-simulation'),
|
|
200
|
+
'--gas-estimate-multiplier',
|
|
201
|
+
String(GLAMSTERDAM_GAS_ESTIMATE_MULTIPLIER)
|
|
202
|
+
], env, l1ContractsPath);
|
|
203
|
+
// Leave headroom for the block gas limit drifting down before the last tx lands.
|
|
204
|
+
const maxTxGas = BigInt(latestBlock.gasLimit) * 99n / 100n;
|
|
205
|
+
const sequencePath = join(l1ContractsPath, 'broadcast', basename(script), String(chainId), 'dry-run', 'run-latest.json');
|
|
206
|
+
const sequence = JSON.parse(readFileSync(sequencePath, 'utf-8'));
|
|
207
|
+
for (const tx of sequence.transactions){
|
|
208
|
+
const gas = BigInt(tx.transaction.gas);
|
|
209
|
+
tx.transaction.gas = `0x${(gas < maxTxGas ? gas : maxTxGas).toString(16)}`;
|
|
210
|
+
}
|
|
211
|
+
// Forge 1.8 resumes from a recovery snapshot under cache/ (fingerprinted, so it cannot be edited) instead of from the
|
|
212
|
+
// broadcast file, and would send the unclamped limits, some larger than a block. Dropping the snapshot and the
|
|
213
|
+
// generation the exported files point at makes it resume from the edited broadcast file, as older forge versions did.
|
|
214
|
+
delete sequence.recovery_generation;
|
|
215
|
+
writeFileSync(sequencePath, JSON.stringify(sequence, null, 2));
|
|
216
|
+
const cacheDir = join(l1ContractsPath, 'cache', basename(script), String(chainId), 'dry-run');
|
|
217
|
+
const sensitivePath = join(cacheDir, 'run-latest.json');
|
|
218
|
+
if (existsSync(sensitivePath)) {
|
|
219
|
+
const sensitive = JSON.parse(readFileSync(sensitivePath, 'utf-8'));
|
|
220
|
+
delete sensitive.recovery_generation;
|
|
221
|
+
writeFileSync(sensitivePath, JSON.stringify(sensitive, null, 2));
|
|
222
|
+
}
|
|
223
|
+
rmSync(join(cacheDir, 'run-latest.json.recovery.json'), {
|
|
224
|
+
force: true
|
|
225
|
+
});
|
|
226
|
+
logger.info(`Broadcasting ${sequence.transactions.length} transactions from ${script}`, {
|
|
227
|
+
maxTxGas
|
|
228
|
+
});
|
|
229
|
+
// --slow waits for each receipt before sending the next tx, so the sender only needs balance for one gas limit at a
|
|
230
|
+
// time and a block-sized tx is not queued behind others from the same sender.
|
|
231
|
+
await runProcess(forgeBin, [
|
|
232
|
+
...baseArgs,
|
|
233
|
+
...broadcastArgs,
|
|
234
|
+
'--resume',
|
|
235
|
+
'--slow',
|
|
236
|
+
...verifyArgs
|
|
237
|
+
], env, l1ContractsPath, getSlowBroadcastTimeout(timeout, sequence.transactions.length));
|
|
146
238
|
}
|
|
147
|
-
writeFileSync(sequencePath, JSON.stringify(sequence, null, 2));
|
|
148
|
-
logger.info(`Broadcasting ${sequence.transactions.length} transactions from ${script}`, {
|
|
149
|
-
maxTxGas
|
|
150
|
-
});
|
|
151
|
-
// --slow waits for each receipt before sending the next tx, so the sender only needs balance for one gas limit at a
|
|
152
|
-
// time and a block-sized tx is not queued behind others from the same sender.
|
|
153
|
-
await runProcess(forgeBin, [
|
|
154
|
-
...baseArgs,
|
|
155
|
-
'--resume',
|
|
156
|
-
'--slow',
|
|
157
|
-
...verifyArgs
|
|
158
|
-
], env, l1ContractsPath);
|
|
159
239
|
// l1-contracts releases that ship this script no longer activate initial validators inside the deploy, and rely on
|
|
160
|
-
//
|
|
240
|
+
// the broadcast wrapper flushing the entry queue afterwards; we bypassed it, so flush here. Older releases flush inline.
|
|
161
241
|
if (result && hasInitialValidators(env.INITIAL_VALIDATORS) && existsSync(join(l1ContractsPath, FLUSH_ENTRY_QUEUE_SCRIPT))) {
|
|
162
242
|
logger.info(`Flushing the entry queue of rollup ${result.rollupAddress}`);
|
|
163
243
|
// flushEntryQueue needs a gas floor left before every deposit, which forge's simulated gas does not cover, so the
|
|
@@ -172,11 +252,9 @@ const JSON_DEPLOY_RESULT_PREFIX = 'JSON DEPLOY RESULT:';
|
|
|
172
252
|
privateKey,
|
|
173
253
|
'--rpc-url',
|
|
174
254
|
rpcUrl,
|
|
175
|
-
'--skip-simulation',
|
|
176
|
-
'--
|
|
177
|
-
|
|
178
|
-
'--broadcast'
|
|
179
|
-
], env, l1ContractsPath);
|
|
255
|
+
...broadcastArgs.filter((arg)=>arg !== '--skip-simulation'),
|
|
256
|
+
'--skip-simulation'
|
|
257
|
+
], env, l1ContractsPath, timeout);
|
|
180
258
|
}
|
|
181
259
|
return result;
|
|
182
260
|
}
|
|
@@ -207,36 +285,31 @@ async function maybeForgeForceProductionBuild(forgeBin, l1ContractsPath, script,
|
|
|
207
285
|
*/ export function getL1ContractsPath() {
|
|
208
286
|
return resolve(dirname(require.resolve('@aztec-foundation/l1-artifacts')), '..', 'l1-contracts');
|
|
209
287
|
}
|
|
210
|
-
|
|
211
|
-
let preparedDeployDir;
|
|
288
|
+
const preparedDeployDirs = new Set();
|
|
212
289
|
function cleanupDeployDir() {
|
|
213
|
-
|
|
290
|
+
for (const directory of preparedDeployDirs){
|
|
214
291
|
try {
|
|
215
|
-
rmSync(
|
|
292
|
+
rmSync(directory, {
|
|
216
293
|
recursive: true,
|
|
217
294
|
force: true
|
|
218
295
|
});
|
|
219
296
|
} catch {
|
|
220
297
|
// ignore cleanup errors
|
|
221
298
|
}
|
|
222
|
-
preparedDeployDir = undefined;
|
|
223
299
|
}
|
|
300
|
+
preparedDeployDirs.clear();
|
|
224
301
|
}
|
|
302
|
+
process.once('exit', cleanupDeployDir);
|
|
225
303
|
/**
|
|
226
304
|
* Prepares a temp directory for forge deployment.
|
|
227
305
|
* Copies all artifacts with preserved timestamps (required for forge cache validity).
|
|
228
306
|
* A fresh broadcast/ directory is created for deployment outputs.
|
|
229
307
|
*/ export function prepareL1ContractsForDeployment() {
|
|
230
|
-
if (preparedDeployDir && existsSync(preparedDeployDir)) {
|
|
231
|
-
logger.verbose(`Using cached deployment directory: ${preparedDeployDir}`);
|
|
232
|
-
return preparedDeployDir;
|
|
233
|
-
}
|
|
234
308
|
const basePath = getL1ContractsPath();
|
|
235
309
|
logger.verbose(`Preparing L1 contracts from: ${basePath}`);
|
|
236
310
|
const tempDir = mkdtempSync(join(tmpdir(), '.foundry-deploy-'));
|
|
237
311
|
logger.verbose(`Created temp directory for deployment: ${tempDir}`);
|
|
238
|
-
|
|
239
|
-
process.on('exit', cleanupDeployDir);
|
|
312
|
+
preparedDeployDirs.add(tempDir);
|
|
240
313
|
// Copy all dirs with preserved timestamps (required for forge cache validity)
|
|
241
314
|
const copyOpts = {
|
|
242
315
|
recursive: true,
|
|
@@ -264,10 +337,73 @@ function cleanupDeployDir() {
|
|
|
264
337
|
foundryToml = foundryToml.replace(/solc\s*=\s*"\.\/solc-[^"]+"/, `solc = "${absoluteSolcPath}"`);
|
|
265
338
|
logger.verbose(`Updated solc path in foundry.toml to: ${absoluteSolcPath}`);
|
|
266
339
|
}
|
|
340
|
+
const cachePath = join(tempDir, FORGE_CACHE_FILE);
|
|
341
|
+
const cache = JSON.parse(readFileSync(cachePath, 'utf-8'));
|
|
342
|
+
if (!cache.preprocessed) {
|
|
343
|
+
// A cache written without test preprocessing is only accepted by forge 1.8 if dynamic test linking is off. Test
|
|
344
|
+
// preprocessing does not affect the contracts and scripts we deploy.
|
|
345
|
+
foundryToml = foundryToml.replace(/^\[profile\.default\]$/m, '$&\ndynamic_test_linking = false');
|
|
346
|
+
}
|
|
267
347
|
writeFileSync(join(tempDir, 'foundry.toml'), foundryToml);
|
|
348
|
+
try {
|
|
349
|
+
patchForgeCache(tempDir, cache);
|
|
350
|
+
} catch (err) {
|
|
351
|
+
logger.warn(`Failed to patch the forge cache, forge will recompile the L1 contracts`, {
|
|
352
|
+
err
|
|
353
|
+
});
|
|
354
|
+
}
|
|
268
355
|
mkdirSync(join(tempDir, 'broadcast'));
|
|
269
356
|
return tempDir;
|
|
270
357
|
}
|
|
358
|
+
const FORGE_CACHE_FILE = join('cache', 'solidity-files-cache.json');
|
|
359
|
+
/**
|
|
360
|
+
* Makes the forge build cache shipped in l1-artifacts valid in a deploy directory, so forge uses the shipped artifacts
|
|
361
|
+
* instead of recompiling all L1 contracts, which takes ~10s per process and yields bytecode with a different metadata
|
|
362
|
+
* hash than the published one.
|
|
363
|
+
*
|
|
364
|
+
* Since 1.8, forge stores the absolute remappings of the project in its cache, and discards a cache whose remappings do
|
|
365
|
+
* not match the current project root. So a cache written in the directory where l1-artifacts was built never matches a
|
|
366
|
+
* copy of it. We regenerate the remappings for the deploy directory in the format forge writes them, which lists every
|
|
367
|
+
* context remapping twice: once with a relative context and once with an absolute one.
|
|
368
|
+
*
|
|
369
|
+
* Caches written by forge before 1.8 also lack the `viaSSACFG` and `experimental` solc settings, and need dynamic test
|
|
370
|
+
* linking disabled (see `prepareL1ContractsForDeployment`).
|
|
371
|
+
*
|
|
372
|
+
* TODO: Once l1-artifacts is built with forge 1.8.5 or later, remove the `viaSSACFG`/`experimental` backfill and the
|
|
373
|
+
* `dynamic_test_linking = false` override, as such caches already carry both settings and record `preprocessed: true`.
|
|
374
|
+
* Keep the remappings rewrite: a forge 1.8 cache stays tied to the directory where it was written.
|
|
375
|
+
*/ function patchForgeCache(deployDir, cache) {
|
|
376
|
+
const root = realpathSync(deployDir);
|
|
377
|
+
const remappings = execFileSync(resolveFoundryBinary('forge'), [
|
|
378
|
+
'remappings'
|
|
379
|
+
], {
|
|
380
|
+
cwd: root,
|
|
381
|
+
encoding: 'utf-8'
|
|
382
|
+
}).split('\n').filter((line)=>line.trim()).flatMap((line)=>{
|
|
383
|
+
const separator = line.indexOf('=');
|
|
384
|
+
const context = line.slice(0, separator).trim();
|
|
385
|
+
const target = line.slice(separator + 1).trim();
|
|
386
|
+
const absoluteTarget = isAbsolute(target) ? target : `${root}/${target}`;
|
|
387
|
+
const remapping = `${context}=${absoluteTarget}`;
|
|
388
|
+
return context.includes(':') ? [
|
|
389
|
+
remapping,
|
|
390
|
+
`${root}/${remapping}`
|
|
391
|
+
] : [
|
|
392
|
+
remapping
|
|
393
|
+
];
|
|
394
|
+
});
|
|
395
|
+
for (const profile of Object.values(cache.profiles ?? {})){
|
|
396
|
+
if (profile.solc) {
|
|
397
|
+
profile.solc.viaSSACFG ??= false;
|
|
398
|
+
profile.solc.experimental ??= false;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
cache.remappings = remappings;
|
|
402
|
+
const cachePath = join(deployDir, FORGE_CACHE_FILE);
|
|
403
|
+
const { atime, mtime } = statSync(cachePath);
|
|
404
|
+
writeFileSync(cachePath, JSON.stringify(cache));
|
|
405
|
+
utimesSync(cachePath, atime, mtime);
|
|
406
|
+
}
|
|
271
407
|
/**
|
|
272
408
|
* Computes the validator data for passing to Solidity.
|
|
273
409
|
* Only computes the G2 public key (which requires scalar multiplication on G2, not available in EVM).
|
|
@@ -344,8 +480,8 @@ function cleanupDeployDir() {
|
|
|
344
480
|
await maybeForgeForceProductionBuild(forgeBin, l1ContractsPath, FORGE_SCRIPT, chainId);
|
|
345
481
|
// Verify contracts on Etherscan when on mainnet/sepolia and ETHERSCAN_API_KEY is available.
|
|
346
482
|
const isVerifiableChain = chainId === mainnet.id || chainId === sepolia.id;
|
|
347
|
-
const shouldVerify = isVerifiableChain && !!
|
|
348
|
-
if (isVerifiableChain && !
|
|
483
|
+
const shouldVerify = isVerifiableChain && !!getEnv().ETHERSCAN_API_KEY;
|
|
484
|
+
if (isVerifiableChain && !getEnv().ETHERSCAN_API_KEY) {
|
|
349
485
|
logger.warn(`Deploying to chain ${chainId} (${chainId === mainnet.id ? 'mainnet' : 'sepolia'}) without ETHERSCAN_API_KEY. ` + `Contracts will NOT be verified on Etherscan. Set ETHERSCAN_API_KEY environment variable to enable verification.`);
|
|
350
486
|
}
|
|
351
487
|
const result = await runForgeScriptBroadcast({
|
package/dest/foundry_binary.d.ts
CHANGED
|
@@ -10,4 +10,4 @@
|
|
|
10
10
|
* Throws with a directive message if none work.
|
|
11
11
|
*/
|
|
12
12
|
export declare function resolveFoundryBinary(name: string): string;
|
|
13
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm91bmRyeV9iaW5hcnkuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9mb3VuZHJ5X2JpbmFyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFlQTs7Ozs7Ozs7OztHQVVHO0FBQ0gsd0JBQWdCLG9CQUFvQixDQUFDLElBQUksRUFBRSxNQUFNLEdBQUcsTUFBTSxDQStCekQifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foundry_binary.d.ts","sourceRoot":"","sources":["../src/foundry_binary.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"foundry_binary.d.ts","sourceRoot":"","sources":["../src/foundry_binary.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA+BzD"}
|
package/dest/foundry_binary.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getEnv } from '@aztec-labs/foundation/config/env';
|
|
1
2
|
import { spawnSync } from 'child_process';
|
|
2
3
|
import { accessSync, constants } from 'fs';
|
|
3
4
|
import { homedir } from 'os';
|
|
@@ -22,7 +23,7 @@ function isExecutable(path) {
|
|
|
22
23
|
* Throws with a directive message if none work.
|
|
23
24
|
*/ export function resolveFoundryBinary(name) {
|
|
24
25
|
const envVar = `${name.toUpperCase()}_BIN`;
|
|
25
|
-
const envBin =
|
|
26
|
+
const envBin = getEnv()[envVar];
|
|
26
27
|
if (envBin) {
|
|
27
28
|
if (!isExecutable(envBin)) {
|
|
28
29
|
throw new Error(`$${envVar} is set to ${envBin}, which does not exist or is not executable.`);
|
|
@@ -39,4 +39,4 @@ export declare class AmsterdamForkDetector {
|
|
|
39
39
|
}): Promise<boolean>;
|
|
40
40
|
private now;
|
|
41
41
|
}
|
|
42
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
42
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW1zdGVyZGFtLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbDFfdHhfdXRpbHMvYW1zdGVyZGFtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLE1BQU0sRUFBZ0IsTUFBTSw0QkFBNEIsQ0FBQztBQUN2RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFJNUQ7Ozs7R0FJRztBQUNILHdCQUFnQixnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsTUFBTSxHQUFHLElBQUksR0FBRyxTQUFTLEdBQUcsT0FBTyxDQUUxRTtBQUVELHlHQUF5RztBQUN6Ryx3QkFBZ0Isa0JBQWtCLENBQUMsV0FBVyxFQUFFLE9BQU8sR0FBRyxNQUFNLENBRS9EO0FBRUQscUZBQXFGO0FBQ3JGLE1BQU0sTUFBTSxtQkFBbUIsR0FBRztJQUFFLFFBQVEsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUE7Q0FBRSxDQUFDO0FBRWxFOzs7OztHQUtHO0FBQ0gscUJBQWEscUJBQXFCO0lBSzlCLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVztJQUM1QixPQUFPLENBQUMsUUFBUSxDQUFDLElBQUk7SUFMdkIsT0FBTyxDQUFDLE1BQU0sQ0FBUztJQUN2QixPQUFPLENBQUMsZ0JBQWdCLENBQXFCO0lBRTdDLFlBQ21CLFdBQVcsRUFBRSxtQkFBbUIsRUFDaEMsSUFBSSxHQUFFO1FBQUUsYUFBYSxDQUFDLEVBQUUsTUFBTSxDQUFDO1FBQUMsWUFBWSxDQUFDLEVBQUUsWUFBWSxDQUFDO1FBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxDQUFBO0tBQU8sRUFDL0Y7SUFFSixpREFBaUQ7SUFDMUMsT0FBTyxDQUFDLEtBQUssRUFBRSxNQUFNLEdBQUcsSUFBSSxHQUFHLFNBQVMsR0FBRyxJQUFJLENBUXJEO0lBRUQ7OztPQUdHO0lBQ1UsUUFBUSxDQUFDLElBQUksR0FBRTtRQUFFLG1CQUFtQixDQUFDLEVBQUUsT0FBTyxDQUFBO0tBQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBbUJwRjtJQUVELE9BQU8sQ0FBQyxHQUFHO0NBR1oifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"amsterdam.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/amsterdam.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAI5D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE1E;AAED,yGAAyG;AACzG,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,OAAO,GAAG,MAAM,CAE/D;AAED,qFAAqF;AACrF,MAAM,MAAM,mBAAmB,GAAG;IAAE,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC;AAElE;;;;;GAKG;AACH,qBAAa,qBAAqB;IAK9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,IAAI;IALvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAAqB;IAE7C,YACmB,WAAW,EAAE,mBAAmB,EAChC,IAAI,GAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,YAAY,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAO,EAC/F;IAEJ,iDAAiD;IAC1C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"amsterdam.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/amsterdam.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAI5D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE1E;AAED,yGAAyG;AACzG,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,OAAO,GAAG,MAAM,CAE/D;AAED,qFAAqF;AACrF,MAAM,MAAM,mBAAmB,GAAG;IAAE,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC;AAElE;;;;;GAKG;AACH,qBAAa,qBAAqB;IAK9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,IAAI;IALvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAAqB;IAE7C,YACmB,WAAW,EAAE,mBAAmB,EAChC,IAAI,GAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,YAAY,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAO,EAC/F;IAEJ,iDAAiD;IAC1C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAQrD;IAED;;;OAGG;IACU,QAAQ,CAAC,IAAI,GAAE;QAAE,mBAAmB,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAmBpF;IAED,OAAO,CAAC,GAAG;CAGZ"}
|
|
@@ -27,8 +27,11 @@ import { AMSTERDAM_MAX_L1_TX_LIMIT, MAX_L1_TX_LIMIT } from './constants.js';
|
|
|
27
27
|
this.active = false;
|
|
28
28
|
}
|
|
29
29
|
/** Records a freshly fetched latest L1 block. */ observe(block) {
|
|
30
|
-
if (isAmsterdamBlock(block)) {
|
|
30
|
+
if (!this.active && isAmsterdamBlock(block)) {
|
|
31
31
|
this.active = true;
|
|
32
|
+
(this.opts.log ?? createLogger('ethereum:amsterdam-fork-detector')).debug('Amsterdam fork detected on L1', {
|
|
33
|
+
blockNumber: block && 'number' in block ? block.number : undefined
|
|
34
|
+
});
|
|
32
35
|
}
|
|
33
36
|
this.lastObservedAtMs = this.now();
|
|
34
37
|
}
|
|
@@ -2,6 +2,7 @@ export declare const WEI_CONST = 1000000000n;
|
|
|
2
2
|
export declare const MAX_L1_TX_LIMIT = 16777216n;
|
|
3
3
|
export declare const AMSTERDAM_MAX_L1_TX_LIMIT = 50000000n;
|
|
4
4
|
export declare const AMSTERDAM_MAX_SLASHED_VALIDATORS_PER_ROUND = 35;
|
|
5
|
+
export declare const INSUFFICIENT_FUNDS_BACKOFF_MS: number;
|
|
5
6
|
export declare const MIN_REPLACEMENT_BUMP_PERCENTAGE = 10;
|
|
6
7
|
export declare const MIN_BLOB_REPLACEMENT_BUMP_PERCENTAGE = 100;
|
|
7
8
|
export declare const BLOCK_TIME_MS = 12000;
|
|
@@ -11,4 +12,4 @@ export declare const BLOB_CAPACITY_SCHEDULE: {
|
|
|
11
12
|
target: number;
|
|
12
13
|
max: number;
|
|
13
14
|
}[];
|
|
14
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbDFfdHhfdXRpbHMvY29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBLGVBQU8sTUFBTSxTQUFTLGNBQWlCLENBQUM7QUFJeEMsZUFBTyxNQUFNLGVBQWUsWUFBYyxDQUFDO0FBVTNDLGVBQU8sTUFBTSx5QkFBeUIsWUFBYyxDQUFDO0FBQ3JELGVBQU8sTUFBTSwwQ0FBMEMsS0FBSyxDQUFDO0FBSTdELGVBQU8sTUFBTSw2QkFBNkIsUUFBZ0IsQ0FBQztBQUkzRCxlQUFPLE1BQU0sK0JBQStCLEtBQUssQ0FBQztBQUlsRCxlQUFPLE1BQU0sb0NBQW9DLE1BQU0sQ0FBQztBQUd4RCxlQUFPLE1BQU0sYUFBYSxRQUFTLENBQUM7QUFHcEMsZUFBTyxNQUFNLFlBQVksVUFBVSxDQUFDO0FBR3BDLGVBQU8sTUFBTSxzQkFBc0I7Ozs7R0FLbEMsQ0FBQyJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/constants.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,cAAiB,CAAC;AAIxC,eAAO,MAAM,eAAe,YAAc,CAAC;AAU3C,eAAO,MAAM,yBAAyB,YAAc,CAAC;AACrD,eAAO,MAAM,0CAA0C,KAAK,CAAC;AAI7D,eAAO,MAAM,+BAA+B,KAAK,CAAC;AAIlD,eAAO,MAAM,oCAAoC,MAAM,CAAC;AAGxD,eAAO,MAAM,aAAa,QAAS,CAAC;AAGpC,eAAO,MAAM,YAAY,UAAU,CAAC;AAGpC,eAAO,MAAM,sBAAsB;;;;GAKlC,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/constants.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,cAAiB,CAAC;AAIxC,eAAO,MAAM,eAAe,YAAc,CAAC;AAU3C,eAAO,MAAM,yBAAyB,YAAc,CAAC;AACrD,eAAO,MAAM,0CAA0C,KAAK,CAAC;AAI7D,eAAO,MAAM,6BAA6B,QAAgB,CAAC;AAI3D,eAAO,MAAM,+BAA+B,KAAK,CAAC;AAIlD,eAAO,MAAM,oCAAoC,MAAM,CAAC;AAGxD,eAAO,MAAM,aAAa,QAAS,CAAC;AAGpC,eAAO,MAAM,YAAY,UAAU,CAAC;AAGpC,eAAO,MAAM,sBAAsB;;;;GAKlC,CAAC"}
|
|
@@ -15,6 +15,9 @@ export const MAX_L1_TX_LIMIT = 16_777_216n;
|
|
|
15
15
|
// raised once RPCs allow more than 50M.
|
|
16
16
|
export const AMSTERDAM_MAX_L1_TX_LIMIT = 50_000_000n;
|
|
17
17
|
export const AMSTERDAM_MAX_SLASHED_VALIDATORS_PER_ROUND = 35;
|
|
18
|
+
// How long a publisher whose send was rejected for insufficient funds is skipped by publisher selection if its balance
|
|
19
|
+
// does not increase in the meantime.
|
|
20
|
+
export const INSUFFICIENT_FUNDS_BACKOFF_MS = 5 * 60 * 1000;
|
|
18
21
|
// setting a minimum bump percentage to 10% due to geth's implementation
|
|
19
22
|
// https://github.com/ethereum/go-ethereum/blob/e3d61e6db028c412f74bc4d4c7e117a9e29d0de0/core/txpool/legacypool/list.go#L298
|
|
20
23
|
export const MIN_REPLACEMENT_BUMP_PERCENTAGE = 10;
|
|
@@ -5,4 +5,4 @@ import { type PriorityFeeStrategy } from './types.js';
|
|
|
5
5
|
* Falls back to network estimate if data is unavailable.
|
|
6
6
|
*/
|
|
7
7
|
export declare const P75AllTxsPriorityFeeStrategy: PriorityFeeStrategy;
|
|
8
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicDc1X2NvbXBldGl0aXZlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbDFfdHhfdXRpbHMvZmVlLXN0cmF0ZWdpZXMvcDc1X2NvbXBldGl0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU1BLE9BQU8sRUFFTCxLQUFLLG1CQUFtQixFQUd6QixNQUFNLFlBQVksQ0FBQztBQUVwQjs7OztHQUlHO0FBQ0gsZUFBTyxNQUFNLDRCQUE0QixFQUFFLG1CQXlKMUMsQ0FBQyJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"p75_competitive.d.ts","sourceRoot":"","sources":["../../../src/l1_tx_utils/fee-strategies/p75_competitive.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,mBAAmB,EAGzB,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,
|
|
1
|
+
{"version":3,"file":"p75_competitive.d.ts","sourceRoot":"","sources":["../../../src/l1_tx_utils/fee-strategies/p75_competitive.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,mBAAmB,EAGzB,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,mBAyJ1C,CAAC"}
|
|
@@ -18,7 +18,7 @@ import { HISTORICAL_BLOCK_COUNT } from './types.js';
|
|
|
18
18
|
blockTag: 'latest'
|
|
19
19
|
}),
|
|
20
20
|
isBlobTx ? client.getBlobBaseFee() : Promise.resolve(undefined),
|
|
21
|
-
client.estimateMaxPriorityFeePerGas()
|
|
21
|
+
client.estimateMaxPriorityFeePerGas(),
|
|
22
22
|
client.getBlock({
|
|
23
23
|
blockTag: 'pending',
|
|
24
24
|
includeTransactions: true
|
|
@@ -110,6 +110,11 @@ import { HISTORICAL_BLOCK_COUNT } from './types.js';
|
|
|
110
110
|
});
|
|
111
111
|
competitiveFee = maxReasonableFee;
|
|
112
112
|
debugInfo.cappedToGwei = formatGwei(maxReasonableFee);
|
|
113
|
+
} else if (networkEstimateResult.status === 'fulfilled' && networkEstimate === 0n && competitiveFee > 0n) {
|
|
114
|
+
logger?.warn('L1 RPC returned a zero priority fee estimate, disabling the competitive fee sanity cap. ' + 'You may be overpaying L1 transaction fees. Review your L1 RPC gas price oracle settings; ' + 'if using Reth, consider setting --gpo.ignoreprice=2 to exclude zero- and one-wei tips.', {
|
|
115
|
+
networkEstimateGwei: formatGwei(networkEstimate),
|
|
116
|
+
competitiveFeeGwei: formatGwei(competitiveFee)
|
|
117
|
+
});
|
|
113
118
|
}
|
|
114
119
|
// Log final decision
|
|
115
120
|
if (competitiveFee > networkEstimate) {
|
|
@@ -7,8 +7,9 @@ export * from './interfaces.js';
|
|
|
7
7
|
export * from './l1_fee_analyzer.js';
|
|
8
8
|
export * from './l1_tx_utils.js';
|
|
9
9
|
export * from './readonly_l1_tx_utils.js';
|
|
10
|
+
export * from './send_cost.js';
|
|
10
11
|
export * from './signer.js';
|
|
11
12
|
export * from './types.js';
|
|
12
13
|
export * from './tx_delayer.js';
|
|
13
14
|
export * from './utils.js';
|
|
14
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sMV90eF91dGlscy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGdCQUFnQixDQUFDO0FBQy9CLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYywyQkFBMkIsQ0FBQztBQUMxQyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLDJCQUEyQixDQUFDO0FBQzFDLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxjQUFjLFlBQVksQ0FBQyJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC"}
|
|
@@ -7,6 +7,7 @@ export * from './interfaces.js';
|
|
|
7
7
|
export * from './l1_fee_analyzer.js';
|
|
8
8
|
export * from './l1_tx_utils.js';
|
|
9
9
|
export * from './readonly_l1_tx_utils.js';
|
|
10
|
+
export * from './send_cost.js';
|
|
10
11
|
export * from './signer.js';
|
|
11
12
|
export * from './types.js';
|
|
12
13
|
export * from './tx_delayer.js';
|
|
@@ -24,6 +24,11 @@ export declare class L1TxUtils extends ReadOnlyL1TxUtils {
|
|
|
24
24
|
delayer?: Delayer;
|
|
25
25
|
/** KZG instance for blob operations. */
|
|
26
26
|
protected kzg?: BlobKzgInstance;
|
|
27
|
+
/**
|
|
28
|
+
* Sender balance and time when a send was last rejected for insufficient funds. Cleared once the balance rises above
|
|
29
|
+
* the recorded one or the backoff expires.
|
|
30
|
+
*/
|
|
31
|
+
private insufficientFunds;
|
|
27
32
|
constructor(client: ViemClient, address: EthAddress, signer: SigningCallback, logger?: Logger, dateProvider?: DateProvider, config?: Partial<L1TxUtilsConfig>, debugMaxGasLimit?: boolean, store?: IL1TxStore | undefined, metrics?: IL1TxMetrics | undefined, kzg?: BlobKzgInstance, delayer?: Delayer);
|
|
28
33
|
get state(): TxUtilsState;
|
|
29
34
|
get lastMinedAtBlockNumber(): bigint | undefined;
|
|
@@ -37,6 +42,20 @@ export declare class L1TxUtils extends ReadOnlyL1TxUtils {
|
|
|
37
42
|
resetNonce(): void;
|
|
38
43
|
getSenderAddress(): EthAddress;
|
|
39
44
|
getSenderBalance(): Promise<bigint>;
|
|
45
|
+
/** Returns the sender balance recorded when a send was last rejected for insufficient funds, if any. */
|
|
46
|
+
getInsufficientFundsAtBalance(): bigint | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Returns whether this sender should be skipped because a previous send was rejected for insufficient funds and its
|
|
49
|
+
* balance has not increased since. Clears the mark once the given current balance is above the recorded one, or once
|
|
50
|
+
* INSUFFICIENT_FUNDS_BACKOFF_MS have elapsed since the rejection: a rejection can come from a send whose gas limit was
|
|
51
|
+
* far above what later sends need, so a balance that did not move is not proof the publisher cannot afford them.
|
|
52
|
+
*/
|
|
53
|
+
isBackedOffForInsufficientFunds(currentBalance: bigint): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Same check as {@link isBackedOffForInsufficientFunds}, but without clearing a lifted backoff or logging, so it can be
|
|
56
|
+
* used for reporting without affecting publisher selection.
|
|
57
|
+
*/
|
|
58
|
+
hasActiveInsufficientFundsBackoff(currentBalance: bigint): boolean;
|
|
40
59
|
/**
|
|
41
60
|
* Rehydrates transaction states from the store and resumes monitoring for pending transactions.
|
|
42
61
|
* This should be called on startup to restore state and resume monitoring of any in-flight transactions.
|
|
@@ -55,6 +74,7 @@ export declare class L1TxUtils extends ReadOnlyL1TxUtils {
|
|
|
55
74
|
txHash: Hex;
|
|
56
75
|
state: L1TxState;
|
|
57
76
|
}>;
|
|
77
|
+
private recordInsufficientFunds;
|
|
58
78
|
private tryGetTxReceipt;
|
|
59
79
|
/**
|
|
60
80
|
* Returns whether a given tx should be considered as timed out and no longer monitored.
|
|
@@ -107,4 +127,4 @@ export declare class L1TxUtils extends ReadOnlyL1TxUtils {
|
|
|
107
127
|
ethereumSlotDuration: bigint | number;
|
|
108
128
|
}, bindings: LoggerBindings): Delayer;
|
|
109
129
|
}
|
|
110
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
130
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibDFfdHhfdXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sMV90eF91dGlscy9sMV90eF91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUlsRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDaEUsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFFLEtBQUssY0FBYyxFQUFnQixNQUFNLDRCQUE0QixDQUFDO0FBSTVGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUc1RCxPQUFPLEVBQ0wsS0FBSyxHQUFHLEVBQ1IsS0FBSyxjQUFjLEVBQ25CLEtBQUssR0FBRyxFQUVSLEtBQUssZ0NBQWdDLEVBQ3JDLEtBQUssYUFBYSxFQUNsQixLQUFLLGtCQUFrQixFQUd4QixNQUFNLE1BQU0sQ0FBQztBQUdkLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUU5QyxPQUFPLEVBQUUsS0FBSyxlQUFlLEVBQTJCLE1BQU0sYUFBYSxDQUFDO0FBRTVFLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsS0FBSyxrQkFBa0IsRUFBRSxpQkFBaUIsRUFBK0IsTUFBTSwyQkFBMkIsQ0FBQztBQUNwSCxPQUFPLEVBQUUsT0FBTyxFQUF3QyxNQUFNLGlCQUFpQixDQUFDO0FBQ2hGLE9BQU8sRUFFTCxLQUFLLFlBQVksRUFDakIsS0FBSyxVQUFVLEVBQ2YsS0FBSyxXQUFXLEVBQ2hCLEtBQUssU0FBUyxFQUVkLEtBQUssZUFBZSxFQUVwQixZQUFZLEVBRWIsTUFBTSxZQUFZLENBQUM7QUFVcEIscUJBQWEsU0FBVSxTQUFRLGlCQUFpQjtJQWlCNUIsTUFBTSxFQUFFLFVBQVU7SUFDM0IsT0FBTyxFQUFFLFVB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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"l1_tx_utils.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/l1_tx_utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAIlE,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAChE,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,cAAc,EAAgB,MAAM,4BAA4B,CAAC;AAI5F,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"l1_tx_utils.d.ts","sourceRoot":"","sources":["../../src/l1_tx_utils/l1_tx_utils.ts"],"names":[],"mappings":"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"}
|