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
| Contract | Description |
|---|---|
| EmeraldVault | The ERC4626 vault — handles deposits, withdrawals, NAV updates, and sweeps |
| EmeraldVaultFactory | Deploys 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
| Asset | Token | Address | Decimals |
|---|---|---|---|
| ETH | WETH | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 | 18 |
| USDC | USDC | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 | 6 |
| USDT | USDT | 0xdAC17F958D2ee523a2206206994597C13D831ec7 | 6 |
| BTC | WBTC | 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599 | 8 |
| GOLD | PAXG | 0x45804880De22913dAFE09f4980848ECE6EcbAf78 | 18 |
Vault Constants
| Parameter | Value | Description |
|---|---|---|
ADMIN_TRANSFER_DELAY | 2 days | Two-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.
| Role | Description |
|---|---|
DEFAULT_ADMIN_ROLE | Can grant/revoke roles and set the omnibus address. Two-step transfer with 2-day delay. |
VAULT_ADMIN | Can sweep, fund the vault, update NAV, and release withdrawals |
GUARDIAN | Can pause/unpause the vault in emergencies |
Key Design Decisions
- Instant-or-queued withdrawals — ERC4626
withdraw()/redeem()revert.requestWithdrawalsettles 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 yield —
managedAssetstracks assets held off-chain.totalAssets()= on-chain balance +managedAssets. - Sweep is an unconditional admin escape hatch —
sweep()moves all liquid assets to the omnibus regardless of pending withdrawals; the admin mustfundVaultafterward before queued users can be paid. - Fee-on-transfer tokens — Explicitly unsupported. Rebasing tokens are also unsupported.
Function Reference
User Functions
| Function | Description |
|---|---|
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
| Function | Returns | Description |
|---|---|---|
totalAssets() | uint256 | On-chain balance + managed assets |
managedAssets() | uint256 | Assets held off-chain |
paused() | bool | Whether the vault is paused |
balanceOf(address) | uint256 | Share balance of an address |
convertToAssets(uint256 shares) | uint256 | Convert shares to asset value |
convertToShares(uint256 assets) | uint256 | Convert assets to share value |
pendingCount() | uint256 | Number of unresolved queued requests |
totalPendingShares() | uint256 | Total shares locked in the queue (asset value = convertToAssets(...)) |
availableLiquidity() | uint256 | Liquid assets currently available for payouts |
withdrawalQueueLength() | uint256 | Total withdrawal requests ever created |
getWithdrawalRequest(uint256 index) | tuple | Full withdrawal request details |
getUserRequests(address user) | uint256[] | List of request indices for a user |
Admin Functions (not for partners)
| Function | Role Required | Description |
|---|---|---|
sweep() | VAULT_ADMIN | Move all liquid assets to the omnibus wallet (no args) |
fundVault(IERC20 token, uint256 amount) | VAULT_ADMIN | Pull a token into the vault for withdrawals |
updateNAV(uint256 newManagedAssets) | VAULT_ADMIN | Update off-chain managed assets |
releaseWithdrawals() | VAULT_ADMIN | Pay queued withdrawals in FIFO order |
setOmnibus(address newOmnibus) | DEFAULT_ADMIN_ROLE | Change the omnibus address |
pause() / unpause() | GUARDIAN | Emergency pause/unpause |