Vault.sol¶
The vault contract holds all user funds with per-user ledger tracking. It separates asset custody from trading logic.
Why the Vault Exists¶
The vault enables gas-free continuous trading. Without it, every order fill would require an on-chain token transfer, meaning traders pay gas on every trade. With the vault, users deposit once and their balance is tracked in an internal ledger. Fills are settled via transferLedger — a ledger update, not a token movement — so traders can keep placing and filling orders without additional gas costs.
This is critical for professional market makers and financial institutions who place hundreds or thousands of orders per day. Without the vault, each fill would cost gas, making active market-making on L1 economically unviable. The vault lets them deposit collateral once, then trade continuously at the speed of the off-chain matching engine while only paying gas on deposit and withdrawal.
Mainnet: 0xC7d4Fd2638e6630C8C61329878676b88A8A24D43 Source: src/Vault.sol
Functions¶
deposit¶
Pull tokens from a user's wallet into the vault.
| Parameter | Type | Description |
|---|---|---|
user | address | Beneficiary account |
token | address | ERC-20 token address |
amount | uint256 | Amount to deposit |
Requirements:
- Caller must have
TRADER_ROLE - User must not be blacklisted
- Amount must be > 0
- User must have approved the vault to spend the token
The active TRADER_ROLE holder is the Sera contract.
Events:
creditLedger¶
Credit a user's vault balance. The caller must have already transferred tokens to the vault in the same transaction.
| Parameter | Type | Description |
|---|---|---|
user | address | Beneficiary account |
token | address | ERC-20 token address |
expectedAmount | uint256 | Amount to credit |
withdraw¶
Debit a user's vault balance and transfer tokens to a recipient.
| Parameter | Type | Description |
|---|---|---|
user | address | Account being debited |
token | address | ERC-20 token address |
amount | uint256 | Amount to withdraw |
to | address | Token recipient |
Requirements:
tomust not be the zero address- Amount must be > 0
- User balance must be sufficient
Events:
transferLedger¶
Internal ledger transfer between two users. No ERC-20 token movement occurs.
| Parameter | Type | Description |
|---|---|---|
fromUser | address | Source account |
toUser | address | Destination account |
token | address | ERC-20 token address |
amount | uint256 | Amount to transfer |
This is used internally during order settlement. The total vault TVL remains constant.
Events:
event Withdrawn(address indexed token, address indexed user, uint256 amount); // fromUser
event Deposited(address indexed token, address indexed user, uint256 amount); // toUser
Both events are emitted to keep standard subgraph indexers in sync with the ledger move, even though no ERC-20 transfer actually happens.
balanceOf¶
Query a user's vault balance for a specific token.
Query the total physical ERC-20 balance held in the vault:
setBlacklisted¶
Blacklist or unblacklist a user account.
Blacklisted users cannot deposit or receive credits, but can still withdraw their existing balance.
Events:
isBlacklisted¶
Check if a user is blacklisted.
rescueToken¶
Rescue tokens that were accidentally sent directly to the vault (not through deposit).
Can only rescue surplus tokens (physical balance minus tracked balance). User-tracked funds cannot be rescued.
Errors¶
| Error | Cause |
|---|---|
BlacklistedUser | User is blacklisted (deposits/credits blocked) |
ZeroAmount | Amount is 0 |
ZeroAddress | Recipient or user is the zero address |
InsufficientBalance | User doesn't have enough balance |
CannotRescueTrackedFunds | Attempted to rescue tracked user funds |
InsufficientSurplus | Rescue amount exceeds surplus |