# Unlocking apyUSD for apxUSD

apyUSD holders can unlock their tokens to receive apxUSD assets. apyUSD is a synchronous ERC-4626 vault — withdrawals and redeems execute immediately and return **apxUSD\_unlock** tokens. apxUSD\_unlock is redeemable 1:1 for apxUSD after a 20 day cooldown period but does not earn yield and is non-transferrable.

{% hint style="warning" %}
You cannot cancel unlocking once it has been initiated and will only be able to convert apxUSD\_unlock to apxUSD after the cooldown period.
{% endhint %}

### Understanding Unlock Methods

The vault provides standard ERC-4626 methods for unlocking, offering flexibility in how users specify amounts:

**For Unlocking (Synchronous — returns apxUSD\_unlock):**

* **`withdraw(assets, receiver, owner)`**: Specify the exact apxUSD amount to receive after cooldown; burn calculated apyUSD shares immediately
  * Use when: You know exactly how much apxUSD you want to unlock
  * Example: "I want to unlock 1000 apxUSD"
* **`redeem(shares, receiver, owner)`**: Specify the exact apyUSD shares to burn; receive calculated apxUSD\_unlock immediately
  * Use when: You know exactly how many apyUSD shares you want to exit
  * Example: "I want to redeem all 950 of my apyUSD shares"

After receiving apxUSD\_unlock tokens, call `UnlockToken.redeem()` once the cooldown period has elapsed to receive apxUSD.

{% hint style="info" %}
Prefer to use the `withdrawForMaxShares` and `redeemForMinAssets` methods to limit price risk when unlocking apyUSD.
{% endhint %}

{% hint style="warning" %}
Multiple unlocks reset the cooldown period. For example, if you unlock 100 apxUSD you will receive apxUSD\_unlock that is convertable to apxUSD after the cooldown period. If you later unlock another 50 apxUSD the cooldown period will reset and you will have to wait the full period to completely unlock the 150 apxUSD.
{% endhint %}

### Price Controls on Unlocking

The apyUSD vault exposes withdraw and redeem methods with price controls to limit price risk between submitting a transaction and the transaction being included in a block:

* **`withdrawForMaxShares(uint256 assets, uint256 maxShares, address receiver)`**: Withdraws exact assets or reverts if more than max shares will be burned
* **`redeemForMinAssets(uint256 shares, uint256 minAssets, address receiver)`**: Redeems exact shares or reverts if less than min assets will be received

### Total Assets and Vested Yield

The apyUSD vault's `totalAssets()` function includes both:

* The vault's apxUSD balance (assets held directly in the vault)
* The `vestedAmount()` available in the LinearVestV0 contract

When a withdrawal is requested, the vault automatically pulls all vested yield from the vesting contract before processing the withdrawal, ensuring the exchange rate reflects the full accrued value and the vault has sufficient assets to fund the withdrawal.

#### Unlock Examples

1. Bob calls `apyUSD.withdraw(1000e18, bob, bob)`
2. apyUSD calculates shares based on `totalAssets()` which includes vested yield
3. apyUSD determines the exchange rate between assets and shares
4. Bob's apyUSD shares are burned immediately
5. 1000 apxUSD is deposited into the UnlockToken contract; Bob receives 1000 apxUSD\_unlock
6. After the cooldown period, Bob calls `UnlockToken.redeem(1000e18, bob, bob)` to receive 1000 apxUSD

### The UnlockToken: Tokenized Escrow During Cooldown

During the cooldown period, unlocked apxUSD assets are held in the **UnlockToken** contract.

**How it works:**

* User calls `apyUSD.withdraw()` or `apyUSD.redeem()` — apyUSD shares are burned synchronously
* The apxUSD assets are deposited into the UnlockToken contract by the vault
* The user immediately receives apxUSD\_unlock tokens (UnlockToken shares), redeemable 1:1 for apxUSD after the cooldown period
* The apyUSD vault is configured as the operator for UnlockToken, allowing it to initiate the redeem request on behalf of the user immediately
* After the cooldown period, the user calls `UnlockToken.redeem()` to receive their apxUSD

{% hint style="info" %}
There is only one instance of UnlockToken and it is used exclusively by the apyUSD vault.
{% endhint %}

### Success & Failure Flows

#### Withdraw Success

Users specify the exact amount of apxUSD to receive after the cooldown period. apyUSD shares are burned immediately and apxUSD\_unlock tokens are returned.

```mermaid
sequenceDiagram
	actor bob as Bob
	participant vault as apyUSD<br/>Vault
	participant unlockToken as UnlockToken
	participant apxUSD

	bob ->> vault: withdraw(1000 apxUSD, bob, bob)

	activate vault
	vault ->> vault: previewWithdraw(1000 apxUSD) → 970 apyUSD shares
	vault ->> vault: pull vested yield from LinearVestV0
	vault ->> vault: burn 970 apyUSD from bob
	vault ->> unlockToken: deposit(1000 apxUSD, bob)
	activate unlockToken
	unlockToken -->> bob: mint 1000 apxUSD_unlock
	deactivate unlockToken
	vault ->> unlockToken: requestRedeem(1000, bob, bob)
	vault -->> bob: returns 970 apyUSD burned
	deactivate vault

	note right of bob: Cooldown period begins

	bob ->> unlockToken: redeem(1000 apxUSD_unlock, bob, bob)
	activate unlockToken
	unlockToken ->> apxUSD: transfer(bob, 1000)
	unlockToken -->> bob: 1000 apxUSD received
	deactivate unlockToken
```

#### Redeem Success

Users specify the exact amount of apyUSD shares to burn. The calculated apxUSD amount is deposited into UnlockToken and redeemable after the cooldown period.

```mermaid
sequenceDiagram
	actor bob as Bob
	participant vault as apyUSD<br/>Vault
	participant unlockToken as UnlockToken
	participant apxUSD

	bob ->> vault: redeem(970 apyUSD, bob, bob)

	activate vault
	vault ->> vault: previewRedeem(970 apyUSD) → 1000 apxUSD
	vault ->> vault: pull vested yield from LinearVestV0
	vault ->> vault: burn 970 apyUSD from bob
	vault ->> unlockToken: deposit(1000 apxUSD, bob)
	activate unlockToken
	unlockToken -->> bob: mint 1000 apxUSD_unlock
	deactivate unlockToken
	vault ->> unlockToken: requestRedeem(1000, bob, bob)
	vault -->> bob: returns 1000 apxUSD queued
	deactivate vault

	note right of bob: Cooldown period begins

	bob ->> unlockToken: redeem(1000 apxUSD_unlock, bob, bob)
	activate unlockToken
	unlockToken ->> apxUSD: transfer(bob, 1000)
	unlockToken -->> bob: 1000 apxUSD received
	deactivate unlockToken
```

#### Withdrawal Failure — Slippage Exceeded

When the slippage is exceeded on withdraw or redeem.

```mermaid
sequenceDiagram
	actor bob as Bob

	box On-chain
	participant vault as apyUSD<br/>Vault
	end

	bob ->> vault: withdrawForMaxShares(1000 apxUSD, bob, maxSharesIn: 950 apyUSD)
	activate vault
	vault ->> vault: previewWithdraw(1000 apxUSD) = 970 apyUSD shares
	vault ->> vault: check slippage: 970 > 950 apyUSD
	vault ->> bob: revert SlippageExceeded(950, 970)
	deactivate vault

	note right of bob: Transaction fails.<br/>Bob can adjust slippage<br/>and retry
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.apyx.fi/technical-overview/unlocking.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
