Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/fortuna/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/fortuna/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fortuna"
version = "7.1.0"
version = "7.3.0"
edition = "2021"

[dependencies]
Expand Down
31 changes: 22 additions & 9 deletions apps/fortuna/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,23 @@ pub struct EthereumConfig {
pub escalation_policy: EscalationPolicyConfig,

/// The minimum percentage profit to earn as a function of the callback cost.
/// For example, 20 means a profit of 20% over the cost of the callback.
/// For example, 20 means a profit of 20% over the cost of a callback that uses the full gas limit.
/// The fee will be raised if the profit is less than this number.
pub min_profit_pct: u64,
/// The minimum value for this is -100. If set to < 0, it means the keeper may lose money on callbacks that use the full gas limit.
pub min_profit_pct: i64,

/// The target percentage profit to earn as a function of the callback cost.
/// For example, 20 means a profit of 20% over the cost of the callback.
/// For example, 20 means a profit of 20% over the cost of a callback that uses the full gas limit.
/// The fee will be set to this target whenever it falls outside the min/max bounds.
pub target_profit_pct: u64,
/// The minimum value for this is -100. If set to < 0, it means the keeper may lose money on callbacks that use the full gas limit.
pub target_profit_pct: i64,

/// The maximum percentage profit to earn as a function of the callback cost.
/// For example, 100 means a profit of 100% over the cost of the callback.
/// For example, 100 means a profit of 100% over the cost of a callback that uses the full gas limit.
/// The fee will be lowered if it is more profitable than specified here.
/// Must be larger than min_profit_pct.
pub max_profit_pct: u64,
/// The minimum value for this is -100. If set to < 0, it means the keeper may lose money on callbacks that use the full gas limit.
pub max_profit_pct: i64,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(In hindsight, I wish that i had specified these values as multipliers, so 0 would be the natural lower bound and you could just say "75" instead of "-25". That's how I did the other scalars and it would have been better here.

However, I'm choosing to support up to -100 now in order to maintain backward compatibility on the config format)


/// Minimum wallet balance for the keeper. If the balance falls below this level, the keeper will
/// withdraw fees from the contract to top up. This functionality requires the keeper to be the fee
Expand All @@ -182,15 +185,20 @@ fn default_priority_fee_multiplier_pct() -> u64 {

#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct EscalationPolicyConfig {
/// The initial gas multiplier to apply to the gas limit.
// The keeper will perform the callback as long as the tx is within this percentage of the configured gas limit.
// Default value is 110, meaning a 10% tolerance over the configured value.
#[serde(default = "default_gas_limit_tolerance_pct")]
pub gas_limit_tolerance_pct: u64,

/// The initial gas multiplier to apply to the tx gas estimate
#[serde(default = "default_initial_gas_multiplier_pct")]
pub initial_gas_multiplier_pct: u64,

/// The gas multiplier to apply to the gas limit during backoff retries.
/// The gas multiplier to apply to the tx gas estimate during backoff retries.
/// The gas on each successive retry is multiplied by this value, with the maximum multiplier capped at `gas_multiplier_cap_pct`.
#[serde(default = "default_gas_multiplier_pct")]
pub gas_multiplier_pct: u64,
/// The maximum gas multiplier to apply to the gas limit during backoff retries.
/// The maximum gas multiplier to apply to the tx gas estimate during backoff retries.
#[serde(default = "default_gas_multiplier_cap_pct")]
pub gas_multiplier_cap_pct: u64,

Expand All @@ -203,6 +211,10 @@ pub struct EscalationPolicyConfig {
pub fee_multiplier_cap_pct: u64,
}

fn default_gas_limit_tolerance_pct() -> u64 {
110
}

fn default_initial_gas_multiplier_pct() -> u64 {
125
}
Expand All @@ -226,6 +238,7 @@ fn default_fee_multiplier_cap_pct() -> u64 {
impl Default for EscalationPolicyConfig {
fn default() -> Self {
Self {
gas_limit_tolerance_pct: default_gas_limit_tolerance_pct(),
initial_gas_multiplier_pct: default_initial_gas_multiplier_pct(),
gas_multiplier_pct: default_gas_multiplier_pct(),
gas_multiplier_cap_pct: default_gas_multiplier_cap_pct(),
Expand Down
15 changes: 8 additions & 7 deletions apps/fortuna/src/keeper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,10 @@ pub async fn run_keeper_threads(
// In the unlikely event that the keeper fees aren't sufficient, the solution to this is to configure the target
// fee percentage to be higher on that specific chain.
chain_eth_config.gas_limit,
chain_eth_config.min_profit_pct,
chain_eth_config.target_profit_pct,
chain_eth_config.max_profit_pct,
// NOTE: unwrap() here so we panic early if someone configures these values below -100.
u64::try_from(100 + chain_eth_config.min_profit_pct).unwrap(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe just switch to expect to give more context

u64::try_from(100 + chain_eth_config.target_profit_pct).unwrap(),
u64::try_from(100 + chain_eth_config.max_profit_pct).unwrap(),
chain_eth_config.fee,
)
.in_current_span(),
Expand Down Expand Up @@ -435,7 +436,7 @@ pub async fn process_event_with_backoff(
&event,
&chain_state,
&contract,
gas_limit,
gas_limit.saturating_mul(escalation_policy.gas_limit_tolerance_pct.into()) / 100,
gas_multiplier_pct,
fee_multiplier_pct,
metrics.clone(),
Expand Down Expand Up @@ -1253,15 +1254,15 @@ pub async fn adjust_fee_if_necessary(
.await
.map_err(|e| anyhow!("Could not estimate transaction cost. error {:?}", e))?;
let target_fee_min = std::cmp::max(
(max_callback_cost * (100 + u128::from(min_profit_pct))) / 100,
(max_callback_cost * u128::from(min_profit_pct)) / 100,
min_fee_wei,
);
let target_fee = std::cmp::max(
(max_callback_cost * (100 + u128::from(target_profit_pct))) / 100,
(max_callback_cost * u128::from(target_profit_pct)) / 100,
min_fee_wei,
);
let target_fee_max = std::cmp::max(
(max_callback_cost * (100 + u128::from(max_profit_pct))) / 100,
(max_callback_cost * u128::from(max_profit_pct)) / 100,
min_fee_wei,
);

Expand Down
Loading