ApyUSD
Inherits: Initializable, ERC20PermitUpgradeable, ERC20PausableUpgradeable, ERC20DenyListUpgradable, AccessManagedUpgradeable, UUPSUpgradeable, ERC4626Upgradeable, IApyUSD, EInvalidCaller
Title: ApyUSD
ERC4626 synchronous tokenized vault for staking ApxUSD
Deposits and withdrawals are synchronous. Withdrawals delegate unlocking delay to UnlockToken. Features:
- Instant deposits/mints with deny list checking via AddressList
- Instant redeems/withdrawals that deposit assets to UnlockToken and start redeem requests
- UnlockToken handles the cooldown period and async claim flow
- ERC4626 compatibility
- Pausable and freezeable for compliance
- UUPS upgradeable pattern
State Variables
FEE_PRECISION
Fee precision constant (100% = 1e18)
uint256 private constant FEE_PRECISION = 1e18
MAX_FEE
Maximum fee allowed (1%)
uint256 private constant MAX_FEE = 0.01e18
APYUSD_STORAGE_LOC
bytes32 private constant APYUSD_STORAGE_LOC = 0x1ff8d3deae3efb825bbaa861079c5ce537ca15be7f99d50a5b2800b88987f100
Functions
_getApyUSDStorage
function _getApyUSDStorage() private pure returns (ApyUSDStorage storage $);
constructor
Note: oz-upgrades-unsafe-allow: constructor
constructor() ;
initialize
Initializes the ApyUSD vault
UnlockToken must be set after deployment using setUnlockToken()
function initialize(
string memory name,
string memory symbol,
address initialAuthority,
address asset,
address initialDenyList
) public initializer;
Parameters
| Name | Type | Description |
|---|---|---|
name | string | |
symbol | string | |
initialAuthority | address | Address of the AccessManager contract |
asset | address | Address of the underlying asset (ApxUSD) |
initialDenyList | address | Address of the AddressList contract for deny list checking |
_authorizeUpgrade
Authorizes contract upgrades
Only callable through AccessManager with ADMIN role
function _authorizeUpgrade(address newImplementation) internal override restricted;
_update
Hook that is called before any token transfer
Enforces pause, freeze, and deny list functionality
function _update(address from, address to, uint256 value)
internal
override(ERC20Upgradeable, ERC20PausableUpgradeable, ERC20DenyListUpgradable);
decimals
Returns the number of decimals used for the token
Overrides both ERC20 and ERC4626 decimals
function decimals() public view override(ERC20Upgradeable, ERC4626Upgradeable) returns (uint8);
_decimalsOffset
Returns the decimals offset for inflation attack protection
Can be overridden to add virtual shares/assets
function _decimalsOffset() internal pure override returns (uint8);
totalAssets
Returns the total amount of assets managed by the vault
Overrides ERC4626 to include vested yield from vesting contract
function totalAssets() public view override returns (uint256);
Returns
| Name | Type | Description |
|---|---|---|
<none> | uint256 | Total assets including vault balance and vested yield |
previewWithdraw
Preview adding an exit fee on withdrawal
Overrides ERC4626 to account for unlocking fees
function previewWithdraw(uint256 assets) public view override returns (uint256);
Parameters
| Name | Type | Description |
|---|---|---|
assets | uint256 | Amount of assets to withdraw (what user receives after fees) |
Returns
| Name | Type | Description |
|---|---|---|
<none> | uint256 | Amount of shares needed to withdraw the requested assets |
previewRedeem
Preview taking an exit fee on redeem
Overrides ERC4626 to account for unlocking fees
function previewRedeem(uint256 shares) public view override returns (uint256);
Parameters
| Name | Type | Description |
|---|---|---|
shares | uint256 | Amount of shares to redeem |
Returns
| Name | Type | Description |
|---|---|---|
<none> | uint256 | Amount of assets user will receive after fees are deducted |
_deposit
Internal deposit/mint function with deny list checking
Overrides ERC4626 internal function to add deny list checks
function _deposit(address caller, address receiver, uint256 assets, uint256 shares)
internal
override
checkNotDenied(caller)
checkNotDenied(receiver);
Parameters
| Name | Type | Description |
|---|---|---|
caller | address | Address initiating the deposit |
receiver | address | Address to receive the shares |
assets | uint256 | Amount of assets to deposit |
shares | uint256 | Amount of shares to mint |
_withdraw
Internal withdraw function that deposits assets to UnlockToken and starts redeem request
Overrides ERC4626 to delegate unlocking delay to UnlockToken
Fees are deducted from user shares but only transferred to feeWallet if it is set. When feeWallet is address(0) or address(this), fees remain in the vault and accrue to depositors.
function _withdraw(address caller, address receiver, address owner, uint256 assets, uint256 shares)
internal
override
checkNotDenied(caller)
checkNotDenied(receiver)
checkNotDenied(owner);
Parameters
| Name | Type | Description |
|---|---|---|
caller | address | Address initiating the withdrawal |
receiver | address | Address to receive the UnlockToken shares |
owner | address | Address that owns the shares |
assets | uint256 | Amount of assets to withdraw |
shares | uint256 | Amount of shares to burn |
setDenyList
Sets the deny list contract
Only callable through AccessManager with ADMIN_ROLE
function setDenyList(IAddressList newDenyList) external restricted;
Parameters
| Name | Type | Description |
|---|---|---|
newDenyList | IAddressList | Address of the new AddressList contract |
setUnlockToken
Sets the UnlockToken contract
Only callable through AccessManager with ADMIN_ROLE
No fund migration is performed - outstanding requests remain on old UnlockToken
function setUnlockToken(IUnlockToken newUnlockToken) external restricted;
Parameters
| Name | Type | Description |
|---|---|---|
newUnlockToken | IUnlockToken | The new UnlockToken contract |
unlockToken
Returns the current UnlockToken contract address
function unlockToken() external view returns (address);
Returns
| Name | Type | Description |
|---|---|---|
<none> | address | Address of the UnlockToken contract |
setVesting
Sets the Vesting contract
Only callable through AccessManager with ADMIN_ROLE
Setting to address(0) removes the vesting contract
function setVesting(IVesting newVesting) external restricted;
Parameters
| Name | Type | Description |
|---|---|---|
newVesting | IVesting | The new Vesting contract (can be address(0) to remove) |
vesting
Returns the current Vesting contract address
function vesting() external view returns (address);
Returns
| Name | Type | Description |
|---|---|---|
<none> | address | Address of the Vesting contract |
unlockingFee
Returns the current unlocking fee
function unlockingFee() public view returns (uint256);
Returns
| Name | Type | Description |
|---|---|---|
<none> | uint256 | Fee as a percentage with 18 decimals (e.g., 0.01e18 = 1%, 1e18 = 100%) |
setUnlockingFee
Sets the unlocking fee
Only callable through AccessManager with ADMIN_ROLE
function setUnlockingFee(uint256 fee) external restricted;
Parameters
| Name | Type | Description |
|---|---|---|
fee | uint256 | Fee as a percentage with 18 decimals (e.g., 0.01e18 = 1%, 1e18 = 100%) |
feeWallet
Returns the current fee wallet address
function feeWallet() public view returns (address);
Returns
| Name | Type | Description |
|---|---|---|
<none> | address | Address of the fee wallet |
setFeeWallet
Sets the fee wallet address
Only callable through AccessManager with ADMIN_ROLE
When feeWallet is address(0) or address(this), fees remain in the vault and accrue to depositors
function setFeeWallet(address wallet) external restricted;
Parameters
| Name | Type | Description |
|---|---|---|
wallet | address | Address to receive fees |
_feeOnRaw
Calculates the fees that should be added to an amount assets that does not already include fees
Used in previewWithdraw and _withdraw operations
function _feeOnRaw(uint256 assets, uint256 feePercentage) private pure returns (uint256);
Parameters
| Name | Type | Description |
|---|---|---|
assets | uint256 | The asset amount before fees |
feePercentage | uint256 | Fee as a percentage with 18 decimals (e.g., 0.01e18 = 1%, 1e18 = 100%) |
Returns
| Name | Type | Description |
|---|---|---|
<none> | uint256 | Fee amount to add |
_feeOnTotal
Calculates the fee part of an amount assets that already includes fees
Used in previewRedeem operations
function _feeOnTotal(uint256 assets, uint256 feePercentage) private pure returns (uint256);
Parameters
| Name | Type | Description |
|---|---|---|
assets | uint256 | The total asset amount including fees |
feePercentage | uint256 | Fee as a percentage with 18 decimals (e.g., 0.01e18 = 1%, 1e18 = 100%) |
Returns
| Name | Type | Description |
|---|---|---|
<none> | uint256 | Fee amount that is part of the total |
depositForMinShares
Deposits exact assets for shares or reverts if less than min shares will be minted
Provides slippage protection for deposits
function depositForMinShares(uint256 assets, uint256 minShares, address receiver)
external
returns (uint256 shares);
Parameters
| Name | Type | Description |
|---|---|---|
assets | uint256 | Amount of assets to deposit |
minShares | uint256 | Minimum amount of shares expected |
receiver | address | Address to receive the shares |
Returns
| Name | Type | Description |
|---|---|---|
shares | uint256 | Amount of shares minted |
mintForMaxAssets
Mint exact shares for assets or reverts if more than max assets will be deposited
Provides slippage protection for mints
function mintForMaxAssets(uint256 shares, uint256 maxAssets, address receiver) external returns (uint256 assets);
Parameters
| Name | Type | Description |
|---|---|---|
shares | uint256 | Amount of shares to mint |
maxAssets | uint256 | Maximum amount of assets willing to deposit |
receiver | address | Address to receive the shares |
Returns
| Name | Type | Description |
|---|---|---|
assets | uint256 | Amount of assets deposited |
withdrawForMaxShares
Withdraws exact assets for shares or reverts if more than max shares will be burned
Provides slippage protection for withdrawals
function withdrawForMaxShares(uint256 assets, uint256 maxShares, address receiver)
external
returns (uint256 shares);
Parameters
| Name | Type | Description |
|---|---|---|
assets | uint256 | Amount of assets to withdraw |
maxShares | uint256 | Maximum amount of shares willing to burn |
receiver | address | Address to receive the assets (as UnlockToken shares) |
Returns
| Name | Type | Description |
|---|---|---|
shares | uint256 | Amount of shares burned |
redeemForMinAssets
Redeems exact shares for assets or reverts if less than min assets will be withdrawn
Provides slippage protection for redemptions
function redeemForMinAssets(uint256 shares, uint256 minAssets, address receiver) external returns (uint256 assets);
Parameters
| Name | Type | Description |
|---|---|---|
shares | uint256 | Amount of shares to redeem |
minAssets | uint256 | Minimum amount of assets expected |
receiver | address | Address to receive the assets (as UnlockToken shares) |
Returns
| Name | Type | Description |
|---|---|---|
assets | uint256 | Amount of assets withdrawn |
pause
Pauses all token transfers
Only callable through AccessManager with ADMIN_ROLE
function pause() external restricted;
unpause
Unpauses all token transfers
Only callable through AccessManager with ADMIN_ROLE
function unpause() external restricted;
Structs
ApyUSDStorage
Note: storage-location: erc7201:apyx.storage.ApyUSD
struct ApyUSDStorage {
/// @notice Reference to the UnlockToken contract for unlocking delay
IUnlockToken unlockToken;
/// @notice Reference to the Vesting contract for yield distribution
IVesting vesting;
/// @notice Unlocking fee as a percentage with 18 decimals (e.g., 0.01e18 = 1%, 1e18 = 100%)
uint256 unlockingFee;
/// @notice Address to receive unlocking fees
address feeWallet;
}