Skip to main content

Smart Contract Overview

Emerald Vault contracts are ERC4626-compliant tokenized vaults with a custom withdrawal queue. They're built on OpenZeppelin 5.2.0 and deployed on Ethereum mainnet.

Contracts

ContractDescription
EmeraldVaultThe ERC4626 vault — handles deposits, withdrawals, NAV updates, and sweeps
EmeraldVaultFactoryDeploys new vault instances with standardized configuration

ABIs

ABIs are available in the repository:

packages/contracts/abi/EmeraldVault.json
packages/contracts/abi/EmeraldVaultFactory.json

Mainnet Token Addresses

AssetTokenAddressDecimals
ETHWETH0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc218
USDCUSDC0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB486
USDTUSDT0xdAC17F958D2ee523a2206206994597C13D831ec76
BTCWBTC0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C5998
GOLDPAXG0x45804880De22913dAFE09f4980848ECE6EcbAf7818

Vault Constants

ParameterValueDescription
ADMIN_TRANSFER_DELAY2 daysTwo-step DEFAULT_ADMIN_ROLE transfer delay

Withdrawals have no fixed time delay and no expiry — a request settles instantly when the vault is liquid, otherwise it waits in a FIFO queue until released or claimed (see Withdrawal Flow).

Access Control Roles

The vault uses OpenZeppelin's AccessControlDefaultAdminRules with a 2-day admin transfer delay.

RoleDescription
DEFAULT_ADMIN_ROLECan grant/revoke roles and set the omnibus address. Two-step transfer with 2-day delay.
VAULT_ADMINCan sweep, fund the vault, update NAV, and release withdrawals
GUARDIANCan pause/unpause the vault in emergencies

Key Design Decisions

  • Instant-or-queued withdrawals — ERC4626 withdraw()/redeem() revert. requestWithdrawal settles instantly when the vault is liquid and the queue is empty, otherwise it joins a FIFO queue (released by admin or self-claimed at the head).
  • Off-chain yieldmanagedAssets tracks assets held off-chain. totalAssets() = on-chain balance + managedAssets.
  • Sweep is an unconditional admin escape hatchsweep() moves all liquid assets to the omnibus regardless of pending withdrawals; the admin must fundVault afterward before queued users can be paid.
  • Fee-on-transfer tokens — Explicitly unsupported. Rebasing tokens are also unsupported.

Function Reference

User Functions

FunctionDescription
deposit(uint256 assets, address receiver[, uint256 partnerId])Deposit the primary asset (3-arg overload attributes to a partner)
depositToken(IERC20 token, uint256 assets, address receiver[, uint256 partnerId])Deposit a secondary accepted token (e.g. USDT, cbBTC)
depositETH(address receiver[, uint256 partnerId])Deposit native ETH into the WETH vault (payable)
requestWithdrawal(uint256 shares[, uint256 partnerId])Withdraw — instant if liquid, else FIFO-queued
claimWithdrawal()Settle your own request when it's at the FIFO head and the vault is liquid (no args)
cancelWithdrawal(uint256 requestIndex)Cancel a queued request (blocked once a NAV update lands)

View Functions

FunctionReturnsDescription
totalAssets()uint256On-chain balance + managed assets
managedAssets()uint256Assets held off-chain
paused()boolWhether the vault is paused
balanceOf(address)uint256Share balance of an address
convertToAssets(uint256 shares)uint256Convert shares to asset value
convertToShares(uint256 assets)uint256Convert assets to share value
pendingCount()uint256Number of unresolved queued requests
totalPendingShares()uint256Total shares locked in the queue (asset value = convertToAssets(...))
availableLiquidity()uint256Liquid assets currently available for payouts
withdrawalQueueLength()uint256Total withdrawal requests ever created
getWithdrawalRequest(uint256 index)tupleFull withdrawal request details
getUserRequests(address user)uint256[]List of request indices for a user

Admin Functions (not for partners)

FunctionRole RequiredDescription
sweep()VAULT_ADMINMove all liquid assets to the omnibus wallet (no args)
fundVault(IERC20 token, uint256 amount)VAULT_ADMINPull a token into the vault for withdrawals
updateNAV(uint256 newManagedAssets)VAULT_ADMINUpdate off-chain managed assets
releaseWithdrawals()VAULT_ADMINPay queued withdrawals in FIFO order
setOmnibus(address newOmnibus)DEFAULT_ADMIN_ROLEChange the omnibus address
pause() / unpause()GUARDIANEmergency pause/unpause