# Better tickets UX Currently there are two protocol limitations that introduce friction when using tickets: - Implicit accounts cannot call contracts with an arbitrary parameter type that contains tickets (only call entrypoints that accept just tickets, via transfer_ticket operation kind) - Implicit accounts cannot call smart rollups with an arbitrary parameter type that contains tickets (only smart contracts can do that, via internal inbox messages) Relevant docs: - https://tezos.gitlab.io/oxford/tickets.html?highlight=tickets#transferring - https://tezos.gitlab.io/alpha/smart_rollups.html#sending-an-internal-inbox-message ## Sending tickets to contracts Implicit accounts are able to send tickets to smart contracts using `Transfer_ticket` operation. The result of such operation is an internal transaction with restricted entrypoint type. ![](https://hackmd.io/_uploads/B1_woNyka.png) The entrypoint must have `ticket a` type, meaning that one cannot pass additional data alongside. However there are cases when it is necessary to do so. ### Current workaround What we can do is splitting the invocation in two parts: - Passing the extra info - Sending the ticket ![](https://hackmd.io/_uploads/HJ20d41JT.png) Invoked contract has to support this two-step workflow i.e. save temporary context. Ideally these two call should be done in a batch to ensure atomicity. ### Improved UX A better option would be `Transaction` operation with arbitrary parameter type allowing tickets. That would: - Simplify the smart contract design (less code => less bugs) - Decrease gas consumption - Resolve ambiguity with multiple operation kinds for interacting with smart contracts From the wallet/indexer perspective it should not introduce any additional work as long as ticket updates are included in the operation receipt. ## Invoking rollups Implicit accounts are not allowed to call smart rollups (i.e. send internal inbox messages), they can only submit blobs (aka external inbox messages). Only smart contracts can send transactions (that can also contain tickets) to rollups. ![](https://hackmd.io/_uploads/SJH_EH1JT.png) ### Current workaround Currently if one wants to send internal inbox message he needs to use additional smart contract as a proxy. ![](https://hackmd.io/_uploads/rkoQYNk1T.png) A proxy should not necessarily be a standalone contract, it can also be an extra feature in the contract containing business logic (yet standalone implementation provides a more clear separation of concerns). ### Better UX A better approach would be allowing implicit account to invoke smart rollups the same way they invoke smart contracts (including the forementioned ticket UX fix). It would: - Simplify smart contract design (or remove the need for a proxy contract) - Reduce gas consumption ## Conclusion Generally this proposal is about aligning different types of accounts in terms of what they can do with tickets — and thus facilitate adoption. ![](https://hackmd.io/_uploads/SJBacryJp.png) ## Updates ### Ticket withdrawals from rollups to implicit accounts (Dec'23) Currently smart rollups can only initiate smart contract calls on L1. On the kernel side you can specify destination address (originated contract), entrypoint, and parameters (either typed or untyped): ``` { /* Atomic_transaction_batch */ "transactions": [ { "parameters": $micheline.017-PtNairob.michelson_v1.expression, "destination": $017-PtNairob.contract_id.originated, "entrypoint"?: $unistring } ... ], "kind": "untyped" } || { /* Atomic_transaction_batch_typed */ "transactions": [ { "parameters": $micheline.017-PtNairob.michelson_v1.expression, "parameters_ty": $micheline.017-PtNairob.michelson_v1.expression, "destination": $017-PtNairob.contract_id.originated, "entrypoint"?: $unistring } ... ], "kind": "typed" } ``` This restriction means that users cannot withdraw their assets (tickets) without an intermediary, which causes: - Extra friction: one needs to discover or deploy a proxy contract that can handle the outbox message call - Trust issue: one has to trust the proxy contract code and/or the shared deployment - Possibility of unrecoverable loss: while ticket transfer cannot fail, a smart contract call might be reverted due to a runtime error and in that case tickets will be lost (since there is no feedback to the rollup about the execution outcome) A clean solution that would not break backward compatibility is introducing another outbox transaction type, e.g.: ``` { /* Atomic_transfer_ticket_batch */ "operations": [ { "ticket_contents": $micheline.017-PtNairob.michelson_v1.expression, "ticket_ty": $micheline.017-PtNairob.michelson_v1.expression, "ticket_ticketer": $017-PtNairob.contract_id.originated, "ticket_amount": $nat, "destination": $017-PtNairob.contract, "entrypoint"?: $unistring } ... ], "kind": "transfer_ticket" } ``` Overall, removing the current limitations on the interaction between implicit and smart rollup accounts would accelerate the ticket adoption.