Skip to content

Commit

Permalink
Add priority fee setting
Browse files Browse the repository at this point in the history
  • Loading branch information
evgeny-stakewise committed Mar 4, 2024
1 parent a4514c7 commit d6e43cb
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 21 deletions.
10 changes: 9 additions & 1 deletion src/commands/start.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,16 @@
'--max-fee-per-gas-gwei',
type=int,
envvar='MAX_FEE_PER_GAS_GWEI',
help=f'Maximum fee per gas limit for transactions. '
help=f'Maximum fee per gas for transactions. '
f'Default is {DEFAULT_MAX_FEE_PER_GAS_GWEI} Gwei.',
default=DEFAULT_MAX_FEE_PER_GAS_GWEI,
)
@click.option(
'--max-priority-fee-per-gas-gwei',
type=int,
envvar='MAX_PRIORITY_FEE_PER_GAS_GWEI',
help='Maximum priority fee per gas for transactions.',
)
@click.option(
'--hot-wallet-password-file',
type=click.Path(exists=True, file_okay=True, dir_okay=False),
Expand Down Expand Up @@ -216,6 +222,7 @@ def start(
hot_wallet_file: str | None,
hot_wallet_password_file: str | None,
max_fee_per_gas_gwei: int,
max_priority_fee_per_gas_gwei: int | None,
database_dir: str | None,
pool_size: int | None,
) -> None:
Expand Down Expand Up @@ -245,6 +252,7 @@ def start(
hot_wallet_file=hot_wallet_file,
hot_wallet_password_file=hot_wallet_password_file,
max_fee_per_gas_gwei=max_fee_per_gas_gwei,
max_priority_fee_per_gas_gwei=max_priority_fee_per_gas_gwei,
database_dir=database_dir,
log_level=log_level,
log_format=log_format,
Expand Down
10 changes: 9 additions & 1 deletion src/commands/start_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,16 @@
'--max-fee-per-gas-gwei',
type=int,
envvar='MAX_FEE_PER_GAS_GWEI',
help=f'Maximum fee per gas limit for transactions. '
help=f'Maximum fee per gas for transactions. '
f'Default is {DEFAULT_MAX_FEE_PER_GAS_GWEI} Gwei.',
default=DEFAULT_MAX_FEE_PER_GAS_GWEI,
)
@click.option(
'--max-priority-fee-per-gas-gwei',
type=int,
envvar='MAX_PRIORITY_FEE_PER_GAS_GWEI',
help='Maximum priority fee per gas for transactions.',
)
@click.option(
'--hot-wallet-password-file',
type=click.Path(exists=True, file_okay=True, dir_okay=False),
Expand Down Expand Up @@ -187,6 +193,7 @@ def start_api(
hot_wallet_file: str | None,
hot_wallet_password_file: str | None,
max_fee_per_gas_gwei: int,
max_priority_fee_per_gas_gwei: int | None,
database_dir: str | None,
api_host: str,
api_port: int,
Expand All @@ -213,6 +220,7 @@ def start_api(
hot_wallet_file=hot_wallet_file,
hot_wallet_password_file=hot_wallet_password_file,
max_fee_per_gas_gwei=max_fee_per_gas_gwei,
max_priority_fee_per_gas_gwei=max_priority_fee_per_gas_gwei,
database_dir=database_dir,
log_level=log_level,
log_format=log_format,
Expand Down
42 changes: 28 additions & 14 deletions src/common/execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import click
from eth_typing import BlockNumber
from web3 import Web3
from web3.exceptions import BadFunctionCallOutput, MethodUnavailable
from web3.types import BlockIdentifier, Wei
from web3._utils.async_transactions import _max_fee_per_gas
from web3.exceptions import BadFunctionCallOutput
from web3.types import BlockIdentifier, TxParams, Wei

from src.common.clients import execution_client, ipfs_fetch_client
from src.common.contracts import keeper_contract, multicall_contract, vault_contract
Expand Down Expand Up @@ -149,8 +150,32 @@ async def get_oracles() -> Oracles:
)


async def get_tx_params() -> TxParams:
tx_params: TxParams = {}

if settings.max_priority_fee_per_gas_gwei:
max_priority_fee_per_gas = Web3.to_wei(settings.max_priority_fee_per_gas_gwei, 'gwei')

# Reference: `_max_fee_per_gas` in web3/_utils/async_transactions.py
block = await execution_client.eth.get_block('latest')
max_fee_per_gas = Wei(max_priority_fee_per_gas + (2 * block['baseFeePerGas']))

tx_params['maxPriorityFeePerGas'] = max_priority_fee_per_gas
tx_params['maxFeePerGas'] = max_fee_per_gas
logger.debug('tx_params %s', tx_params)

return tx_params


async def check_gas_price() -> bool:
max_fee_per_gas = await _get_max_fee_per_gas()
if settings.max_priority_fee_per_gas_gwei:
# custom gas-price logic
tx_params = await get_tx_params()
max_fee_per_gas = Wei(int(tx_params['maxFeePerGas']))
else:
# fallback to logic from web3
max_fee_per_gas = await _max_fee_per_gas(execution_client, {})

if max_fee_per_gas >= Web3.to_wei(settings.max_fee_per_gas_gwei, 'gwei'):
logging.warning(
'Current gas price (%s gwei) is too high. '
Expand All @@ -163,17 +188,6 @@ async def check_gas_price() -> bool:
return True


async def _get_max_fee_per_gas() -> Wei:
try:
priority_fee = await execution_client.eth.max_priority_fee
except MethodUnavailable:
priority_fee = await _calculate_median_priority_fee()
latest_block = await execution_client.eth.get_block('latest')
base_fee = latest_block['baseFeePerGas']
max_fee_per_gas = priority_fee + base_fee
return Wei(max_fee_per_gas)


async def _calculate_median_priority_fee(block_id: BlockIdentifier = 'latest') -> Wei:
block = await execution_client.eth.get_block(block_id)

Expand Down
3 changes: 3 additions & 0 deletions src/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class Settings(metaclass=Singleton):
hot_wallet_file: Path
hot_wallet_password_file: Path
max_fee_per_gas_gwei: int
max_priority_fee_per_gas_gwei: int | None
database: Path

log_level: str
Expand Down Expand Up @@ -91,6 +92,7 @@ def set(
metrics_port: int = DEFAULT_METRICS_PORT,
metrics_host: str = DEFAULT_METRICS_HOST,
max_fee_per_gas_gwei: int = DEFAULT_MAX_FEE_PER_GAS_GWEI,
max_priority_fee_per_gas_gwei: int | None = None,
deposit_data_file: str | None = None,
keystores_dir: str | None = None,
keystores_password_file: str | None = None,
Expand Down Expand Up @@ -121,6 +123,7 @@ def set(
self.metrics_host = metrics_host
self.metrics_port = metrics_port
self.max_fee_per_gas_gwei = max_fee_per_gas_gwei
self.max_priority_fee_per_gas_gwei = max_priority_fee_per_gas_gwei

self.deposit_data_file = (
Path(deposit_data_file) if deposit_data_file else vault_dir / 'deposit_data.json'
Expand Down
4 changes: 3 additions & 1 deletion src/harvest/execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from src.common.clients import execution_client
from src.common.contracts import vault_contract
from src.common.execution import get_tx_params
from src.common.typings import HarvestParams
from src.common.utils import format_error
from src.config.networks import ETH_NETWORKS
Expand All @@ -19,14 +20,15 @@ async def submit_harvest_transaction(harvest_params: HarvestParams) -> HexStr |

logger.info('Submitting harvest transaction...')
try:
tx_params = await get_tx_params()
tx = await vault_contract.functions.updateState(
(
harvest_params.rewards_root,
harvest_params.reward,
harvest_params.unlocked_mev_reward,
harvest_params.proof,
)
).transact()
).transact(tx_params)
except Exception as e:
logger.error('Failed to harvest: %s', format_error(e))
if settings.verbose:
Expand Down
15 changes: 11 additions & 4 deletions src/validators/execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
validators_registry_contract,
vault_contract,
)
from src.common.execution import get_tx_params
from src.common.ipfs import fetch_harvest_params
from src.common.metrics import metrics
from src.common.typings import OraclesApproval
Expand Down Expand Up @@ -249,16 +250,19 @@ async def register_single_validator(
multi_proof.proof,
]
try:
tx_params = await get_tx_params()

if update_state_call is not None:
register_call = vault_contract.encode_abi(
fn_name='registerValidator',
args=register_call_args,
)
tx = await vault_contract.functions.multicall(
[update_state_call, register_call]
).transact()
).transact(tx_params)
else:
tx = await vault_contract.functions.registerValidator(*register_call_args).transact()
register_func = vault_contract.functions.registerValidator
tx = await register_func(*register_call_args).transact(tx_params)
except Exception as e:
logger.error('Failed to register validator: %s', format_error(e))
if settings.verbose:
Expand Down Expand Up @@ -305,16 +309,19 @@ async def register_multiple_validator(
multi_proof.proof,
]
try:
tx_params = await get_tx_params()

if update_state_call is not None:
register_call = vault_contract.encode_abi(
fn_name='registerValidators',
args=register_call_args,
)
tx = await vault_contract.functions.multicall(
[update_state_call, register_call]
).transact()
).transact(tx_params)
else:
tx = await vault_contract.functions.registerValidators(*register_call_args).transact()
register_func = vault_contract.functions.registerValidators
tx = await register_func(*register_call_args).transact(tx_params)
except Exception as e:
logger.error('Failed to register validators: %s', format_error(e))
if settings.verbose:
Expand Down

0 comments on commit d6e43cb

Please sign in to comment.