owned this note
owned this note
Published
Linked with GitHub
---
title: Ticket transfer into and out of implicit accounts
tags: protocol, tickets
---
# Ticket UX proposal - Support for Implicit Accounts
## Motiviation
One source of motivation is that tickets are extensively used for TORUs to represent deposited assets. Unfortunately tickets cannot be held by implicit accounts and, therefore, are not fully controlled by implicit account holders.
This proposal will introduce mechanism to allow implicit accounts to hold, receive and send tickets to either implicit or originated accounts.
## Transfer tickets from implicit accounts to originated accounts
This is somehow already supported with a `Transfer_ticket` external manager operation. However, in this proposal, we will **replace `Transfer_ticket` with use of regular transfers** since implicit accounts can now hold tickets. Transfers will be simply contract calls, where the parameter contains one or more types of tickets.
Therefore, after this proposal is implemented, one way for implicit accounts to send tickets to originated accounts will be simply a transfer to a contract like the following.
octez-client transfer 4 from alice to contract \
with entrypoint 'this_is_a_contract_call' \
and contents '"I am a ticket"' \
and type string
## Transfer tickets from originated accounts to implicit accounts
This is the focus of the proposal. We will allow this type of transfers in the following arrangement.
To transfer tickets to an implicit account, an originated account, which is a smart contract, will first execute the instruction `CONTRACT %
ty` with an implicit account address at the stack top, to get a `ty contract` where `ty` is a Michelson type `ticket cty` for some `cty`.
Upon successful execution, the smart contract can send tickets via a `TRANSFER TOKENs` instruction, with some amount of Tez if it chooses to.
The reason that we can re-use the `CONTRACT`/`TRANSFER_TOKENS` facility because implicit accounts at this point do not assign any other meaning to entrypoints.
### A transfer as example
A contract may execute these instruction to transfer a ticket.
CONTRACT (ticket string) ;
IF_NONE
{
PUSH string "should not happen" ;
FAILWITH
}
{
PUSH nat 4 ;
PUSH string "I am a ticket" ;
TICKET ;
PUSH mutez 0 ;
SWAP ;
TRANSFER_TOKEN ;
...
}
Suppose that the stack is `"tz1AAA..." : ticket` where
`ticket1` is of type `ticket string`.
Then, the `TRANSFER_TOKEN` generates an internal operation that transfer `ticket` to the implicit account `tz1AAA...`.
### New operation types
A new internal operation is introduced to capture this change.
```ocaml=
type 'kind internal_operation_contents =
...
| Transaction_to_implicit_with_tickets : {
destination : Signature.Public_key_hash.t;
ticket : ex_ticket;
}
-> Kind.transaction internal_operation_contents
...
```
A corresponding `Transaction_to_implicity_with_tickets_result` should be introduced as well.
## Transfer tickets from implicit accounts to implicit accounts
This is another operation that this proposal will enable.
Similar to the situation in which originated accounts transfer tickets to implicit accounts, we will use `default` as entrypoint of transfers.
We will use the existing `Transaction` for receiving the `manager_operation`.
```ocaml=
(* alpha_context.mli *)
type _ manager_operation =
...
| Transaction : {
amount : Tez.tez;
parameters : Script.lazy_expr;
entrypoint : Entrypoint.t;
destination : Contract.t;
}
-> Kind.transaction manager_operation
```
A `Transaction` is recognised as a transfer of one ticket to an implicit account when the `entrypoint` is `default` and the `destination` is pointing to an implicit account.
### *Typing problem*
The `Transaction` manager operation as mentioned lacks the key information of the exact typing of the ticket, so that we do not confuse a ticket of type `ticket int` with a ticket of type `ticket string`. It seems necessary to have a dedicated manager operation with the necessary type information.
#### Existentially typed tickets
Existential type is here to rescue. As part of our project, we will introduce a method to encode an existentially typed ticket in Micheline format.
An existentially type ticket `(Pair ty ticket)` in Micheline comprises of a type ascription `ty` which is an unparsed Michelson type `'a`; and an unparsed ticket `ticket` of type `ticket 'a`.
There is only one possible place to use this unparsed format of existentially typed tickets, in the `ticket` field of the external manager operations `Transaction`. When those operations are received, `ty` is parsed and checked to ensure that it is a comparable `'a` Michelson type, and `ticket` is parsed into a `ticket 'a` value. Conversely, those operations are unparsed as such into this form.
From the users' perspective, a ticket can now be encoded into the input to the transfer call. For example, a transfer can be initiated with `tezos-client` sending a ticket with a `string` content from the implicit account `alice` to the implicit account `bob`.
octez-client transfer 4 tickets from alice to bob \
with entrypoint \
and contents '"I am a ticket"' \
and type string \
and ticketer ticketing_contract
### Moving tickets
As the new operations have sufficient information to move tickets, moving tickets involves only invoking the existing `Ticket_balance.transfer_ticket` functions to adjust the balances.
## Transfer tickets from originated to originated
This is essentially a contract call, which is already supported.
## Alternatives and extensions
### Multiple transfers with generic types
It is often desirable to allow users to transfer tickets of different types. For instance, users may want to transfer tickets of `ticket string` and `ticket nat` in one transaction to save gas cost. This is technically challenging for implicit to implicit transfers because the entrypoint type is not generic at this point. We may need a different manager operation type that takes a type, so that we can at least compute `has_tickets` witness later.
So far existentially typed tickets may handle this requirement sufficiently.
## Appendix
### Capability table
| Capabilities | To implicit account | To originated contract |
| ------------------------ | ------------------------------------------- | ------------------------------------ |
| From implicit account | Default entrypoint only, (?) Zero Tez along | Any valid entrypoint, Zero Tez along |
| From originated contract | Default entrypoint only, (?) Zero Tez along | Any valid entrypoint, Tez along |
| Interface | To implicit account | To originated contract |
| ------------------------ | ---------------------- | ---------------------- |
| From implicit account | RPC: `Transfer_ticket` | RPC: `Transfer_ticket` |
| From originated contract | IR: `TRANSFER_TOKENS` | IR: `TRANSFER_TOKENS` |
1. What is the utility of sending Tez and ticket together? Any real use case?
2. It is technically doable to make all of them to send some Tez along. But is it needed for MVP?