@aztec/ethereum 3.0.0-nightly.20251209 → 3.0.0-nightly.20251211
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/contracts/tally_slashing_proposer.d.ts +3 -2
- package/dest/contracts/tally_slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/tally_slashing_proposer.js +1 -1
- package/dest/deploy_l1_contracts.d.ts +7 -7
- package/dest/deploy_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_l1_contracts.js +1 -1
- package/dest/forwarder_proxy.d.ts +32 -0
- package/dest/forwarder_proxy.d.ts.map +1 -0
- package/dest/forwarder_proxy.js +93 -0
- package/dest/l1_reader.d.ts +3 -1
- package/dest/l1_reader.d.ts.map +1 -1
- package/dest/l1_reader.js +6 -0
- package/dest/l1_tx_utils/config.d.ts +3 -3
- package/dest/l1_tx_utils/config.d.ts.map +1 -1
- package/dest/l1_tx_utils/config.js +17 -3
- package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +41 -0
- package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +48 -0
- package/dest/l1_tx_utils/index-blobs.d.ts +3 -0
- package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -0
- package/dest/l1_tx_utils/index-blobs.js +2 -0
- package/dest/l1_tx_utils/interfaces.d.ts +2 -2
- package/dest/l1_tx_utils/interfaces.d.ts.map +1 -1
- package/dest/l1_tx_utils/l1_tx_utils.d.ts +1 -1
- package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils/l1_tx_utils.js +17 -4
- 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 +38 -37
- package/dest/test/chain_monitor.d.ts +2 -2
- package/dest/test/chain_monitor.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +1 -1
- package/dest/test/rollup_cheat_codes.d.ts +2 -2
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +1 -1
- package/dest/test/tx_delayer.d.ts +1 -1
- package/dest/test/tx_delayer.d.ts.map +1 -1
- package/dest/test/tx_delayer.js +3 -2
- package/dest/types.d.ts +57 -2
- package/dest/types.d.ts.map +1 -1
- package/dest/utils.d.ts +2 -2
- package/dest/utils.d.ts.map +1 -1
- package/package.json +22 -9
- package/src/contracts/tally_slashing_proposer.ts +3 -1
- package/src/deploy_l1_contracts.ts +2 -2
- package/src/forwarder_proxy.ts +108 -0
- package/src/l1_reader.ts +8 -0
- package/src/l1_tx_utils/config.ts +24 -6
- package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +119 -0
- package/src/l1_tx_utils/index-blobs.ts +2 -0
- package/src/l1_tx_utils/interfaces.ts +1 -1
- package/src/l1_tx_utils/l1_tx_utils.ts +24 -4
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +48 -49
- package/src/test/chain_monitor.ts +2 -1
- package/src/test/eth_cheat_codes.ts +1 -1
- package/src/test/rollup_cheat_codes.ts +2 -1
- package/src/test/tx_delayer.ts +4 -2
- package/src/types.ts +62 -0
- package/src/utils.ts +1 -1
- package/dest/index.d.ts +0 -18
- package/dest/index.d.ts.map +0 -1
- package/dest/index.js +0 -17
- package/src/index.ts +0 -17
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
+
import type { Logger } from '@aztec/foundation/log';
|
|
4
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
5
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
6
|
+
|
|
7
|
+
import { type Hex, extractChain } from 'viem';
|
|
8
|
+
import { anvil, mainnet, sepolia } from 'viem/chains';
|
|
9
|
+
|
|
10
|
+
import { L1Deployer } from './deploy_l1_contracts.js';
|
|
11
|
+
import type { ExtendedViemWalletClient } from './types.js';
|
|
12
|
+
|
|
13
|
+
export const FORWARDER_SOLIDITY_SOURCE = `
|
|
14
|
+
contract ForwarderProxy {
|
|
15
|
+
function forward(address target, bytes calldata data) external payable returns (bytes memory) {
|
|
16
|
+
(bool success, bytes memory result) = target.call{value: msg.value}(data);
|
|
17
|
+
require(success, "call failed");
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
}`;
|
|
21
|
+
|
|
22
|
+
export const FORWARDER_ABI = [
|
|
23
|
+
{
|
|
24
|
+
inputs: [
|
|
25
|
+
{
|
|
26
|
+
internalType: 'address',
|
|
27
|
+
name: 'target',
|
|
28
|
+
type: 'address',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
internalType: 'bytes',
|
|
32
|
+
name: 'data',
|
|
33
|
+
type: 'bytes',
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
name: 'forward',
|
|
37
|
+
outputs: [
|
|
38
|
+
{
|
|
39
|
+
internalType: 'bytes',
|
|
40
|
+
name: '',
|
|
41
|
+
type: 'bytes',
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
stateMutability: 'payable',
|
|
45
|
+
type: 'function',
|
|
46
|
+
},
|
|
47
|
+
] as const;
|
|
48
|
+
|
|
49
|
+
export const FORWARDER_BYTECODE =
|
|
50
|
+
'0x6080604052348015600e575f5ffd5b506103bf8061001c5f395ff3fe60806040526004361061001d575f3560e01c80636fadcf7214610021575b5f5ffd5b61003b600480360381019061003691906101d0565b610051565b604051610048919061029d565b60405180910390f35b60605f5f8573ffffffffffffffffffffffffffffffffffffffff1634868660405161007d9291906102f9565b5f6040518083038185875af1925050503d805f81146100b7576040519150601f19603f3d011682016040523d82523d5f602084013e6100bc565b606091505b509150915081610101576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100f89061036b565b60405180910390fd5b80925050509392505050565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61013e82610115565b9050919050565b61014e81610134565b8114610158575f5ffd5b50565b5f8135905061016981610145565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126101905761018f61016f565b5b8235905067ffffffffffffffff8111156101ad576101ac610173565b5b6020830191508360018202830111156101c9576101c8610177565b5b9250929050565b5f5f5f604084860312156101e7576101e661010d565b5b5f6101f48682870161015b565b935050602084013567ffffffffffffffff81111561021557610214610111565b5b6102218682870161017b565b92509250509250925092565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61026f8261022d565b6102798185610237565b9350610289818560208601610247565b61029281610255565b840191505092915050565b5f6020820190508181035f8301526102b58184610265565b905092915050565b5f81905092915050565b828183375f83830152505050565b5f6102e083856102bd565b93506102ed8385846102c7565b82840190509392505050565b5f6103058284866102d5565b91508190509392505050565b5f82825260208201905092915050565b7f63616c6c206661696c65640000000000000000000000000000000000000000005f82015250565b5f610355600b83610311565b915061036082610321565b602082019050919050565b5f6020820190508181035f83015261038281610349565b905091905056fea26469706673582212209a1c8cf638cf1569450a731ef9457b862f9e153b0a46e5555429bcf4dffd999564736f6c634300081e0033' as Hex;
|
|
51
|
+
|
|
52
|
+
const FORWARDER_ARTIFACT = {
|
|
53
|
+
name: 'Forwarder',
|
|
54
|
+
contractAbi: FORWARDER_ABI,
|
|
55
|
+
contractBytecode: FORWARDER_BYTECODE,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Deploys the forwarder proxy contract to L1.
|
|
60
|
+
* @param client - The L1 client to use for deployment
|
|
61
|
+
* @param logger - Optional logger
|
|
62
|
+
* @returns The deployed forwarder contract address
|
|
63
|
+
*/
|
|
64
|
+
export async function deployForwarderProxy(client: ExtendedViemWalletClient, logger?: Logger): Promise<EthAddress> {
|
|
65
|
+
const log = logger ?? createLogger('ethereum:forwarder');
|
|
66
|
+
const nonce = await client.getTransactionCount({ address: client.account.address });
|
|
67
|
+
const deployer = new L1Deployer(client, nonce, new DateProvider(), false, log, undefined, false);
|
|
68
|
+
|
|
69
|
+
log.info('Deploying forwarder proxy contract');
|
|
70
|
+
const deployment = await deployer.deploy(FORWARDER_ARTIFACT, []);
|
|
71
|
+
log.info(`Forwarder proxy deployed at ${deployment.address.toString()}`);
|
|
72
|
+
|
|
73
|
+
return deployment.address;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Main function for deploying the forwarder proxy from command line.
|
|
78
|
+
* Usage: node forwarder_proxy.js <private_key> <rpc_url>
|
|
79
|
+
*/
|
|
80
|
+
async function main() {
|
|
81
|
+
const args = process.argv.slice(2);
|
|
82
|
+
if (args.length < 3) {
|
|
83
|
+
console.error('Usage: node forwarder_proxy.js <private_key> <rpc_url> <chain_id>');
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const [privateKey, rpcUrl, chainId] = args;
|
|
88
|
+
|
|
89
|
+
// Dynamic import to avoid pulling in dependencies at module load time
|
|
90
|
+
const { createExtendedL1Client } = await import('./client.js');
|
|
91
|
+
|
|
92
|
+
const client = createExtendedL1Client(
|
|
93
|
+
[rpcUrl],
|
|
94
|
+
privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`,
|
|
95
|
+
extractChain({ chains: [mainnet, sepolia, anvil], id: parseInt(chainId) as any }),
|
|
96
|
+
);
|
|
97
|
+
const address = await deployForwarderProxy(client);
|
|
98
|
+
|
|
99
|
+
console.log(`Forwarder proxy deployed at: ${address.toString()}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Only run main if this is the entry point
|
|
103
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
104
|
+
main().catch(err => {
|
|
105
|
+
console.error('Failed to deploy forwarder proxy:', err);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
});
|
|
108
|
+
}
|
package/src/l1_reader.ts
CHANGED
|
@@ -6,6 +6,8 @@ import { type L1ContractAddresses, l1ContractAddressesMapping } from './l1_contr
|
|
|
6
6
|
export interface L1ReaderConfig {
|
|
7
7
|
/** List of URLs of Ethereum RPC nodes that services will connect to (comma separated). */
|
|
8
8
|
l1RpcUrls: string[];
|
|
9
|
+
/** The RPC Url of the ethereum debug host for trace and debug methods. */
|
|
10
|
+
l1DebugRpcUrls: string[];
|
|
9
11
|
/** The chain ID of the ethereum host. */
|
|
10
12
|
l1ChainId: number;
|
|
11
13
|
/** The deployed l1 contract addresses */
|
|
@@ -30,6 +32,12 @@ export const l1ReaderConfigMappings: ConfigMappingsType<L1ReaderConfig> = {
|
|
|
30
32
|
parseEnv: (val: string) => val.split(',').map(url => url.trim()),
|
|
31
33
|
defaultValue: [],
|
|
32
34
|
},
|
|
35
|
+
l1DebugRpcUrls: {
|
|
36
|
+
env: 'ETHEREUM_DEBUG_HOSTS',
|
|
37
|
+
description: 'The RPC Url of the ethereum debug host for trace and debug methods.',
|
|
38
|
+
parseEnv: (val: string) => val.split(',').map(url => url.trim()),
|
|
39
|
+
defaultValue: [],
|
|
40
|
+
},
|
|
33
41
|
viemPollingIntervalMS: {
|
|
34
42
|
env: 'L1_READER_VIEM_POLLING_INTERVAL_MS',
|
|
35
43
|
description: 'The polling interval viem uses in ms',
|
|
@@ -29,9 +29,9 @@ export interface L1TxUtilsConfig {
|
|
|
29
29
|
*/
|
|
30
30
|
priorityFeeRetryBumpPercentage?: number;
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
32
|
+
* Minimum priority fee per gas in Gwei. Acts as a floor for the computed priority fee.
|
|
33
33
|
*/
|
|
34
|
-
|
|
34
|
+
minimumPriorityFeePerGas?: number;
|
|
35
35
|
/**
|
|
36
36
|
* Maximum number of speed-up attempts
|
|
37
37
|
*/
|
|
@@ -90,10 +90,21 @@ export const l1TxUtilsConfigMappings: ConfigMappingsType<L1TxUtilsConfig> = {
|
|
|
90
90
|
env: 'L1_PRIORITY_FEE_RETRY_BUMP_PERCENTAGE',
|
|
91
91
|
...numberConfigHelper(50),
|
|
92
92
|
},
|
|
93
|
-
|
|
94
|
-
description:
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
minimumPriorityFeePerGas: {
|
|
94
|
+
description:
|
|
95
|
+
'Minimum priority fee per gas in Gwei. Acts as a floor for the computed priority fee. If network conditions require a higher fee, the higher fee will be used.',
|
|
96
|
+
env: 'L1_MINIMUM_PRIORITY_FEE_PER_GAS_GWEI',
|
|
97
|
+
fallback: ['L1_FIXED_PRIORITY_FEE_PER_GAS', 'L1_FIXED_PRIORITY_FEE_PER_GAS_GWEI'],
|
|
98
|
+
deprecatedFallback: [
|
|
99
|
+
{
|
|
100
|
+
env: 'L1_FIXED_PRIORITY_FEE_PER_GAS',
|
|
101
|
+
message: deprecatedFixedFeeMessage('L1_FIXED_PRIORITY_FEE_PER_GAS'),
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
env: 'L1_FIXED_PRIORITY_FEE_PER_GAS_GWEI',
|
|
105
|
+
message: deprecatedFixedFeeMessage('L1_FIXED_PRIORITY_FEE_PER_GAS_GWEI'),
|
|
106
|
+
},
|
|
107
|
+
],
|
|
97
108
|
...floatConfigHelper(0),
|
|
98
109
|
},
|
|
99
110
|
maxSpeedUpAttempts: {
|
|
@@ -141,3 +152,10 @@ export const defaultL1TxUtilsConfig = getDefaultConfig<L1TxUtilsConfig>(
|
|
|
141
152
|
export function getL1TxUtilsConfigEnvVars(): L1TxUtilsConfig {
|
|
142
153
|
return getConfigFromMappings(l1TxUtilsConfigMappings);
|
|
143
154
|
}
|
|
155
|
+
|
|
156
|
+
function deprecatedFixedFeeMessage(envVar: string): string {
|
|
157
|
+
return (
|
|
158
|
+
`Environment variable ${envVar} is deprecated. It is now used as a MINIMUM priority fee rather than a fixed value. ` +
|
|
159
|
+
'Please use L1_MINIMUM_PRIORITY_FEE_PER_GAS_GWEI instead. If network conditions require a higher fee, the higher fee will be used.'
|
|
160
|
+
);
|
|
161
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
+
import type { Logger } from '@aztec/foundation/log';
|
|
3
|
+
import type { DateProvider } from '@aztec/foundation/timer';
|
|
4
|
+
|
|
5
|
+
import { type Hex, encodeFunctionData } from 'viem';
|
|
6
|
+
|
|
7
|
+
import type { EthSigner } from '../eth-signer/eth-signer.js';
|
|
8
|
+
import { FORWARDER_ABI } from '../forwarder_proxy.js';
|
|
9
|
+
import type { ExtendedViemWalletClient, ViemClient } from '../types.js';
|
|
10
|
+
import type { L1TxUtilsConfig } from './config.js';
|
|
11
|
+
import type { IL1TxMetrics, IL1TxStore } from './interfaces.js';
|
|
12
|
+
import { L1TxUtilsWithBlobs } from './l1_tx_utils_with_blobs.js';
|
|
13
|
+
import { createViemSigner } from './signer.js';
|
|
14
|
+
import type { L1BlobInputs, L1TxConfig, L1TxRequest, SigningCallback } from './types.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Extends L1TxUtilsWithBlobs to wrap all transactions through a forwarder contract.
|
|
18
|
+
* This is mainly used for testing the archiver's ability to decode transactions that go through proxies.
|
|
19
|
+
*/
|
|
20
|
+
export class ForwarderL1TxUtils extends L1TxUtilsWithBlobs {
|
|
21
|
+
constructor(
|
|
22
|
+
client: ViemClient | ExtendedViemWalletClient,
|
|
23
|
+
senderAddress: EthAddress,
|
|
24
|
+
signingCallback: SigningCallback,
|
|
25
|
+
logger: Logger | undefined,
|
|
26
|
+
dateProvider: DateProvider | undefined,
|
|
27
|
+
config: Partial<L1TxUtilsConfig>,
|
|
28
|
+
debugMaxGasLimit: boolean,
|
|
29
|
+
store: IL1TxStore | undefined,
|
|
30
|
+
metrics: IL1TxMetrics | undefined,
|
|
31
|
+
private readonly forwarderAddress: EthAddress,
|
|
32
|
+
) {
|
|
33
|
+
super(client, senderAddress, signingCallback, logger, dateProvider, config, debugMaxGasLimit, store, metrics);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Wraps the transaction request in a call to the forwarder contract.
|
|
38
|
+
*/
|
|
39
|
+
private wrapInForwarder(request: L1TxRequest): L1TxRequest {
|
|
40
|
+
const forwarderCalldata = encodeFunctionData({
|
|
41
|
+
abi: FORWARDER_ABI,
|
|
42
|
+
functionName: 'forward',
|
|
43
|
+
args: [request.to as Hex, request.data as Hex],
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
to: this.forwarderAddress.toString() as Hex,
|
|
48
|
+
data: forwarderCalldata,
|
|
49
|
+
value: request.value,
|
|
50
|
+
abi: request.abi, // Preserve the original ABI for error decoding
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Override sendAndMonitorTransaction to wrap the request in a forwarder call.
|
|
56
|
+
*/
|
|
57
|
+
public override sendAndMonitorTransaction(request: L1TxRequest, gasConfig?: L1TxConfig, blobInputs?: L1BlobInputs) {
|
|
58
|
+
this.logger.debug(`Wrapping transaction to ${request.to} in forwarder at ${this.forwarderAddress.toString()}`);
|
|
59
|
+
const wrappedRequest = this.wrapInForwarder(request);
|
|
60
|
+
return super.sendAndMonitorTransaction(wrappedRequest, gasConfig, blobInputs);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function createForwarderL1TxUtilsFromViemWallet(
|
|
65
|
+
client: ExtendedViemWalletClient,
|
|
66
|
+
forwarderAddress: EthAddress,
|
|
67
|
+
deps: {
|
|
68
|
+
logger?: Logger;
|
|
69
|
+
dateProvider?: DateProvider;
|
|
70
|
+
store?: IL1TxStore;
|
|
71
|
+
metrics?: IL1TxMetrics;
|
|
72
|
+
} = {},
|
|
73
|
+
config: Partial<L1TxUtilsConfig> = {},
|
|
74
|
+
debugMaxGasLimit: boolean = false,
|
|
75
|
+
) {
|
|
76
|
+
return new ForwarderL1TxUtils(
|
|
77
|
+
client,
|
|
78
|
+
EthAddress.fromString(client.account.address),
|
|
79
|
+
createViemSigner(client),
|
|
80
|
+
deps.logger,
|
|
81
|
+
deps.dateProvider,
|
|
82
|
+
config,
|
|
83
|
+
debugMaxGasLimit,
|
|
84
|
+
deps.store,
|
|
85
|
+
deps.metrics,
|
|
86
|
+
forwarderAddress,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function createForwarderL1TxUtilsFromEthSigner(
|
|
91
|
+
client: ViemClient,
|
|
92
|
+
signer: EthSigner,
|
|
93
|
+
forwarderAddress: EthAddress,
|
|
94
|
+
deps: {
|
|
95
|
+
logger?: Logger;
|
|
96
|
+
dateProvider?: DateProvider;
|
|
97
|
+
store?: IL1TxStore;
|
|
98
|
+
metrics?: IL1TxMetrics;
|
|
99
|
+
} = {},
|
|
100
|
+
config: Partial<L1TxUtilsConfig> = {},
|
|
101
|
+
debugMaxGasLimit: boolean = false,
|
|
102
|
+
) {
|
|
103
|
+
const callback: SigningCallback = async (transaction, _signingAddress) => {
|
|
104
|
+
return (await signer.signTransaction(transaction)).toViemTransactionSignature();
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return new ForwarderL1TxUtils(
|
|
108
|
+
client,
|
|
109
|
+
signer.address,
|
|
110
|
+
callback,
|
|
111
|
+
deps.logger,
|
|
112
|
+
deps.dateProvider,
|
|
113
|
+
config,
|
|
114
|
+
debugMaxGasLimit,
|
|
115
|
+
deps.store,
|
|
116
|
+
deps.metrics,
|
|
117
|
+
forwarderAddress,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
@@ -46,7 +46,7 @@ export interface IL1TxStore {
|
|
|
46
46
|
* @param account - The sender account address
|
|
47
47
|
* @param stateId - The state ID to delete
|
|
48
48
|
*/
|
|
49
|
-
deleteState(account: string, stateId: number): Promise<void>;
|
|
49
|
+
deleteState(account: string, ...stateId: number[]): Promise<void>;
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* Clears all transaction states for a specific account.
|
|
@@ -130,12 +130,32 @@ export class L1TxUtils extends ReadOnlyL1TxUtils {
|
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
// Clean up excess states if we have more than MAX_L1_TX_STATES
|
|
134
|
+
if (loadedStates.length > MAX_L1_TX_STATES) {
|
|
135
|
+
this.logger.warn(
|
|
136
|
+
`Found ${loadedStates.length} tx states for account ${account}, pruning to most recent ${MAX_L1_TX_STATES}`,
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
// Keep only the most recent MAX_L1_TX_STATES
|
|
140
|
+
const statesToKeep = loadedStates.slice(-MAX_L1_TX_STATES);
|
|
141
|
+
const statesToDelete = loadedStates.slice(0, -MAX_L1_TX_STATES);
|
|
142
|
+
|
|
143
|
+
// Batch delete old states in a transaction for efficiency
|
|
144
|
+
const idsToDelete = statesToDelete.map(s => s.id);
|
|
145
|
+
await this.store.deleteState(account, ...idsToDelete);
|
|
146
|
+
|
|
147
|
+
this.txs = statesToKeep;
|
|
148
|
+
this.logger.info(
|
|
149
|
+
`Cleaned up ${statesToDelete.length} old tx states, kept ${statesToKeep.length} for account ${account}`,
|
|
150
|
+
);
|
|
151
|
+
} else {
|
|
152
|
+
// Convert loaded states (which have id) to the txs format
|
|
153
|
+
this.txs = loadedStates;
|
|
154
|
+
this.logger.info(`Rehydrated ${loadedStates.length} tx states for account ${account}`);
|
|
155
|
+
}
|
|
136
156
|
|
|
137
157
|
// Find all pending states and resume monitoring
|
|
138
|
-
const pendingStates =
|
|
158
|
+
const pendingStates = this.txs.filter(state => !TerminalTxUtilsState.includes(state.status));
|
|
139
159
|
if (pendingStates.length === 0) {
|
|
140
160
|
return;
|
|
141
161
|
}
|
|
@@ -199,21 +199,18 @@ export class ReadOnlyL1TxUtils {
|
|
|
199
199
|
() => this.client.getBlock({ blockTag: 'latest' }),
|
|
200
200
|
'Getting latest block',
|
|
201
201
|
);
|
|
202
|
-
const networkEstimatePromise =
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
() => this.client.getFeeHistory({ blockCount: HISTORICAL_BLOCK_COUNT, rewardPercentiles: [75] }),
|
|
215
|
-
'Getting fee history',
|
|
216
|
-
);
|
|
202
|
+
const networkEstimatePromise = this.tryTwice(
|
|
203
|
+
() => this.client.estimateMaxPriorityFeePerGas(),
|
|
204
|
+
'Estimating max priority fee per gas',
|
|
205
|
+
);
|
|
206
|
+
const pendingBlockPromise = this.tryTwice(
|
|
207
|
+
() => this.client.getBlock({ blockTag: 'pending', includeTransactions: true }),
|
|
208
|
+
'Getting pending block',
|
|
209
|
+
);
|
|
210
|
+
const feeHistoryPromise = this.tryTwice(
|
|
211
|
+
() => this.client.getFeeHistory({ blockCount: HISTORICAL_BLOCK_COUNT, rewardPercentiles: [75] }),
|
|
212
|
+
'Getting fee history',
|
|
213
|
+
);
|
|
217
214
|
const blobBaseFeePromise = isBlobTx
|
|
218
215
|
? this.tryTwice(() => this.client.getBlobBaseFee(), 'Getting blob base fee')
|
|
219
216
|
: null;
|
|
@@ -221,9 +218,9 @@ export class ReadOnlyL1TxUtils {
|
|
|
221
218
|
const [latestBlockResult, networkEstimateResult, pendingBlockResult, feeHistoryResult, blobBaseFeeResult] =
|
|
222
219
|
await Promise.allSettled([
|
|
223
220
|
latestBlockPromise,
|
|
224
|
-
networkEstimatePromise
|
|
225
|
-
pendingBlockPromise
|
|
226
|
-
feeHistoryPromise
|
|
221
|
+
networkEstimatePromise,
|
|
222
|
+
pendingBlockPromise,
|
|
223
|
+
feeHistoryPromise,
|
|
227
224
|
blobBaseFeePromise ?? Promise.resolve(0n),
|
|
228
225
|
]);
|
|
229
226
|
|
|
@@ -243,15 +240,24 @@ export class ReadOnlyL1TxUtils {
|
|
|
243
240
|
this.logger?.warn('Failed to get L1 blob base fee', attempt);
|
|
244
241
|
}
|
|
245
242
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
243
|
+
// Get competitive priority fee
|
|
244
|
+
let priorityFee = this.getCompetitivePriorityFee(networkEstimateResult, pendingBlockResult, feeHistoryResult);
|
|
245
|
+
|
|
246
|
+
// Apply minimum priority fee as a floor if configured
|
|
247
|
+
if (gasConfig.minimumPriorityFeePerGas) {
|
|
248
|
+
const minimumFee = BigInt(Math.trunc(gasConfig.minimumPriorityFeePerGas * Number(WEI_CONST)));
|
|
249
|
+
if (minimumFee > priorityFee) {
|
|
250
|
+
this.logger?.debug('Using minimum priority fee as floor', {
|
|
251
|
+
minimumPriorityFeePerGas: formatGwei(minimumFee),
|
|
252
|
+
competitiveFee: formatGwei(priorityFee),
|
|
253
|
+
});
|
|
254
|
+
priorityFee = minimumFee;
|
|
255
|
+
} else {
|
|
256
|
+
this.logger?.debug('Competitive fee exceeds minimum, using competitive fee', {
|
|
257
|
+
minimumPriorityFeePerGas: formatGwei(minimumFee),
|
|
258
|
+
competitiveFee: formatGwei(priorityFee),
|
|
259
|
+
});
|
|
260
|
+
}
|
|
255
261
|
}
|
|
256
262
|
let maxFeePerGas = baseFee;
|
|
257
263
|
|
|
@@ -280,18 +286,15 @@ export class ReadOnlyL1TxUtils {
|
|
|
280
286
|
(previousGasPrice!.maxPriorityFeePerGas * (100_00n + BigInt(bumpPercentage * 1_00))) / 100_00n;
|
|
281
287
|
const minMaxFee = (previousGasPrice!.maxFeePerGas * (100_00n + BigInt(bumpPercentage * 1_00))) / 100_00n;
|
|
282
288
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
// Apply bump percentage to competitive fee
|
|
286
|
-
competitivePriorityFee = (priorityFee * (100_00n + BigInt(configBump * 1_00))) / 100_00n;
|
|
289
|
+
// Apply bump percentage to competitive fee
|
|
290
|
+
const competitivePriorityFee = (priorityFee * (100_00n + BigInt(configBump * 1_00))) / 100_00n;
|
|
287
291
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
292
|
+
this.logger?.debug(`Speed-up attempt ${attempt}: using competitive fee strategy`, {
|
|
293
|
+
networkEstimate: formatGwei(priorityFee),
|
|
294
|
+
competitiveFee: formatGwei(competitivePriorityFee),
|
|
295
|
+
minRequired: formatGwei(minPriorityFee),
|
|
296
|
+
bumpPercentage: configBump,
|
|
297
|
+
});
|
|
295
298
|
|
|
296
299
|
// Use maximum between competitive fee and minimum required bump
|
|
297
300
|
const finalPriorityFee = competitivePriorityFee > minPriorityFee ? competitivePriorityFee : minPriorityFee;
|
|
@@ -302,20 +305,16 @@ export class ReadOnlyL1TxUtils {
|
|
|
302
305
|
maxFeePerGas += finalPriorityFee;
|
|
303
306
|
maxFeePerGas = maxFeePerGas > minMaxFee ? maxFeePerGas : minMaxFee;
|
|
304
307
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
});
|
|
309
|
-
}
|
|
308
|
+
this.logger?.debug(`Speed-up fee decision: using ${feeSource} fee`, {
|
|
309
|
+
finalPriorityFee: formatGwei(finalPriorityFee),
|
|
310
|
+
});
|
|
310
311
|
} else {
|
|
311
312
|
// First attempt: apply configured bump percentage to competitive fee
|
|
312
313
|
// multiply by 100 & divide by 100 to maintain some precision
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
});
|
|
318
|
-
}
|
|
314
|
+
priorityFee = (priorityFee * (100_00n + BigInt((gasConfig.priorityFeeBumpPercentage || 0) * 1_00))) / 100_00n;
|
|
315
|
+
this.logger?.debug('Initial transaction: using competitive fee from market analysis', {
|
|
316
|
+
networkEstimate: formatGwei(priorityFee),
|
|
317
|
+
});
|
|
319
318
|
maxFeePerGas += priorityFee;
|
|
320
319
|
}
|
|
321
320
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { RollupContract } from '@aztec/ethereum/contracts';
|
|
2
|
+
import { InboxContract } from '@aztec/ethereum/contracts';
|
|
2
3
|
import { CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
4
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { toBigIntBE, toHex } from '@aztec/foundation/bigint-buffer';
|
|
2
|
-
import { keccak256 } from '@aztec/foundation/crypto';
|
|
2
|
+
import { keccak256 } from '@aztec/foundation/crypto/keccak';
|
|
3
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
4
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
5
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { RollupContract
|
|
1
|
+
import { RollupContract } from '@aztec/ethereum/contracts';
|
|
2
2
|
import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
3
|
+
import type { ViemPublicClient } from '@aztec/ethereum/types';
|
|
3
4
|
import { CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
4
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
6
|
import { createLogger } from '@aztec/foundation/log';
|
package/src/test/tx_delayer.ts
CHANGED
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
|
|
19
19
|
import { type ViemClient, isExtendedClient } from '../types.js';
|
|
20
20
|
|
|
21
|
+
const MAX_WAIT_TIME_SECONDS = 180;
|
|
22
|
+
|
|
21
23
|
export function waitUntilBlock<T extends Client>(
|
|
22
24
|
client: T,
|
|
23
25
|
blockNumber: number | bigint,
|
|
@@ -36,7 +38,7 @@ export function waitUntilBlock<T extends Client>(
|
|
|
36
38
|
return currentBlockNumber >= BigInt(blockNumber);
|
|
37
39
|
},
|
|
38
40
|
`Wait until L1 block ${blockNumber}`,
|
|
39
|
-
timeout ??
|
|
41
|
+
timeout ?? MAX_WAIT_TIME_SECONDS,
|
|
40
42
|
0.1,
|
|
41
43
|
);
|
|
42
44
|
}
|
|
@@ -66,7 +68,7 @@ export function waitUntilL1Timestamp<T extends Client>(
|
|
|
66
68
|
return currentTs >= BigInt(timestamp);
|
|
67
69
|
},
|
|
68
70
|
`Wait until L1 timestamp ${timestamp}`,
|
|
69
|
-
timeout ??
|
|
71
|
+
timeout ?? MAX_WAIT_TIME_SECONDS,
|
|
70
72
|
0.1,
|
|
71
73
|
);
|
|
72
74
|
}
|
package/src/types.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
Client,
|
|
6
6
|
FallbackTransport,
|
|
7
7
|
GetContractReturnType,
|
|
8
|
+
Hex,
|
|
8
9
|
HttpTransport,
|
|
9
10
|
PublicActions,
|
|
10
11
|
PublicClient,
|
|
@@ -16,6 +17,67 @@ import type {
|
|
|
16
17
|
/** Type for a viem public client */
|
|
17
18
|
export type ViemPublicClient = PublicClient<FallbackTransport<HttpTransport[]>, Chain>;
|
|
18
19
|
|
|
20
|
+
export type PublicRpcDebugSchema = [
|
|
21
|
+
{
|
|
22
|
+
Method: 'debug_traceTransaction';
|
|
23
|
+
Parameters: [txHash: `0x${string}`, options: { tracer: 'callTracer' }];
|
|
24
|
+
ReturnType: DebugCallTrace;
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
Method: 'trace_transaction';
|
|
28
|
+
Parameters: [txHash: `0x${string}`];
|
|
29
|
+
ReturnType: TraceTransactionResponse[];
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
/** Return type for a debug_traceTransaction call */
|
|
34
|
+
export type DebugCallTrace = {
|
|
35
|
+
from: Hex;
|
|
36
|
+
to?: Hex;
|
|
37
|
+
type: string;
|
|
38
|
+
input?: Hex;
|
|
39
|
+
output?: Hex;
|
|
40
|
+
gas?: Hex;
|
|
41
|
+
gasUsed?: Hex;
|
|
42
|
+
value?: Hex;
|
|
43
|
+
error?: string;
|
|
44
|
+
calls?: DebugCallTrace[];
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/** Action object for a trace_transaction call */
|
|
48
|
+
export type TraceAction = {
|
|
49
|
+
from: Hex;
|
|
50
|
+
to?: Hex;
|
|
51
|
+
callType: string;
|
|
52
|
+
gas?: Hex;
|
|
53
|
+
input?: Hex;
|
|
54
|
+
value?: Hex;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** Result object for a trace_transaction call */
|
|
58
|
+
export type TraceResult = {
|
|
59
|
+
gasUsed?: Hex;
|
|
60
|
+
output?: Hex;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/** Return type for a single trace in trace_transaction response */
|
|
64
|
+
export type TraceTransactionResponse = {
|
|
65
|
+
action: TraceAction;
|
|
66
|
+
result?: TraceResult;
|
|
67
|
+
error?: string;
|
|
68
|
+
subtraces: number;
|
|
69
|
+
traceAddress: number[];
|
|
70
|
+
type: string;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/** Type for a viem public client with support for debug methods */
|
|
74
|
+
export type ViemPublicDebugClient = PublicClient<
|
|
75
|
+
FallbackTransport<HttpTransport[]>,
|
|
76
|
+
Chain,
|
|
77
|
+
undefined,
|
|
78
|
+
[...PublicRpcSchema, ...PublicRpcDebugSchema]
|
|
79
|
+
>;
|
|
80
|
+
|
|
19
81
|
export type ExtendedViemWalletClient = Client<
|
|
20
82
|
FallbackTransport<readonly HttpTransport[]>,
|
|
21
83
|
Chain,
|
package/src/utils.ts
CHANGED
package/dest/index.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export * from './constants.js';
|
|
2
|
-
export * from './deploy_l1_contracts.js';
|
|
3
|
-
export * from './chain.js';
|
|
4
|
-
export * from './l1_tx_utils/index.js';
|
|
5
|
-
export * from './l1_contract_addresses.js';
|
|
6
|
-
export * from './l1_reader.js';
|
|
7
|
-
export * from './utils.js';
|
|
8
|
-
export * from './config.js';
|
|
9
|
-
export * from './types.js';
|
|
10
|
-
export * from './contracts/index.js';
|
|
11
|
-
export * from './queries.js';
|
|
12
|
-
export * from './client.js';
|
|
13
|
-
export * from './account.js';
|
|
14
|
-
export * from './l1_types.js';
|
|
15
|
-
export * from './l1_artifacts.js';
|
|
16
|
-
export * from './publisher_manager.js';
|
|
17
|
-
export * from './eth-signer/index.js';
|
|
18
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGdCQUFnQixDQUFDO0FBQy9CLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLDRCQUE0QixDQUFDO0FBQzNDLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxZQUFZLENBQUM7QUFDM0IsY0FBYyxzQkFBc0IsQ0FBQztBQUNyQyxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLG1CQUFtQixDQUFDO0FBQ2xDLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyx1QkFBdUIsQ0FBQyJ9
|
package/dest/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
|
package/dest/index.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export * from './constants.js';
|
|
2
|
-
export * from './deploy_l1_contracts.js';
|
|
3
|
-
export * from './chain.js';
|
|
4
|
-
export * from './l1_tx_utils/index.js';
|
|
5
|
-
export * from './l1_contract_addresses.js';
|
|
6
|
-
export * from './l1_reader.js';
|
|
7
|
-
export * from './utils.js';
|
|
8
|
-
export * from './config.js';
|
|
9
|
-
export * from './types.js';
|
|
10
|
-
export * from './contracts/index.js';
|
|
11
|
-
export * from './queries.js';
|
|
12
|
-
export * from './client.js';
|
|
13
|
-
export * from './account.js';
|
|
14
|
-
export * from './l1_types.js';
|
|
15
|
-
export * from './l1_artifacts.js';
|
|
16
|
-
export * from './publisher_manager.js';
|
|
17
|
-
export * from './eth-signer/index.js';
|