|
1 | 1 | from collections import defaultdict |
2 | | -from typing import cast |
| 2 | +from queue import Queue |
3 | 3 |
|
4 | 4 | from eth_typing import BlockNumber, ChecksumAddress |
5 | 5 | from sw_utils import is_meta_vault_upgraded_to_release, memoize |
|
13 | 13 | VaultContract, |
14 | 14 | ) |
15 | 15 | from src.config.settings import settings |
| 16 | +from src.meta_vault.typings import SubVaultRedemption |
16 | 17 |
|
17 | 18 |
|
18 | 19 | async def distribute_meta_vault_redemption_assets( |
19 | | - vault_to_redemption_assets: defaultdict[ChecksumAddress, Wei], |
| 20 | + vault_to_redemption_assets: dict[ChecksumAddress, Wei], |
20 | 21 | block_number: BlockNumber | None = None, |
21 | 22 | ) -> defaultdict[ChecksumAddress, Wei]: |
22 | 23 | """ |
23 | 24 | Parameters: |
24 | 25 | vault_to_redemption_assets: A mapping of vault addresses to their respective redemption assets, |
25 | 26 | which may include meta vaults. |
26 | 27 |
|
27 | | - Distribute redemption assets from meta vaults to their underlying sub-vaults. |
| 28 | + Distribute redemption assets from meta vaults across their entire sub-vault tree. |
28 | 29 | Returns a mapping of vault addresses to their respective redemption assets, |
29 | | - ensuring all assets are assigned to non-meta vaults. |
| 30 | + including leaf vaults, root meta vaults, and all intermediary meta sub-vaults. |
30 | 31 | """ |
31 | | - final_vault_to_redemption_assets: defaultdict[ChecksumAddress, int] = defaultdict(lambda: 0) |
| 32 | + final_vault_to_redemption_assets: defaultdict[ChecksumAddress, Wei] = defaultdict( |
| 33 | + lambda: Wei(0) |
| 34 | + ) |
32 | 35 |
|
| 36 | + queue: Queue[tuple[ChecksumAddress, Wei]] = Queue() |
33 | 37 | for vault, assets in vault_to_redemption_assets.items(): |
34 | | - if await is_meta_vault(vault): |
35 | | - sub_vaults_redemptions = await get_meta_vault_redemption_assets( |
36 | | - meta_vault_address=vault, |
37 | | - assets_to_redeem=assets, |
38 | | - block_number=block_number, |
39 | | - ) |
40 | | - for sub_vault, sub_assets in sub_vaults_redemptions.items(): |
41 | | - final_vault_to_redemption_assets[sub_vault] += sub_assets |
42 | | - else: |
43 | | - final_vault_to_redemption_assets[vault] += assets |
44 | | - |
45 | | - return cast(defaultdict[ChecksumAddress, Wei], final_vault_to_redemption_assets) |
46 | | - |
47 | | - |
48 | | -async def get_meta_vault_redemption_assets( |
| 38 | + queue.put((vault, assets)) |
| 39 | + |
| 40 | + while not queue.empty(): |
| 41 | + vault, assets = queue.get() |
| 42 | + final_vault_to_redemption_assets[vault] = Wei( |
| 43 | + final_vault_to_redemption_assets[vault] + assets |
| 44 | + ) |
| 45 | + if not await is_meta_vault(vault): |
| 46 | + continue |
| 47 | + sub_vaults_redemptions = await get_sub_vaults_redemptions( |
| 48 | + meta_vault_address=vault, |
| 49 | + assets_to_redeem=assets, |
| 50 | + block_number=block_number, |
| 51 | + ) |
| 52 | + for sub_vault_redemption in sub_vaults_redemptions: |
| 53 | + queue.put((sub_vault_redemption.vault, sub_vault_redemption.assets)) |
| 54 | + |
| 55 | + return final_vault_to_redemption_assets |
| 56 | + |
| 57 | + |
| 58 | +async def get_sub_vaults_redemptions( |
49 | 59 | meta_vault_address: ChecksumAddress, |
50 | 60 | assets_to_redeem: Wei, |
51 | 61 | block_number: BlockNumber | None = None, |
52 | | -) -> defaultdict[ChecksumAddress, Wei]: |
| 62 | +) -> list[SubVaultRedemption]: |
53 | 63 | """ |
54 | | - This function distributes the specified assets to redeem from the meta vault |
55 | | - among its underlying sub-vaults. It handles both regular and nested meta vaults. |
56 | | - Finally every asset should be assigned to a non-meta vault. |
| 64 | + Distribute the specified assets to redeem from the meta vault across its |
| 65 | + direct sub-vaults only. Does not recurse into nested meta vaults. |
57 | 66 |
|
58 | | - Returns a mapping of vault addresses to their respective redemption assets. |
| 67 | + Returns a list of SubVaultRedemption entries, one per direct sub-vault. |
59 | 68 | """ |
60 | | - vault_to_redemption_assets: defaultdict[ChecksumAddress, int] = defaultdict(lambda: 0) |
61 | 69 | meta_vault_contract = MetaVaultContract(meta_vault_address) |
62 | | - |
63 | 70 | sub_vaults_registry_address = await meta_vault_contract.sub_vaults_registry() |
64 | 71 | sub_vaults_registry_contract = SubVaultsRegistryContract(sub_vaults_registry_address) |
65 | 72 |
|
66 | 73 | sub_vaults_redemptions = await sub_vaults_registry_contract.calculate_sub_vaults_redemptions( |
67 | 74 | assets_to_redeem, block_number=block_number |
68 | 75 | ) |
69 | | - |
70 | | - for sub_vault_redemption in sub_vaults_redemptions: |
71 | | - if sub_vault_redemption.assets > 0 and await is_meta_vault(sub_vault_redemption.vault): |
72 | | - sub_vault_assets = await get_meta_vault_redemption_assets( |
73 | | - meta_vault_address=sub_vault_redemption.vault, |
74 | | - assets_to_redeem=sub_vault_redemption.assets, |
75 | | - block_number=block_number, |
76 | | - ) |
77 | | - for vault, assets in sub_vault_assets.items(): |
78 | | - vault_to_redemption_assets[vault] += assets |
79 | | - else: |
80 | | - vault_to_redemption_assets[sub_vault_redemption.vault] += sub_vault_redemption.assets |
81 | | - |
82 | | - return cast(defaultdict[ChecksumAddress, Wei], vault_to_redemption_assets) |
| 76 | + return sub_vaults_redemptions |
83 | 77 |
|
84 | 78 |
|
85 | 79 | @memoize |
|
0 commit comments