diff --git a/acceptance-tests/src/test/java/linea/plugin/acc/test/rpc/linea/EstimateGasCompatibilityModeTest.java b/acceptance-tests/src/test/java/linea/plugin/acc/test/rpc/linea/EstimateGasCompatibilityModeTest.java index 4649d5aca..6c0e8aa15 100644 --- a/acceptance-tests/src/test/java/linea/plugin/acc/test/rpc/linea/EstimateGasCompatibilityModeTest.java +++ b/acceptance-tests/src/test/java/linea/plugin/acc/test/rpc/linea/EstimateGasCompatibilityModeTest.java @@ -16,30 +16,52 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.List; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.Transaction; public class EstimateGasCompatibilityModeTest extends EstimateGasTest { + private static final BigDecimal PRICE_MULTIPLIER = BigDecimal.valueOf(1.2); @Override public List getTestCliOptions() { return getTestCommandLineOptionsBuilder() .set("--plugin-linea-estimate-gas-compatibility-mode-enabled=", "true") + .set( + "--plugin-linea-estimate-gas-compatibility-mode-multiplier=", + PRICE_MULTIPLIER.toPlainString()) .build(); } @Override protected void assertIsProfitable( final Transaction tx, + final Wei baseFee, final Wei estimatedPriorityFee, final Wei estimatedMaxGasPrice, final long estimatedGasLimit) { final var minGasPrice = minerNode.getMiningParameters().getMinTransactionGasPrice(); + final var minPriorityFee = minGasPrice.subtract(baseFee); + final var compatibilityMinPriorityFee = + Wei.of( + PRICE_MULTIPLIER + .multiply(new BigDecimal(minPriorityFee.getAsBigInteger())) + .setScale(0, RoundingMode.CEILING) + .toBigInteger()); // since we are in compatibility mode, we want to check that returned profitable priority fee is - // the min mineable gas price - assertThat(estimatedMaxGasPrice).isEqualTo(minGasPrice); + // the min priority fee per gas * multiplier + base fee + final var expectedMaxGasPrice = baseFee.add(compatibilityMinPriorityFee); + assertThat(estimatedMaxGasPrice).isEqualTo(expectedMaxGasPrice); + } + + @Override + protected void assertMinGasPriceLowerBound(final Wei baseFee, final Wei estimatedMaxGasPrice) { + // since we are in compatibility mode, we want to check that returned profitable priority fee is + // the min priority fee per gas * multiplier + base fee + assertIsProfitable(null, baseFee, null, estimatedMaxGasPrice, 0); } } diff --git a/acceptance-tests/src/test/java/linea/plugin/acc/test/rpc/linea/EstimateGasTest.java b/acceptance-tests/src/test/java/linea/plugin/acc/test/rpc/linea/EstimateGasTest.java index 9dc90202b..1f4493a60 100644 --- a/acceptance-tests/src/test/java/linea/plugin/acc/test/rpc/linea/EstimateGasTest.java +++ b/acceptance-tests/src/test/java/linea/plugin/acc/test/rpc/linea/EstimateGasTest.java @@ -26,7 +26,6 @@ import net.consensys.linea.bl.TransactionProfitabilityCalculator; import net.consensys.linea.config.LineaProfitabilityCliOptions; import net.consensys.linea.config.LineaProfitabilityConfiguration; -import net.consensys.linea.config.LineaTransactionSelectorConfiguration; import net.consensys.linea.rpc.linea.LineaEstimateGas; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt64; @@ -48,7 +47,6 @@ public class EstimateGasTest extends LineaPluginTestBase { protected static final double ESTIMATE_GAS_MIN_MARGIN = 1.0; protected static final Wei MIN_GAS_PRICE = Wei.of(1_000_000_000); protected static final int MAX_TRANSACTION_GAS_LIMIT = 30_000_000; - protected LineaTransactionSelectorConfiguration txSelectorConf; protected LineaProfitabilityConfiguration profitabilityConf; @Override @@ -137,11 +135,12 @@ public void lineaEstimateGasIsProfitable() { .signature(LineaEstimateGas.FAKE_SIGNATURE_FOR_SIZE_CALCULATION) .build(); - assertIsProfitable(tx, estimatedPriorityFee, estimatedMaxGasPrice, estimatedGasLimit); + assertIsProfitable(tx, baseFee, estimatedPriorityFee, estimatedMaxGasPrice, estimatedGasLimit); } protected void assertIsProfitable( final org.hyperledger.besu.ethereum.core.Transaction tx, + final Wei baseFee, final Wei estimatedPriorityFee, final Wei estimatedMaxGasPrice, final long estimatedGasLimit) { @@ -180,8 +179,12 @@ public void lineaEstimateGasPriorityFeeMinGasPriceLowerBound() { final var baseFee = Wei.fromHexString(respLinea.baseFeePerGas()); final var estimatedPriorityFee = Wei.fromHexString(respLinea.priorityFeePerGas()); final var estimatedMaxGasPrice = baseFee.add(estimatedPriorityFee); - final var minGasPrice = minerNode.getMiningParameters().getMinTransactionGasPrice(); + assertMinGasPriceLowerBound(baseFee, estimatedMaxGasPrice); + } + + protected void assertMinGasPriceLowerBound(final Wei baseFee, final Wei estimatedMaxGasPrice) { + final var minGasPrice = minerNode.getMiningParameters().getMinTransactionGasPrice(); assertThat(estimatedMaxGasPrice).isEqualTo(minGasPrice); } diff --git a/arithmetization/src/main/java/net/consensys/linea/config/LineaRpcCliOptions.java b/arithmetization/src/main/java/net/consensys/linea/config/LineaRpcCliOptions.java index 05b1e543f..cefc9fcb1 100644 --- a/arithmetization/src/main/java/net/consensys/linea/config/LineaRpcCliOptions.java +++ b/arithmetization/src/main/java/net/consensys/linea/config/LineaRpcCliOptions.java @@ -15,6 +15,8 @@ package net.consensys.linea.config; +import java.math.BigDecimal; + import com.google.common.base.MoreObjects; import picocli.CommandLine; @@ -22,13 +24,27 @@ public class LineaRpcCliOptions { private static final String ESTIMATE_GAS_COMPATIBILITY_MODE_ENABLED = "--plugin-linea-estimate-gas-compatibility-mode-enabled"; + private static final boolean DEFAULT_ESTIMATE_GAS_COMPATIBILITY_MODE_ENABLED = false; + private static final String ESTIMATE_GAS_COMPATIBILITY_MODE_MULTIPLIER = + "--plugin-linea-estimate-gas-compatibility-mode-multiplier"; + private static final BigDecimal DEFAULT_ESTIMATE_GAS_COMPATIBILITY_MODE_MULTIPLIER = + BigDecimal.valueOf(1.2); @CommandLine.Option( names = {ESTIMATE_GAS_COMPATIBILITY_MODE_ENABLED}, paramLabel = "", description = - "Set to true to return the min mineable gas price, instead of the profitable price (default: ${DEFAULT-VALUE})") - private boolean estimateGasCompatibilityModeEnabled = false; + "Set to true to return the min mineable gas price * multiplier, instead of the profitable price (default: ${DEFAULT-VALUE})") + private boolean estimateGasCompatibilityModeEnabled = + DEFAULT_ESTIMATE_GAS_COMPATIBILITY_MODE_ENABLED; + + @CommandLine.Option( + names = {ESTIMATE_GAS_COMPATIBILITY_MODE_MULTIPLIER}, + paramLabel = "", + description = + "Set to multiplier to apply to the min priority fee per gas when the compatibility mode is enabled (default: ${DEFAULT-VALUE})") + private BigDecimal estimateGasCompatibilityMultiplier = + DEFAULT_ESTIMATE_GAS_COMPATIBILITY_MODE_MULTIPLIER; private LineaRpcCliOptions() {} @@ -50,6 +66,7 @@ public static LineaRpcCliOptions create() { public static LineaRpcCliOptions fromConfig(final LineaRpcConfiguration config) { final LineaRpcCliOptions options = create(); options.estimateGasCompatibilityModeEnabled = config.estimateGasCompatibilityModeEnabled(); + options.estimateGasCompatibilityMultiplier = config.estimateGasCompatibilityMultiplier(); return options; } @@ -61,6 +78,7 @@ public static LineaRpcCliOptions fromConfig(final LineaRpcConfiguration config) public LineaRpcConfiguration toDomainObject() { return LineaRpcConfiguration.builder() .estimateGasCompatibilityModeEnabled(estimateGasCompatibilityModeEnabled) + .estimateGasCompatibilityMultiplier(estimateGasCompatibilityMultiplier) .build(); } @@ -68,6 +86,7 @@ public LineaRpcConfiguration toDomainObject() { public String toString() { return MoreObjects.toStringHelper(this) .add(ESTIMATE_GAS_COMPATIBILITY_MODE_ENABLED, estimateGasCompatibilityModeEnabled) + .add(ESTIMATE_GAS_COMPATIBILITY_MODE_MULTIPLIER, estimateGasCompatibilityMultiplier) .toString(); } } diff --git a/arithmetization/src/main/java/net/consensys/linea/config/LineaRpcConfiguration.java b/arithmetization/src/main/java/net/consensys/linea/config/LineaRpcConfiguration.java index 5742ab45e..6551c9247 100644 --- a/arithmetization/src/main/java/net/consensys/linea/config/LineaRpcConfiguration.java +++ b/arithmetization/src/main/java/net/consensys/linea/config/LineaRpcConfiguration.java @@ -15,8 +15,11 @@ package net.consensys.linea.config; +import java.math.BigDecimal; + import lombok.Builder; /** The Linea RPC configuration. */ @Builder(toBuilder = true) -public record LineaRpcConfiguration(boolean estimateGasCompatibilityModeEnabled) {} +public record LineaRpcConfiguration( + boolean estimateGasCompatibilityModeEnabled, BigDecimal estimateGasCompatibilityMultiplier) {} diff --git a/arithmetization/src/main/java/net/consensys/linea/rpc/linea/LineaEstimateGas.java b/arithmetization/src/main/java/net/consensys/linea/rpc/linea/LineaEstimateGas.java index 50662b625..23b214336 100644 --- a/arithmetization/src/main/java/net/consensys/linea/rpc/linea/LineaEstimateGas.java +++ b/arithmetization/src/main/java/net/consensys/linea/rpc/linea/LineaEstimateGas.java @@ -17,7 +17,9 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity.create; +import java.math.BigDecimal; import java.math.BigInteger; +import java.math.RoundingMode; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.annotations.VisibleForTesting; @@ -112,17 +114,13 @@ public LineaEstimateGas.Response execute(final PluginRpcRequest request) { .log(); final var estimatedGasUsed = estimateGasUsed(callParameters, transaction, minGasPrice); - final Wei profitablePriorityFee = - txProfitabilityCalculator.profitablePriorityFeePerGas( - transaction, profitabilityConf.estimateGasMinMargin(), minGasPrice, estimatedGasUsed); - final Wei baseFee = blockchainService .getNextBlockBaseFee() .orElseThrow(() -> new IllegalStateException("Not on a baseFee market")); final Wei estimatedPriorityFee = - getEstimatedPriorityFee(baseFee, profitablePriorityFee, minGasPrice); + getEstimatedPriorityFee(transaction, baseFee, minGasPrice, estimatedGasUsed); final var response = new Response(create(estimatedGasUsed), create(baseFee), create(estimatedPriorityFee)); @@ -132,13 +130,25 @@ public LineaEstimateGas.Response execute(final PluginRpcRequest request) { } private Wei getEstimatedPriorityFee( - final Wei baseFee, final Wei profitablePriorityFee, final Wei minGasPrice) { + final Transaction transaction, + final Wei baseFee, + final Wei minGasPrice, + final long estimatedGasUsed) { final Wei priorityFeeLowerBound = minGasPrice.subtract(baseFee); if (rpcConfiguration.estimateGasCompatibilityModeEnabled()) { - return priorityFeeLowerBound; + return Wei.of( + rpcConfiguration + .estimateGasCompatibilityMultiplier() + .multiply(new BigDecimal(priorityFeeLowerBound.getAsBigInteger())) + .setScale(0, RoundingMode.CEILING) + .toBigInteger()); } + final Wei profitablePriorityFee = + txProfitabilityCalculator.profitablePriorityFeePerGas( + transaction, profitabilityConf.estimateGasMinMargin(), minGasPrice, estimatedGasUsed); + if (profitablePriorityFee.greaterOrEqualThan(priorityFeeLowerBound)) { return profitablePriorityFee; } diff --git a/gradle/dependency-management.gradle b/gradle/dependency-management.gradle index 4be7dac3f..3ced8b1ee 100644 --- a/gradle/dependency-management.gradle +++ b/gradle/dependency-management.gradle @@ -116,7 +116,7 @@ dependencyManagement { dependency 'com.splunk.logging:splunk-library-javalogging:1.11.5' - dependency 'io.vertx:vertx-core:4.3.8' + dependency 'io.vertx:vertx-core:4.5.4' dependency 'com.slack.api:slack-api-client:1.32.1'