Security
Keys
- Keys are secret keys:
qg_sk_followed by 32 random bytes in base58. Use them only on servers. - A key is shown once, when it is created. Qiguard stores only an HMAC-SHA256 hash of it and its first 12 characters for display.
- A secret key sent by a browser (an
Originheader together withSec-Fetch-Mode: cors) is refused with403 ORIGIN_NOT_ALLOWED. A server-side proxy stripsOriginandSec-Fetch-*before it forwards a request. AnOrigincheck stops other websites from using a key; it does not stop a script that forges headers, so keep keys off the client. - Rotation: create a new key, deploy it, then revoke the old key now or with a 24-hour overlap. A revoked key stops working within 60 seconds.
- Every key change and every sign-in is in the dashboard audit log, exportable as CSV.
Transport
- HTTPS only. A plain HTTP request gets
400 HTTPS_REQUIRED, never a redirect, and a key seen on plain HTTP is revoked at once. Strict-Transport-Security: max-age=31536000; includeSubDomainson every answer.
Funds
- The API never holds user funds, user keys or seeds. Every trade moves from the taker's wallet through the settlement contract in one transaction, and the contract pays the output to the taker.
- Approve the exact
sellAmount. The SDK does this by default and refuses an unlimited approval unless asked for it. - The settlement contracts are upgradeable proxies, shared with CEXORDEX (Contracts and fees).
- The contract checks
minBuyAmount(net of the fee) on chain: the taker receives at least that amount, or the transaction reverts. - The Qiguard relayer wallet holds only gas. Fees go from the contract straight to the fee recipient.
Gasless signatures
The taker's signature fixes the sell token and amount, the buy token, the minimum output, the recipient (the taker), the adapter and the deadline. Nobody can redirect the funds or lower the minimum.
The signed message is seen, before the transaction is included, by the integrator's backend, Qiguard and the broadcast channel (48.club and bloXroute on BSC; the Base sequencer RPC on Base). Any of them can submit the signature first with its own route and keep the value between the fair output and minBuyAmount; the taker always receives at least minBuyAmount. Gasless slippage therefore defaults to 50 bps (at most 300), and gasless transactions never go to a public mempool.
The relayer accepts only the fields of the signed message and a route description. It builds the transaction itself and can sign only fillOrderWithPermit2 calls to the settlement contract, with value 0 and a capped gas limit and gas price, or a 0-value cancel to itself. It simulates every transaction before sending it and never sends one whose simulation reverts.
Dashboard
- Sign-in with Ethereum (EIP-4361): a one-time nonce valid for 5 minutes, bound to
dashboard.qiguard.com, issued only after the Cloudflare Turnstile check. - Session cookies are
HttpOnly; Secure; SameSite=Laxand bound to the dashboard host; every change needs a CSRF token. - Account export (JSON) and account deletion: deletion revokes every key and session at once, and the remaining data is purged after 30 days.
This page as Markdown: security.md. All pages for tools: llms.txt.