# TZIP-15 Token Transferlist Interface: request for comment

**URL:** https://forum.tezosagora.org/t/tzip-15-token-transferlist-interface-request-for-comment/2062
**Category:** Research and Development
**Tags:** michelson, ligo, smartpy
**Created:** [July 8, 2020, 1:44pm UTC](https://forum.tezosagora.org/t/tzip-15-token-transferlist-interface-request-for-comment/2062 "2020-07-08T13:44:48Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![TQTezos](https://forum.tezosagora.org/letter_avatar_proxy/v4/letter/t/8c91f0/32.png) [@TQTezos](https://forum.tezosagora.org/u/TQTezos)
#### Post date: [July 8, 2020, 1:44pm UTC](https://forum.tezosagora.org/t/tzip-15-token-transferlist-interface-request-for-comment/2062/1 "2020-07-08T13:44:48Z")

</div>

## Introduction

[TZIP-15](https://gitlab.com/tzip/tzip/-/blob/master/proposals/tzip-15/tzip-15.md) is a new specification that proposes a standard for a transfer filtering interface, a common requirement for token contracts which represent real-world financial assets (e.g. securities). The idea of the interface is to propose a lightweight permission schema, that takes the form of user transferlists, i.e. lists of who is authorized to send and/or receive a transfer. For token contracts which use this mechanism, it is impossible for a user to send or receive transfers without being listed on the transferlist.

A transferlist (in other contexts known as a “whitelist”) is a list of pairs of userIds that are allowed to send and receive tokens, respectively. A mechanism is provided to assert that each transfer is allowed by the transferlist before it completes. A block of transfers can be asserted as a whole and will be rejected if one of the senders or receivers doesn’t belong to the transferlist.

A transferlist can be either restricted or unrestricted. The parameter unrestricted is a boolean; when it is set to False, the transferlist is restricted, and its user will fail the asserts (i.e. assertReceivers and assertTransfers).

Alternately, a restricted transferlist will generally behave as if its allowedTransferlists is empty.

This interface can either be used as part of a token contract (i.e. in a monolith configuration) or as a separate contract that is queried on demand.

### Summary of the entrypoints

Here are the 8 entrypoints defined in the standard, grouped by category:

_Assertion_

- assertReceivers  
Succeed if each userId in the list is associated to a transferlist that can receive transfers.
- assertTransfers  
Succeed if each pair of from/to userId’s is associated with transferlists that may send to/receive from each other, respectively.

_Management_

- setIssuer  
Set the issuer’s userId
- updateUser  
Add, update, or remove a user
- updateTransferlist  
Add, update, or remove a transferlist

_Informative_

- getIssuer  
Get the issuer’s userId
- getUser  
Get user’s transferlistId if the userId exists in users, returns None otherwise
- assertTransferlist  
Succeed if the given transferlistId exists in transferlists, the given unrestricted bool matches its unrestricted state, and the given allowedTransferlists is a subset of its allowedTransferlists

## Transferlist Examples

To illustrate how the transferlist works, here is an example of an assetTransfers call with several users and transferlists.

Consider the following setup where userId is a string and transferlistId is an integer:

Users:

```
"alice": 0

"bob": 0

"charlie": 1

"dan": 2

```

Transferlists:

```
0: (unrestricted: True, allowedTransferlists: {0, 2})

1: (unrestricted: True, allowedTransferlists: {1})

2: (unrestricted: False, allowedTransferlists: {1, 2})

```

Then suppose the following call to assertTransfers were made:

```
assertTransfers

{ Pair "alice" { "bob", "dan" }

, Pair "bob" { "alice" }

, Pair "charlie" { "charlie", "dan" }

}

```

1. alice → bob  
Alice and Bob are on the same transferlist (0), which contains itself in its allowedTransferlists and is unrestricted, so this succeeds.

2. alice → dan  
Alice is on a transferlist (0) that contains Dan’s transferlistId (2) in its allowedTransferlists and is unrestricted, but it fails because Dan’s transferlist is restricted.

3. bob → alice  
This succeeds by the same logic as Alice → Bob: they’re on the same unrestricted transferlist that contains its own transferlistId in its allowedTransferlists.

4. charlie → charlie  
This succeeds since Charlie’s transferlist is unrestricted and contains its own transferlistId in its allowedTransferlists.

5. charlie → dan  
This fails because Dan’s transferlist (2) is restricted.

Thus the above call to assertTransfers will fail.

**Diagramming the Transferlist interface**

 ![](https://forum.tezosagora.org/uploads/default/original/1X/51dab1239a5d601d4a7e0a393590b1c8c957b369.png)

## Request for comment

The full specifications are published on TZIP under[TZIP-15](https://gitlab.com/tzip/tzip/-/blob/master/proposals/tzip-15/tzip-15.md), and we are now requesting comments from the Tezos community.

Below are a few questions that we are eager to discuss:

- updateTransferList is optimized for potentially-large allowed outbound sets, i.e. it accepts granular patches, but it could be simplified if all allowed outbound sets are small. What are some use cases for large outbound sets?
- If a canonical userId for the issuer were specified, the setIssuer and getIssuer entrypoints could be removed. Would this be better than explicitly distinguishing the issuer on-chain?
- What off-chain tools would be helpful to administrate a transferlist contract?

If you have any questions, feedback, or comments about this new specification, please submit them in the section below, or directly on [the GitLab repo](https://gitlab.com/tzip/tzip/-/blob/master/proposals/tzip-15/tzip-15.md). The core behavior is implemented in [Lorentz](https://gitlab.com/morley-framework/morley/-/tree/master/code/lorentz), [SmartPy](https://smartpy.io/), and partially in [LIGO](https://ligolang.org/). You can find the links at the bottom of the blog post.

## Next Steps

**Tutorial**

A tutorial on how to use the transferlist is in development and will be added to the [Assets portal](https://assets.tqtezos.com/docs/intro/) soon.

**Implementations**

Some implementations of transferlist contracts are currently under development:

- An implementation of compile-time wrapping and separate-contract transferlists in Lorentz can be found [here](https://github.com/tqtezos/lorentz-contract-whitelist)
- A partial implementation of a compile-time wrapper in LIGO can be found [here](https://github.com/tqtezos/ligo-contract-whitelist)
- An implementation of the separate-contract transferlist in SmartPy can be found [here](https://gitlab.com/tezos-paris-hub/whitelisting-smartpy)

* * *

_Thanks to the teams at Neofacto, Tezos Paris Hub, and Serokell for their feedback on TZIP-15 to date._
