Permits & Tickets
Permits are the on-chain representation of tickets in TIX Protocol. Each permit is a unique, verifiable record of ticket ownership.
Permit Structure
struct Permit {
owner: Pubkey, // Current ticket holder's wallet
status: u8, // 0=Active, 1=Used, 2=Void
version: u64, // Increments on every change
ticket_id: u64, // Unique identifier within event
padding: [u8; 16], // Reserved for listing lock data
}Status Values
Active
0
Ticket is valid
Transfer, list, resell
Used
1
Ticket has been redeemed
None (terminal state)
Void
2
Ticket has been cancelled
None (terminal state)
Paged Storage
Permits are stored in contiguous vectors within PermitPage accounts, minimizing account creation cost.
Storage Layout
Page Calculation
Page Initialization
On first write to a page, the program allocates a vector of 128 default permits:
Version Tracking
Every permit has a version number that increments on any mutation:
issue_permit
0 → 1
transfer_permit
+1
mark_used
+1
mark_void
+1
accept_offer
+1
Purpose
Version tracking prevents stale operations:
Listing Version Mismatch — When a listing is created, it stores the current permit version. If the permit changes before purchase, the sale is rejected.
Race Condition Prevention — Concurrent transfer attempts are serialized by version checks.
Listing Locks
When a ticket is listed for sale, the permit is "locked" to prevent simultaneous transfers.
Lock Mechanism
The permit's padding area stores lock information:
padding[0]
Lock flag (0=unlocked, 1=locked)
padding[1..9]
Expiry timestamp (i64 little-endian)
Lock Flow
Expiry Handling
If a listing expires:
transfer_permitcan proceed (checks expiry timestamp)accept_offerwill fail withListingExpiredcancel_listingcan clean up the stale listing
Guard Rails
TicketAlreadyMinted
Prevents re-issuing the same ticket slot:
SupplyExceeded
Prevents minting beyond event capacity:
PermitNotActive
Blocks operations on used/void tickets:
ListingActive
Prevents transfers while listing is active:
Best Practices
For Integrators
Batch Issuance — Issue multiple tickets in a single transaction when possible
Page Pre-allocation — Consider ticket ID assignment in your own database to minimize page creation
Version Caching — Store permit versions when creating listings
For Clients
Always Fetch Fresh — Get latest permit state before operations
Handle Version Errors — Retry with updated version on mismatch
Check Lock Status — Verify permit isn't locked before transfer attempts
Last updated