Skip to content

Process redeemer#664

Open
cyc60 wants to merge 71 commits intov5-releasefrom
process-redeemer
Open

Process redeemer#664
cyc60 wants to merge 71 commits intov5-releasefrom
process-redeemer

Conversation

@cyc60
Copy link
Contributor

@cyc60 cyc60 commented Feb 18, 2026

No description provided.

cyc60 and others added 30 commits January 9, 2026 00:40
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>

# Conflicts:
#	poetry.lock
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an internal CLI command to process the OsToken redeemer (exit-queue checkpoints + automatic redemption execution), while generalizing harvest/withdrawable-asset helpers to work with arbitrary vault addresses (needed for multi-vault/meta-vault flows).

Changes:

  • Parameterize get_harvest_params and get_withdrawable_assets with an explicit vault address and update call sites accordingly.
  • Introduce process_redeemer internal command to process exit queue and redeem eligible OsToken positions (with multiproof + multicall).
  • Skip redemption-position iteration when merkle_root is zero (no active set) and extend typings to track available_shares / shares_to_redeem.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/withdrawals/assets.py Updates harvest-param fetch to pass explicit vault address.
src/validators/tasks.py Updates harvest/withdrawable calls to new vault-parameterized signatures.
src/validators/execution.py Makes get_withdrawable_assets accept a vault argument.
src/reward_splitter/tasks.py Updates harvest-param fetch to pass explicit vault address.
src/redemptions/typings.py Extends OsTokenPosition with redemption-tracking fields.
src/redemptions/tasks.py Adds ZERO_MERKLE_ROOT guard to skip empty redeemable sets.
src/main.py Registers the new internal process_redeemer CLI command.
src/harvest/tasks.py Updates harvest-param fetch to pass explicit vault address.
src/common/startup_check.py Updates harvest/withdrawable calls to new vault-parameterized signatures.
src/common/harvest.py Makes get_harvest_params accept a vault argument.
src/common/contracts.py Adds OsToken redeemer wrapper methods (queued shares, exit queue processing, sub-vault redemption, etc.).
src/commands/internal/process_redeemer.py New command implementing redemption selection + multiproof redemption + exit queue processing.
src/commands/tests/test_internal/test_process_redeemer.py New unit tests for the redeemer processing logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +314 to +321
vault_positions_shares = Wei(sum(p.available_shares for p in positions))
vault_positions_assets = os_token_converter.to_assets(vault_positions_shares)

if vault_positions_assets <= withdrawable_assets or not await is_meta_vault(vault_address):
return withdrawable_assets

logger.info('Vault %s is a meta-vault with insufficient withdrawable assets.', vault_address)
additional_assets_needed = Wei(vault_positions_assets - withdrawable_assets)
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_try_redeem_sub_vaults decides how much to redeem from sub-vaults using the sum of all available_shares in the vault. Since the overall redemption in this run is capped by queued_shares, this can trigger an on-chain redeemSubVaultsAssets for assets that will never be redeemed in this round (e.g., when queued_shares is smaller than total vault position shares or gets exhausted on earlier vaults). Consider limiting the required shares/assets to the maximum that could actually be redeemed for this vault in the current round (based on remaining queued shares / selection), or move sub-vault redemption to after positions are selected.

Suggested change
vault_positions_shares = Wei(sum(p.available_shares for p in positions))
vault_positions_assets = os_token_converter.to_assets(vault_positions_shares)
if vault_positions_assets <= withdrawable_assets or not await is_meta_vault(vault_address):
return withdrawable_assets
logger.info('Vault %s is a meta-vault with insufficient withdrawable assets.', vault_address)
additional_assets_needed = Wei(vault_positions_assets - withdrawable_assets)
# Use the shares that are actually intended to be redeemed in this round for this vault.
# Prefer `shares_to_redeem` when present; fall back to `available_shares` otherwise.
requested_shares = Wei(
sum(
(getattr(p, 'shares_to_redeem', None) or p.available_shares)
for p in positions
)
)
if requested_shares == 0:
# Nothing to redeem for this vault in the current round.
return withdrawable_assets
requested_assets = os_token_converter.to_assets(requested_shares)
if requested_assets <= withdrawable_assets or not await is_meta_vault(vault_address):
return withdrawable_assets
logger.info('Vault %s is a meta-vault with insufficient withdrawable assets.', vault_address)
additional_assets_needed = Wei(requested_assets - withdrawable_assets)

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@evgeny-stakewise evgeny-stakewise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comments

cyc60 added 9 commits March 5, 2026 10:29
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +33 to +41
last_rewards = await keeper_contract.get_last_rewards_update(block_number)
if last_rewards is None:
return None
return {vault: None for vault in vaults}

ipfs_data = await ipfs_fetch_client.fetch_json(last_rewards.ipfs_hash)

for vault in vaults:
if not await keeper_contract.can_harvest(vault, block_number):
results[vault] = None
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_multiple_harvest_params now fetches IPFS data (ipfs_fetch_client.fetch_json) before checking can_harvest for any vaults. This regresses the previous behavior where non-harvestable vaults would return early without an IPFS fetch, and can now cause unnecessary IPFS load or even crash the caller when IPFS is unavailable despite can_harvest being false. Consider checking can_harvest first (for all vaults) and only fetching IPFS data if at least one vault is harvestable, or restoring the early-return behavior in get_harvest_params for the single-vault case.

Copilot uses AI. Check for mistakes.
cyc60 added 3 commits March 6, 2026 22:05
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +25 to +35
"""Get harvest params for multiple vaults.

Checks can_harvest for all vaults first, then fetches IPFS data only
if at least one vault is harvestable.
"""
if not vaults:
return {}

last_rewards = await keeper_contract.get_last_rewards_update(block_number)
if last_rewards is None:
return None
return {vault: None for vault in vaults}
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring says can_harvest is checked for all vaults before fetching remote data, but the implementation calls keeper_contract.get_last_rewards_update() first. This adds an extra (potentially expensive) chain log lookup even when no vault is harvestable. Consider checking can_harvest for the provided vaults first and only then fetching last rewards/IPFS (or update the docstring if the order is intentional).

Copilot uses AI. Check for mistakes.
cyc60 added 2 commits March 9, 2026 13:03
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Signed-off-by: cyc60 <avsysoev60@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants