Skip to content

Commit 3ea2ac7

Browse files
devin-ai-integration[bot]Jayant Krishnamurthyjayantk
authored
feat(fortuna): configurable escalation policy for transactions. (#2244)
* feat: add backoff_gas_multiplier_cap_pct to fortuna config Co-Authored-By: Jayant Krishnamurthy <jayant@dourolabs.xyz> * feat: replace hardcoded gas ceiling with configurable cap in process_event Co-Authored-By: Jayant Krishnamurthy <jayant@dourolabs.xyz> * feat: apply gas multiplier cap in process_event_with_backoff Co-Authored-By: Jayant Krishnamurthy <jayant@dourolabs.xyz> * fix: initialize backoff_gas_multiplier_cap_pct in BlockchainState Co-Authored-By: Jayant Krishnamurthy <jayant@dourolabs.xyz> * gr * make this sane * config defaults --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Jayant Krishnamurthy <jayant@dourolabs.xyz> Co-authored-by: Jayant Krishnamurthy <jayantkrishnamurthy@gmail.com>
1 parent 4a409be commit 3ea2ac7

File tree

5 files changed

+167
-49
lines changed

5 files changed

+167
-49
lines changed

apps/fortuna/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/fortuna/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "fortuna"
3-
version = "6.8.1"
3+
version = "7.0.0"
44
edition = "2021"
55

66
[dependencies]

apps/fortuna/config.sample.yaml

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,32 @@ chains:
66
# Keeper configuration for the chain
77
reveal_delay_blocks: 0
88
gas_limit: 500000
9-
# Increase the transaction gas limit by 10% each time the callback fails
10-
# defaults to 100 (i.e., don't change the gas limit) if not specified.
11-
backoff_gas_multiplier_pct: 110
9+
10+
# Multiplier for the priority fee estimate, as a percentage (i.e., 100 = no change).
11+
# Defaults to 100 if the field is omitted.
12+
priority_fee_multiplier_pct: 100
13+
14+
escalation_policy:
15+
# Pad the first callback transaction's gas estimate by 25%,
16+
# then multiply each successive callback transaction's gas estimate by 10% until the cap is reached.
17+
# All numbers are expressed as percentages where 100 = no change.
18+
initial_gas_multiplier_pct: 125
19+
gas_multiplier_pct: 110
20+
gas_multiplier_cap_pct: 600
21+
22+
# Multiply successive callback transaction's fees by 10% until the cap is reached.
23+
# All numbers are expressed as percentages where 100 = no change.
24+
# (See also priority_fee_multiplier_pct above to generically adjust the priority fee estimates for the chain --
25+
# adjusting that parameter will influence the fee of the first transaction, in addition to other things)
26+
fee_multiplier_pct: 110
27+
fee_multiplier_cap_pct: 200
28+
1229
min_keeper_balance: 100000000000000000
1330

1431
# Provider configuration
1532
# How much to charge in fees
1633
fee: 1500000000000000
1734

18-
# Multiplier for the priority fee estimate, as a percentage (i.e., 100 = no change).
19-
# Defaults to 100 if the field is omitted.
20-
priority_fee_multiplier_pct: 100
21-
2235
# Configuration for dynamic fees under high gas prices. The keeper will set
2336
# on-chain fees to make between [min_profit_pct, max_profit_pct] of the max callback
2437
# cost in profit per transaction.

apps/fortuna/src/config.rs

Lines changed: 100 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,13 @@ pub struct EthereumConfig {
134134
/// The gas limit to use for entropy callback transactions.
135135
pub gas_limit: u64,
136136

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,
140144

141145
/// The minimum percentage profit to earn as a function of the callback cost.
142146
/// For example, 20 means a profit of 20% over the cost of the callback.
@@ -170,16 +174,104 @@ pub struct EthereumConfig {
170174
/// Maximum number of hashes to record in a request.
171175
/// This should be set according to the maximum gas limit the provider supports for callbacks.
172176
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,
177177
}
178178

179-
fn default_backoff_gas_multiplier_pct() -> u64 {
179+
fn default_priority_fee_multiplier_pct() -> u64 {
180180
100
181181
}
182182

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+
183275
/// A commitment that the provider used to generate random numbers at some point in the past.
184276
/// These historical commitments need to be stored in the configuration to support transition points where
185277
/// 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 {
227319
1
228320
}
229321

230-
fn default_priority_fee_multiplier_pct() -> u64 {
231-
100
232-
}
233-
234322
/// Configuration values for the keeper service that are shared across chains.
235323
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
236324
pub struct KeeperConfig {

0 commit comments

Comments
 (0)