Onboarding
This document describes the on-chain account lifecycle, funding flows, and API wallet management for Market Makers.
Overview
Hypercall uses a manager/agent model:
- Manager: The EOA that owns the account (typically your main wallet)
- Account: A minimal proxy contract (clone) that holds funds and executes on-chain actions
- API Wallet: An EOA authorized by the manager to sign trading requests (agent)
All on-chain interactions occur via the Exchange contract.
Contract Addresses
Testnet
- Exchange: ``
Mainnet
- Details are shared privately.
Account Lifecycle
1. Check Existing Accounts
Before creating a new account, check if you already have accounts:
function getAccounts(address manager) external view returns (ManagedAccount[] memory);
Example (ethers.js):
const exchange = new ethers.Contract(EXCHANGE_ADDRESS, EXCHANGE_ABI, provider);
const accounts = await exchange.getAccounts(managerAddress);
// Returns: [{ account: "0x...", manager: "0x...", apiWallets: ["0x..."] }]
2. Create Account
Creates a new account with msg.sender as the manager:
function createAccount() external payable returns (address account);
Requirements:
accountImplmust be set by governancemsg.value >= getCreationDeposit()(minimum deposit in HYPE)- If
creationDepositUsd == 0, no minimum deposit is required - Otherwise,
getCreationDeposit()converts USD amount to HYPE using current spot price
- If
Behavior:
- Deploys a deterministic minimal proxy (clone) of
accountImpl - Sets
msg.senderas the account manager - If
msg.value > 0, performs a HYPE deposit on behalf of the account- Transfers HYPE to
HYPE_SYSTEM_ADDRESS(HyperCore bridge) - If deposit >= $1 worth of HYPE, account is activated on HyperCore (activation fee deducted)
- Transfers HYPE to
Example (ethers.js):
// Get minimum deposit (in HYPE wei)
const minDeposit = await exchange.getCreationDeposit();
// Or set to ~$1-2 worth of HYPE for activation
const depositAmount = ethers.parseEther("0.001"); // Adjust based on HYPE price
const tx = await exchange.createAccount({ value: depositAmount });
const receipt = await tx.wait();
// Account address is deterministic - can predict before creation
Predict Account Address:
function predictNextAccount(address manager) external view returns (address);
Use this to know the account address before creation (useful for UI/UX).
3. Account Transfer
Managers can transfer account ownership (not directly callable; occurs during creation or via governance):
event AccountTransferred(address indexed account, address indexed oldManager, address indexed newManager);
Account transfer functionality is provided on request.
API Wallet Management
API wallets are EOAs authorized by the manager to sign trading requests. They sign EIP-712 messages that are verified on-chain.
Add API Wallet
function addApiWallet(address account, address apiWallet) external;
Requirements:
msg.sender == managers[account](must be the account manager)apiWalletmust not be active for any other account/manageraccount != address(0)andapiWallet != address(0)
Behavior:
- Maps
apiWallet -> accountandapiWallet -> manager - Adds
apiWalletto the account's API wallet set - Emits
ApiWalletAdded(account, manager, apiWallet)
Example:
const tx = await exchange.addApiWallet(accountAddress, apiWalletAddress);
await tx.wait();
Remove API Wallet
function removeApiWallet(address account, address apiWallet) external;
Requirements:
msg.sender == managers[account]apiWalletmust be active for this account/manager
Behavior:
- Removes mappings for
apiWallet - Removes
apiWalletfrom the account's API wallet set - Emits
ApiWalletRemoved(account, manager, apiWallet)
Query API Wallets
function getAccountByApiWallet(address apiWallet) external view returns (ManagedAccount memory);
Returns the account, manager, and all API wallets for the account if apiWallet is active. Returns zero struct if inactive.
Example:
const managedAccount = await exchange.getAccountByApiWallet(apiWalletAddress);
if (managedAccount.account !== ethers.ZeroAddress) {
console.log("Account:", managedAccount.account);
console.log("Manager:", managedAccount.manager);
console.log("API Wallets:", managedAccount.apiWallets);
}
Funding & Deposits
USDC Deposit To Hypercall
function depositUsdcFor(address account, uint256 amount) external;
depositUsdcFor is the direct HyperEVM funding path for Hypercall cash balances. It transfers native HyperEVM USDC from msg.sender into Exchange, then Exchange deposits that USDC into its HyperCore balance through Circle's CoreDepositWallet.
Who may call it:
- Any wallet, router, solver, or zap contract may call this method.
msg.senderpays the USDC.accountis the Hypercall account or wallet to credit. Do not infer the credited account frommsg.sender.
Requirements:
account != address(0)amount > 0msg.sendermust approveExchangeforamountnative HyperEVM USDC- The deployed
Exchangeimplementation must be constructed with the native HyperEVM USDC token andCoreDepositWalletaddresses for the target network
Events and crediting:
event UsdcDeposit(
address indexed account,
address indexed from,
address indexed token,
uint256 amount,
uint32 dstDex
);
The event is emitted by Exchange after the CoreDepositWallet.depositFor call. The backend must match this event to the observed HyperCore deposit into the Exchange balance before crediting Hypercall cash. The credited Hypercall account is the explicit account event field.
Example:
const usdc = new ethers.Contract(USDC_ADDRESS, ERC20_ABI, signer);
const exchange = new ethers.Contract(EXCHANGE_ADDRESS, EXCHANGE_ABI, signer);
await usdc.approve(EXCHANGE_ADDRESS, amount);
await exchange.depositUsdcFor(accountAddress, amount);
Option Token Deposit Function
function depositOption(address account, address token, uint256 amount) external;
Supported Token Types:
- Option ERC20 Tokens (registered in
OptionRegistry):msg.value == 0(required)- Burns the option token via
IOptionToken(token).burnFrom(msg.sender, amount) - Emits
Deposit(account, msg.sender, token, amount) - RSM indexer picks up the event and credits the account's option position
Requirements:
accountmust be a registered Hypercall accountoptionRegistry != address(0)(must be set)msg.sendermust have approvedExchangeforamount
Example (option token deposit):
const option = new ethers.Contract(OPTION_TOKEN_ADDRESS, ERC20_ABI, signer);
const exchange = new ethers.Contract(EXCHANGE_ADDRESS, EXCHANGE_ABI, signer);
await option.approve(EXCHANGE_ADDRESS, amount);
await exchange.depositOption(accountAddress, OPTION_TOKEN_ADDRESS, amount);
Transfer From Account
Managers can transfer tokens from their account to any recipient on HyperEVM:
function transferFromAccount(address account, address token, address recipient, uint256 amount) external;
Requirements:
msg.sender == managers[account]recipient != address(0)
Use Cases:
- Complete HyperCore -> HyperEVM transfers initiated by the account
- Rescue funds from an account
- Withdraw to a different address
Example:
await exchange.transferFromAccount(
accountAddress,
tokenAddress,
recipientAddress,
amount
);
Integration with Off-Chain API
Once an account is created and an API wallet is added:
- Off-chain API authentication: Use the API wallet's private key to sign EIP-712 messages (see Authentication)
- On-chain verification: The RSM Sequencer calls
Exchange.hlRequestOrder(or similar) with your signed request - Execution: The Exchange verifies the signature, recovers the API wallet, maps it to your account, and executes on-chain actions
See Also:
- Authentication for off-chain API authentication
Events
event AccountTransferred(address indexed account, address indexed oldManager, address indexed newManager);
event ApiWalletAdded(address indexed account, address indexed manager, address indexed apiWallet);
event ApiWalletRemoved(address indexed account, address indexed manager, address indexed apiWallet);
event Deposit(address indexed account, address indexed from, address indexed token, uint256 amount);
event Withdraw(address indexed account, address indexed to, address indexed token, uint256 amount);
Errors
All errors are defined in IExchangeBase.sol:
Exchange__AccountManagerNotSet(address account): Account doesn't existExchange__ApiWalletAlreadyActive(address apiWallet): API wallet already in useExchange__ApiWalletNotActive(address apiWallet): API wallet not foundExchange__CreationDepositNotMet(uint256 expected): Insufficientmsg.valueExchange__TokenNotSupported(address token): Token not supported for depositExchange__MsgValueIncorrect(uint256 expected):msg.valuemismatchExchange__NotManager(address account, address notManager): Caller is not the manager
Security Considerations
-
Manager Key Security: The manager key controls account ownership and API wallet management. Store securely (hardware wallet recommended).
-
API Wallet Key Security: API wallet keys sign trading requests. Use separate keys per account/environment. Rotate regularly.
-
Nonce Management: Each signer (API wallet, manager, RSM) has a separate nonce space. Track nonces off-chain to avoid replay attacks.
-
Account Activation: Accounts must be activated on HyperCore (deposit >= $1 HYPE) before they can trade perps. Check activation status via HyperCore API.
-
Deterministic Addresses: Account addresses are deterministic based on manager address and creation count. Use
predictNextAccountto know addresses before creation.