@@ -134,9 +134,13 @@ pub struct EthereumConfig {
134
134
/// The gas limit to use for entropy callback transactions.
135
135
pub gas_limit : u64 ,
136
136
137
- /// The percentage multiplier to apply to the gas limit for each backoff.
138
- #[ serde( default = "default_backoff_gas_multiplier_pct" ) ]
139
- pub backoff_gas_multiplier_pct : u64 ,
137
+ /// The percentage multiplier to apply to priority fee estimates (100 = no change, e.g. 150 = 150% of base fee)
138
+ #[ serde( default = "default_priority_fee_multiplier_pct" ) ]
139
+ pub priority_fee_multiplier_pct : u64 ,
140
+
141
+ /// The escalation policy governs how the gas limit and fee are increased during backoff retries.
142
+ #[ serde( default ) ]
143
+ pub escalation_policy : EscalationPolicyConfig ,
140
144
141
145
/// The minimum percentage profit to earn as a function of the callback cost.
142
146
/// For example, 20 means a profit of 20% over the cost of the callback.
@@ -170,16 +174,104 @@ pub struct EthereumConfig {
170
174
/// Maximum number of hashes to record in a request.
171
175
/// This should be set according to the maximum gas limit the provider supports for callbacks.
172
176
pub max_num_hashes : Option < u32 > ,
173
-
174
- /// The percentage multiplier to apply to the priority fee (100 = no change, e.g. 150 = 150% of base fee)
175
- #[ serde( default = "default_priority_fee_multiplier_pct" ) ]
176
- pub priority_fee_multiplier_pct : u64 ,
177
177
}
178
178
179
- fn default_backoff_gas_multiplier_pct ( ) -> u64 {
179
+ fn default_priority_fee_multiplier_pct ( ) -> u64 {
180
180
100
181
181
}
182
182
183
+ #[ derive( Clone , Debug , serde:: Serialize , serde:: Deserialize ) ]
184
+ pub struct EscalationPolicyConfig {
185
+ /// The initial gas multiplier to apply to the gas limit.
186
+ #[ serde( default = "default_initial_gas_multiplier_pct" ) ]
187
+ pub initial_gas_multiplier_pct : u64 ,
188
+
189
+ /// The gas multiplier to apply to the gas limit during backoff retries.
190
+ /// The gas on each successive retry is multiplied by this value, with the maximum multiplier capped at `gas_multiplier_cap_pct`.
191
+ #[ serde( default = "default_gas_multiplier_pct" ) ]
192
+ pub gas_multiplier_pct : u64 ,
193
+ /// The maximum gas multiplier to apply to the gas limit during backoff retries.
194
+ #[ serde( default = "default_gas_multiplier_cap_pct" ) ]
195
+ pub gas_multiplier_cap_pct : u64 ,
196
+
197
+ /// The fee multiplier to apply to the fee during backoff retries.
198
+ /// The initial fee is 100% of the estimate (which itself may be padded based on our chain configuration)
199
+ /// The fee on each successive retry is multiplied by this value, with the maximum multiplier capped at `fee_multiplier_cap_pct`.
200
+ #[ serde( default = "default_fee_multiplier_pct" ) ]
201
+ pub fee_multiplier_pct : u64 ,
202
+ #[ serde( default = "default_fee_multiplier_cap_pct" ) ]
203
+ pub fee_multiplier_cap_pct : u64 ,
204
+ }
205
+
206
+ fn default_initial_gas_multiplier_pct ( ) -> u64 {
207
+ 125
208
+ }
209
+
210
+ fn default_gas_multiplier_pct ( ) -> u64 {
211
+ 110
212
+ }
213
+
214
+ fn default_gas_multiplier_cap_pct ( ) -> u64 {
215
+ 600
216
+ }
217
+
218
+ fn default_fee_multiplier_pct ( ) -> u64 {
219
+ 110
220
+ }
221
+
222
+ fn default_fee_multiplier_cap_pct ( ) -> u64 {
223
+ 200
224
+ }
225
+
226
+ impl Default for EscalationPolicyConfig {
227
+ fn default ( ) -> Self {
228
+ Self {
229
+ initial_gas_multiplier_pct : default_initial_gas_multiplier_pct ( ) ,
230
+ gas_multiplier_pct : default_gas_multiplier_pct ( ) ,
231
+ gas_multiplier_cap_pct : default_gas_multiplier_cap_pct ( ) ,
232
+ fee_multiplier_pct : default_fee_multiplier_pct ( ) ,
233
+ fee_multiplier_cap_pct : default_fee_multiplier_cap_pct ( ) ,
234
+ }
235
+ }
236
+ }
237
+
238
+ impl EscalationPolicyConfig {
239
+ pub fn get_gas_multiplier_pct ( & self , num_retries : u64 ) -> u64 {
240
+ self . apply_escalation_policy (
241
+ num_retries,
242
+ self . initial_gas_multiplier_pct ,
243
+ self . gas_multiplier_pct ,
244
+ self . gas_multiplier_cap_pct ,
245
+ )
246
+ }
247
+
248
+ pub fn get_fee_multiplier_pct ( & self , num_retries : u64 ) -> u64 {
249
+ self . apply_escalation_policy (
250
+ num_retries,
251
+ 100 ,
252
+ self . fee_multiplier_pct ,
253
+ self . fee_multiplier_cap_pct ,
254
+ )
255
+ }
256
+
257
+ fn apply_escalation_policy (
258
+ & self ,
259
+ num_retries : u64 ,
260
+ initial : u64 ,
261
+ multiplier : u64 ,
262
+ cap : u64 ,
263
+ ) -> u64 {
264
+ let mut current = initial;
265
+ let mut i = 0 ;
266
+ while i < num_retries && current < cap {
267
+ current = current. saturating_mul ( multiplier) / 100 ;
268
+ i += 1 ;
269
+ }
270
+
271
+ current. min ( cap)
272
+ }
273
+ }
274
+
183
275
/// A commitment that the provider used to generate random numbers at some point in the past.
184
276
/// These historical commitments need to be stored in the configuration to support transition points where
185
277
/// the commitment changes. In theory, this information is stored on the blockchain, but unfortunately it
@@ -227,10 +319,6 @@ fn default_chain_sample_interval() -> u64 {
227
319
1
228
320
}
229
321
230
- fn default_priority_fee_multiplier_pct ( ) -> u64 {
231
- 100
232
- }
233
-
234
322
/// Configuration values for the keeper service that are shared across chains.
235
323
#[ derive( Clone , Debug , serde:: Serialize , serde:: Deserialize ) ]
236
324
pub struct KeeperConfig {
0 commit comments