Skip to main content
POST
Create a deposit
Opens a perp margin account and funds it, or tops up one you already have, with one signed Action for the DepositModule. The venue verifies it and submits it through Matching.verifyAndMatch, paying the gas; the module pulls your USDC, deposits it into the perp’s cash, and Matching records you as the account’s owner.
Either approve USDC to the DepositModule once, on chain, or sign a permit with the deposit and never send a transaction yourself. Either way every deposit is this endpoint, and the venue pays its gas.
Wallets with an EIP-7702 delegation cannot sign for Matching with a plain signature. Matching verifies signatures with OpenZeppelin’s SignatureChecker, which treats any address that has code — including an EOA with a 7702 delegation — as a contract wallet and asks it via ERC-1271 instead of recovering the signature. The deposit is refused with OV_InvalidSignature unless the delegate contract implements isValidSignature. Use an undelegated EOA, or a wallet that supports ERC-1271. The same applies to orders and withdrawals.

Before your first deposit

Approve the DepositModule to move at least the amount you will deposit, from the wallet that will own the account:
USDC on Base is 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913.

Or sign a permit instead

USDC on Base supports EIP-2612 permits, so you can skip the on-chain approve entirely: sign a Permit with USDC’s domain (name USD Coin, version 2, chain 8453) for spender = the DepositModule, a value of at least the deposit amount, and your current USDC nonce. Send it alongside the action:
The venue submits the permit, then the deposit, and pays the gas for both. If your allowance already covers the deposit — you approved earlier, or someone else submitted your permit first — the permit is skipped, not failed. A permit USDC refuses (expired, already used, or signed for another spender) comes back as a 400.

Signing the action

Sign an Action against the same Matching domain as an order, with: In data:
  • amount is USDC in 6-decimal base units: 1000000000 is 1,000 USDC. It must be explicit — the “whole balance” sentinel type(uint256).max is refused — and at least the venue’s minimum (10 USDC).
  • asset is the perp’s cash asset, 0xA74E49b4Ed7cb176bc02ef4D8a1A3240C9aD4272 — the quote_asset_address that GET /v1/markets reports for cNGN-PERP. No other asset is accepted.
  • managerForNewAccount is the perp risk manager, 0xDE0423D0a1E15536265C9513d2e0c10DAb5835D4. For a top-up it is ignored; send the same address or zero.
Your account’s cash is credited at 18 decimals, so 1,000 USDC appears on chain as 1000000000000000000000. The response states the amount in all three forms. Send the action’s seven fields as strings (numbers in base 10, data as hex) with the signature:

What is checked

In order, and every check fails closed:
  1. The request: module, signer equals owner, expiry, data exactly three words, the perp cash asset, an explicit amount at or above the minimum, and the perp risk manager for a new account. Refused with 400.
  2. At most one deposit in progress per owner, three requests a minute, and six submitted deposits an hour. Refused with 429; the hourly limit sends Retry-After. A request refused for any other reason does not count toward the hour.
  3. The signature authorizes the action. Refused with 401.
  4. Read from the chain before anything is submitted, each refused with 400 and what to do: the nonce is unused; for a top-up, you own the account and it is a perp account; your wallet holds the USDC and has approved the DepositModule for it.
  5. The executor’s simulation. The reverts above, if they still happen (a race), come back as 400 with revert naming them; any other revert is 422.
503 means deposits are off or paused: the venue’s gas wallet is below its reserve, or the hour’s budget of sponsored gas is spent. error says which; retry later.

The outcome

A 200 carries the transaction and what it credited:
With a permit that was needed, the response also carries permit_tx_hash. subaccount_id is your new account when you sent 0. Use it as subaccount_id on your orders. action_hash identifies the deposit: it is the EIP-712 hash of your signed action (Matching.getActionHash). status is one of:

Checking a deposit later

Returns the deposit’s record. A submitted deposit is re-read from the chain first, so a receipt that timed out resolves to confirmed (with subaccount_id) or reverted on the next read. Sending the same signed request again is also safe at any point: the venue answers it from its record and never submits it twice — after a timeout, a dropped connection or a restart. A 502 means the venue could not confirm whether the deposit was submitted: look it up by action_hash, or resend the same request, before signing a new one. A second signed deposit is a second deposit.

Body

application/json
action
object
required

A Matching Action for the DepositModule, signed with EIP-712 against the Matching domain.

signature
string
required

EIP-712 signature by signer: 65 bytes, or longer for an ERC-1271 wallet.

permit
object

Optional EIP-2612 permit on Base USDC from owner to the DepositModule, instead of a prior approve. The venue submits it with the DepositModule as spender, and skips it when the allowance already covers the deposit.

Response

Submitted. receipt_status timeout means broadcast but not yet confirmed; resubmit the same request for the outcome.

accepted
boolean
required

True once mined successfully.

tx_hash
string
required
amount_usdc
string
required

The deposit in USDC, with 6 decimal places.

amount_units
string
required

The same amount in 6-decimal USDC base units, as signed.

credited_cash_e18
string
required

What the account's cash rises by, at the ledger's 18 decimals.

action_hash
string

EIP-712 hash of the signed action (Matching.getActionHash); the key for GET /v1/deposits/{action_hash}.

status
enum<string>
Available options:
pending,
submitted,
confirmed,
reverted,
rejected,
unknown
receipt_status
enum<string>

timeout: broadcast, not yet confirmed.

Available options:
success,
reverted,
timeout
block_number
string
subaccount_id
string

The account credited: your new account when subaccount_id was 0. Absent until the receipt is known.

permit_tx_hash
string

The permit's transaction, when the deposit carried a permit and it was needed.