# 5.4 Token Registry - ARC21

The Token Registry Program is a standard program designed for issuing and managing new tokens on the Aleo blockchain. It operates as a singleton program because on Aleo, all imported programs must be known and deployed before the importing program, and dynamic cross-program calls are not currently supported which makes composability difficult to implement. This means that a DeFi program must be compiled with support for all token programs that it will ever interact with. If a new token program is subsequently deployed on-chain, the DeFi program will need to be re-compiled and redeployed on chain in order to interact with that token.

In the near-term, support for program upgradability will resolve this but currently, the issue is circumvented by means of the [token registry](https://explorer.provable.com/program/token_registry.aleo) which can manage balances for many different ARC-20 tokens. This program would be the standard "hub" that all tokens and DeFi programs interface with. Individual ARC-20 tokens can register with the registry and mint new tokens via this program. Transfers of token value will occur by direct call to the registry rather than the ARC-20 program itself. The benefit of this approach is that DeFi programs do not need to be compiled with any special knowledge of individual ARC-20 tokens: their sole dependency will be the registry. Hence the deployment of new tokens does not require re-deployment of DeFi programs. Similarly, individual ARC-20 tokens can also be compiled with dependence on the registry, but no dependence on the DeFi programs. The registry thus allows interoperability between new tokens and DeFi programs, with no need for program re-deployment. As a secondary benefit, the registry will provide privacy benefits (via an improved anonymity set) because all private transfers within the registry will conceal the identity of the specific token being transferred.

This standard is emerged from extensive discussions and the approval of the [ARC-21 proposal](https://vote.aleo.org/p/21) to enable token interoperability across different applications.

This documentation outlines the functions of the Token Registry Program and provides guidance on how to use it. The original source code can be found [here](https://github.com/demox-labs/aleo-standard-programs/blob/main/token_registry/src/main.leo).

### How to use the Token Registry Program[​](https://developer.aleo.org/guides/standards/token_registry/#how-to-use-the-token-registry-program) <a href="#how-to-use-the-token-registry-program" id="how-to-use-the-token-registry-program"></a>

Anyone can create a new token on Aleo using the `token_registry.aleo` program by calling the `register_token` transition with a unique token ID and specifying any name, symbol, decimals, and maximum supply. An optional `external_authorization_required` boolean grants extra control over token available to spend by requiring extra approval from an `external_authorization_party`, the `external_authorization_party` can unlocks certain amount of balances for spending with expiration over a specific owner's token using `prehook_public` or `prehook_private`. The admin can also set `external_authorization_party` to another address with `update_token_management` later if needed.

Once a token is registered, the tokens can be minted either publicly using `mint_public` or privately to a specific recipient using `mint_private` with roles `MINTER_ROLE` or `SUPPLY_MANAGER_ROLE` if not admin. The tokens can also be burned either publicly with `burn_public` or privately with `burn_private` with roles `BURNER_ROLE` or `SUPPLY_MANAGER_ROLE` if not admin.

The token owner then can transfer the token either publicly using `transfer_public` or privately to a specific recipient using `transfer_private`. The token can also be converted from public to private using `transfer_public_to_private` or from private to public using `transfer_private_to_public`.

For an example of how the flow works, please refer to the [Usage Example with Token Registry Program](https://developer.aleo.org/guides/wallets/usage_example).

### Token Registry Program Data Structures[​](https://developer.aleo.org/guides/standards/token_registry/#token-registry-program-data-structures) <a href="#token-registry-program-data-structures" id="token-registry-program-data-structures"></a>

#### Token Record[​](https://developer.aleo.org/guides/standards/token_registry/#token-record) <a href="#token-record" id="token-record"></a>

```rust
  record Token {
    owner: address,
    amount: u128,
    token_id: field,
    external_authorization_required: bool,
    authorized_until: u32
  }
```

**Token Record Fields**[**​**](https://developer.aleo.org/guides/standards/token_registry/#token-record-fields)

* `owner`: The address of the token owner.
* `amount`: The amount of tokens in the account.
* `token_id`: The unique identifier for the token.
* `external_authorization_required`: Whether or not the token requires external authorization.
* `authorized_until`: The block height until which the token is authorized.

#### Token Metadata Struct[​](https://developer.aleo.org/guides/standards/token_registry/#token-metadata-struct) <a href="#token-metadata-struct" id="token-metadata-struct"></a>

```rust
  struct TokenMetadata {
    token_id: field,
    name: u128, // ASCII text represented in bits, and the u128 value of the bitstring
    symbol: u128, // ASCII text represented in bits, and the u128 value of the bitstring
    decimals: u8,
    supply: u128,
    max_supply: u128,
    admin: address,
    external_authorization_required: bool, // whether or not this token requires authorization from an external program before transferring
    external_authorization_party: address
  }
```

**Token Metadata Struct Fields**[**​**](https://developer.aleo.org/guides/standards/token_registry/#token-metadata-struct-fields)

* `token_id`: The unique identifier for the token.
* `name`: The name of the token.
* `symbol`: The symbol of the token.
* `decimals`: The number of decimals for the token.
* `supply`: The total supply of the token.
* `max_supply`: The maximum supply of the token.
* `admin`: The address of the token admin.
* `external_authorization_required`: Whether or not the token requires external authorization.
* `external_authorization_party`: The address of the external authorization party.

#### Token Owner Struct[​](https://developer.aleo.org/guides/standards/token_registry/#token-owner-struct) <a href="#token-owner-struct" id="token-owner-struct"></a>

```rust
  struct TokenOwner {
    account: address,
    token_id: field
  }
```

**Token Owner Struct Fields**[**​**](https://developer.aleo.org/guides/standards/token_registry/#token-owner-struct-fields)

* `account`: The address of the token owner.
* `token_id`: The unique identifier for the token.

#### Balance Struct[​](https://developer.aleo.org/guides/standards/token_registry/#balance-struct) <a href="#balance-struct" id="balance-struct"></a>

```rust
  struct Balance {
    token_id: field,
    account: address,
    balance: u128,
    authorized_until: u32
  }
```

**Balance Struct Fields**[**​**](https://developer.aleo.org/guides/standards/token_registry/#balance-struct-fields)

* `token_id`: The unique identifier for the token.
* `account`: The address of the token owner.
* `balance`: The balance of the token.
* `authorized_until`: The block height until which the token is authorized.

#### Allowance Struct[​](https://developer.aleo.org/guides/standards/token_registry/#allowance-struct) <a href="#allowance-struct" id="allowance-struct"></a>

```rust
  struct Allowance {
    account: address,
    spender: address,
    token_id: field
  }
```

**Allowance Struct Fields**[**​**](https://developer.aleo.org/guides/standards/token_registry/#allowance-struct-fields)

* `account`: The address of the token owner.
* `spender`: The address of the spender.
* `token_id`: The unique identifier for the token.

### Token Registry Program Mappings[​](https://developer.aleo.org/guides/standards/token_registry/#token-registry-program-mappings) <a href="#token-registry-program-mappings" id="token-registry-program-mappings"></a>

`mapping registered_tokens: field => TokenMetadata;`\
Mapping of token IDs to token metadata structs.

`mapping balances: field => Balance;`\
Mapping of the hash of the token ID and the account address to the balance struct.

`mapping allowances: field => Allowance;`\
Mapping of the hash of the token ID, the account address, and the spender address to the allowance struct.

`mapping roles: field => u8;`\
Mapping of the hash of the token ID and the account address to the role.

### Token Registry Program Constants[​](https://developer.aleo.org/guides/standards/token_registry/#token-registry-program-constants) <a href="#token-registry-program-constants" id="token-registry-program-constants"></a>

`const CREDITS_RESERVED_TOKEN_ID: field = 3443843282313283355522573239085696902919850365217539366784739393210722344986field;`\
Token ID reserved for the ALEO token.

`const MINTER_ROLE: u8 = 1u8;`\
Role for the minter.

`const BURNER_ROLE: u8 = 2u8;`\
Role for the burner.

`const SUPPLY_MANAGER_ROLE: u8 = 3u8;`\
Role for the supply manager.

### Token Registry Program Functions[​](https://developer.aleo.org/guides/standards/token_registry/#token-registry-program-functions) <a href="#token-registry-program-functions" id="token-registry-program-functions"></a>

The Token Registry Program includes the following functions:

#### `initialize()`[​](https://developer.aleo.org/guides/standards/token_registry/#initialize) <a href="#initialize" id="initialize"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description)

Initializes the Token Registry Program by registering the ALEO token with predefined metadata. The token is initialized with a specific token ID, name "credits", symbol "credits", 6 decimals, and a max supply of 10 quadrillion. The program sets itself (wrapped\_credits.aleo) as the admin and disables external authorization requirements to ensure the token metadata cannot be modified after initialization.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters)

Parameters are hardcoded in program to safeguard against frontrunning.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns)

None.

#### `register_token()`[​](https://developer.aleo.org/guides/standards/token_registry/#register_token) <a href="#register_token" id="register_token"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-1)

Registers a new token with the Token Registry Program.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-1)

* `public token_id: field`: The unique identifier for the token.
* `public name: u128`: The name of the token.
* `public symbol: u128`: The symbol of the token.
* `public decimals: u8`: The number of decimals for the token.
* `public max_supply: u128`: The maximum supply of the token.
* `public external_authorization_required: bool`: Whether or not the token requires external authorization.
* `public external_authorization_party: address`: The address of the external authorization party.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-1)

* `Future`: A Future to finalize the token registration.

#### `update_token_management()`[​](https://developer.aleo.org/guides/standards/token_registry/#update_token_management) <a href="#update_token_management" id="update_token_management"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-2)

Updates the token management settings.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-2)

* `public token_id: field`: The unique identifier for the token.
* `public admin: address`: The address of the admin.
* `public external_authorization_party: address`: The address of the external authorization party.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-2)

* `Future`: A Future to finalize the token management update.

#### `set_role()`[​](https://developer.aleo.org/guides/standards/token_registry/#set_role) <a href="#set_role" id="set_role"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-3)

Sets the role for a specific token ID.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-3)

* `public token_id: field`: The unique identifier for the token.
* `public account: address`: The address of the account.
* `public role: u8`: The role to set.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-3)

* `Future`: A Future to finalize the role set.

#### `remove_role()`[​](https://developer.aleo.org/guides/standards/token_registry/#remove_role) <a href="#remove_role" id="remove_role"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-4)

Removes the role for a specific token ID.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-4)

* `public token_id: field`: The unique identifier for the token.
* `public account: address`: The address of the account.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-4)

* `Future`: A Future to finalize the role removal.

#### `mint_public()`[​](https://developer.aleo.org/guides/standards/token_registry/#mint_public) <a href="#mint_public" id="mint_public"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-5)

Mints a new token publicly by the specific token ID's admin.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-5)

* `public token_id: field`: The unique identifier for the token.
* `public recipient: address`: The address of the recipient.
* `public amount: u128`: The amount of tokens to mint.
* `public authorized_until: u32`: The block height until which the token is authorized.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-5)

* `Future`: A Future to finalize the mint.

#### `mint_private()`[​](https://developer.aleo.org/guides/standards/token_registry/#mint_private) <a href="#mint_private" id="mint_private"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-6)

Mints a new token privately by the specific token ID's admin.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-6)

* `public token_id: field`: The unique identifier for the token.
* `recipient: address`: The address of the recipient that is not visible to the public.
* `public amount: u128`: The amount of tokens to mint.
* `public external_authorization_required: bool`: Whether or not the token requires external authorization.
* `public authorized_until: u32`: The block height until which the token is authorized.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-6)

* `Token`: The token record.
* `Future`: A Future to finalize the mint.

#### `burn_public()`[​](https://developer.aleo.org/guides/standards/token_registry/#burn_public) <a href="#burn_public" id="burn_public"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-7)

Burns a token publicly by the specific token ID's admin.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-7)

* `public token_id: field`: The unique identifier for the token.
* `public owner: address`: The address of the owner.
* `public amount: u128`: The amount of tokens to burn.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-7)

* `Future`: A Future to finalize the burn.

#### `burn_private()`[​](https://developer.aleo.org/guides/standards/token_registry/#burn_private) <a href="#burn_private" id="burn_private"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-8)

Burns a token privately by the specific token ID's admin.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-8)

* `input_record: Token`: The token record.
* `public amount: u128`: The amount of tokens to burn.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-8)

* `Token`: The token record with remaining balance.
* `Future`: A Future to finalize the burn.

#### `prehook_public()`[​](https://developer.aleo.org/guides/standards/token_registry/#prehook_public) <a href="#prehook_public" id="prehook_public"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-9)

A function for the authorized party to modify authorized amount and new expiration publicly.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-9)

* `public owner: address`: The address of the owner.
* `public amount: u128`: The amount of tokens to prehook.
* `public authorized_until: u32`: The block height until which the token is authorized.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-9)

* `Future`: A Future to finalize the prehook.

#### `prehook_private()`[​](https://developer.aleo.org/guides/standards/token_registry/#prehook_private) <a href="#prehook_private" id="prehook_private"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-10)

A function for the authorized party to modify authorized amount and new expiration privately.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-10)

* `input_record: Token`: The token record.
* `amount: u128`: The amount of tokens to prehook.
* `authorized_until: u32`: The block height until which the token is authorized.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-10)

* `Token`: The unauthorized token record.
* `Token`: The authorized token record.
* `Future`: A Future to finalize the prehook.

#### `transfer_public()`[​](https://developer.aleo.org/guides/standards/token_registry/#transfer_public) <a href="#transfer_public" id="transfer_public"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-11)

Transfers a token publicly by the token owner.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-11)

* `public token_id: field`: The unique identifier for the token.
* `public recipient: address`: The address of the recipient.
* `public amount: u128`: The amount of tokens to transfer.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-11)

* `Future`: A Future to finalize the transfer.

#### `transfer_public_as_signer()`[​](https://developer.aleo.org/guides/standards/token_registry/#transfer_public_as_signer) <a href="#transfer_public_as_signer" id="transfer_public_as_signer"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-12)

Transfers a token publicly by the token owner as the transaction signer in any arbitrary program calls.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-12)

* `public token_id: field`: The unique identifier for the token.
* `public recipient: address`: The address of the recipient.
* `public amount: u128`: The amount of tokens to transfer.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-12)

* `Future`: A Future to finalize the transfer.

#### `approve_public()`[​](https://developer.aleo.org/guides/standards/token_registry/#approve_public) <a href="#approve_public" id="approve_public"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-13)

Approves a token for a spender to be able to transfer the token on behalf of the owner.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-13)

* `public token_id: field`: The unique identifier for the token.
* `public spender: address`: The address of the spender.
* `public amount: u128`: The amount of tokens to approve.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-13)

* `Future`: A Future to finalize the approval.

#### `unapprove_public()`[​](https://developer.aleo.org/guides/standards/token_registry/#unapprove_public) <a href="#unapprove_public" id="unapprove_public"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-14)

Revokes or reduces the approval for a spender to transfer the token on behalf of the owner.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-14)

* `public token_id: field`: The unique identifier for the token.
* `public spender: address`: The address of the spender.
* `public amount: u128`: The amount of tokens to unapprove.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-14)

* `Future`: A Future to finalize the unapproval.

#### `transfer_from_public()`[​](https://developer.aleo.org/guides/standards/token_registry/#transfer_from_public) <a href="#transfer_from_public" id="transfer_from_public"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-15)

Transfers a token from the owner to the recipient after getting approval from the owner.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-15)

* `public token_id: field`: The unique identifier for the token.
* `public owner: address`: The address of the owner.
* `public recipient: address`: The address of the recipient.
* `public amount: u128`: The amount of tokens to transfer.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-15)

* `Future`: A Future to finalize the transfer.

#### `transfer_public_to_private()`[​](https://developer.aleo.org/guides/standards/token_registry/#transfer_public_to_private) <a href="#transfer_public_to_private" id="transfer_public_to_private"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-16)

Convert public token to private token by its owner.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-16)

* `public token_id: field`: The unique identifier for the token.
* `recipient: address`: The address of the recipient that is not visible to the public.
* `public amount: u128`: The amount of tokens to transfer.
* `public external_authorization_required: bool`: Whether or not the token requires external authorization.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-16)

* `Token`: The token record.
* `Future`: A Future to finalize the transfer.

#### `transfer_from_public_to_private()`[​](https://developer.aleo.org/guides/standards/token_registry/#transfer_from_public_to_private) <a href="#transfer_from_public_to_private" id="transfer_from_public_to_private"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-17)

Convert public token to private token on behalf of the token owner after getting approval from the owner.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-17)

* `public token_id: field`: The unique identifier for the token.
* `public owner: address`: The address of the owner.
* `recipient: address`: The address of the recipient that is not visible to the public.
* `public amount: u128`: The amount of tokens to transfer.
* `public external_authorization_required: bool`: Whether or not the token requires external authorization.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-17)

* `Token`: The token record.
* `Future`: A Future to finalize the transfer.

#### `transfer_private()`[​](https://developer.aleo.org/guides/standards/token_registry/#transfer_private) <a href="#transfer_private" id="transfer_private"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-18)

Transfers a token privately by the token owner.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-18)

* `recipient: address`: The address of the recipient that is not visible to the public.
* `amount: u128`: The amount of tokens to transfer.
* `input_record: Token`: The token record.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-18)

* `Token`: The remaining token record.
* `Token`: The receiving token record.
* `Future`: A Future to finalize the transfer.

#### `transfer_private_to_public()`[​](https://developer.aleo.org/guides/standards/token_registry/#transfer_private_to_public) <a href="#transfer_private_to_public" id="transfer_private_to_public"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-19)

Convert private token to public token by the token owner.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-19)

* `public recipient: address`: The address of the recipient that is visible to the public.
* `public amount: u128`: The amount of tokens to transfer.
* `input_record: Token`: The token record.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-19)

* `Token`: The remaining token record.
* `Future`: A Future to finalize the transfer.

#### `join()`[​](https://developer.aleo.org/guides/standards/token_registry/#join) <a href="#join" id="join"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-20)

Joins two private token records and become one single record. Does not change the total amount of the tokens.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-20)

* `private token_1: Token`: The first token record.
* `private token_2: Token`: The second token record.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-20)

* `Token`: The joined token record.

#### `split()`[​](https://developer.aleo.org/guides/standards/token_registry/#split) <a href="#split" id="split"></a>

**Description**[**​**](https://developer.aleo.org/guides/standards/token_registry/#description-21)

Splits a private token record into two new token records. Does not change the total amount of the tokens.

**Parameters**[**​**](https://developer.aleo.org/guides/standards/token_registry/#parameters-21)

* `private token: Token`: The token record.
* `private amount: u128`: The amount of tokens to split.

**Returns**[**​**](https://developer.aleo.org/guides/standards/token_registry/#returns-21)

* `Token`: The splitted token record.
* `Token`: The remaining token record.
