diff --git a/src/blockchain/deposit_strategy/base_deposit_strategy.py b/src/blockchain/deposit_strategy/base_deposit_strategy.py index 780283a2..113a6c93 100644 --- a/src/blockchain/deposit_strategy/base_deposit_strategy.py +++ b/src/blockchain/deposit_strategy/base_deposit_strategy.py @@ -1,21 +1,58 @@ import logging +import variables +from blockchain.deposit_strategy.gas_price_calculator import GasPriceCalculator +from blockchain.deposit_strategy.strategy import DepositStrategy from blockchain.typings import Web3 -from metrics.metrics import DEPOSITABLE_ETHER, POSSIBLE_DEPOSITS_AMOUNT +from metrics.metrics import DEPOSIT_AMOUNT_OK, DEPOSITABLE_ETHER, GAS_FEE, GAS_OK, POSSIBLE_DEPOSITS_AMOUNT from web3.types import Wei logger = logging.getLogger(__name__) -class BaseDepositStrategy: - """ - Attributes: - DEPOSITABLE_KEYS_THRESHOLD: If the Staking Module has at least THRESHOLD amount of depositable keys, deposits are allowed - """ - DEPOSITABLE_KEYS_THRESHOLD = 1 - - def __init__(self, w3: Web3): +class BaseDepositStrategy(DepositStrategy): + def __init__(self, w3: Web3, gas_price_calculator: GasPriceCalculator): self.w3 = w3 + self._gas_price_calculator = gas_price_calculator + + def can_deposit_keys_based_on_ether(self, module_id: int) -> bool: + possible_keys = self.deposited_keys_amount(module_id) + success = False + threshold = self._depositable_keys_threshold() + if possible_keys < threshold: + logger.info( + { + 'msg': f'Possible deposits amount is {possible_keys}. Skip deposit.', + 'module_id': module_id, + 'threshold': threshold, + } + ) + else: + base_fee_per_gas = self._gas_price_calculator.get_pending_base_fee() + success = self.is_deposit_recommended_based_on_keys_amount(possible_keys, base_fee_per_gas, module_id) + DEPOSIT_AMOUNT_OK.labels(module_id).set(int(success)) + return success + + def is_gas_price_ok(self, module_id: int) -> bool: + """ + Determines if the gas price is ok for doing a deposit. + """ + current_gas_fee = self._gas_price_calculator.get_pending_base_fee() + GAS_FEE.labels('current_fee', module_id).set(current_gas_fee) + + current_buffered_ether = self.w3.lido.lido.get_depositable_ether() + if current_buffered_ether > variables.MAX_BUFFERED_ETHERS: + success = current_gas_fee <= variables.MAX_GAS_FEE + else: + recommended_gas_fee = self._gas_price_calculator.get_recommended_gas_fee() + GAS_FEE.labels('recommended_fee', module_id).set(recommended_gas_fee) + GAS_FEE.labels('max_fee', module_id).set(variables.MAX_GAS_FEE) + success = recommended_gas_fee >= current_gas_fee + GAS_OK.labels(module_id).set(int(success)) + return success + + def _depositable_keys_threshold(self) -> int: + return 1 def _depositable_ether(self) -> Wei: depositable_ether = self.w3.lido.lido.get_depositable_ether() @@ -31,6 +68,19 @@ def deposited_keys_amount(self, module_id: int) -> int: POSSIBLE_DEPOSITS_AMOUNT.labels(module_id, 0).set(possible_deposits_amount) return possible_deposits_amount + def is_deposit_recommended_based_on_keys_amount(self, deposits_amount: int, base_fee: int, module_id: int) -> bool: + return self._recommended_max_gas(deposits_amount, module_id) >= base_fee + + @staticmethod + def _recommended_max_gas(deposits_amount: int, module_id: int): + # For one key recommended gas fee will be around 10 + # For 10 keys around 100 gwei. For 20 keys ~ 800 gwei + # ToDo percentiles for all modules? + recommended_max_gas = (deposits_amount**3 + 100) * 10**8 + logger.info({'msg': 'Calculate recommended max gas based on possible deposits.', 'value': recommended_max_gas}) + GAS_FEE.labels('based_on_buffer_fee', module_id).set(recommended_max_gas) + return recommended_max_gas + class MellowDepositStrategy(BaseDepositStrategy): """ @@ -58,3 +108,11 @@ def deposited_keys_amount(self, module_id: int) -> int: ) POSSIBLE_DEPOSITS_AMOUNT.labels(module_id, 1).set(possible_deposits_amount) return possible_deposits_amount if possible_deposits_amount_assumption == possible_deposits_amount else 0 + + +class CSMDepositStrategy(BaseDepositStrategy): + def is_deposit_recommended_based_on_keys_amount(self, deposits_amount: int, base_fee: int, module_id: int) -> bool: + return True + + def _depositable_keys_threshold(self) -> int: + return 2 diff --git a/src/blockchain/deposit_strategy/gas_price_calculator.py b/src/blockchain/deposit_strategy/gas_price_calculator.py index 5aa3c9c3..d8fed486 100644 --- a/src/blockchain/deposit_strategy/gas_price_calculator.py +++ b/src/blockchain/deposit_strategy/gas_price_calculator.py @@ -5,10 +5,8 @@ import numpy import variables -from blockchain.deposit_strategy.base_deposit_strategy import BaseDepositStrategy from blockchain.typings import Web3 from eth_typing import BlockNumber -from metrics.metrics import DEPOSIT_AMOUNT_OK, GAS_FEE, GAS_OK from web3.types import Wei logger = logging.getLogger(__name__) @@ -21,61 +19,12 @@ class GasPriceCalculator: def __init__(self, w3: Web3): self.w3 = w3 - def is_gas_price_ok(self, module_id: int) -> bool: - """ - Determines if the gas price is ok for doing a deposit. - """ - current_gas_fee = self._get_pending_base_fee() - GAS_FEE.labels('current_fee', module_id).set(current_gas_fee) - - current_buffered_ether = self.w3.lido.lido.get_depositable_ether() - if current_buffered_ether > variables.MAX_BUFFERED_ETHERS: - success = current_gas_fee <= variables.MAX_GAS_FEE - else: - recommended_gas_fee = self._get_recommended_gas_fee() - GAS_FEE.labels('recommended_fee', module_id).set(recommended_gas_fee) - GAS_FEE.labels('max_fee', module_id).set(variables.MAX_GAS_FEE) - success = recommended_gas_fee >= current_gas_fee - GAS_OK.labels(module_id).set(int(success)) - return success - - def _get_pending_base_fee(self) -> Wei: + def get_pending_base_fee(self) -> Wei: base_fee_per_gas = self.w3.eth.get_block('pending')['baseFeePerGas'] logger.info({'msg': 'Fetch base_fee_per_gas for pending block.', 'value': base_fee_per_gas}) return base_fee_per_gas - def calculate_deposit_recommendation(self, deposit_strategy: BaseDepositStrategy, module_id: int) -> bool: - possible_keys = deposit_strategy.deposited_keys_amount(module_id) - success = False - if possible_keys < deposit_strategy.DEPOSITABLE_KEYS_THRESHOLD: - logger.info( - { - 'msg': f'Possible deposits amount is {possible_keys}. Skip deposit.', - 'module_id': module_id, - 'threshold': deposit_strategy.DEPOSITABLE_KEYS_THRESHOLD, - } - ) - else: - recommended_max_gas = GasPriceCalculator._calculate_recommended_gas_based_on_deposit_amount( - possible_keys, - module_id, - ) - base_fee_per_gas = self._get_pending_base_fee() - success = recommended_max_gas >= base_fee_per_gas - DEPOSIT_AMOUNT_OK.labels(module_id).set(int(success)) - return success - - @staticmethod - def _calculate_recommended_gas_based_on_deposit_amount(deposits_amount: int, module_id: int) -> int: - # For one key recommended gas fee will be around 10 - # For 10 keys around 100 gwei. For 20 keys ~ 800 gwei - # ToDo percentiles for all modules? - recommended_max_gas = (deposits_amount ** 3 + 100) * 10 ** 8 - logger.info({'msg': 'Calculate recommended max gas based on possible deposits.', 'value': recommended_max_gas}) - GAS_FEE.labels('based_on_buffer_fee', module_id).set(recommended_max_gas) - return recommended_max_gas - - def _get_recommended_gas_fee(self) -> Wei: + def get_recommended_gas_fee(self) -> Wei: gas_history = self._fetch_gas_fee_history(variables.GAS_FEE_PERCENTILE_DAYS_HISTORY_1) return Wei(int(numpy.percentile(gas_history, variables.GAS_FEE_PERCENTILE_1))) diff --git a/src/blockchain/deposit_strategy/strategy.py b/src/blockchain/deposit_strategy/strategy.py new file mode 100644 index 00000000..8587d421 --- /dev/null +++ b/src/blockchain/deposit_strategy/strategy.py @@ -0,0 +1,11 @@ +import abc + + +class DepositStrategy(abc.ABC): + @abc.abstractmethod + def can_deposit_keys_based_on_ether(self, module_id: int) -> bool: + pass + + @abc.abstractmethod + def is_gas_price_ok(self, module_id: int) -> bool: + pass diff --git a/src/bots/depositor.py b/src/bots/depositor.py index 5e988077..e6fa4f85 100644 --- a/src/bots/depositor.py +++ b/src/bots/depositor.py @@ -5,10 +5,11 @@ import variables from blockchain.contracts.staking_module import StakingModuleContract -from blockchain.deposit_strategy.base_deposit_strategy import BaseDepositStrategy, MellowDepositStrategy +from blockchain.deposit_strategy.base_deposit_strategy import BaseDepositStrategy, CSMDepositStrategy, MellowDepositStrategy from blockchain.deposit_strategy.deposit_transaction_sender import Sender from blockchain.deposit_strategy.gas_price_calculator import GasPriceCalculator from blockchain.deposit_strategy.prefered_module_to_deposit import get_preferred_to_deposit_modules +from blockchain.deposit_strategy.strategy import DepositStrategy from blockchain.executor import Executor from blockchain.typings import Web3 from metrics.metrics import ( @@ -39,9 +40,10 @@ def run_depositor(w3): logger.info({'msg': 'Initialize Depositor bot.'}) sender = Sender(w3) gas_price_calculator = GasPriceCalculator(w3) - mellow_deposit_strategy = MellowDepositStrategy(w3) - base_deposit_strategy = BaseDepositStrategy(w3) - depositor_bot = DepositorBot(w3, sender, gas_price_calculator, mellow_deposit_strategy, base_deposit_strategy) + mellow_deposit_strategy = MellowDepositStrategy(w3, gas_price_calculator) + base_deposit_strategy = BaseDepositStrategy(w3, gas_price_calculator) + csm_strategy = CSMDepositStrategy(w3, gas_price_calculator) + depositor_bot = DepositorBot(w3, sender, mellow_deposit_strategy, base_deposit_strategy, csm_strategy) e = Executor( w3, @@ -65,15 +67,15 @@ def __init__( self, w3: Web3, sender: Sender, - gas_price_calcaulator: GasPriceCalculator, mellow_deposit_strategy: MellowDepositStrategy, base_deposit_strategy: BaseDepositStrategy, + csm_strategy: CSMDepositStrategy, ): self.w3 = w3 self._sender = sender - self._gas_price_calculator = gas_price_calcaulator self._mellow_strategy = mellow_deposit_strategy self._general_strategy = base_deposit_strategy + self._csm_strategy = csm_strategy transports = [] @@ -186,17 +188,17 @@ def _deposit_to_module(self, module_id: int) -> bool: can_deposit = self.w3.lido.deposit_security_module.can_deposit(module_id) logger.info({'msg': 'Can deposit to module.', 'value': can_deposit}) - gas_is_ok = self._gas_price_calculator.is_gas_price_ok(module_id) + strategy, is_mellow = self._select_strategy(module_id) + gas_is_ok = strategy.is_gas_price_ok(module_id) logger.info({'msg': 'Calculate gas recommendations.', 'value': gas_is_ok}) - strategy, is_mellow = self._select_strategy(module_id) - is_deposit_amount_ok = self._gas_price_calculator.calculate_deposit_recommendation(strategy, module_id) + is_deposit_amount_ok = strategy.can_deposit_keys_based_on_ether(module_id) logger.info({'msg': 'Calculations deposit recommendations.', 'value': is_deposit_amount_ok, 'is_mellow': is_mellow}) if is_mellow and not is_deposit_amount_ok: strategy = self._general_strategy is_mellow = False - is_deposit_amount_ok = self._gas_price_calculator.calculate_deposit_recommendation(strategy, module_id) + is_deposit_amount_ok = strategy.can_deposit_keys_based_on_ether(module_id) logger.info({'msg': 'Calculations deposit recommendations.', 'value': is_deposit_amount_ok, 'is_mellow': is_mellow}) if is_depositable and quorum and can_deposit and gas_is_ok and is_deposit_amount_ok: @@ -210,7 +212,9 @@ def _deposit_to_module(self, module_id: int) -> bool: logger.info({'msg': 'Checks failed. Skip deposit.'}) return False - def _select_strategy(self, module_id) -> tuple[BaseDepositStrategy, bool]: + def _select_strategy(self, module_id) -> tuple[DepositStrategy, bool]: + if module_id == 3: + return self._csm_strategy, False if self._is_mellow_depositable(module_id): return self._mellow_strategy, True return self._general_strategy, False diff --git a/tests/blockchain/deposit_strategy/test_base_deposit_strategy.py b/tests/blockchain/deposit_strategy/test_base_deposit_strategy.py new file mode 100644 index 00000000..a833ae2a --- /dev/null +++ b/tests/blockchain/deposit_strategy/test_base_deposit_strategy.py @@ -0,0 +1,13 @@ +from unittest.mock import Mock + +import pytest + + +@pytest.mark.unit +def test_csm_deposit_strategy(csm_strategy): + csm_strategy.deposited_keys_amount = Mock(return_value=1) + assert not csm_strategy.can_deposit_keys_based_on_ether(3) + + csm_strategy.deposited_keys_amount = Mock(return_value=2) + csm_strategy._gas_price_calculator.get_pending_base_fee = Mock(return_value=10) + assert csm_strategy.can_deposit_keys_based_on_ether(3) diff --git a/tests/blockchain/deposit_strategy/test_gas_price_calculator.py b/tests/blockchain/deposit_strategy/test_gas_price_calculator.py index d72f4bd8..bee2fd3a 100644 --- a/tests/blockchain/deposit_strategy/test_gas_price_calculator.py +++ b/tests/blockchain/deposit_strategy/test_gas_price_calculator.py @@ -2,28 +2,29 @@ import pytest import variables +from blockchain.deposit_strategy.base_deposit_strategy import BaseDepositStrategy MODULE_ID = 1 @pytest.mark.unit -def test_is_gas_price_ok(gas_price_calculator): - gas_price_calculator._get_pending_base_fee = Mock(return_value=10) - gas_price_calculator._get_recommended_gas_fee = Mock(return_value=20) +def test_is_gas_price_ok(base_deposit_strategy): + base_deposit_strategy._gas_price_calculator.get_pending_base_fee = Mock(return_value=10) + base_deposit_strategy._gas_price_calculator.get_recommended_gas_fee = Mock(return_value=20) variables.MAX_GAS_FEE = 300 - gas_price_calculator.w3.lido.lido.get_depositable_ether = Mock(return_value=100) + base_deposit_strategy._gas_price_calculator.w3.lido.lido.get_depositable_ether = Mock(return_value=100) variables.MAX_BUFFERED_ETHERS = 200 - assert gas_price_calculator.is_gas_price_ok(MODULE_ID) + assert base_deposit_strategy.is_gas_price_ok(MODULE_ID) - gas_price_calculator._get_recommended_gas_fee = Mock(return_value=5) - assert not gas_price_calculator.is_gas_price_ok(MODULE_ID) + base_deposit_strategy._gas_price_calculator.get_recommended_gas_fee = Mock(return_value=5) + assert not base_deposit_strategy.is_gas_price_ok(MODULE_ID) - gas_price_calculator.w3.lido.lido.get_depositable_ether = Mock(return_value=300) - assert gas_price_calculator.is_gas_price_ok(MODULE_ID) + base_deposit_strategy._gas_price_calculator.w3.lido.lido.get_depositable_ether = Mock(return_value=300) + assert base_deposit_strategy.is_gas_price_ok(MODULE_ID) - gas_price_calculator._get_pending_base_fee = Mock(return_value=400) - assert not gas_price_calculator.is_gas_price_ok(MODULE_ID) + base_deposit_strategy._gas_price_calculator.get_pending_base_fee = Mock(return_value=400) + assert not base_deposit_strategy.is_gas_price_ok(MODULE_ID) @pytest.mark.unit @@ -31,9 +32,8 @@ def test_is_gas_price_ok(gas_price_calculator): 'deposits,expected_range', [(1, (0, 20)), (5, (20, 100)), (10, (50, 1000)), (100, (1000, 1000000))], ) -def test_calculate_recommended_gas_based_on_deposit_amount(gas_price_calculator, deposits, expected_range): - assert expected_range[0] * 10 ** 9 <= gas_price_calculator._calculate_recommended_gas_based_on_deposit_amount(deposits, MODULE_ID) <= \ - expected_range[1] * 10 ** 9 +def test_calculate_recommended_gas_based_on_deposit_amount(deposits, expected_range): + assert expected_range[0] * 10**9 <= BaseDepositStrategy._recommended_max_gas(deposits, MODULE_ID) <= expected_range[1] * 10**9 @pytest.mark.unit @@ -42,16 +42,16 @@ def test_get_recommended_gas_fee(gas_price_calculator): variables.GAS_FEE_PERCENTILE_DAYS_HISTORY_1 = 1 variables.GAS_FEE_PERCENTILE_1 = 50 - assert gas_price_calculator._get_recommended_gas_fee() == 5 + assert gas_price_calculator.get_recommended_gas_fee() == 5 variables.GAS_FEE_PERCENTILE_1 = 30 - assert gas_price_calculator._get_recommended_gas_fee() == 3 + assert gas_price_calculator.get_recommended_gas_fee() == 3 @pytest.mark.integration def test_get_pending_base_fee(gas_price_calculator_integration): - pending_gas = gas_price_calculator_integration._get_pending_base_fee() - assert 1 <= pending_gas <= 1000 * 10 ** 9 + pending_gas = gas_price_calculator_integration.get_pending_base_fee() + assert 1 <= pending_gas <= 1000 * 10**9 @pytest.mark.integration diff --git a/tests/bots/test_depositor.py b/tests/bots/test_depositor.py index f6f1b45b..63ec9774 100644 --- a/tests/bots/test_depositor.py +++ b/tests/bots/test_depositor.py @@ -14,16 +14,16 @@ def depositor_bot( web3_lido_unit, deposit_transaction_sender, - gas_price_calculator, mellow_deposit_strategy, base_deposit_strategy, block_data, + csm_strategy, ): variables.MESSAGE_TRANSPORTS = '' variables.DEPOSIT_MODULES_WHITELIST = [1, 2] web3_lido_unit.lido.staking_router.get_staking_module_ids = Mock(return_value=[1, 2]) web3_lido_unit.eth.get_block = Mock(return_value=block_data) - yield DepositorBot(web3_lido_unit, deposit_transaction_sender, mellow_deposit_strategy, base_deposit_strategy, gas_price_calculator) + yield DepositorBot(web3_lido_unit, deposit_transaction_sender, mellow_deposit_strategy, base_deposit_strategy, csm_strategy) @pytest.fixture @@ -131,8 +131,10 @@ def test_depositor_deposit_to_module(depositor_bot, is_depositable, quorum, is_g depositor_bot._check_module_status = Mock(return_value=is_depositable) depositor_bot._get_quorum = Mock(return_value=quorum) depositor_bot._mellow_works = False - depositor_bot._gas_price_calculator.is_gas_price_ok = Mock(return_value=is_gas_price_ok) - depositor_bot._gas_price_calculator.calculate_deposit_recommendation = Mock(return_value=is_deposited_keys_amount_ok) + strategy = Mock() + strategy.is_gas_price_ok = Mock(return_value=is_gas_price_ok) + strategy.can_deposit_keys_based_on_ether = Mock(return_value=is_deposited_keys_amount_ok) + depositor_bot._select_strategy = Mock(return_value=(strategy, False)) assert not depositor_bot._deposit_to_module(1) @@ -254,6 +256,7 @@ def test_depositor_bot_non_mellow_deposits( mellow_deposit_strategy_integration, base_deposit_strategy_integration, gas_price_calculator_integration, + csm_strategy_integration, module_id, add_accounts_to_guardian, ): @@ -303,9 +306,9 @@ def test_depositor_bot_non_mellow_deposits( db: DepositorBot = DepositorBot( web3_lido_integration, deposit_transaction_sender_integration, - gas_price_calculator_integration, mellow_deposit_strategy_integration, base_deposit_strategy_integration, + csm_strategy_integration, ) # Clear the message storage and execute the bot without any messages diff --git a/tests/bots/test_mellow.py b/tests/bots/test_mellow.py index 72f2fc9b..9c3968c4 100644 --- a/tests/bots/test_mellow.py +++ b/tests/bots/test_mellow.py @@ -27,6 +27,7 @@ def test_depositor_bot_mellow_deposits( deposit_transaction_sender_integration, mellow_deposit_strategy_integration, base_deposit_strategy_integration, + csm_strategy_integration, gas_price_calculator_integration, module_id, add_accounts_to_guardian, @@ -53,9 +54,9 @@ def test_depositor_bot_mellow_deposits( db: DepositorBot = DepositorBot( web3_lido_integration, deposit_transaction_sender_integration, - gas_price_calculator_integration, mellow_deposit_strategy_integration, base_deposit_strategy_integration, + csm_strategy_integration, ) # Clear the message storage and execute the bot without any messages @@ -69,7 +70,7 @@ def test_depositor_bot_mellow_deposits( db.message_storage.messages = deposit_messages # All the mellow specific checks - mellow_strategy = MellowDepositStrategy(web3_lido_integration) + mellow_strategy = MellowDepositStrategy(web3_lido_integration, gas_price_calculator_integration) initial_vault_balance = web3_lido_integration.lido.simple_dvt_staking_strategy.vault_balance() buffered = web3_lido_integration.lido.lido.get_buffered_ether() unfinalized = web3_lido_integration.lido.lido_locator.withdrawal_queue_contract.unfinalized_st_eth() diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py index 19f55366..cccd4352 100644 --- a/tests/fixtures/__init__.py +++ b/tests/fixtures/__init__.py @@ -20,6 +20,8 @@ from .strategy import ( base_deposit_strategy, base_deposit_strategy_integration, + csm_strategy, + csm_strategy_integration, deposit_transaction_sender, deposit_transaction_sender_integration, gas_price_calculator, @@ -52,4 +54,6 @@ 'deposit_transaction_sender_integration', 'mellow_deposit_strategy', 'mellow_deposit_strategy_integration', + 'csm_strategy', + 'csm_strategy_integration', ] diff --git a/tests/fixtures/strategy.py b/tests/fixtures/strategy.py index a6feadc5..5228a13f 100644 --- a/tests/fixtures/strategy.py +++ b/tests/fixtures/strategy.py @@ -1,27 +1,27 @@ import pytest -from blockchain.deposit_strategy.base_deposit_strategy import BaseDepositStrategy, MellowDepositStrategy +from blockchain.deposit_strategy.base_deposit_strategy import BaseDepositStrategy, CSMDepositStrategy, MellowDepositStrategy from blockchain.deposit_strategy.deposit_transaction_sender import Sender from blockchain.deposit_strategy.gas_price_calculator import GasPriceCalculator @pytest.fixture -def base_deposit_strategy(web3_lido_unit): - yield BaseDepositStrategy(web3_lido_unit) +def base_deposit_strategy(web3_lido_unit, gas_price_calculator): + yield BaseDepositStrategy(web3_lido_unit, gas_price_calculator) @pytest.fixture -def base_deposit_strategy_integration(web3_lido_integration): - yield BaseDepositStrategy(web3_lido_integration) +def base_deposit_strategy_integration(web3_lido_integration, gas_price_calculator_integration): + yield BaseDepositStrategy(web3_lido_integration, gas_price_calculator_integration) @pytest.fixture -def mellow_deposit_strategy(web3_lido_unit): - yield MellowDepositStrategy(web3_lido_unit) +def mellow_deposit_strategy(web3_lido_unit, gas_price_calculator): + yield MellowDepositStrategy(web3_lido_unit, gas_price_calculator) @pytest.fixture -def mellow_deposit_strategy_integration(web3_lido_integration): - yield MellowDepositStrategy(web3_lido_integration) +def mellow_deposit_strategy_integration(web3_lido_integration, gas_price_calculator_integration): + yield MellowDepositStrategy(web3_lido_integration, gas_price_calculator_integration) @pytest.fixture @@ -42,3 +42,13 @@ def gas_price_calculator(web3_lido_unit): @pytest.fixture def gas_price_calculator_integration(web3_lido_integration): yield GasPriceCalculator(web3_lido_integration) + + +@pytest.fixture +def csm_strategy(web3_lido_unit, gas_price_calculator): + yield CSMDepositStrategy(web3_lido_unit, gas_price_calculator) + + +@pytest.fixture +def csm_strategy_integration(web3_lido_integration, gas_price_calculator_integration): + yield CSMDepositStrategy(web3_lido_integration, gas_price_calculator_integration)