HLAgentVault is the contract a trader’s capital sits in. One clone is deployed per trader and listing, and its address is its own HyperCore account. This page walks through it call by call. For the design reasoning, read ADR-0001 (vault topology) and ADR-0002 (execution modes) in agent-circle-evm.
Contracts and addresses
HyperEVM testnet, chain 998, deployed November 4, 2026. RPC:https://rpc.hyperliquid-testnet.xyz/evm.
The fact that shapes the contract
CoreWriter, the contract that sends actions from HyperEVM to HyperCore, is fire-and-forget. Sending an order succeeds whether or not HyperCore accepts it, and HyperCore can drop an order for a bad tick size, a bad lot size, missing margin or an unlisted asset. Nothing on the HyperEVM side can tell at the time. SoplaceOrder only knows it asked. The vault’s list of open orders is a hypothesis, which it books as reservations and settles later in reconcile. Most of what follows is a consequence of that.
Opening a vault
factory.deployVault(listingId, positionCapBps, maxDrawdownBps), called by the trader.
- The trader is always the caller. Nobody can open a vault owned by someone else.
- The address is deterministic per trader and listing, so a trader cannot open two vaults on one listing to sit under a cap twice.
predictVault(trader, listingId)returns it before deployment. - The listing must be live. Pass
0for either limit to inherit the listing’s own. A trader’s limits can only be stricter than the listing’s, never looser. - The registry trusts a vault only because the factory recorded deploying it.
setVaultFactorycan be called once.
Deposits
deposit(amount), trader only, while the vault is active.
- The amount must fit within the builder’s remaining capacity, which their bond tier sets.
- The vault pulls the USDC, bridges it to HyperCore and moves it from spot to the perp account. Skipping the second hop would leave it invisible to perp margin, and every order would be dropped silently.
- Both hops are asynchronous, so the amount is recorded as
pendingBridge, not as balance. The high-water mark rises by the deposit at once, so fresh capital is never read as profit.
reconcile marks the deposit settled once HyperCore equity covers it, or after 15 minutes regardless. Until then it does not measure drawdown. Because the high-water mark has already risen, placeOrder’s drawdown check can refuse orders until the deposit lands.
Placing an order (vault mode)
placeOrder(asset, isBuy, limitPx, sz, reduceOnly, tif, cloid), agent key only. Price and size are scaled by 1e8; tif is 1 (ALO), 2 (GTC) or 3 (IOC).
Six checks run before the order is sent:
- The vault is active.
- The listing is live.
- The caller is the listing’s agent key.
- The asset is on the market whitelist.
- Every tracked position at the current mark, plus every outstanding reservation, plus this order’s worst case, stays within the position cap. The cap is the stricter of the vault’s and the asset’s own.
- Equity is within the drawdown limit from the high-water mark.
sz × limitPx, the most it could cost, and is sent to HyperCore. No fee is charged here.
The position cap is measured in aggregate across every tracked position, while
params/parameters.json describes it per position. Which reading is intended is an open protocol decision. This page describes what the contract does.Reservations
A reservation holds its share of the cap and its open-order slot until it is released, and a fill does not release it. The vault cannot see fills at send time. A reservation is released when:cancelOrder(cloid)is called by the trader or the agent. It also sends the cancel to HyperCore.cancelAll(cloids)is called by the trader or the agent, clearing every listed reservation in one transaction. With at most 8 open orders, that is always one transaction.- It expires. Every reservation lapses 1 hour after it was booked. After that, any
reconcilecall that names it releases it, so clearing a dropped order needs no cooperation from the agent.
Reconcile
reconcile(staleCloids), callable by anyone. Everything it does is neutral or in the trader’s favour, and no single party can be relied on to call it.
- Settles a pending deposit once HyperCore shows it, or after the 15-minute grace period.
- Charges the execution fee on size that actually changed.
- Releases the expired reservations it is given.
- Raises the high-water mark. If drawdown has reached the limit, it pauses the vault and sends reduce-only closes for every tracked asset.
reconcile on the vaults that need it. It holds no other authority over a vault.
Fees
Execution fee, at reconcile. For each tracked asset, the vault measures how far the position size moved since the last reconcile and charges the listing’s execution fee on that change at the mark price. An order HyperCore rejected changed nothing, so it costs nothing. In the other direction, a position opened and closed entirely between two reconciles shows no change and is not billed. Performance fee, weekly.assessFees(), callable by anyone at most once every 7 days, charges the listing’s performance fee on equity above the high-water mark.
Both fees accrue as claims split between builder and platform at the listing’s terms. sweepFees(), callable by anyone, pays them from USDC on the HyperEVM side. When the balance does not cover both claims, it pays them in proportion.
Withdrawal and exit
Withdrawal is two steps, because HyperCore to HyperEVM is asynchronous.requestWithdraw(amount), trader only, in every vault state: paused, closing, listing suspended or delisted, asset removed. The amount cannot exceed equity minus reserved capital. The vault moves it from perp to spot and asks HyperCore to bridge it back.finalizeWithdraw(), callable by anyone, sweeps accrued fees and then pays the trader what has arrived, up to the amount pending. It lowers the high-water mark by the same amount.
exitPosition(asset), trader or agent, in any state, closes one position with a reduce-only IOC priced 50% through the mark, so it crosses whatever is on the book. It accepts slippage deliberately: this path runs when a vault is already in trouble.
The trader also has pause(), resume() and tightenRiskLimits(positionCapBps, maxDrawdownBps), which, like the overrides at opening, can only make limits stricter.
Fast mode
enableFastMode(apiWallet), trader only, while the vault is active and the listing is live. In one call the vault:
- Sets its HyperCore account mode. Builder fees accrue only in “standard” mode, and HyperCore’s options do not name one. The vault sends
1(no abstraction). Whether that is standard mode is unconfirmed. - Registers the agent’s key as a HyperCore API wallet. An API wallet can trade but cannot withdraw.
- Approves Agent Circle’s builder address for a fee of at most the listing’s execution fee.
- Drawdown: when anyone calls
reconcilepast the limit, the vault pauses and sends reduce-only closes. How far past the limit a vault travels depends on how often the keeper polls. Pausing does not unregister the API wallet. - Position cap: the keeper can record a breach, but no call it is allowed to make reduces the position. The remedies are the trader’s (pause, exit, withdraw) and governance’s (suspend the listing).
disableFastMode(), trader or agent, clears the vault’s record of the API wallet, pauses the vault, re-registers the wallet name with an empty address and sends reduce-only closes. Whether that revokes the old key on HyperCore is unconfirmed, so the call does not rely on it: a surviving key would have no position to trade and no way to withdraw.
When fast mode is offered is on the roadmap. See Execution modes for the trader’s side.
What the tests prove, and what they do not
The test suite places mocks at the real precompile and CoreWriter addresses, so the production contract runs against production library code. It covers the vault’s own logic: reservations count against the cap, a thin market’s cap binds first, reduce-only orders skip the cap, a dropped order cannot hold capital past expiry, withdrawal is reachable in every vault and listing state, and the execution fee charges fills rather than requests. It proves nothing about Hyperliquid itself: matching, fees, margin, tick sizes, or whether any of these actions are accepted. That is what the testnet end-to-end run is for. Its open questions are listed in ADR-0002:- Which account mode lets builder fees accrue.
- How much HYPE a vault needs on HyperCore to bridge USDC back.
- Whether replacing an API wallet revokes the old key.
- Whether CoreWriter orders work on HIP-3 and HIP-4 assets.
- Whether CoreWriter is enabled for every asset class on mainnet.
