|
10 | 10 | from src.services.staking_vaults import StakingVaultsService |
11 | 11 | from src.types import FrameNumber, ReferenceBlockStamp, SlotNumber |
12 | 12 | from src.utils.apr import get_steth_by_shares |
| 13 | +from tests.factory.blockstamp import BlockStampFactory |
13 | 14 | from tests.modules.accounting.staking_vault.conftest import ( |
14 | 15 | ExtraValueFactory, |
15 | 16 | FeeTestConstants, |
@@ -41,7 +42,6 @@ def service(self, web3, monkeypatch): |
41 | 42 |
|
42 | 43 | fake_blockstamp = MagicMock() |
43 | 44 | fake_blockstamp.block_number = 0 |
44 | | - |
45 | 45 | monkeypatch.setattr("src.services.staking_vaults.get_blockstamp", MagicMock(return_value=fake_blockstamp)) |
46 | 46 |
|
47 | 47 | return svc |
@@ -111,42 +111,100 @@ def test_zero_time_elapsed_allowed(self, service): |
111 | 111 |
|
112 | 112 | assert fees[vault_adr].prev_fee == 0 |
113 | 113 |
|
114 | | - def test_initial_epoch_zero_uses_non_negative_prev_ref_slot(self, service): |
115 | | - # Setup |
| 114 | + def test_negative_ref_slot_on_first_report(self, service, monkeypatch): |
| 115 | + # initial_epoch - frame_epoches <= 0 |
116 | 116 | vault_adr = VaultAddresses.VAULT_0 |
117 | 117 | vault = VaultInfoFactory.build(vault=vault_adr, liability_shares=0, max_liability_shares=0) |
118 | | - blockstamp = self.make_blockstamp(block=10, slot=100) |
119 | 118 |
|
120 | | - service.w3.lido_contracts.accounting_oracle.get_last_processing_ref_slot.return_value = 0 |
| 119 | + service.w3.lido_contracts.accounting_oracle.get_last_processing_ref_slot.return_value = None |
121 | 120 | service._get_prev_vault_ipfs_report = MagicMock(return_value=None) |
122 | 121 | service._get_vault_events_for_fees = MagicMock(return_value=({}, set())) |
123 | 122 | service._calculate_vault_fee_components = MagicMock(return_value=(Decimal(0), Decimal(0), Decimal(0), 0)) |
124 | 123 |
|
125 | | - with patch("src.services.staking_vaults.get_blockstamp", return_value=MagicMock(block_number=0)) as get_bs_mock: |
126 | | - # Act |
127 | | - service.get_vaults_fees( |
128 | | - blockstamp=blockstamp, |
129 | | - vaults={vault_adr: vault}, |
130 | | - vaults_total_values={}, |
131 | | - latest_onchain_ipfs_report_data=OnChainIpfsVaultReportDataFactory.build(report_cid=""), |
132 | | - core_apr_ratio=Decimal("0"), |
133 | | - pre_total_pooled_ether=Wei(0), |
134 | | - pre_total_shares=0, |
135 | | - frame_config=FrameConfig(initial_epoch=0, epochs_per_frame=1, fast_lane_length_slots=0), |
136 | | - chain_config=ChainConfig(slots_per_epoch=32, seconds_per_slot=12, genesis_time=0), |
137 | | - current_frame=FrameNumber(0), |
138 | | - ) |
| 124 | + # Negative prev_slot -> events should be fetched from 0 block |
| 125 | + blockstamp = self.make_blockstamp(block=3 * 32 - 1, slot=3 * 32 - 1) |
| 126 | + monkeypatch.setattr( |
| 127 | + "src.services.staking_vaults.get_blockstamp", |
| 128 | + lambda cc, slot, last_finalized_slot_number: BlockStampFactory.build(block_number=slot), |
| 129 | + ) |
| 130 | + |
| 131 | + service.get_vaults_fees( |
| 132 | + blockstamp=blockstamp, |
| 133 | + vaults={vault_adr: vault}, |
| 134 | + vaults_total_values={}, |
| 135 | + latest_onchain_ipfs_report_data=OnChainIpfsVaultReportDataFactory.build(report_cid=""), |
| 136 | + core_apr_ratio=Decimal("0"), |
| 137 | + pre_total_pooled_ether=Wei(0), |
| 138 | + pre_total_shares=0, |
| 139 | + frame_config=FrameConfig(initial_epoch=3, epochs_per_frame=5, fast_lane_length_slots=0), |
| 140 | + chain_config=ChainConfig(slots_per_epoch=32, seconds_per_slot=12, genesis_time=0), |
| 141 | + current_frame=FrameNumber(0), |
| 142 | + ) |
| 143 | + |
| 144 | + service._get_vault_events_for_fees.assert_called_once_with( |
| 145 | + vault_hub=service.w3.lido_contracts.vault_hub, |
| 146 | + from_block=1, |
| 147 | + to_block=3 * 32 - 1, |
| 148 | + ) |
139 | 149 |
|
140 | | - # Assert |
141 | | - assert get_bs_mock.call_args.kwargs["slot"] == SlotNumber(0) |
142 | 150 | service._calculate_vault_fee_components.assert_called_once_with( |
143 | 151 | vault_address=vault_adr, |
144 | 152 | vault_info=vault, |
145 | 153 | vault_total_value=0, |
146 | 154 | vault_events=[], |
147 | | - report_interval_seconds=100 * 12, |
| 155 | + report_interval_seconds=(3 * 32 - 1) * 12, |
148 | 156 | prev_ref_slot_timestamp=0, |
149 | | - current_ref_slot_timestamp=100 * 12, |
| 157 | + current_ref_slot_timestamp=(3 * 32 - 1) * 12, |
| 158 | + core_apr_ratio=Decimal(0), |
| 159 | + pre_total_pooled_ether=0, |
| 160 | + pre_total_shares=0, |
| 161 | + block_timestamps={}, |
| 162 | + ) |
| 163 | + |
| 164 | + def test_first_ref_slot_calculate_on_first_report(self, service, monkeypatch): |
| 165 | + # initial_epoch - frame_epoches > 0 |
| 166 | + vault_adr = VaultAddresses.VAULT_0 |
| 167 | + vault = VaultInfoFactory.build(vault=vault_adr, liability_shares=0, max_liability_shares=0) |
| 168 | + |
| 169 | + service.w3.lido_contracts.accounting_oracle.get_last_processing_ref_slot.return_value = None |
| 170 | + service._get_prev_vault_ipfs_report = MagicMock(return_value=None) |
| 171 | + service._get_vault_events_for_fees = MagicMock(return_value=({}, set())) |
| 172 | + service._calculate_vault_fee_components = MagicMock(return_value=(Decimal(0), Decimal(0), Decimal(0), 0)) |
| 173 | + |
| 174 | + monkeypatch.setattr( |
| 175 | + "src.services.staking_vaults.get_blockstamp", |
| 176 | + lambda cc, slot, last_finalized_slot_number: BlockStampFactory.build(block_number=slot), |
| 177 | + ) |
| 178 | + |
| 179 | + # First report -> events should be fetched from initial_epoch - frame_epoches |
| 180 | + blockstamp = self.make_blockstamp(block=10 * 32 - 1, slot=10 * 32 - 1) |
| 181 | + service.get_vaults_fees( |
| 182 | + blockstamp=blockstamp, |
| 183 | + vaults={vault_adr: vault}, |
| 184 | + vaults_total_values={}, |
| 185 | + latest_onchain_ipfs_report_data=OnChainIpfsVaultReportDataFactory.build(report_cid=""), |
| 186 | + core_apr_ratio=Decimal("0"), |
| 187 | + pre_total_pooled_ether=Wei(0), |
| 188 | + pre_total_shares=0, |
| 189 | + frame_config=FrameConfig(initial_epoch=10, epochs_per_frame=5, fast_lane_length_slots=0), |
| 190 | + chain_config=ChainConfig(slots_per_epoch=32, seconds_per_slot=12, genesis_time=0), |
| 191 | + current_frame=FrameNumber(0), |
| 192 | + ) |
| 193 | + |
| 194 | + service._get_vault_events_for_fees.assert_called_once_with( |
| 195 | + vault_hub=service.w3.lido_contracts.vault_hub, |
| 196 | + from_block=(10 - 5) * 32, |
| 197 | + to_block=10 * 32 - 1, |
| 198 | + ) |
| 199 | + |
| 200 | + service._calculate_vault_fee_components.assert_called_once_with( |
| 201 | + vault_address=vault_adr, |
| 202 | + vault_info=vault, |
| 203 | + vault_total_value=0, |
| 204 | + vault_events=[], |
| 205 | + report_interval_seconds=5 * 32 * 12, |
| 206 | + prev_ref_slot_timestamp=(5 * 32 - 1) * 12, |
| 207 | + current_ref_slot_timestamp=(10 * 32 - 1) * 12, |
150 | 208 | core_apr_ratio=Decimal(0), |
151 | 209 | pre_total_pooled_ether=0, |
152 | 210 | pre_total_shares=0, |
|
0 commit comments