-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tests for Negative rebase feature #240
Changes from all commits
999b674
f218f96
7babcf1
879ea9a
f7a3133
663c02f
7875736
0bcd086
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import pytest | ||
from brownie import Contract, web3, reverts, accounts, chain # type: ignore | ||
from utils.evm_script import encode_error | ||
from utils.test.exit_bus_data import LidoValidator | ||
from utils.test.extra_data import ExtraDataService | ||
from utils.test.oracle_report_helpers import ( | ||
oracle_report, | ||
) | ||
|
||
from utils.test.helpers import ETH | ||
from utils.config import ( | ||
contracts, | ||
) | ||
|
||
INITIAL_SLASHING_AMOUNT_PWEI = 1000 | ||
INACTIVITY_PENALTIES_AMOUNT_PWEI = 101 | ||
ONE_PWEI = ETH(0.001) | ||
|
||
@pytest.fixture(scope="module") | ||
def oracle_report_sanity_checker() -> Contract: | ||
return contracts.oracle_report_sanity_checker | ||
|
||
|
||
def test_negative_rebase_correct_exited_validators_count_pos_rebase(oracle_report_sanity_checker): | ||
locator = contracts.lido_locator | ||
assert oracle_report_sanity_checker.address == locator.oracleReportSanityChecker() | ||
|
||
reported_validators = exited_validators_count() | ||
|
||
reported_validators_values = [value + 2 for value in reported_validators.values()] | ||
oracle_report(cl_diff=ETH(300), stakingModuleIdsWithNewlyExitedValidators=list(reported_validators.keys()), | ||
numExitedValidatorsByStakingModule=reported_validators_values) | ||
|
||
count = oracle_report_sanity_checker.getReportDataCount() | ||
assert count > 0 | ||
(_, stored_exited_validators, _) = oracle_report_sanity_checker.reportData(count - 1) | ||
|
||
assert stored_exited_validators == sum(reported_validators_values) | ||
|
||
def test_negative_rebase_correct_exited_validators_count_neg_rebase(oracle_report_sanity_checker): | ||
locator = contracts.lido_locator | ||
assert oracle_report_sanity_checker.address == locator.oracleReportSanityChecker() | ||
|
||
reported_validators = exited_validators_count() | ||
|
||
reported_validators_values = [value + 3 for value in reported_validators.values()] | ||
oracle_report(cl_diff=-ETH(40000), stakingModuleIdsWithNewlyExitedValidators=list(reported_validators.keys()), | ||
numExitedValidatorsByStakingModule=reported_validators_values) | ||
|
||
count = oracle_report_sanity_checker.getReportDataCount() | ||
assert count > 0 | ||
(_, stored_exited_validators, _) = oracle_report_sanity_checker.reportData(count - 1) | ||
|
||
assert stored_exited_validators == sum(reported_validators_values) | ||
|
||
def test_negative_rebase_correct_balance_neg_rebase(oracle_report_sanity_checker): | ||
locator = contracts.lido_locator | ||
assert oracle_report_sanity_checker.address == locator.oracleReportSanityChecker() | ||
|
||
cl_decrease = ETH(40000) | ||
oracle_report(cl_diff=-cl_decrease, exclude_vaults_balances=True) | ||
|
||
count = oracle_report_sanity_checker.getReportDataCount() | ||
assert count > 0 | ||
(_, _, cl_balance) = oracle_report_sanity_checker.reportData(count - 1) | ||
assert cl_balance == cl_decrease | ||
|
||
cl_decrease2 = ETH(30000) | ||
oracle_report(cl_diff=-cl_decrease2, exclude_vaults_balances=True) | ||
count = oracle_report_sanity_checker.getReportDataCount() | ||
assert count > 0 | ||
(_, _, cl_balance) = oracle_report_sanity_checker.reportData(count - 1) | ||
|
||
assert cl_balance == cl_decrease2 | ||
|
||
|
||
def test_blocked_huge_negative_rebase(oracle_report_sanity_checker): | ||
locator = contracts.lido_locator | ||
assert oracle_report_sanity_checker.address == locator.oracleReportSanityChecker() | ||
|
||
(_, cl_validators, cl_balance) = contracts.lido.getBeaconStat() | ||
|
||
max_cl_balance = (INITIAL_SLASHING_AMOUNT_PWEI + INACTIVITY_PENALTIES_AMOUNT_PWEI) * ONE_PWEI * cl_validators | ||
error_cl_decrease = cl_balance // 10 # 10% of current balance will lead to error | ||
print("max_cl_balance", max_cl_balance) | ||
with reverts(encode_error("IncorrectCLBalanceDecrease(uint256, uint256)", [error_cl_decrease, max_cl_balance])): | ||
oracle_report(cl_diff=-error_cl_decrease, exclude_vaults_balances=True, silent=True) | ||
|
||
def test_negative_rebase_more_than_54_reports(oracle_report_sanity_checker): | ||
locator = contracts.lido_locator | ||
assert oracle_report_sanity_checker.address == locator.oracleReportSanityChecker() | ||
|
||
reported_validators_values = exited_validators_count().values() | ||
for _ in range(58): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am curious why 58? The test name suggests 54 reports. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well. It says more than 54, so just to be sure that reporting is not blocked on the bound of 54 rebases |
||
reported_validators_values = [value + 3 for value in reported_validators_values] | ||
oracle_report(cl_diff=-ETH(400), stakingModuleIdsWithNewlyExitedValidators=exited_validators_count().keys(), | ||
numExitedValidatorsByStakingModule=reported_validators_values) | ||
|
||
count = oracle_report_sanity_checker.getReportDataCount() | ||
assert count > 0 | ||
(_, stored_exited_validators, _) = oracle_report_sanity_checker.reportData(count - 1) | ||
|
||
assert stored_exited_validators == sum(reported_validators_values) | ||
|
||
|
||
def exited_validators_count(): | ||
assert contracts.lido_locator.stakingRouter() == contracts.staking_router | ||
ids = contracts.staking_router.getStakingModuleIds() | ||
exited = {} | ||
for id in ids: | ||
exited[id] = contracts.staking_router.getStakingModule(id)["exitedValidatorsCount"] | ||
|
||
return exited |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am curious why we get this result , cl_diff was -40_000 ETH then cl_balance in positive 40_000 ETH
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the result on how sanity checker keeps the negative rebases. It stores negative balance changes as a positive number (abs delta) or 0 if there was a positive rebase. To logic behind it that it's only negative changes are important and it tracks the cumulative negative rebases over 54 days. Here is the corresponding code https://github.com/lidofinance/core/blob/669d8e57ddcd6605ee076fe2fcdca5d4751fa154/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol#L675