Skip to content

Commit 8ab0376

Browse files
feat(aggregator): gas price bump percentage limit (#1445)
Co-authored-by: Julian Arce <[email protected]>
1 parent 6887704 commit 8ab0376

File tree

6 files changed

+46
-4
lines changed

6 files changed

+46
-4
lines changed

aggregator/pkg/aggregator.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ func (agg *Aggregator) sendAggregatedResponse(batchIdentifierHash [32]byte, batc
329329
nonSignerStakesAndSignature,
330330
agg.AggregatorConfig.Aggregator.GasBaseBumpPercentage,
331331
agg.AggregatorConfig.Aggregator.GasBumpIncrementalPercentage,
332+
agg.AggregatorConfig.Aggregator.GasBumpPercentageLimit,
332333
agg.AggregatorConfig.Aggregator.TimeToWaitBeforeBump,
333334
onGasPriceBumped,
334335
)

config-files/config-aggregator.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ aggregator:
4141
gas_base_bump_percentage: 25 # Percentage to overestimate gas price when sending a task
4242
gas_bump_incremental_percentage: 20 # An extra percentage to overestimate in each bump of respond to task. This is additive between tries
4343
# Gas used formula = est_gas_by_node * (gas_base_bump_percentage + gas_bum_incremental_percentage * i) / 100, where i is the iteration number.
44+
gas_bump_percentage_limit: 150 # The max percentage to bump the gas price.
45+
# The Gas formula is percentage (gas_base_bump_percentage + gas_bump_incremental_percentage * i) / 100) is checked against this value
46+
# If it is higher, it will default to `gas_bump_percentage_limit`
4447
time_to_wait_before_bump: 72s # The time to wait for the receipt when responding to task. Suggested value 72 seconds (6 blocks)
4548

4649
## Operator Configurations

core/chainio/avs_writer.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func NewAvsWriterFromConfig(baseConfig *config.BaseConfig, ecdsaConfig *config.E
8989
// - If no receipt is found, but the batch state indicates the response has already been processed, it exits
9090
// without an error (returning `nil, nil`).
9191
// - An error if the process encounters a fatal issue (e.g., permanent failure in verifying balances or state).
92-
func (w *AvsWriter) SendAggregatedResponse(batchIdentifierHash [32]byte, batchMerkleRoot [32]byte, senderAddress [20]byte, nonSignerStakesAndSignature servicemanager.IBLSSignatureCheckerNonSignerStakesAndSignature, gasBumpPercentage uint, gasBumpIncrementalPercentage uint, timeToWaitBeforeBump time.Duration, onGasPriceBumped func(*big.Int)) (*types.Receipt, error) {
92+
func (w *AvsWriter) SendAggregatedResponse(batchIdentifierHash [32]byte, batchMerkleRoot [32]byte, senderAddress [20]byte, nonSignerStakesAndSignature servicemanager.IBLSSignatureCheckerNonSignerStakesAndSignature, gasBumpPercentage uint, gasBumpIncrementalPercentage uint, gasBumpPercentageLimit uint, timeToWaitBeforeBump time.Duration, onGasPriceBumped func(*big.Int)) (*types.Receipt, error) {
9393
txOpts := *w.Signer.GetTxOpts()
9494
txOpts.NoSend = true // simulate the transaction
9595
simTx, err := w.RespondToTaskV2Retryable(&txOpts, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature, retry.SendToChainRetryParams())
@@ -116,11 +116,12 @@ func (w *AvsWriter) SendAggregatedResponse(batchIdentifierHash [32]byte, batchMe
116116
previousTxGasPrice := txOpts.GasPrice
117117
// in order to avoid replacement transaction underpriced
118118
// the bumped gas price has to be at least 10% higher than the previous one.
119-
minimumGasPriceBump := utils.CalculateGasPriceBumpBasedOnRetry(previousTxGasPrice, 10, 0, 0)
119+
minimumGasPriceBump := utils.CalculateGasPriceBumpBasedOnRetry(previousTxGasPrice, 10, 0, gasBumpPercentageLimit, 0)
120120
suggestedBumpedGasPrice := utils.CalculateGasPriceBumpBasedOnRetry(
121121
gasPrice,
122122
gasBumpPercentage,
123123
gasBumpIncrementalPercentage,
124+
gasBumpPercentageLimit,
124125
i,
125126
)
126127
// check the new gas price is sufficiently bumped.

core/config/aggregator.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type AggregatorConfig struct {
2727
BlsServiceTaskTimeout time.Duration
2828
GasBaseBumpPercentage uint
2929
GasBumpIncrementalPercentage uint
30+
GasBumpPercentageLimit uint
3031
TimeToWaitBeforeBump time.Duration
3132
}
3233
}
@@ -45,6 +46,7 @@ type AggregatorConfigFromYaml struct {
4546
BlsServiceTaskTimeout time.Duration `yaml:"bls_service_task_timeout"`
4647
GasBaseBumpPercentage uint `yaml:"gas_base_bump_percentage"`
4748
GasBumpIncrementalPercentage uint `yaml:"gas_bump_incremental_percentage"`
49+
GasBumpPercentageLimit uint `yaml:"gas_bump_percentage_limit"`
4850
TimeToWaitBeforeBump time.Duration `yaml:"time_to_wait_before_bump"`
4951
} `yaml:"aggregator"`
5052
}
@@ -93,6 +95,7 @@ func NewAggregatorConfig(configFilePath string) *AggregatorConfig {
9395
BlsServiceTaskTimeout time.Duration
9496
GasBaseBumpPercentage uint
9597
GasBumpIncrementalPercentage uint
98+
GasBumpPercentageLimit uint
9699
TimeToWaitBeforeBump time.Duration
97100
}(aggregatorConfigFromYaml.Aggregator),
98101
}

core/utils/eth_client_utils.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,19 @@ func WeiToEth(wei *big.Int) float64 {
6363
// Simple algorithm to calculate the gasPrice bump based on:
6464
// the currentGasPrice, a base bump percentage, a retry percentage, and the retry count.
6565
// Formula: currentGasPrice + (currentGasPrice * (baseBumpPercentage + retryCount * incrementalRetryPercentage) / 100)
66-
func CalculateGasPriceBumpBasedOnRetry(currentGasPrice *big.Int, baseBumpPercentage uint, retryAttemptPercentage uint, retryCount int) *big.Int {
66+
func CalculateGasPriceBumpBasedOnRetry(currentGasPrice *big.Int, baseBumpPercentage uint, retryAttemptPercentage uint, bumpPercentageLimit uint, retryCount int) *big.Int {
6767
// Incremental percentage increase for each retry attempt (i*retryAttemptPercentage)
6868
incrementalRetryPercentage := new(big.Int).Mul(big.NewInt(int64(retryAttemptPercentage)), big.NewInt(int64(retryCount)))
6969

7070
// Total bump percentage: base bump + incremental retry percentage
7171
totalBumpPercentage := new(big.Int).Add(big.NewInt(int64(baseBumpPercentage)), incrementalRetryPercentage)
7272

73+
// Make sure the percentage to bump isn't higher than the limit
74+
bumpPercentageLimitAsBigInt := big.NewInt(int64(bumpPercentageLimit))
75+
if totalBumpPercentage.Cmp(bumpPercentageLimitAsBigInt) > 0 {
76+
totalBumpPercentage = bumpPercentageLimitAsBigInt
77+
}
78+
7379
// Calculate the bump amount: currentGasPrice * totalBumpPercentage / 100
7480
bumpAmount := new(big.Int).Mul(currentGasPrice, totalBumpPercentage)
7581
bumpAmount = new(big.Int).Div(bumpAmount, big.NewInt(100))

core/utils/eth_client_utils_test.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,40 @@ func TestCalculateGasPriceBumpBasedOnRetry(t *testing.T) {
2727

2828
for i := 0; i < len(gasPrices); i++ {
2929
currentGasPrice := gasPrices[i]
30-
bumpedGasPrice := utils.CalculateGasPriceBumpBasedOnRetry(currentGasPrice, baseBumpPercentage, incrementalRetryPercentage, i)
30+
bumpedGasPrice := utils.CalculateGasPriceBumpBasedOnRetry(currentGasPrice, baseBumpPercentage, incrementalRetryPercentage, 100, i)
3131
expectedGasPrice := expectedBumpedGasPrices[i]
3232

3333
if bumpedGasPrice.Cmp(expectedGasPrice) != 0 {
3434
t.Errorf("Bumped gas price does not match expected gas price, expected value %v, got: %v", expectedGasPrice, bumpedGasPrice)
3535
}
3636
}
37+
}
38+
39+
func TestCalculateGasPriceBumpBasedOnRetryPercentageLimit(t *testing.T) {
40+
baseBumpPercentage := uint(20)
41+
incrementalRetryPercentage := uint(5)
3742

43+
gasPrices := [5]*big.Int{
44+
big.NewInt(3000000000),
45+
big.NewInt(3000000000),
46+
big.NewInt(4000000000),
47+
big.NewInt(4000000000),
48+
big.NewInt(5000000000)}
49+
50+
expectedBumpedGasPrices := [5]*big.Int{
51+
big.NewInt(3600000000),
52+
big.NewInt(3750000000),
53+
big.NewInt(5200000000),
54+
big.NewInt(5200000000),
55+
big.NewInt(6500000000)}
56+
57+
for i := 0; i < len(gasPrices); i++ {
58+
currentGasPrice := gasPrices[i]
59+
bumpedGasPrice := utils.CalculateGasPriceBumpBasedOnRetry(currentGasPrice, baseBumpPercentage, incrementalRetryPercentage, 30, i)
60+
expectedGasPrice := expectedBumpedGasPrices[i]
61+
62+
if bumpedGasPrice.Cmp(expectedGasPrice) != 0 {
63+
t.Errorf("Bumped gas price does not match expected gas price, expected value %v, got: %v", expectedGasPrice, bumpedGasPrice)
64+
}
65+
}
3866
}

0 commit comments

Comments
 (0)