feat: use linea_estimateGas instead of getFeeData for all L2 transact… (#660)

* feat: use linea_estimateGas instead of getFeeData for all L2 transactions

* feat: use linea_estimateGas instead of getFeeData for L2 transactionswith call data and enable json-rpc-pricing-propagation

* feat: set DISABLE_JSON_RPC_PRICING_PROPAGATION of coordinator as false for e2e ci
This commit is contained in:
jonesho
2025-02-12 01:05:09 +08:00
committed by GitHub
parent bf8a00dfc6
commit 0eb6eb4ff4
9 changed files with 126 additions and 34 deletions

View File

@@ -75,13 +75,13 @@ start-env-with-tracing-v1:
make start-env COMPOSE_FILE=docker/compose-tracing-v1.yml LINEA_PROTOCOL_CONTRACTS_ONLY=true
start-env-with-tracing-v1-ci:
make start-env COMPOSE_FILE=docker/compose-tracing-v1-ci-extension.yml
make start-env COMPOSE_FILE=docker/compose-tracing-v1-ci-extension.yml DISABLE_JSON_RPC_PRICING_PROPAGATION=false
start-env-with-tracing-v2:
make start-env COMPOSE_FILE=docker/compose-tracing-v2.yml LINEA_PROTOCOL_CONTRACTS_ONLY=true
start-env-with-tracing-v2-ci:
make start-env COMPOSE_FILE=docker/compose-tracing-v2-ci-extension.yml
make start-env COMPOSE_FILE=docker/compose-tracing-v2-ci-extension.yml DISABLE_JSON_RPC_PRICING_PROPAGATION=false
start-env-with-staterecovery: COMPOSE_PROFILES:=l1,l2,staterecovery
start-env-with-staterecovery: L1_CONTRACT_VERSION:=6

View File

@@ -63,7 +63,7 @@ services:
file: compose-spec-l2-services.yml
service: coordinator
environment:
config__override__l2-network-gas-pricing__json-rpc-pricing-propagation__disabled: true
config__override__l2-network-gas-pricing__json-rpc-pricing-propagation__disabled: ${DISABLE_JSON_RPC_PRICING_PROPAGATION:-true}
config__override__type2-state-proof-provider__endpoints: # leave empty to disable
command: [ 'java', '-Dvertx.configurationFile=/var/lib/coordinator/vertx-options.json', '-Dlog4j2.configurationFile=/var/lib/coordinator/log4j2-dev.xml', '-jar', 'libs/coordinator.jar', '--traces-limits', 'config/traces-limits-v1.toml', '--smart-contract-errors', 'config/smart-contract-errors.toml', '--gas-price-cap-time-of-day-multipliers', 'config/gas-price-cap-time-of-day-multipliers.toml', 'config/coordinator-docker.config.toml', 'config/coordinator-docker-web3signer-override.config.toml' ]
volumes:

View File

@@ -64,7 +64,7 @@ services:
file: compose-spec-l2-services.yml
service: coordinator
environment:
config__override__l2-network-gas-pricing__json-rpc-pricing-propagation__disabled: true
config__override__l2-network-gas-pricing__json-rpc-pricing-propagation__disabled: ${DISABLE_JSON_RPC_PRICING_PROPAGATION:-true}
config__override__type2-state-proof-provider__endpoints: # leave empty to disable
command: [ 'java', '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005','-Dvertx.configurationFile=/var/lib/coordinator/vertx-options.json', '-Dlog4j2.configurationFile=/var/lib/coordinator/log4j2-dev.xml', '-jar', 'libs/coordinator.jar', '--traces-limits-v2', 'config/traces-limits-v2.toml', '--smart-contract-errors', 'config/smart-contract-errors.toml', '--gas-price-cap-time-of-day-multipliers', 'config/gas-price-cap-time-of-day-multipliers.toml', 'config/coordinator-docker.config.toml', 'config/coordinator-docker-traces-v2-override.config.toml' ]
volumes:

View File

@@ -45,7 +45,14 @@ plugin-linea-tx-pool-profitability-check-p2p-enabled=false
plugin-linea-tx-pool-profitability-check-api-enabled=false
plugin-linea-tx-pool-simulation-check-api-enabled=true
plugin-linea-tx-pool-simulation-check-p2p-enabled=false
plugin-linea-extra-data-pricing-enabled=true
plugin-linea-tx-pool-min-margin="0.8"
plugin-linea-min-margin="1.0"
plugin-linea-fixed-gas-cost-wei=30000000
plugin-linea-variable-gas-cost-wei=1000000000
plugin-linea-extra-data-set-min-gas-price-enabled=true
plugin-linea-estimate-gas-compatibility-mode-enabled=false
plugin-linea-estimate-gas-min-margin="1.2"
Xbonsai-limit-trie-logs-enabled=false
bonsai-historical-block-limit=1024

View File

@@ -1,7 +1,7 @@
import { ethers } from "ethers";
import { describe, expect, it } from "@jest/globals";
import { config } from "./config/tests-config";
import { waitForEvents, etherToWei } from "./common/utils";
import { waitForEvents, etherToWei, LineaEstimateGasClient } from "./common/utils";
import { MESSAGE_SENT_EVENT_SIGNATURE } from "./common/constants";
const l1AccountManager = config.getL1AccountManager();
@@ -140,47 +140,73 @@ describe("Bridge ERC20 Tokens L1 -> L2 and L2 -> L1", () => {
const l2TokenBridge = config.getL2TokenBridgeContract();
const l2Token = config.getL2TokenContract();
const l2Provider = config.getL2Provider();
const lineaEstimateGasClient = new LineaEstimateGasClient(config.getL2BesuNodeEndpoint()!);
const l2TokenAddress = await l2Token.getAddress();
const l2TokenBridgeAddress = await l2TokenBridge.getAddress();
const { maxPriorityFeePerGas: l2MaxPriorityFeePerGas, maxFeePerGas: l2MaxFeePerGas } =
await l2Provider.getFeeData();
// Mint token
let lineaEstimateGasFee = await lineaEstimateGasClient.lineaEstimateGas(
l2Account.address,
l2TokenAddress,
l2Token.interface.encodeFunctionData("mint", [l2Account.address, bridgeAmount]),
);
let nonce = await l2Provider.getTransactionCount(l2Account.address, "pending");
const mintResponse = await l2Token.connect(l2Account).mint(l2Account.address, bridgeAmount, {
maxPriorityFeePerGas: lineaEstimateGasFee.maxPriorityFeePerGas,
maxFeePerGas: lineaEstimateGasFee.maxFeePerGas,
gasLimit: lineaEstimateGasFee.gasLimit,
nonce: nonce,
});
const mintTxReceipt = await mintResponse.wait();
logger.debug(`Mint tx receipt received=${JSON.stringify(mintTxReceipt)}`);
await Promise.all([
(
await l2Token.connect(l2Account).mint(l2Account.address, bridgeAmount, {
nonce: nonce,
maxPriorityFeePerGas: l2MaxPriorityFeePerGas,
maxFeePerGas: l2MaxFeePerGas,
})
).wait(),
(
await l2Token.connect(l2Account).approve(l2TokenBridge.getAddress(), ethers.parseEther("100"), {
maxPriorityFeePerGas: l2MaxPriorityFeePerGas,
maxFeePerGas: l2MaxFeePerGas,
nonce: nonce + 1,
})
).wait(),
]);
// Approve token
lineaEstimateGasFee = await lineaEstimateGasClient.lineaEstimateGas(
l2Account.address,
l2TokenAddress,
l2Token.interface.encodeFunctionData("approve", [l2TokenBridgeAddress, ethers.parseEther("100")]),
);
nonce = await l2Provider.getTransactionCount(l2Account.address, "pending");
const approveResponse = await l2Token.connect(l2Account).approve(l2TokenBridgeAddress, ethers.parseEther("100"), {
maxPriorityFeePerGas: lineaEstimateGasFee.maxPriorityFeePerGas,
maxFeePerGas: lineaEstimateGasFee.maxFeePerGas,
gasLimit: lineaEstimateGasFee.gasLimit,
nonce: nonce,
});
const approveTxReceipt = await approveResponse.wait();
logger.debug(`Approve tx receipt received=${JSON.stringify(approveTxReceipt)}`);
const allowanceL2Account = await l2Token.allowance(l2Account.address, l2TokenBridge.getAddress());
// Retrieve token allowance
const allowanceL2Account = await l2Token.allowance(l2Account.address, l2TokenBridgeAddress);
logger.debug(`Current allowance of L2 account to L2 TokenBridge is ${allowanceL2Account.toString()}`);
logger.debug(`Current balance of L2 account is ${await l2Token.balanceOf(l2Account)}`);
logger.debug(`Current balance of L2 account is ${await l2Token.balanceOf(l2Account)}`);
logger.debug("Calling the bridgeToken function on the L2 TokenBridge contract");
// Bridge token
logger.debug(`0.01 ether = ${etherToWei("0.01").toString(16)}`);
nonce = await l2Provider.getTransactionCount(l2Account.address, "pending");
const bridgeTokenTx = await l2TokenBridge
lineaEstimateGasFee = await lineaEstimateGasClient.lineaEstimateGas(
l2Account.address,
l2TokenBridgeAddress,
l2TokenBridge.interface.encodeFunctionData("bridgeToken", [l2TokenAddress, bridgeAmount, l1Account.address]),
etherToWei("0.01").toString(16),
);
const bridgeResponse = await l2TokenBridge
.connect(l2Account)
.bridgeToken(await l2Token.getAddress(), bridgeAmount, l1Account.address, {
value: etherToWei("0.01"),
maxPriorityFeePerGas: l2MaxPriorityFeePerGas,
maxFeePerGas: l2MaxFeePerGas,
maxPriorityFeePerGas: lineaEstimateGasFee.maxPriorityFeePerGas,
maxFeePerGas: lineaEstimateGasFee.maxFeePerGas,
gasLimit: lineaEstimateGasFee.gasLimit,
nonce: nonce,
});
const bridgeTxReceipt = await bridgeResponse.wait();
logger.debug(`Bridge tx receipt received=${JSON.stringify(bridgeTxReceipt)}`);
const receipt = await bridgeTokenTx.wait();
const sentEventLog = receipt?.logs.find((log) => log.topics[0] == MESSAGE_SENT_EVENT_SIGNATURE);
const sentEventLog = bridgeTxReceipt?.logs.find((log) => log.topics[0] == MESSAGE_SENT_EVENT_SIGNATURE);
const messageSentEvent = l2MessageService.interface.decodeEventLog(
"MessageSent",

View File

@@ -81,6 +81,46 @@ export class RollupGetZkEVMBlockNumberClient {
}
}
export class LineaEstimateGasClient {
private endpoint: URL;
public constructor(endpoint: URL) {
this.endpoint = endpoint;
}
public async lineaEstimateGas(
from: string,
to: string,
data: string = "0x",
value: string = "0x0",
): Promise<{ maxFeePerGas: bigint; maxPriorityFeePerGas: bigint; gasLimit: bigint }> {
const request = {
method: "post",
body: JSON.stringify({
jsonrpc: "2.0",
method: "linea_estimateGas",
params: [
{
from,
to,
data,
value,
},
],
id: 1,
}),
};
const response = await fetch(this.endpoint, request);
const responseJson = await response.json();
assert("result" in responseJson);
return {
maxFeePerGas: BigInt(responseJson.result.baseFeePerGas) + BigInt(responseJson.result.priorityFeePerGas),
maxPriorityFeePerGas: BigInt(responseJson.result.priorityFeePerGas),
gasLimit: BigInt(responseJson.result.gasLimit),
};
}
}
export class TransactionExclusionClient {
private endpoint: URL;

View File

@@ -76,6 +76,13 @@ export default class TestSetup {
return this.config.L2.sequencerEndpoint;
}
public getL2BesuNodeEndpoint(): URL | undefined {
if (!this.isLocalL2Config(this.config.L2)) {
return undefined;
}
return this.config.L2.besuNodeRpcUrl;
}
public getTransactionExclusionEndpoint(): URL | undefined {
if (!this.isLocalL2Config(this.config.L2)) {
return undefined;

View File

@@ -1,13 +1,14 @@
import { ethers } from "ethers";
import { describe, expect, it } from "@jest/globals";
import { config } from "./config/tests-config";
import { RollupGetZkEVMBlockNumberClient, etherToWei } from "./common/utils";
import { LineaEstimateGasClient, RollupGetZkEVMBlockNumberClient, etherToWei } from "./common/utils";
import { TRANSACTION_CALLDATA_LIMIT } from "./common/constants";
const l2AccountManager = config.getL2AccountManager();
describe("Layer 2 test suite", () => {
const l2Provider = config.getL2Provider();
const lineaEstimateGasClient = new LineaEstimateGasClient(config.getL2BesuNodeEndpoint()!);
it.concurrent("Should revert if transaction data size is above the limit", async () => {
const account = await l2AccountManager.generateAccount();
@@ -26,7 +27,11 @@ describe("Layer 2 test suite", () => {
const nonce = await l2Provider.getTransactionCount(account.address, "pending");
logger.debug(`Fetched nonce. nonce=${nonce} account=${account.address}`);
const { maxPriorityFeePerGas, maxFeePerGas } = await l2Provider.getFeeData();
const { maxPriorityFeePerGas, maxFeePerGas } = await lineaEstimateGasClient.lineaEstimateGas(
account.address,
await dummyContract.getAddress(),
dummyContract.interface.encodeFunctionData("setPayload", [ethers.randomBytes(1000)]),
);
logger.debug(`Fetched fee data. maxPriorityFeePerGas=${maxPriorityFeePerGas} maxFeePerGas=${maxFeePerGas}`);
const tx = await dummyContract.connect(account).setPayload(ethers.randomBytes(1000), {

View File

@@ -2,7 +2,7 @@ import { ethers, Wallet } from "ethers";
import { describe, expect, it } from "@jest/globals";
import type { Logger } from "winston";
import { config } from "./config/tests-config";
import { encodeFunctionCall, etherToWei, waitForEvents } from "./common/utils";
import { encodeFunctionCall, etherToWei, LineaEstimateGasClient, waitForEvents } from "./common/utils";
import { MESSAGE_SENT_EVENT_SIGNATURE } from "./common/constants";
async function sendL1ToL2Message(
@@ -71,6 +71,7 @@ async function sendL2ToL1Message(
const l2Provider = config.getL2Provider();
const dummyContract = config.getL1DummyContract(l1Account);
const l2MessageService = config.getL2MessageServiceContract(l2Account);
const lineaEstimateGasClient = new LineaEstimateGasClient(config.getL2BesuNodeEndpoint()!);
const valueAndFee = etherToWei("0.001");
const calldata = withCalldata
@@ -81,7 +82,12 @@ async function sendL2ToL1Message(
const nonce = await l2Provider.getTransactionCount(l2Account.address, "pending");
logger.debug(`Fetched nonce. nonce=${nonce} account=${l2Account.address}`);
const { maxPriorityFeePerGas, maxFeePerGas } = await l2Provider.getFeeData();
const { maxPriorityFeePerGas, maxFeePerGas, gasLimit } = await lineaEstimateGasClient.lineaEstimateGas(
l2Account.address,
await l2MessageService.getAddress(),
l2MessageService.interface.encodeFunctionData("sendMessage", [destinationAddress, valueAndFee, calldata]),
etherToWei("0.001").toString(16),
);
logger.debug(`Fetched fee data. maxPriorityFeePerGas=${maxPriorityFeePerGas} maxFeePerGas=${maxFeePerGas}`);
const tx = await l2MessageService.sendMessage(destinationAddress, valueAndFee, calldata, {
@@ -89,6 +95,7 @@ async function sendL2ToL1Message(
nonce,
maxPriorityFeePerGas,
maxFeePerGas,
gasLimit,
});
logger.debug(`sendMessage transaction sent. transactionHash=${tx.hash}`);