Skip to content

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.

function deposit(address user, address token, uint256 amount) external
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:

event Deposited(address indexed token, address indexed user, uint256 amount);

creditLedger

Credit a user's vault balance. The caller must have already transferred tokens to the vault in the same transaction.

function creditLedger(address user, address token, uint256 expectedAmount) external
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.

function withdraw(address user, address token, uint256 amount, address to) external
Parameter Type Description
user address Account being debited
token address ERC-20 token address
amount uint256 Amount to withdraw
to address Token recipient

Requirements:

  • to must not be the zero address
  • Amount must be > 0
  • User balance must be sufficient

Events:

event Withdrawn(address indexed token, address indexed user, uint256 amount);

transferLedger

Internal ledger transfer between two users. No ERC-20 token movement occurs.

function transferLedger(address fromUser, address toUser, address token, uint256 amount) external
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.

function balanceOf(address token, address user) external view returns (uint256)

Query the total physical ERC-20 balance held in the vault:

function balanceOf(address token) external view returns (uint256)

setBlacklisted

Blacklist or unblacklist a user account.

function setBlacklisted(address user, bool _isBlacklisted) external

Blacklisted users cannot deposit or receive credits, but can still withdraw their existing balance.

Events:

event Blacklisted(address indexed user, bool isBlacklisted);

isBlacklisted

Check if a user is blacklisted.

function isBlacklisted(address user) external view returns (bool)

rescueToken

Rescue tokens that were accidentally sent directly to the vault (not through deposit).

function rescueToken(address token, address to, uint256 amount) external

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