Tickets
Tezos tickets are authenticated quantities issued by contracts. A ticket of type sp.ticket[t]
has three elements:
Its ticketer, which is the contract that issued the ticket
Its contents of type
t
, also knowns as the wrapped value or payload, which can be any data typeIts amount of type
sp.nat
, which is an arbitrary number that represents a quantity or value for the ticket
A ticket's ticketer and contents cannot be changed.
Tickets themselves cannot be duplicated, but you can split one ticket into multiple tickets by creating duplicate tickets each with a portion of the original ticket's amount. The new tickets have the same ticketer and contents, and the sum of their amounts is always the amount of the original ticket. Similarly, you can join tickets with matching ticketers and contents into a single ticket with the sum of the joined tickets' amounts.
You cannot read the contents of a ticket directly; you must use sp.read_ticket
to access it.
- sp.ticket(contents: t, amount: sp.nat) → sp.ticket[t]
Create a ticket with the given contents and amount. The ticketer is always the contract's address via
sp.self_address()
.
- sp.read_ticket(ticket: sp.ticket[t]) → sp.pair[sp.record(ticketer=sp.address, contents=t, amount=sp.nat), sp.ticket[t]]
Reads the contents of a ticket and returns a pair of:
The ticket data, itself a record of the ticket's ticketer, contents, and amount.
A copy of the original ticket that can still be used.
Note that using
sp.read_ticket
on a ticket consumes it, destroying the originalsp.ticket
type. To access the ticket again, you muse use the copy that the function returns.This example creates a ticket and then reads it:
smartpy# Create ticket ticket_contents = (sp.int(5), "hello") ticket = sp.ticket(ticket_contents, 2) # Read ticket (ticket_data, new_ticket) = sp.read_ticket(ticket) assert ticket_data.contents == ticket_contents assert ticket_data.amount == 2 assert ticket_data.ticketer == sp.self_address()
Joining and splitting tickets
- sp.join_tickets(t1: sp.ticket[t], t2: sp.ticket[t]) → sp.ticket[t]
Merges two tickets into one by adding their amounts. Fails if the tickets differ in their ticketer or contents.
- sp.split_ticket(ticket: sp.ticket[t], amount1: sp.nat, amount2: sp.nat) → sp.pair[sp.ticket[t], sp.ticket[t]]
Splits a ticket into two parts with the specified amounts. Fails if
amount1 + amount2
is not equal to the original ticket's amount.
For example, this code creates a ticket, splits it, and joins the split tickets:
# Create ticket
ticket_contents = (sp.int(5), "hello")
big_ticket = sp.ticket(ticket_contents, 100)
# Split ticket
(small_ticket_1, small_ticket_2) = sp.split_ticket(big_ticket, 70, 30)
# Verify ticket amounts
(data_1, small_ticket_1_new) = sp.read_ticket(small_ticket_1)
assert data_1.contents == ticket_contents
assert data_1.amount == 70
(data_2, small_ticket_2_new) = sp.read_ticket(small_ticket_2)
assert data_2.contents == ticket_contents
assert data_2.amount == 30
## Join tickets
joined_ticket = sp.join_tickets(small_ticket_1_new, small_ticket_2_new)
(data_joined, joined_ticket_new) = sp.read_ticket(joined_ticket)
assert data_joined.amount == 100
Transferring tickets
To transfer a ticket, send it as a parameter to an entrypoint with sp.transfer
as usual:
contract_opt = sp.contract(sp.ticket[sp.pair[sp.int, sp.string]], contract_address, entrypoint = "accept_ticket")
with sp.match(contract_opt):
with sp.case.Some as contract:
sp.transfer(ticket, sp.mutez(0), contract)
with None:
sp.trace("Failed to find contract")