Intent Settlement

Traders sign a session once. The relayer validates each typed order, and PrismPerpSettlement verifies it again — signature, session grant, nonce, deadline — and settles every order in a batch on its own.

Protocol modules

Signing a transaction for every order is fine at 8-hour horizons and unusable at 100ms ones. PrismPerp separates authorisation from execution: one session signature authorises a scoped key, and every subsequent order is a typed message the relayer can verify without touching the user wallet.

solidity
EIP712Domain(
  string  name,              // "PrismPerp"
  string  version,           // "1"
  uint256 chainId,           // 46630 testnet · 4663 mainnet
  address verifyingContract
)

Order(
  address trader,
  uint8   market,      // 0 = C-VIX30, 1 = FR-BASIS-BTC, 2 = FR-BASIS-ETH
  bool    isLong,
  address collateral,  // the token margin and fee are drawn in: signed, not chosen by the relayer
  uint256 size,        // notional, 1e18
  uint256 margin,      // collateral posted, 1e18
  int256  limitPrice,  // worst level, 1e18, signed. long fills <=, short fills >=. 0 = off
  uint64  leverage,
  uint64  nonce,
  uint64  deadline
)

Session(
  address trader,
  address sessionKey,
  uint32  scope,       // bits: 1 open · 2 close · 4 cancel · 8 paper collateral
  uint64  epoch,       // the wallet's revocation counter
  uint64  issuedAt,
  uint64  expiresAt    // at most 7 days after issuedAt
)
  • Nonces are single-use per trader: a unique index rejects a reuse at the relayer, and the contract's own nonce map rejects it again on-chain.
  • An order signed by a session key settles only with the wallet's Session grant beside it, and the contract checks the grant itself: signed by the trader, naming this key, unexpired, holding the open scope, and at the wallet's current epoch.
  • Each order in a batch settles on its own. One that fails — a balance withdrawn between signing and settlement, a limit the index moved through — is rejected with its reason and the rest settle; it does not burn its nonce.
  • The relayer can close a position only on a signed ClosePosition from the trader or a key holding the close scope. The trader can always close from their own wallet without it.
  • revokeAllSessions() bumps the wallet's epoch: one transaction ends every key it ever delegated to, whether or not the relayer cooperates.