erc_4626.vault_protocol.nara.deposit_redeem
Documentation for eth_defi.erc_4626.vault_protocol.nara.deposit_redeem Python module.
NaraUSD+ synchronous deposits and cooldown-based redemptions.
Classes
NaraUSD+ manager with synchronous deposits and asynchronous cooldown redemptions. |
|
Parse a completed NaraUSD+ |
|
Persist a NaraUSD+ cooldown redemption request. |
- class NaraRedemptionTicket
Bases:
eth_defi.vault.deposit_redeem.RedemptionTicketPersist a NaraUSD+ cooldown redemption request.
The vault keeps one active cooldown per owner and does not assign request identifiers, so the request transaction hash provides a stable identity. The observed cooldown state binds the ticket to that specific request.
- cooldown_end: datetime.datetime
Naive UTC deadline recorded by the vault after
cooldownShares.
- get_request_id()
Return the request transaction hash as an integer identity.
- Returns
Unique integer derived from the request transaction hash.
- Return type
- __init__(vault_address, owner, to, raw_shares, tx_hash, cooldown_end, raw_assets)
- Parameters
vault_address (eth_typing.evm.HexAddress) –
owner (eth_typing.evm.HexAddress) –
to (eth_typing.evm.HexAddress) –
raw_shares (int) –
tx_hash (hexbytes.main.HexBytes) –
cooldown_end (datetime.datetime) –
raw_assets (int) –
- Return type
None
- class NaraRedemptionRequest
Bases:
eth_defi.vault.deposit_redeem.RedemptionRequestParse a completed NaraUSD+
cooldownSharestransaction.- parse_redeem_transaction(tx_hashes)
Create a persistent ticket after the request succeeds.
- Parameters
tx_hashes (list[hexbytes.main.HexBytes]) – Broadcast transaction hashes; the final hash is
cooldownShares.- Returns
Persistable ticket for the later
unstakeclaim.- Return type
eth_defi.erc_4626.vault_protocol.nara.deposit_redeem.NaraRedemptionTicket
- __init__(vault, owner, to, shares, raw_shares, funcs)
- Parameters
vault (VaultBase) –
owner (eth_typing.evm.HexAddress) –
to (eth_typing.evm.HexAddress) –
shares (decimal.Decimal) –
raw_shares (int) –
funcs (list[web3.contract.contract.ContractFunction]) –
- Return type
None
- broadcast(from_=None, gas=1000000)
Broadcast all the transactions in this request.
- Parameters
from – Address to send the transactions from
gas (int) – Gas limit to use for each transaction
from_ (eth_typing.evm.HexAddress) –
- Returns
List of transaction hashes
- Return type
list[hexbytes.main.HexBytes]
- class NaraDepositManager
Bases:
eth_defi.erc_4626.deposit_redeem.ERC4626DepositManagerNaraUSD+ manager with synchronous deposits and asynchronous cooldown redemptions.
NaraUSD+ is Nara’s appreciating staking token for NaraUSD. Deposits mint shares immediately through the standard ERC-4626 path, but redemptions are asynchronous: the holder starts an owner-specific cooldown, waits for it to mature, then claims the underlying NaraUSD. This manager keeps the inherited synchronous deposit flow and replaces the redemption flow with a two-step cooldown/claim lifecycle tracked by
NaraRedemptionTicket.Deposit process
Synchronous, fully inherited. After
approve(),create_deposit_request()builds a single ERC-4626depositcall andestimate_deposit()uses the standardpreviewDepositpath.can_create_deposit_request()gates onmaxDeposit(owner) > 0.Redemption process
Asynchronous, two-step.
create_redemption_request()does not build aredeem/withdrawcall — it builds a singlecooldownShares(raw_shares)call that escrows the shares and starts the owner’s cooldown, returning aNaraRedemptionRequest. After the request confirms,NaraRedemptionRequest.parse_redeem_transaction()reads the vault’scooldowns(owner)state to build a persistable ticket. Once the cooldown matures,finish_redemption()builds theunstake(to)claim that sends NaraUSD to the receiver.has_synchronous_redemption()returnsFalse. The receiver may differ from the owner but cannot be the zero address.Queues and settlement
Per-owner cooldown state rather than a numbered queue: the vault keeps at most one active cooldown per owner and assigns no request id, so the ticket is identified by the request transaction hash together with the observed
cooldown_endand escrowedraw_assets. Attempting a second cooldown while one is active raises.get_redemption_request_status()maps livecooldowns()state plus the latest block timestamp topending,claimableornone(the last also covering a claimed, removed or superseded cooldown).Lockups and cooldowns
Deposits have no lockup. Redemptions carry the live cooldown read from
cooldownDuration():estimate_redemption_delay()returns it, andNaraVault.get_estimated_lock_up()reports the same value (currently seven days on Ethereum).get_redemption_delay_over()returns the per-owner cooldown expiry when one exists.Whitelisting / access control
Permissionless. No NaraUSD+-specific whitelist is applied beyond the inherited
check_deposit_whitelist()preflight;can_create_redemption_request()simply requires a positive share balance and no cooldown already in progress.Anvil settlement (force_settle)
Deposits settle in their originating transaction. Redemption settlement is time-based, not keeper-based:
force_settle()advances an Anvil chain to the ticket’scooldown_endand returns a hashless pending-to-claimable result. It never broadcastsunstake; callers must submit the guardedfinish_redemption()claim themselves. A supplied local mock is accepted only when it is the same deployed contract as this manager’s vault, preventing it from advancing an unrelated production ticket.- create_redemption_request(owner, to=None, shares=None, raw_shares=None, check_max_deposit=True, check_enough_token=True)
Start the owner-specific NaraUSD+ share cooldown.
- Parameters
owner (eth_typing.evm.HexAddress) – NaraUSD+ share owner initiating the cooldown.
to (Optional[eth_typing.evm.HexAddress]) – Final NaraUSD receiver, defaulting to the share owner.
shares (Optional[decimal.Decimal]) – Decimal NaraUSD+ share amount, exclusive with
raw_shares.raw_shares (Optional[int]) – Raw NaraUSD+ share amount, exclusive with
shares.check_max_deposit (bool) – Retained inherited argument; Nara controls redemption through cooldown state.
check_enough_token (bool) – Check the owner’s current NaraUSD+ balance.
- Returns
One-call cooldown request to settle through
finish_redemption().- Return type
eth_defi.erc_4626.vault_protocol.nara.deposit_redeem.NaraRedemptionRequest
- has_synchronous_redemption()
Return whether NaraUSD+ redemptions settle immediately.
- Returns
Always
Falsebecause the owner must complete a cooldown first.- Return type
- is_redemption_in_progress(owner)
Check whether an owner has an unclaimed NaraUSD+ cooldown.
- Parameters
owner (eth_typing.evm.HexAddress) – Share owner to inspect.
- Returns
Truewhen the vault records a non-zero cooldown deadline.- Return type
- force_settle(ticket, *, mock=None, ignore_liquidity=False)
Advance an Anvil Nara cooldown to the ticket’s claimable deadline.
Nara has no keeper or operator settlement transaction. Advancing the local Anvil clock is the complete settlement boundary, so the result intentionally contains no transaction hashes. The later
unstakecall remains a manager-owned guarded claim.- Parameters
ticket (Optional[Union[eth_defi.vault.deposit_redeem.DepositTicket, eth_defi.vault.deposit_redeem.RedemptionTicket]]) – A pending
NaraRedemptionTicket, orNonefor the synchronous deposit no-op.mock (Optional[object]) – Optional local
MockNaraVaultbound to this exact manager vault. It is an identity guard only: Nara settlement is time-based and never calls an operator method on the supplied object.ignore_liquidity (bool) – Unsupported because a Nara cooldown is a time gate, not a redemption-liquidity gate.
- Returns
A synchronous no-op or a pending-to-claimable, hashless cooldown settlement result.
- Raises
UnsupportedVaultSimulation – If this is not Anvil, the mock is unrelated, the ticket is not a live Nara cooldown, or advancing time does not make it claimable.
- Return type
- can_create_deposit_request(owner)
Check NaraUSD+’s current ERC-4626 deposit maximum.
- Parameters
owner (eth_typing.evm.HexAddress) – Prospective deposit receiver.
- Returns
Truewhen the current maximum is positive.- Return type
- can_create_redemption_request(owner)
Check whether the owner can start a NaraUSD+ cooldown.
- Parameters
owner (eth_typing.evm.HexAddress) – Share owner to inspect.
- Returns
Truewhen the owner has shares and no active cooldown.- Return type
- estimate_redemption_delay()
Read the currently configured NaraUSD+ cooldown duration.
- Returns
Current cooldown as a timedelta.
- Return type
- fetch_cooldown(address)
Read an owner’s current NaraUSD+ cooldown state.
- get_redemption_delay_over(address)
Return an owner’s cooldown expiry, when one exists.
- Parameters
address (Union[eth_typing.evm.HexAddress, str]) – NaraUSD+ share owner.
- Returns
Naive UTC cooldown expiry, or
Nonewhen no claim is pending.- Return type
- can_finish_redeem(redemption_ticket)
Check whether a NaraUSD+ cooldown claim can now be submitted.
- Parameters
redemption_ticket (eth_defi.erc_4626.vault_protocol.nara.deposit_redeem.NaraRedemptionTicket) – Persisted cooldown request.
- Returns
Truewhen the current chain timestamp has reached the deadline.- Return type
- reconstruct_redemption_ticket(data)
Reconstruct a NaraUSD+ cooldown ticket after a process restart.
- Parameters
data (dict) – Data produced by
serialize_redemption_ticket().- Returns
NaraUSD+ cooldown ticket.
- Return type
eth_defi.erc_4626.vault_protocol.nara.deposit_redeem.NaraRedemptionTicket
- serialize_redemption_ticket(ticket)
Serialise a NaraUSD+ ticket with its exact cooldown identity.
- Parameters
ticket (eth_defi.erc_4626.vault_protocol.nara.deposit_redeem.NaraRedemptionTicket) – NaraUSD+ cooldown ticket.
- Returns
JSON-compatible persistent ticket data.
- Return type
- get_redemption_request_status(ticket)
Report whether a NaraUSD+ cooldown is pending or claimable.
- Parameters
ticket (eth_defi.erc_4626.vault_protocol.nara.deposit_redeem.NaraRedemptionTicket) – NaraUSD+ cooldown ticket.
- Returns
pendingbefore maturity,claimableafterwards, ornonewhen the cooldown was claimed, removed, or superseded by another cooldown for the same owner.- Return type
- finish_redemption(redemption_ticket)
Build the NaraUSD+ post-cooldown claim transaction.
- Parameters
redemption_ticket (eth_defi.erc_4626.vault_protocol.nara.deposit_redeem.NaraRedemptionTicket) – Matured cooldown ticket.
- Returns
unstakecontract call that sends NaraUSD to the requested receiver.- Return type
web3.contract.contract.ContractFunction
- __init__(vault)
- Parameters
vault (ERC4626Vault) –
- analyse_deposit(claim_tx_hash, deposit_ticket)
Analyse a mined ERC-4626 deposit or guarded SimpleVault wrapper.
A ticket permits a settlement call through a non-vault wrapper, such as a SimpleVault Safe or its module. The event analyser still filters events by the underlying vault address.
- Parameters
claim_tx_hash (Union[hexbytes.main.HexBytes, str]) – Mined deposit transaction hash.
deposit_ticket (Optional[eth_defi.vault.deposit_redeem.DepositTicket]) – Optional ticket for a guarded non-vault call.
- Returns
Decoded executed deposit quantities or a revert description.
- Return type
Union[eth_defi.vault.deposit_redeem.DepositRedeemEventAnalysis, eth_defi.vault.deposit_redeem.DepositRedeemEventFailure]
- analyse_redemption(claim_tx_hash, redemption_ticket)
Analyse a mined ERC-4626 redemption or guarded SimpleVault wrapper.
A ticket permits a non-vault transaction target for a guarded settlement; the decoded
Withdrawevent must still originate from this vault.- Parameters
claim_tx_hash (Union[hexbytes.main.HexBytes, str]) – Mined redemption transaction hash.
redemption_ticket (Optional[eth_defi.vault.deposit_redeem.RedemptionTicket]) – Optional ticket for a guarded non-vault call.
- Returns
Decoded executed redemption quantities or a revert description.
- Return type
Union[eth_defi.vault.deposit_redeem.DepositRedeemEventAnalysis, eth_defi.vault.deposit_redeem.DepositRedeemEventFailure]
- can_finish_deposit(deposit_ticket)
Synchronous deposits can be finished immediately.
- Parameters
deposit_ticket (eth_defi.erc_4626.deposit_redeem.ERC4626DepositTicket) –
- check_deposit_whitelist(owner)
Reject a deposit when the vault’s whitelist excludes the owner.
Shared deposit-preflight helper implementing the whitelisting contract every manager must honour: when a vault applies a deposit whitelist policy that is applicable and queryable, and
owneris not a member of it, raiseWhitelistingRequiredbefore any transaction is broadcast so the caller can surface a “whitelisting required” state instead of paying gas for a guaranteed revert.The check is intentionally conservative — it only raises when the whitelist information can be obtained and is applicable:
if
is_whitelisted_deposit()raisesNotImplementedError, the vault-wide policy cannot be determined for this adapter/version, so no exception is raised;if the vault is permissionless, no exception is raised;
if
is_account_whitelisted()raisesNotImplementedError, per-account membership cannot be queried, so no exception is raised;only when the policy is applicable and the owner is provably not admitted is
WhitelistingRequiredraised.
Adapters that need a stricter fail-closed policy for an unknown admission state should override their own preflight and raise
VaultFlowUnavailablein addition to calling this helper (see the Lagoon manager for an example).- Parameters
owner (eth_typing.evm.HexAddress) – Deposit owner and controller whose whitelist membership is checked.
- Raises
WhitelistingRequired – When the vault applies an applicable, queryable whitelist policy and
owneris not permitted to deposit.- Return type
None
- create_deposit_request(owner, to=None, amount=None, raw_amount=None, check_max_deposit=True, check_enough_token=True)
Build the deposit request transaction(s) for an owner.
Abstracts the ERC-4626, ERC-7540, Lagoon and other protocol deposit flows behind a common request wrapper.
Whitelisting contract: implementations must raise
WhitelistingRequiredbefore returning a request when the vault applies a deposit whitelist policy, that policy is applicable and queryable, andowneris not permitted to deposit. Callcheck_deposit_whitelist()at the start of the preflight to satisfy this contract. When the whitelist information cannot be obtained (the adapter’s whitelist reads raiseNotImplementedError) the manager must not raiseWhitelistingRequired; it either proceeds — letting any real denial surface as an onchain revert — or fails closed with a plainVaultFlowUnavailablewhen unknown admission is unsafe.- Parameters
owner (eth_typing.evm.HexAddress) – Deposit owner and controller.
to (eth_typing.evm.HexAddress) – Optional separate receiver, where the protocol supports it.
amount (decimal.Decimal) – Human-readable denomination-token amount, converted using the denomination token decimals when
raw_amountis not given.raw_amount (int) – Raw denomination-token amount, overriding
amount.check_max_deposit – Preflight the deposit against the vault’s deposit capacity.
check_enough_token – Preflight that
ownerholds enough denomination token.
- Returns
Deposit request wrapper ready for signing and parsing.
- Raises
WhitelistingRequired – If the vault whitelist is applicable and excludes
owner.VaultFlowUnavailable – If the deposit cannot be safely prepared before broadcast.
- Return type
- create_deposit_request_for_guard_validation(owner, raw_amount)
Build ERC-4626 deposit calldata after a proven global closure.
This Anvil-only diagnostic path is available only when the selected vault’s authoritative global closure reader reports that deposits are unavailable to every account. It preserves the normal protocol admission preflight and all permanent amount constraints, while omitting the temporary closed-deposit capacity and token-balance checks needed to encode the production-equivalent deposit call.
- Parameters
owner (eth_typing.evm.HexAddress) – Safe/SimpleVault address that would own the minted shares.
raw_amount (int) – Raw denomination-token amount from the rejected real-deposit attempt.
- Returns
Single ERC-4626 deposit request for isolated GuardV0 validation.
- Raises
UnsupportedVaultSimulation – If the provider is not Anvil or the vault is not globally closed.
WhitelistingRequired – If the protocol admission policy excludes
owner.
- Return type
- estimate_deposit(owner, amount, block_identifier='latest')
How many shares we get for a deposit.
- Parameters
owner (eth_typing.evm.HexAddress) –
amount (decimal.Decimal) –
block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) –
- Return type
- estimate_redeem(owner, shares, block_identifier='latest')
How many denomination tokens we get for a redeem.
- Parameters
owner (eth_typing.evm.HexAddress) –
shares (decimal.Decimal) –
block_identifier (Union[Literal['latest', 'earliest', 'pending', 'safe', 'finalized'], eth_typing.evm.BlockNumber, eth_typing.evm.Hash32, eth_typing.encoding.HexStr, int]) –
- Return type
- fetch_completed_redemption_tx_hash(ticket)
Find an operator-owned terminal redemption transaction when available.
Claim-based protocols finish through
finish_redemption()and do not need this lookup. Operator-finalised protocols override the hook to find and validate the transaction that paid the requested receiver.- Parameters
ticket (eth_defi.vault.deposit_redeem.RedemptionTicket) – Persisted redemption request to locate.
- Returns
Terminal transaction hash, or
Noneif the protocol has not observed one yet.- Return type
Optional[hexbytes.main.HexBytes]
- fetch_depositable_raw_assets(owner)
Read the vault’s current raw deposit limit for an owner.
Overridable deposit-limit hook. The base implementation reads the standard ERC-4626
maxDeposit(). Multi-asset or non-standard vaults that do not implementmaxDeposit(for example Upshift’s multi-asset vault) override this to answer from their own limit reader, so the deposit preflight does not depend on the ERC-4626 method being present.- Parameters
owner (eth_typing.evm.HexAddress) – Account the deposit limit is queried for.
- Returns
Raw deposit limit, or
Nonewhen the vault exposes no limit. A zeromaxDepositis omitted from this owner-specific capacity hook (EIP-4626 is not universally honoured), consistent witheth_defi.erc_4626.flow.deposit_4626(). The normal deposit preflight separately recognises a meaningful global zero throughERC4626Vault.fetch_deposit_closed_reason().- Raises
VaultFlowUnavailable – When the vault does not expose a readable ERC-4626
maxDepositand no protocol-specific override is provided, instead of leaking a raw web3 ABI/read error.- Return type
- fetch_vault_flow_events(hypersync_client, start_block, end_block)
Fetch asynchronous vault request events from an indexed backend.
The base implementation returns no events for vault managers that do not have a two-phase deposit or redemption flow.
- Parameters
- Returns
Iterator of protocol-neutral pending vault flow events.
- Return type
collections.abc.Iterator[eth_defi.vault.flow_events.PendingVaultFlow]
- finish_deposit(deposit_ticket)
Can we finish the deposit process in async vault.
We can claim our shares from the vault now
- Parameters
deposit_ticket (eth_defi.vault.deposit_redeem.DepositTicket) –
- Return type
web3.contract.contract.ContractFunction
- force_redemption_liquidity(owner, raw_shares, failure)
Provision an unavailable synchronous redemption on an Anvil fork.
Concrete managers may implement this only for a source-proven liquidity failure. The default is deliberately unsupported: this hook must never bypass admission, minimums, maturity or time locks.
- Parameters
owner (eth_typing.evm.HexAddress) – Redemption owner.
raw_shares (int) – Exact raw share quantity requested.
failure (eth_defi.vault.deposit_redeem.VaultFlowUnavailable) – Typed preflight failure that prompted the intervention request.
- Returns
Structured intervention evidence from a concrete manager.
- Raises
UnsupportedVaultSimulation – Always for managers without a protocol-specific implementation.
- Return type
eth_defi.vault.deposit_redeem.VaultRedemptionSimulationIntervention
- get_deposit_approval_target()
Return the ERC-20 spender required for a deposit request.
Standard ERC-4626 and the currently supported async adapters pull denomination tokens from the vault address itself. An adapter using a different router or silo must override this method; guarded callers use it to whitelist and validate the exact approval calldata.
- Returns
ERC-20 approval spender address.
- Return type
- get_deposit_delay_over(address)
Estimate when a pending async deposit request will settle.
Mirror of
get_redemption_delay_over()for the deposit side.Used to show an estimated settlement time for unsettled deposits (e.g. in the trade-executor
trade-uitable).Default returns
None: the protocol has no deterministic onchain settlement schedule (e.g. operator-driven ERC-7540 vaults like Lagoon). Subclasses with a predictable settlement cadence (e.g. Ostium V1.5) override this to return an estimated UTC timestamp.
- Parameters
address (Union[eth_typing.evm.HexAddress, str]) – Owner of the pending deposit request.
- Returns
Naive UTC timestamp when the deposit is expected to settle, or
Nonewhen no onchain estimate is available.- Return type
- get_deposit_request_status(ticket)
Query the current status of an async deposit request.
Default implementation probes via
can_finish_deposit(). Subclasses should override for more accurate status reporting (e.g. distinguishingreclaimablefrompending).- Parameters
ticket (eth_defi.vault.deposit_redeem.DepositTicket) –
- Return type
- get_max_deposit(owner)
How much we can deposit
- Parameters
owner (eth_typing.evm.HexAddress) –
- Return type
- has_synchronous_deposit()
Does this vault support synchronous deposits?
E.g. ERC-4626 vaults
- Return type
- is_deposit_in_progress(owner)
Check if the owner has an active deposit request.
- Parameters
owner (eth_typing.evm.HexAddress) – Owner of the shares
- Returns
True if there is an active redemption request
- Return type
- reclaim_deposit(ticket)
Return a function to recover funds after a failed async deposit settlement.
Returns
Noneif the protocol does not support reclaim.- Parameters
ticket (eth_defi.vault.deposit_redeem.DepositTicket) –
- Return type
Optional[web3.contract.contract.ContractFunction]
- reclaim_withdrawal(ticket)
Return a function to recover shares after a failed async withdrawal settlement.
Returns
Noneif the protocol does not support reclaim.- Parameters
- Return type
Optional[web3.contract.contract.ContractFunction]
- reconstruct_deposit_ticket(data)
Reconstruct a deposit ticket from a serialised dict.
Default returns a base
DepositTicket. Subclasses override for protocol-specific ticket types.- Parameters
data (dict) –
- Return type
- serialize_deposit_ticket(ticket)
Serialise a deposit ticket to a dict for persistence.
The trade-executor stores this in
trade.other_dataso that the settlement retry module can reconstruct the ticket after a process restart.Default implementation stores base
DepositTicketfields. Subclasses override to add protocol-specific fields (e.g.settlement_idfor Ostium,requestIdfor ERC-7540).- Parameters
ticket (eth_defi.vault.deposit_redeem.DepositTicket) –
- Return type