diff --git a/.gitignore b/.gitignore index 7ef84715..371989c1 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ database .vscode .coverage .python-version +.history diff --git a/pyproject.toml b/pyproject.toml index aa59f437..2896bc98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -128,5 +128,6 @@ ignore_names = [ "DATA_DIR", # settings "contract_event", "get_from_block", "process_events", # event processor "validators_root", # ApprovalRequest - "previous_version", "current_version", "genesis_validators_root", "fork_info", "voluntary_exit" # remote.py + "previous_version", "current_version", "genesis_validators_root", "fork_info", "voluntary_exit", # remote.py + "rounding" # decimal context ] diff --git a/src/common/startup_check.py b/src/common/startup_check.py index 9ca34e99..9d0e6bcb 100644 --- a/src/common/startup_check.py +++ b/src/common/startup_check.py @@ -16,7 +16,7 @@ get_protocol_config, ) from src.common.harvest import get_harvest_params -from src.common.utils import format_error, warning_verbose +from src.common.utils import format_error, round_down, warning_verbose from src.common.wallet import hot_wallet from src.config.networks import NETWORKS from src.config.settings import settings @@ -219,9 +219,13 @@ async def startup_checks() -> None: harvest_params = await get_harvest_params() withdrawable_assets = await get_withdrawable_assets(harvest_params) + + # Note. We round down assets in the log message because of the case when assets + # is slightly less than required amount to register validator. + # Standard rounding will show that we have enough assets, but in fact we don't. logger.info( 'Vault withdrawable assets: %s %s', - round(Web3.from_wei(withdrawable_assets, 'ether'), 2), + round_down(Web3.from_wei(withdrawable_assets, 'ether'), 2), settings.network_config.VAULT_BALANCE_SYMBOL, ) diff --git a/src/common/tests/__init__.py b/src/common/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/common/tests/test_utils.py b/src/common/tests/test_utils.py new file mode 100644 index 00000000..e9f70a88 --- /dev/null +++ b/src/common/tests/test_utils.py @@ -0,0 +1,8 @@ +from decimal import Decimal +from src.common.utils import round_down + + +def test_round_down(): + assert round_down(100, 2) == Decimal('100.00') + assert round_down(Decimal('100.123'), 2) == Decimal('100.12') + assert round_down(Decimal('100.999'), 2) == Decimal('100.99') diff --git a/src/common/utils.py b/src/common/utils.py index 0036d63b..6712e41f 100644 --- a/src/common/utils.py +++ b/src/common/utils.py @@ -2,6 +2,7 @@ import logging from collections import defaultdict from datetime import datetime, timezone +from decimal import ROUND_FLOOR, Decimal, localcontext from pathlib import Path from typing import Any, Iterator @@ -113,3 +114,12 @@ def add_fields(self, log_record, record, message_dict): # type: ignore log_record['level'] = log_record['level'].upper() else: log_record['level'] = record.levelname + + +def round_down(d: int | Decimal, precision: int) -> Decimal: + if isinstance(d, int): + d = Decimal(d) + + with localcontext() as ctx: + ctx.rounding = ROUND_FLOOR + return round(d, precision)