Skip to content

Commit 9a1f7ff

Browse files
ahhdasquadgazzz
andcommitted
refunder: Make gas price parameters configurable (#3897)
## Problem The refunder was experiencing issues with hardcoded gas price parameters that were too low for current network conditions: ### Errors observed: 1. `Refunding txs are likely not mined in time, as the current gas price 826120518137.4663 is higher than MAX_GAS_PRICE specified 800000000000` 2. `transaction gas price below minimum: gas tip cap 5773015156, minimum needed 25000000000` ### Root cause: - `MAX_GAS_PRICE` was hardcoded to 800 Gwei (current gas prices ~826 Gwei) - `START_PRIORITY_FEE_TIP` was hardcoded to 2 Gwei (node requires minimum 25 Gwei) ## Solution This PR makes both gas price parameters configurable via CLI arguments or environment variables: - `--max-gas-price` / `MAX_GAS_PRICE` (default: 2000 Gwei / 2,000,000,000,000 wei) - `--start-priority-fee-tip` / `START_PRIORITY_FEE_TIP` (default: 30 Gwei / 30,000,000,000 wei) The new defaults are set higher to accommodate current network conditions while still being configurable for future adjustments. ## Changes - Added two new CLI arguments with environment variable support - Refactored `Submitter` and `RefundService` to accept configurable parameters - Updated tests to use test-specific constants - Updated argument display formatting to show new parameters ## Testing - [x] Code compiles successfully (`cargo check -p refunder`) - [x] No linter errors - [x] Unit tests updated and passing --------- Co-authored-by: ilya <[email protected]>
1 parent 3bafecb commit 9a1f7ff

File tree

5 files changed

+52
-15
lines changed

5 files changed

+52
-15
lines changed

crates/e2e/tests/e2e/refunder.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ async fn refunder_tx(web3: Web3) {
142142
validity_duration as i64 / 2,
143143
10i64,
144144
refunder_signer,
145+
2_000_000_000_000, // max_gas_price: 2000 Gwei
146+
30_000_000_000, // start_priority_fee_tip: 30 Gwei
145147
);
146148

147149
assert_ne!(

crates/refunder/src/arguments.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ pub struct Arguments {
6666
/// The port at which we serve our metrics
6767
#[clap(long, env, default_value = "9590")]
6868
pub metrics_port: u16,
69+
70+
/// Maximum gas price (in wei) for submitting refund transactions
71+
/// Default is 2000 Gwei (2_000_000_000_000 wei)
72+
#[clap(long, env, default_value = "2000000000000")]
73+
pub max_gas_price: u64,
74+
75+
/// Starting priority fee tip (in wei) for refund transactions
76+
/// Default is 30 Gwei (30_000_000_000 wei)
77+
#[clap(long, env, default_value = "30000000000")]
78+
pub start_priority_fee_tip: u64,
6979
}
7080

7181
impl std::fmt::Display for Arguments {
@@ -82,6 +92,8 @@ impl std::fmt::Display for Arguments {
8292
logging,
8393
db_url,
8494
refunder_pk,
95+
max_gas_price,
96+
start_priority_fee_tip,
8597
} = self;
8698

8799
write!(f, "{http_client}")?;
@@ -97,6 +109,8 @@ impl std::fmt::Display for Arguments {
97109
let _intentionally_ignored = refunder_pk;
98110
writeln!(f, "refunder_pk: SECRET")?;
99111
writeln!(f, "metrics_port: {metrics_port}")?;
112+
writeln!(f, "max_gas_price: {max_gas_price}")?;
113+
writeln!(f, "start_priority_fee_tip: {start_priority_fee_tip}")?;
100114
Ok(())
101115
}
102116
}

crates/refunder/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ pub async fn run(args: arguments::Arguments) {
8181
i64::try_from(args.min_validity_duration.as_secs()).unwrap_or(i64::MAX),
8282
args.min_price_deviation_bps,
8383
refunder_account,
84+
args.max_gas_price,
85+
args.start_priority_fee_tip,
8486
);
8587
loop {
8688
tracing::info!("Staring a new refunding loop");

crates/refunder/src/refund_service.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ pub struct RefundService {
3131
pub min_validity_duration: i64,
3232
pub min_price_deviation: f64,
3333
pub submitter: Submitter,
34+
pub max_gas_price: u64,
35+
pub start_priority_fee_tip: u64,
3436
}
3537

3638
#[derive(Debug, Eq, PartialEq)]
@@ -41,13 +43,16 @@ enum RefundStatus {
4143
}
4244

4345
impl RefundService {
46+
#[allow(clippy::too_many_arguments)]
4447
pub fn new(
4548
db: PgPool,
4649
web3: Web3,
4750
ethflow_contracts: Vec<CoWSwapEthFlow::Instance>,
4851
min_validity_duration: i64,
4952
min_price_deviation_bps: i64,
5053
signer: Box<dyn TxSigner<Signature> + Send + Sync + 'static>,
54+
max_gas_price: u64,
55+
start_priority_fee_tip: u64,
5156
) -> Self {
5257
let signer_address = signer.address();
5358
let gas_estimator = Box::new(web3.legacy.clone());
@@ -58,12 +63,16 @@ impl RefundService {
5863
ethflow_contracts,
5964
min_validity_duration,
6065
min_price_deviation: min_price_deviation_bps as f64 / 10000f64,
66+
max_gas_price,
67+
start_priority_fee_tip,
6168
submitter: Submitter {
6269
web3,
6370
signer_address,
6471
gas_estimator,
6572
gas_parameters_of_last_tx: None,
6673
nonce_of_last_submission: None,
74+
max_gas_price,
75+
start_priority_fee_tip,
6776
},
6877
}
6978
}

crates/refunder/src/submitter.rs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,11 @@ use {
1818
std::time::Duration,
1919
};
2020

21-
// Max gas price used for submitting transactions
22-
const MAX_GAS_PRICE: u64 = 800_000_000_000;
23-
2421
// The gas price buffer determines the gas price buffer used to
2522
// send out EIP1559 txs.
2623
// Example: If the prevailing gas is 10Gwei and the buffer factor is 1.20
2724
// then the gas_price used will be 12.
2825
const GAS_PRICE_BUFFER_FACTOR: f64 = 1.3;
29-
// Starting priority fee that the refunder is willing to pay. (=2 Gwei)
30-
const START_PRIORITY_FEE_TIP: u64 = 2_000_000_000;
3126

3227
// In order to resubmit a new tx with the same nonce, the gas tip and
3328
// max_fee_per_gas needs to be increased by at least 10 percent.
@@ -44,6 +39,8 @@ pub struct Submitter {
4439
pub gas_estimator: Box<dyn GasPriceEstimating>,
4540
pub gas_parameters_of_last_tx: Option<GasPrice1559>,
4641
pub nonce_of_last_submission: Option<u64>,
42+
pub max_gas_price: u64,
43+
pub start_priority_fee_tip: u64,
4744
}
4845

4946
impl Submitter {
@@ -77,6 +74,8 @@ impl Submitter {
7774
gas_price_estimation,
7875
nonce,
7976
self.nonce_of_last_submission,
77+
self.max_gas_price,
78+
self.start_priority_fee_tip,
8079
)?;
8180

8281
self.gas_parameters_of_last_tx = Some(gas_price);
@@ -113,13 +112,15 @@ fn calculate_submission_gas_price(
113112
web3_gas_estimation: GasPrice1559,
114113
newest_nonce: u64,
115114
nonce_of_last_submission: Option<u64>,
115+
max_gas_price: u64,
116+
start_priority_fee_tip: u64,
116117
) -> Result<GasPrice1559> {
117118
// The gas price of the refund tx is the current prevailing gas price
118119
// of the web3 gas estimation plus a buffer.
119120
let mut new_gas_price = web3_gas_estimation.bump(GAS_PRICE_BUFFER_FACTOR);
120121
// limit the prio_fee to max_fee_per_gas as otherwise tx is invalid
121122
new_gas_price.max_priority_fee_per_gas =
122-
(START_PRIORITY_FEE_TIP as f64).min(new_gas_price.max_fee_per_gas);
123+
(start_priority_fee_tip as f64).min(new_gas_price.max_fee_per_gas);
123124

124125
// If tx from the previous submission was not mined,
125126
// we incease the tip and max_gas_fee for miners
@@ -136,15 +137,15 @@ fn calculate_submission_gas_price(
136137
.max(gas_price_of_last_submission.max_priority_fee_per_gas);
137138
}
138139

139-
if new_gas_price.max_fee_per_gas > MAX_GAS_PRICE as f64 {
140+
if new_gas_price.max_fee_per_gas > max_gas_price as f64 {
140141
tracing::warn!(
141142
"Refunding txs are likely not mined in time, as the current gas price {:?} is higher \
142143
than MAX_GAS_PRICE specified {:?}",
143144
new_gas_price.max_fee_per_gas,
144-
MAX_GAS_PRICE
145+
max_gas_price
145146
);
146147
new_gas_price.max_fee_per_gas =
147-
f64::min(MAX_GAS_PRICE as f64, new_gas_price.max_fee_per_gas);
148+
f64::min(max_gas_price as f64, new_gas_price.max_fee_per_gas);
148149
}
149150
new_gas_price.max_priority_fee_per_gas = f64::min(
150151
new_gas_price.max_priority_fee_per_gas,
@@ -159,6 +160,9 @@ mod tests {
159160

160161
#[test]
161162
fn test_calculate_submission_gas_price() {
163+
const TEST_MAX_GAS_PRICE: u64 = 800_000_000_000;
164+
const TEST_START_PRIORITY_FEE_TIP: u64 = 2_000_000_000;
165+
162166
// First case: previous tx was successful
163167
let max_fee_per_gas = 4_000_000_000f64;
164168
let web3_gas_estimation = GasPrice1559 {
@@ -174,11 +178,13 @@ mod tests {
174178
web3_gas_estimation,
175179
newest_nonce,
176180
nonce_of_last_submission,
181+
TEST_MAX_GAS_PRICE,
182+
TEST_START_PRIORITY_FEE_TIP,
177183
)
178184
.unwrap();
179185
let expected_result = GasPrice1559 {
180186
max_fee_per_gas: max_fee_per_gas * GAS_PRICE_BUFFER_FACTOR,
181-
max_priority_fee_per_gas: START_PRIORITY_FEE_TIP as f64,
187+
max_priority_fee_per_gas: TEST_START_PRIORITY_FEE_TIP as f64,
182188
base_fee_per_gas: 2_000_000_000f64,
183189
};
184190
assert_eq!(result, expected_result);
@@ -187,24 +193,26 @@ mod tests {
187193
let max_fee_per_gas_of_last_tx = max_fee_per_gas * 2f64;
188194
let gas_price_of_last_submission = GasPrice1559 {
189195
max_fee_per_gas: max_fee_per_gas_of_last_tx,
190-
max_priority_fee_per_gas: START_PRIORITY_FEE_TIP as f64,
196+
max_priority_fee_per_gas: TEST_START_PRIORITY_FEE_TIP as f64,
191197
base_fee_per_gas: 2_000_000_000f64,
192198
};
193199
let result = calculate_submission_gas_price(
194200
Some(gas_price_of_last_submission),
195201
web3_gas_estimation,
196202
newest_nonce,
197203
nonce_of_last_submission,
204+
TEST_MAX_GAS_PRICE,
205+
TEST_START_PRIORITY_FEE_TIP,
198206
)
199207
.unwrap();
200208
let expected_result = GasPrice1559 {
201209
max_fee_per_gas: max_fee_per_gas_of_last_tx * GAS_PRICE_BUMP,
202-
max_priority_fee_per_gas: START_PRIORITY_FEE_TIP as f64 * GAS_PRICE_BUMP,
210+
max_priority_fee_per_gas: TEST_START_PRIORITY_FEE_TIP as f64 * GAS_PRICE_BUMP,
203211
base_fee_per_gas: 2_000_000_000f64,
204212
};
205213
assert_eq!(result, expected_result);
206214
// Thrid case: MAX_GAS_PRICE is not exceeded
207-
let max_fee_per_gas = MAX_GAS_PRICE as f64 + 1000f64;
215+
let max_fee_per_gas = TEST_MAX_GAS_PRICE as f64 + 1000f64;
208216
let web3_gas_estimation = GasPrice1559 {
209217
base_fee_per_gas: 2_000_000_000f64,
210218
max_fee_per_gas,
@@ -217,12 +225,14 @@ mod tests {
217225
web3_gas_estimation,
218226
newest_nonce,
219227
nonce_of_last_submission,
228+
TEST_MAX_GAS_PRICE,
229+
TEST_START_PRIORITY_FEE_TIP,
220230
)
221231
.unwrap();
222232
let expected_result = GasPrice1559 {
223233
base_fee_per_gas: 2_000_000_000f64,
224-
max_fee_per_gas: MAX_GAS_PRICE as f64,
225-
max_priority_fee_per_gas: START_PRIORITY_FEE_TIP as f64,
234+
max_fee_per_gas: TEST_MAX_GAS_PRICE as f64,
235+
max_priority_fee_per_gas: TEST_START_PRIORITY_FEE_TIP as f64,
226236
};
227237
assert_eq!(result, expected_result);
228238
}

0 commit comments

Comments
 (0)