Skip to content

Commit

Permalink
Refactor profitability formula with fixed and variable gas cost
Browse files Browse the repository at this point in the history
Signed-off-by: Fabio Di Fabio <[email protected]>
  • Loading branch information
fab-10 committed May 10, 2024
1 parent a1d0dba commit 87567d4
Show file tree
Hide file tree
Showing 15 changed files with 153 additions and 151 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,8 @@
import org.web3j.protocol.http.HttpService;

public class EstimateGasTest extends LineaPluginTestBase {
protected static final int VERIFICATION_GAS_COST = 1_200_000;
protected static final int VERIFICATION_CAPACITY = 90_000;
protected static final int GAS_PRICE_RATIO = 15;
protected static final int FIXED_GAS_COST_KWEI = 1_200_000;
protected static final int VARIABLE_GAS_COST_KWEI = 90_000;
protected static final double MIN_MARGIN = 1.0;
protected static final double ESTIMATE_GAS_MIN_MARGIN = 1.0;
protected static final Wei MIN_GAS_PRICE = Wei.of(1_000_000_000);
Expand All @@ -65,9 +64,8 @@ public List<String> getTestCliOptions() {

protected TestCommandLineOptionsBuilder getTestCommandLineOptionsBuilder() {
return new TestCommandLineOptionsBuilder()
.set("--plugin-linea-verification-gas-cost=", String.valueOf(VERIFICATION_GAS_COST))
.set("--plugin-linea-verification-capacity=", String.valueOf(VERIFICATION_CAPACITY))
.set("--plugin-linea-gas-price-ratio=", String.valueOf(GAS_PRICE_RATIO))
.set("--plugin-linea-fixed-gas-cost-kwei=", String.valueOf(FIXED_GAS_COST_KWEI))
.set("--plugin-linea-variable-gas-cost-kwei=", String.valueOf(VARIABLE_GAS_COST_KWEI))
.set("--plugin-linea-min-margin=", String.valueOf(MIN_MARGIN))
.set("--plugin-linea-estimate-gas-min-margin=", String.valueOf(ESTIMATE_GAS_MIN_MARGIN))
.set("--plugin-linea-max-tx-gas-limit=", String.valueOf(MAX_TRANSACTION_GAS_LIMIT));
Expand All @@ -82,9 +80,8 @@ public void setMinGasPrice() {
public void createDefaultConfigurations() {
profitabilityConf =
LineaProfitabilityCliOptions.create().toDomainObject().toBuilder()
.verificationCapacity(VERIFICATION_CAPACITY)
.verificationGasCost(VERIFICATION_GAS_COST)
.gasPriceRatio(GAS_PRICE_RATIO)
.fixedCostKWei(FIXED_GAS_COST_KWEI)
.variableCostKWei(VARIABLE_GAS_COST_KWEI)
.minMargin(MIN_MARGIN)
.estimateGasMinMargin(ESTIMATE_GAS_MIN_MARGIN)
.build();
Expand Down Expand Up @@ -161,7 +158,7 @@ protected void assertIsProfitable(

final var profitablePriorityFee =
profitabilityCalculator.profitablePriorityFeePerGas(
tx, profitabilityConf.txPoolMinMargin(), minGasPrice, estimatedGasLimit);
tx, profitabilityConf.txPoolMinMargin(), estimatedGasLimit);

assertThat(profitablePriorityFee.greaterThan(minGasPrice)).isTrue();

Expand All @@ -170,7 +167,6 @@ protected void assertIsProfitable(
"Test",
tx,
profitabilityConf.txPoolMinMargin(),
minerNode.getMiningParameters().getMinTransactionGasPrice(),
estimatedMaxGasPrice,
estimatedGasLimit))
.isTrue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package net.consensys.linea.bl;

import java.math.BigDecimal;
import java.math.BigInteger;

import lombok.extern.slf4j.Slf4j;
import net.consensys.linea.compress.LibCompress;
Expand All @@ -25,68 +26,50 @@

@Slf4j
public class TransactionProfitabilityCalculator {

private static final BigInteger TO_WEI_MULTIPLIER = BigInteger.valueOf(1000);
private final LineaProfitabilityConfiguration profitabilityConf;
private final double preComputedValue;
private final double priceAdjustment;

public TransactionProfitabilityCalculator(
final LineaProfitabilityConfiguration profitabilityConf) {
this.profitabilityConf = profitabilityConf;
this.preComputedValue =
profitabilityConf.gasPriceRatio() * profitabilityConf.verificationGasCost();
this.priceAdjustment = profitabilityConf.gasPriceAdjustment().getAsBigInteger().doubleValue();
}

public Wei profitablePriorityFeePerGas(
final Transaction transaction,
final double minMargin,
final Wei minGasPrice,
final long gas) {
final double compressedTxSize = getCompressedTxSize(transaction);
final Transaction transaction, final double minMargin, final long gas) {
final int compressedTxSize = getCompressedTxSize(transaction);

final var profitAt =
(preComputedValue
* compressedTxSize
* minGasPrice.getAsBigInteger().doubleValue()
/ (gas * profitabilityConf.verificationCapacity())
+ priceAdjustment)
* minMargin;
final var profitAtKWei =
minMargin
* (profitabilityConf.variableCostKWei() * compressedTxSize / gas
+ profitabilityConf.fixedCostKWei());

final var adjustedProfit = Wei.ofNumber(BigDecimal.valueOf(profitAt).toBigInteger());
final var profitAtWei =
Wei.ofNumber(BigDecimal.valueOf(profitAtKWei).toBigInteger().multiply(TO_WEI_MULTIPLIER));

log.atDebug()
.setMessage(
"Estimated profitable priorityFeePerGas: {}; estimateGasMinMargin={}, verificationCapacity={}, "
+ "verificationGasCost={}, gasPriceRatio={}, gasPriceAdjustment={}, gas={}, minGasPrice={}, "
+ "l1GasPrice={}, txSize={}, compressedTxSize={}")
.addArgument(adjustedProfit::toHumanReadableString)
.addArgument(profitabilityConf.estimateGasMinMargin())
.addArgument(profitabilityConf.verificationCapacity())
.addArgument(profitabilityConf.verificationGasCost())
.addArgument(profitabilityConf.gasPriceRatio())
.addArgument(profitabilityConf.gasPriceAdjustment()::toHumanReadableString)
"Estimated profitable priorityFeePerGas: {}; minMargin={}, fixedCostKWei={}, "
+ "variableCostKWei={}, gas={}, txSize={}, compressedTxSize={}")
.addArgument(profitAtWei::toHumanReadableString)
.addArgument(minMargin)
.addArgument(profitabilityConf.fixedCostKWei())
.addArgument(profitabilityConf.variableCostKWei())
.addArgument(gas)
.addArgument(minGasPrice::toHumanReadableString)
.addArgument(
() -> minGasPrice.multiply(profitabilityConf.gasPriceRatio()).toHumanReadableString())
.addArgument(transaction::getSize)
.addArgument(compressedTxSize)
.log();

return adjustedProfit;
return profitAtWei;
}

public boolean isProfitable(
final String context,
final Transaction transaction,
final double minMargin,
final Wei minGasPrice,
final Wei effectiveGasPrice,
final long gas) {

final Wei profitablePriorityFee =
profitablePriorityFeePerGas(transaction, minMargin, minGasPrice, gas);
final Wei profitablePriorityFee = profitablePriorityFeePerGas(transaction, minMargin, gas);

if (effectiveGasPrice.lessThan(profitablePriorityFee)) {
log(
Expand All @@ -96,8 +79,7 @@ public boolean isProfitable(
minMargin,
effectiveGasPrice,
profitablePriorityFee,
gas,
minGasPrice);
gas);
return false;
}

Expand All @@ -108,12 +90,11 @@ public boolean isProfitable(
minMargin,
effectiveGasPrice,
profitablePriorityFee,
gas,
minGasPrice);
gas);
return true;
}

private double getCompressedTxSize(final Transaction transaction) {
private int getCompressedTxSize(final Transaction transaction) {
final byte[] bytes = transaction.encoded().toArrayUnsafe();
return LibCompress.CompressedSize(bytes, bytes.length);
}
Expand All @@ -125,12 +106,11 @@ private void log(
final double minMargin,
final Wei effectiveGasPrice,
final Wei profitableGasPrice,
final long gasUsed,
final Wei minGasPrice) {
final long gasUsed) {
leb.setMessage(
"Context {}. Transaction {} has a margin of {}, minMargin={}, effectiveGasPrice={},"
+ " profitableGasPrice={}, verificationCapacity={}, verificationGasCost={}, gasPriceRatio={},, gasPriceAdjustment={}"
+ " gasUsed={}, minGasPrice={}")
+ " profitableGasPrice={}, fixedCostKWei={}, variableCostKWei={}, "
+ " gasUsed={}")
.addArgument(context)
.addArgument(transaction::getHash)
.addArgument(
Expand All @@ -140,12 +120,9 @@ private void log(
.addArgument(minMargin)
.addArgument(effectiveGasPrice::toHumanReadableString)
.addArgument(profitableGasPrice::toHumanReadableString)
.addArgument(profitabilityConf.verificationCapacity())
.addArgument(profitabilityConf.verificationGasCost())
.addArgument(profitabilityConf.gasPriceRatio())
.addArgument(profitabilityConf.gasPriceAdjustment()::toHumanReadableString)
.addArgument(profitabilityConf.fixedCostKWei())
.addArgument(profitabilityConf.variableCostKWei())
.addArgument(gasUsed)
.addArgument(minGasPrice::toHumanReadableString)
.log();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,15 @@

import com.google.common.base.MoreObjects;
import jakarta.validation.constraints.Positive;
import net.consensys.linea.config.converters.WeiConverter;
import org.hyperledger.besu.datatypes.Wei;
import picocli.CommandLine;

/** The Linea profitability calculator CLI options. */
public class LineaProfitabilityCliOptions {
public static final String VERIFICATION_GAS_COST = "--plugin-linea-verification-gas-cost";
public static final int DEFAULT_VERIFICATION_GAS_COST = 1_200_000;
public static final String FIXED_GAS_COST_KWEI = "--plugin-linea-fixed-gas-cost-kwei";
public static final long DEFAULT_FIXED_GAS_COST_KWEI = 1_200_000;

public static final String VERIFICATION_CAPACITY = "--plugin-linea-verification-capacity";
public static final int DEFAULT_VERIFICATION_CAPACITY = 90_000;

public static final String GAS_PRICE_RATIO = "--plugin-linea-gas-price-ratio";
public static final int DEFAULT_GAS_PRICE_RATIO = 15;

public static final String GAS_PRICE_ADJUSTMENT = "--plugin-linea-gas-price-adjustment";
public static final Wei DEFAULT_GAS_PRICE_ADJUSTMENT = Wei.ZERO;
public static final String VARIABLE_GAS_COST_KWEI = "--plugin-linea-variable-gas-cost-kwei";
public static final long DEFAULT_VARIABLE_GAS_COST_KWEI = 90_000;

public static final String MIN_MARGIN = "--plugin-linea-min-margin";
public static final BigDecimal DEFAULT_MIN_MARGIN = BigDecimal.ONE;
Expand All @@ -56,36 +48,19 @@ public class LineaProfitabilityCliOptions {

@Positive
@CommandLine.Option(
names = {VERIFICATION_GAS_COST},
names = {FIXED_GAS_COST_KWEI},
hidden = true,
paramLabel = "<INTEGER>",
description = "L1 verification gas cost (default: ${DEFAULT-VALUE})")
private int verificationGasCost = DEFAULT_VERIFICATION_GAS_COST;
description = "Fixed gas cost in KWei (default: ${DEFAULT-VALUE})")
private long fixedGasCostKwei = DEFAULT_FIXED_GAS_COST_KWEI;

@Positive
@CommandLine.Option(
names = {VERIFICATION_CAPACITY},
names = {VARIABLE_GAS_COST_KWEI},
hidden = true,
paramLabel = "<INTEGER>",
description = "L1 verification capacity (default: ${DEFAULT-VALUE})")
private int verificationCapacity = DEFAULT_VERIFICATION_CAPACITY;

@Positive
@CommandLine.Option(
names = {GAS_PRICE_RATIO},
hidden = true,
paramLabel = "<INTEGER>",
description = "L1/L2 gas price ratio (default: ${DEFAULT-VALUE})")
private int gasPriceRatio = DEFAULT_GAS_PRICE_RATIO;

@CommandLine.Option(
names = {GAS_PRICE_ADJUSTMENT},
hidden = true,
converter = WeiConverter.class,
paramLabel = "<WEI>",
description =
"Amount to add to the calculated profitable gas price (default: ${DEFAULT-VALUE})")
private Wei gasPriceAdjustment = DEFAULT_GAS_PRICE_ADJUSTMENT;
description = "Variable gas cost in KWei (default: ${DEFAULT-VALUE})")
private long variableGasCostKwei = DEFAULT_VARIABLE_GAS_COST_KWEI;

@Positive
@CommandLine.Option(
Expand Down Expand Up @@ -151,10 +126,8 @@ public static LineaProfitabilityCliOptions create() {
public static LineaProfitabilityCliOptions fromConfig(
final LineaProfitabilityConfiguration config) {
final LineaProfitabilityCliOptions options = create();
options.verificationGasCost = config.verificationGasCost();
options.verificationCapacity = config.verificationCapacity();
options.gasPriceRatio = config.gasPriceRatio();
options.gasPriceAdjustment = config.gasPriceAdjustment();
options.fixedGasCostKwei = config.fixedCostKWei();
options.variableGasCostKwei = config.variableCostKWei();
options.minMargin = BigDecimal.valueOf(config.minMargin());
options.estimageGasMinMargin = BigDecimal.valueOf(config.estimateGasMinMargin());
options.txPoolMinMargin = BigDecimal.valueOf(config.txPoolMinMargin());
Expand All @@ -170,10 +143,8 @@ public static LineaProfitabilityCliOptions fromConfig(
*/
public LineaProfitabilityConfiguration toDomainObject() {
return LineaProfitabilityConfiguration.builder()
.verificationGasCost(verificationGasCost)
.verificationCapacity(verificationCapacity)
.gasPriceRatio(gasPriceRatio)
.gasPriceAdjustment(gasPriceAdjustment)
.fixedCostKWei(fixedGasCostKwei)
.variableCostKWei(variableGasCostKwei)
.minMargin(minMargin.doubleValue())
.estimateGasMinMargin(estimageGasMinMargin.doubleValue())
.txPoolMinMargin(txPoolMinMargin.doubleValue())
Expand All @@ -185,10 +156,8 @@ public LineaProfitabilityConfiguration toDomainObject() {
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add(VERIFICATION_GAS_COST, verificationGasCost)
.add(VERIFICATION_CAPACITY, verificationCapacity)
.add(GAS_PRICE_RATIO, gasPriceRatio)
.add(GAS_PRICE_ADJUSTMENT, gasPriceAdjustment)
.add(FIXED_GAS_COST_KWEI, fixedGasCostKwei)
.add(VARIABLE_GAS_COST_KWEI, variableGasCostKwei)
.add(MIN_MARGIN, minMargin)
.add(ESTIMATE_GAS_MIN_MARGIN, estimageGasMinMargin)
.add(TX_POOL_MIN_MARGIN, txPoolMinMargin)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,22 @@
package net.consensys.linea.config;

import lombok.Builder;
import org.hyperledger.besu.datatypes.Wei;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

/** The Linea profitability calculator configuration. */
@Builder(toBuilder = true)
public record LineaProfitabilityConfiguration(
int verificationGasCost,
int verificationCapacity,
int gasPriceRatio,
Wei gasPriceAdjustment,
double minMargin,
double estimateGasMinMargin,
double txPoolMinMargin,
boolean txPoolCheckApiEnabled,
boolean txPoolCheckP2pEnabled) {}
@Accessors(fluent = true)
@Getter
@ToString
public class LineaProfitabilityConfiguration {
@Setter private volatile long fixedCostKWei;
@Setter private volatile long variableCostKWei;
double minMargin;
double estimateGasMinMargin;
double txPoolMinMargin;
boolean txPoolCheckApiEnabled;
boolean txPoolCheckP2pEnabled;
}
Loading

0 comments on commit 87567d4

Please sign in to comment.