Early access. Multi-Asset Collateral is in early access and is being enabled for accounts in stages (see Multi-Asset Collateral for how to check). A deposit from an address that isn’t enabled yet is never credited. The token stays in the deposit contract and can be reclaimed after the deposit expires (see If a deposit fails). Start with a small amount.
Prerequisites
- An enabled wallet with the token on Robinhood Chain mainnet, plus a little native ETH for gas. Chain IDs are listed under Environments. For ETH collateral you only need native ETH, since step 2 wraps it.
- A subaccount to use. The examples use
accountIndex1, a spare subaccount, so the collateral and loan are kept apart from your main account. A subaccount with USDG uses that USDG before it borrows anything. - An API key scoped to that subaccount (or to all subaccounts), for steps 4 and 5 only. See API keys and
accountIndex. Steps 1–3 and 6 don’t need an API key. - A Robinhood Chain mainnet RPC endpoint (your node or RPC provider).
- Python with
web3,eth-accountandcryptography:
Step 1: Set up and check the asset
The setup reads the asset, including its token contract (contractId), from GET /v1/spotAssets and asks the BridgeVault whether it accepts deposits of that token. Fill in the chain values from the docs rather than copying them from elsewhere: CHAIN_ID from Environments, and BRIDGE_VAULT_ADDRESS from the per-environment chainId / verifyingContract table on POST /v1/withdraw.
depositConfig returns allowed: true. An asset can be listed on GET /v1/spotAssets before the vault accepts it.
Step 2: Wrap, approve and deposit
Size the deposit in whole multiples of the asset’sstepSize, so the credited size is a whole number of base quantums when you withdraw it later. Then send three transactions:
- Wrap native ETH into WETH with
deposit(). Skip this for a Stock Token. - Approve the
BridgeVaultto pull the token. Token deposits go to theBridgeVaultdirectly, not through the USDG deposit proxy. - Call
initiateDeposit(owner, accountIndex, token, amount).ownermust be the sending wallet.
DepositInitiated event in its receipt carries the inboxIndex you need to reclaim it.
Step 3: Confirm the credit
PollGET /v1/spotPositions for the holding, then read GET /v1/account:
GET /v1/account goes from 404 to 200. An example mainnet response after depositing 0.0098795 WETH (address and ids replaced with placeholders):
- The token was kept, not converted.
netQuoteBalance(your USDG) is still0, and the WETH appears underspotPositions. - It counts as collateral immediately.
equityincludes the token’s full value, andborrowHeadroomis about value ×ltvInitial($24.96 × 0.5). There is no “enable” step. freeCollateralis0. That’s expected: it counts perp-side cash only. UseborrowHeadroomandmarginStateinstead.
GET /v1/accountTransferUpdates as a DEPOSIT row with spotAssetId, the size as amount, and status: APPLIED. It also streams on the spotPositions channel with reason: DEPOSIT.
Step 4: Trade a perp on the loan
There is no borrow call. Place a cross-margin perp order as usual, and when the subaccount has no USDG to cover it, Arcus lends USDG against your collateral automatically. This step reuses the order signing from Trade over REST. It assumespriv (your Ed25519 key) and api_key (its hex public key) for a key scoped to ACCOUNT_INDEX.
loanBalanceis the USDG lent to you: the order’s initial margin, plus the fee and any unrealized loss.freeCollateralis negative. That’s by design on a borrowing account.marginState: healthyis the health signal.- No transfer row is created. Borrowing isn’t a transfer, so the loan shows only as
loanBalance. - Interest accrues on
loanBalanceat the current borrow rate. The rate streams on thelendingRateschannel asratePpm; over REST,GET /v1/lendingAttributesreturns it asborrowRatePpm. Each settlement appears as anINTEREST_SETTLEMENTrow onGET /v1/accountTransferUpdates.
Step 5: Repay the loan
A loan left after you close stays until you pay it down. Deposit USDG to the subaccount, or sell some of the collateral withPOST /v1/settleLoan. settleLoan sells at the mark price minus a small spread set by Arcus and never below your minPrice. It never sells more than the loan and accrued interest need, so you can overshoot maxQuantity.
settleLoan signs the legacy message, timestamp + "settleLoan" + canonical_json(body), like cancelAllOrders (see Authentication). maxQuantity must be a multiple of the asset’s stepSize, and minPrice a multiple of its tickSize. Base minPrice on the mark price, which is what the sale executes against: read it from GET /v1/prices for the asset’s priceSourceMarketId. oraclePrice on GET /v1/spotAssets is the oracle price, which can differ from the mark.
200 with status: APPLIED means the sale ran, so compare executedQuantity with maxQuantity and check newLoanBalance. 202 with status: ACK means the engine hadn’t confirmed in time; watch the account for the result. 422 with status: REJECTED carries a rejectReason. The shape of an APPLIED response, per the API reference (illustrative values):
GET /v1/spotFills, and the proceeds as a LOAN_SETTLEMENT_PAYMENT row on GET /v1/accountTransferUpdates.
Step 6: Withdraw the token
Withdraw withPOST /v1/withdraw, setting spotAssetId. A token withdrawal is signed by the wallet with the SpotAssetWithdraw EIP-712 type, under its own domain, "Arcus Spot Withdraw". It uses the same chainId and verifyingContract (the BridgeVault) as a USDG withdrawal. A signature over the USDG Withdraw type is rejected.
amount is an integer string of the asset’s base quantums: size ÷ stepSize. To withdraw 0.0098795 WETH at a stepSize of 0.0000001, send "98795". A decimal such as "0.0098795" is rejected. Sign the same integer as the uint256 amount.
202 response (address and ids replaced with placeholders):
amount, even though you sent base quantums. The transfer row once it reaches APPLIED:
withdraw(amount) on the WETH contract:
Common errors
Next steps
- Multi-Asset Collateral: LTV, interest, liquidation and worked examples.
- Subaccounts: keep collateral and loans in their own
accountIndex. - Trade over REST and Trade over WebSocket: order signing in full.