Every action that modifies state on Vela — placing an order, cancelling an order, requesting a withdrawal — requires a valid ECDSA signature from the account holder’s Ethereum wallet. This makes Vela’s authentication model identical to Ethereum’s: your private key is your identity, and signatures are your authorization.Documentation Index
Fetch the complete documentation index at: https://docs.vela.monolithsystematic.com/llms.txt
Use this file to discover all available pages before exploring further.
Elliptic Curve: secp256k1
Vela uses the secp256k1 elliptic curve, the same curve used by Bitcoin and Ethereum. Signatures are produced using the standard ECDSA algorithm over this curve. Curve parameters (for reference):- Field prime:
p = 2²⁵⁶ − 2³² − 977 - Generator point: standard secp256k1
G - Order:
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
k256 crate (part of the RustCrypto ecosystem) for all signature operations. k256 is a pure-Rust, constant-time implementation with no unsafe code.
EIP-191 Personal Sign
Raw ECDSA signatures over arbitrary data have a replay attack vector: a signature produced for one application could be replayed in another. EIP-191 prevents this by prepending a standard prefix before hashing:\x19Ethereum Signed Message:\n prefix ensures that a personal signature cannot be mistaken for an Ethereum transaction signature (which uses a different prefix).
Vela uses personal_sign (EIP-191 personal sign) for all signatures. This is the standard method exposed by MetaMask, ethers.js (signer.signMessage()), and all major Ethereum wallets.
Order Signing
The signing payload for an order is the canonical JSON encoding of the order parameters:- No whitespace (no spaces after
:or,) - Fields in this exact order:
market_id,side,price,quantity,order_type,time_in_force,nonce - All values are strings or integers — no floats
- UTF-8 encoding
Address Recovery
The engine recovers the signer address from the signature and verifies it matches the claimed address:v) — either 27 or 28 — to select which of the two possible public keys corresponds to the signature. The k256 crate handles this via RecoveryId.
Nonce Replay Prevention
Each order includes anonce field. The engine maintains a nonce high-water mark per account, initialized at 0:
- When an order with
nonce = Nis accepted, the high-water mark becomesN - Any future order with
nonce ≤ Nis rejected withDUPLICATE_NONCE - Nonces must be strictly increasing, but do not need to be contiguous
Cancel Signing
Cancel requests are also signed to prevent unauthorized order cancellation:WebSocket Authentication
WebSocket private channel authentication uses a challenge-response scheme:- Client sends
request_challengewith address - Server returns a random
nonce(hex string, 24 bytes) - Client signs:
"Vela Exchange\nNonce: " + challenge_nonce - Client sends
authwith address and signature - Server recovers address, verifies match, grants session
Vela Exchange\nNonce: ...) is distinct from order signing to prevent cross-use of signatures.
Rust Implementation (k256)
Security Properties
| Property | Mechanism |
|---|---|
| Authentication | secp256k1 ECDSA — only private key holder can sign |
| Authorization | Signature covers full order details — no partial authorization |
| Integrity | Any field modification invalidates the signature |
| Replay prevention | Per-account nonce high-water mark |
| Cross-application isolation | EIP-191 prefix prevents signature reuse across apps |
| Constant-time | k256 crate uses constant-time operations |