ZIP 227 — Issuance of Zcash Shielded Assets
Terminology
The key words "MUST", "MUST NOT", "SHOULD", "RECOMMENDED", and "MAY" in this document are to be interpreted as described in BCP 14 [1] when, and only when, they appear in all capitals.
The term "network upgrade" in this document is to be interpreted as described in ZIP 200 [7].
The character § is used when referring to sections of the Zcash Protocol Specification. [24]
The terms "Orchard" and "Action" in this document are to be interpreted as described in ZIP 224 [9].
We define the following additional terms:
Asset: A type of note that can be transferred on the Zcash blockchain. Each Asset is identified by an Asset Identifier Specification: Asset Identifier, Asset Digest, and Asset Base.
ZEC is the default (and currently the only defined) Asset for the Zcash mainnet.
TAZ is the default (and currently the only defined) Asset for the Zcash testnet.
We use the term "Custom Asset" to refer to any Asset other than ZEC and TAZ.
Issuance Action: an instance of a single issuance of a Zcash Shielded Asset. It defines the issuance of a single Asset Identifier.
Issuance Bundle: the bundle in the transaction that contains all the issuance actions of that transaction.
Abstract
This ZIP (ZIP 227) proposes the Orchard Zcash Shielded Assets (OrchardZSA) protocol, in conjunction with ZIP 226 [10]. This protocol is an extension of the Orchard protocol that enables the creation, transfer and burn of Custom Assets on the Zcash chain. The creation of such Assets is defined in this ZIP (ZIP 227), while the transfer and burn of such Assets is defined in ZIP 226 [10]. This ZIP must only be implemented in conjunction with ZIP 226 [10]. The proposed issuance mechanism is only valid for the OrchardZSA transfer protocol, because it produces notes that can only be transferred via this protocol.
Motivation
This ZIP introduces the issuance mechanism for Custom Assets on the Zcash chain. While originally part of a single ZSA ZIP, the issuance mechanism turned out to be substantial enough to stand on its own and justify the creation of this supporting ZIP for ZIP 226 [10].
This ZIP only enables transparent issuance. As a first step, transparency will allow for proper testing of the applications that will be most used in the Zcash ecosystem, and will enable the supply of Assets to be tracked.
The issuance mechanism described in this ZIP is broad enough for issuers to either create Assets on Zcash (i.e. Assets that originate on the Zcash blockchain), as well as for institutions to create bridges from other chains and issue Assets that wrap tokens from those chains. This enables what we hope will be a useful set of applications.
Use Cases
The design presented in this ZIP enables issuance of shielded Assets in various modes:
The issuer may or may not know the receivers of the issued Asset in advance.
The Asset can be of non-fungible type, where each Asset type can be made part of a single “series”.
The supply of the Asset can be limited in advance or not.
The Asset can be a wrapped version of an Asset issued by another chain (as long as there is a bridge that supports transfer of that Asset between chains).
See the Concrete Applications section for more details.
Requirements
Any user of the Zcash blockchain can issue Custom Assets on chain.
The issuance mechanism should enable public tracking of the supply of the Assets on the Zcash blockchain.
Issuing or changing the attributes of a specific Asset should require cryptographic authorization.
The Asset identification should be unique (among all shielded pools) and different issuer public keys should not be able to generate the same Asset Identifier.
An issuer should be able to issue different Assets in the same transaction. In other words, in a single "issuance bundle", the issuer should be able publish many "issuance actions", potentially creating multiple Custom Assets.
Every "issuance action" should contain a boolean that defines whether the specific Custom Asset can have further tokens issued or not.
Specification: Issuance Keys, Issuer Identifier, and Issuance Authorization Signature Scheme
Issuance Keys
The OrchardZSA Protocol adds the following keys used for issuance:
The issuance authorizing key, denoted as , is the key used to authorize the issuance of Asset Identifiers by a given issuer, and is only used by that issuer.
The issuance validating key, denoted as , is the key that is used to validate issuance transactions. This key is used to validate the issuance of Asset Identifiers by a given issuer.
The relations between these keys are shown in the following diagram:
Diagram of Issuance Key Components for the OrchardZSA Protocol
Issuer Identifier
The identifier for a particular issuer is denoted by . This identifier is used by all blockchain users (specifically the owners of notes for that Asset, and consensus validators) to associate the Asset in question with the issuer.
is equal to the encoding (specified below in Derivation of issuance validating key) of the issuance validating key used to validate the issuance of Asset Identifiers by that issuer.
Note: the equality of and might not hold in future when key rotation is specified for issuance key pairs.
Issuance Authorization Signature Scheme
The issuance authorization signature, encoded in the issueAuthSig field of an issuance bundle, is used to authorize the issuance of Custom Assets by the issuer.
The issuance authorization signature scheme, , comprises all the associated types and algorithms required for a signature scheme in §4.1.7 ‘Signature’ [27].
Batch verification MAY be used. Precomputation MAY be used if and only if it produces equivalent results.
Orchard ZSA Issuance Authorization Signature Scheme
In the OrchardZSA protocol, we instantiate the issuance authorization signature scheme as a BIP-340 Schnorr signature over the secp256k1 curve. We define the constants as per the secp256k1 standard parameters, as described in BIP 340.
The associated types of the signature scheme, which are identical to BIP 340, are as follows:
where denotes the set of sequences of bytes, and denotes the type of byte sequences of arbitrary length, as defined in the Zcash protocol specification [25].
The issuance authorizing key generation algorithm and the issuance validating key derivation algorithm are defined in the Issuance Key Derivation section, while the corresponding signing and validation algorithms are defined in the Issuance Authorization Signing and Validation section.
Issuance Key Derivation
Issuance authorizing key generation for hierarchical deterministic wallets
The issuance authorizing key is generated using the Hardened-only key derivation process defined in ZIP 32 [3]. For the context, we define the following constants:
\mathsf{Issuance.MKGDomain} := \texttt{“ZcashSA\_Issue\_V1”}
Let be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes. We define the master extended issuance key .
We use hardened-only child key derivation as defined in ZIP 32 [4] for the issuance authorizing key.
:
Return
We use the notation of ZIP 32 [6] for shielded HD paths, and define the issuance authorizing key path as . We fix the path levels as follows:
: a constant set to $227$ (i.e. ). is thus $227'$ (or ) following the BIP 43 recommendation. [22]
: Defined as in ZIP 32 [5].
: fixed to index .
From the generated , we set the issuance authorizing key to be .
Derivation of issuance validating key
Define $mathsf{IssueAuthSig.DerivePublic} ;{small ⦂}; (mathsf{isk} ;{small ⦂}; mathsf{IssueAuthSig.Private}) to mathsf{IssueAuthSig.Public}$ as:
\mathsf{ik} := \textit{PubKey}(\mathsf{isk})
Return if the \textit{PubKey} algorithm invocation fails, otherwise return .
where the \textit{PubKey} algorithm is defined in BIP 340 [23], and the output of the algorithm is in big-endian order as defined in BIP 340.
The encoding of this validating key, , includes an initial byte indicating the signature scheme, which MUST be indicating BIP 340. That is, . This enables future ZIPs to specify alternative signature schemes. Note that this encoding currently only appears in the issuer field of an issuance bundle.
It is possible for the \textit{PubKey} algorithm to fail with very low probability, which means that could return with very low probability. If this happens, discard the keys and repeat with a different .
This allows the issuer to use the same wallet it usually uses to transfer Assets, while keeping a disconnect from the other keys. Specifically, this method is aligned with the requirements and motivation of ZIP 32 [2]. It provides further anonymity and the ability to delegate issuance of an Asset (or in the future, use a multi-signature protocol) while the rest of the keys remain safe in the wallet.
Issuance Authorization Signing and Validation
Define $mathsf{IssueAuthSig.Sign} ;{small ⦂}; (mathsf{isk} ;{small ⦂}; mathsf{IssueAuthSig.Private}) times (M ;{small ⦂}; mathsf{IssueAuthSig.Message}) to mathsf{IssueAuthSig.Signature}$ as:
Let the auxiliary data .
Let with auxiliary data .
Return if the algorithm fails in the previous step, otherwise return .
where the algorithm is defined in BIP 340 [23]. Note that could return with very low probability.
Define $mathsf{IssueAuthSig.Validate} ;{small ⦂}; (mathsf{ik} ;{small ⦂}; mathsf{IssueAuthSig.Public}) times (M ;{small ⦂}; mathsf{IssueAuthSig.Message}) times (text{σ} ;{small ⦂}; mathsf{IssueAuthSig.Signature}) to mathbb{B}$ as:
Return if .
Return if succeeds, otherwise .
where the algorithm is defined in BIP 340 [23].
The field of an issuance bundle encodes the signature with an initial byte indicating the signature scheme, which MUST be indicating BIP 340. That is, . This enables future ZIPs to specify alternative signature schemes.
Specification: Asset Identifier, Asset Digest, and Asset Base
The definition of the Asset Identifier, and that of the Asset Digest and Asset Base for a given Asset Identifier, will be described in this section. For context, the relations between the Asset Identifier, Asset Digest, and Asset Base are shown in the following diagram:
Diagram relating the Asset Identifier, Asset Digest, and Asset Base.
Note: To keep notations light and concise, we may omit in the subscript when the Asset Identifier is clear from the context.
Asset Identifier
Every Asset has a globally-unique Asset Identifier, denoted . A given Asset Identifier is used across all Zcash protocols that support ZSAs -- that is, the OrchardZSA protocol and potentially future Zcash shielded protocols.
ZIP 227 Asset Identifiers
Assets issued using the protocol specified in this ZIP are scoped to the that issued them. Within that scope, Asset Identifier uniqueness is obtained by way of an asset description, , which includes any information pertaining to the issuance. is a non-empty byte sequence which SHOULD be a well-formed UTF-8 code unit sequence according to Unicode 15.0.0 or later.
Define
\mathsf{assetDescHash} := \textsf{BLAKE2b-256}(\texttt{“ZSA-AssetDescCRH”},\; \mathsf{asset\_desc}),
We define Asset Identifiers for Assets issued under this ZIP as
and define their canonical encoding as
Note that the initial byte is a version byte, enabling future ZIPs to specify alternative issuance protocols and Asset Identifiers. (This should not be confused with the first byte of , currently equal to the first byte of , that indicates the issuance signature scheme.)
Wallets MUST NOT display just the string to their users as the name of the Asset. Some possible alternatives include:
Wallets could allow clients to provide an additional configuration file that stores a one-to-one mapping of names to Asset Identifiers via a petname system [35]. This allows clients to rename the Assets in a way they find useful. Default versions of this file with well-known Assets listed can be made available online as a starting point for clients.
The Asset Digest could be used as a more compact byte sequence to uniquely determine an Asset, and wallets could support clients scanning QR codes to load Asset information into their wallets.
Asset Digests
From the Asset Identifier, we derive an Asset Digest
\mathsf{AssetDigest_{AssetId}} := \textsf{BLAKE2b-512}(\texttt{“ZSA-Asset-Digest”},\; \mathsf{EncodeAssetId}(\mathsf{AssetId})),
where is the canonical encoding scheme for the Asset Identifier.
Asset Bases
From the Asset Digest, we derive a specific Asset Base that represents the Custom Asset within each shielded protocol:
This Asset Base is included in shielded notes within the shielded protocol.
OrchardZSA Asset Bases
In the case of the OrchardZSA protocol, we define
\mathsf{ZSAValueBase}(\mathsf{AssetDigest}) := \mathsf{GroupHash}^\mathbb{P}(\texttt{"z.cash:OrchardZSA"}, \mathsf{AssetDigest})
where is defined as in [32].
Diagram relating the Issuer identifier, asset description, asset description hash, Asset Identifier, Asset Digest, and Asset Base for the OrchardZSA Protocol.
Specification: Issue Note, Issuance Action, Issuance Bundle and Issuance Protocol
Issue Note
Let be as defined in §5.3 ‘Constants’ [30]. An Issue Note represents that a value of a specific Custom Asset is issued to a recipient. An Issue Note is a tuple , where:
is the diversifier of the recipient's shielded payment address, as in §3.2 ‘Notes’ [26].
is the recipient's diversified transmission key, as in §3.2 ‘Notes’ [26].
is the value of the note in terms of the number of Asset tokens.
is the Asset Base corresponding to the ZSA being issued in the Issue Note.
is used to derive the nullifier of the note, and is computed as in Computation of ρ.
MUST be sampled uniformly at random by the issuer.
ZIP 230 [16] defines, in IssueNoteDescription, field encodings which together with from the parent Issuance Bundle and from the parent Issuance Action, specify an Issue Note.
Let be the type of an Issue Note, i.e.
The note commitments of Issue Notes are computed in the same manner as for OrchardZSA Notes. They will be added to the note commitment tree as any other shielded note when the transaction issuing the Asset is included on chain. This prevents future usage of the note from being linked to the issuance transaction, as the nullifier key is not known to the validators and chain observers.
Issuance Action
An issuance action, IssueAction, is the instance of issuing a specific Custom Asset, and contains the following fields:
assetDescHash: the hash of the Asset description, as defined in the ZIP 227 Asset Identifiers section.
vNotes: an array of Issue Notes containing the unencrypted output notes to the recipients of the Asset.
flagsIssuance: a byte that stores the boolean that defines whether the issuance of that specific Custom Asset is finalized or not.
The boolean is set by the Issuer to signal that there will be no further issuance of the specific Custom Asset. As we will see in Specification: Consensus Rule Changes, transactions that attempt to issue further amounts of a Custom Asset that has previously been finalized will be rejected.
The complete encoding of these fields into an IssueAction is defined in ZIP 230 [15].
Issuance Bundle
An issuance bundle is the aggregate of all the issuance-related information. Specifically, contains all the issuance actions and the issuer signature on the transaction SIGHASH that validates the issuance itself. It contains the following fields:
issuer: the issuer identifier, that allows the validators to verify that the is properly associated with the issuer.
vIssueActions: an array of issuance actions, of type IssueAction.
issueAuthSig: the encoding of a signature of the transaction SIGHASH, signed by the issuance authorizing key, , that validates the issuance.
The issuance bundle is added within the transaction format as a new bundle. The detailed encoding of the issuance bundle as a part of the V6 transaction format is defined in ZIP 230 [17].
Computation of ρ
We define a function $mathsf{DeriveIssuedRho} : mathbb{F}_{q_{mathbb{P}}} times {0 .. 2^{32} - 1} times {0 .. 2^{32} - 1} to mathbb{F}_{q_{mathbb{P}}}$ for Issue Notes in the OrchardZSA Protocol as follows:
\mathsf{DeriveIssuedRho}(\mathsf{nf}, \mathsf{i_{A}}, \mathsf{i_{N}}) := \mathsf{ToBase}^{\mathsf{Orchard}}\big(\mathsf{PRF}^{\mathsf{expand}}\big(\mathsf{I2LEOSP}_{256}(\mathsf{nf}), [\mathtt{0x84}] \,||\, \mathsf{I2LEOSP}_{32}(\mathsf{i_{A}}) \,||\, \mathsf{I2LEOSP}_{32}(\mathsf{i_{N}})\big)\big),
where is defined in §4.2.3 ‘Orchard Key Components’ [28], and is defined in §5.4.2 ‘Pseudo Random Functions’ [31].
The field of an Issue Note is computed as
where is the nullifier for the input note in the first Action in the first Action Group of the OrchardZSA Bundle of the transaction, is the zero-based index of the Issuance Action in the Issuance Bundle, and is the zero-based index of the Issue Note in the Issuance Action.
NOTE: This implicitly requires that there always is an Action Group in the OrchardZSA bundle of the transaction. This is enforced by a consensus rule in the Specification: Consensus Rule Changes section.
Issuance Protocol
The issuer program performs the following operations:
For all actions IssueAction:
encode as a UTF-8 byte string.
compute
compute from the issuer identifier and as decribed in the Specification: Asset Identifier, Asset Digest, and Asset Base section.
compute from as decribed in the Specification: Asset Identifier, Asset Digest, and Asset Base section.
set the boolean as desired (if more issuance actions are to be created for this , set , otherwise set ).
for each recipient :
generate an Issue Note,
$mathsf{note}_i = (mathsf{d}_i, mathsf{pk}_{mathsf{d}_i}, mathsf{v}_i, mathsf{AssetBase}, text{ρ}_i, mathsf{rseed}_i)$.encode the into the vector vNotes of the IssueAction.
encode the IssueAction into the vector vIssueActions of the bundle.
For the IssueBundle (see “ZSA Issuance Bundle Fields” in [17]):
encode the vIssueActions vector.
fill the issuerLength and issuer fields using .
sign the SIGHASH transaction hash with the issuance authorizing key, , using the signature scheme. The signature is then added to the issuance bundle.
Note: The note commitment is not included in the IssuanceAction itself. As explained below, it is computed later by the validators and added to the note commitment tree.
Specification: Reference Notes and Global Issuance State
Reference Notes
A reference note for a Custom Asset MUST be included by the issuer as the first Note in the Action of the Issuance Bundle where that Custom Asset is being issued for the first time.
A reference note for a Custom Asset is an Issue Note where the value is set to , the Asset Base () corresponds to that of the Custom Asset, and the recipient address is set to the default diversified payment address (i.e. the diversified payment address with diversifier index ) derived from the all-zero Orchard spending key using the algorithm specified in §4.2.3 ‘Orchard Key Components’ [28]. This corresponds to a 43-byte u8 array with the following entries:
[ 204, 54, 96, 25, 89, 33, 59, 107, 12, 219, 150, 167, 92, 23, 195, 166, 104, 169, 127, 13, 106, 140, 92, 225, 100, 165, 24, 234, 155, 169, 165, 14, 167, 81, 145, 253, 134, 27, 15, 241, 14, 98, 176, ]
Global Issuance State
The maximum total supply of any issued Custom Asset is denoted by the constant .
Issuance requires the following additions to the global state:
A map, , from the Asset Base, , to a tuple , for every Asset that has been issued. We use the notation , , and to access, respectively, the elements of the tuple stored in the global state for a given . If , it is assumed that , , and .
For any Asset represented by :
stores the amount of the Asset in circulation, computed as the amount of the Asset that has been issued less the amount of the Asset that has been burnt.
is a Boolean that stores the finalization status of the Asset (i.e.: whether the flag has been set to in any preceding issuance transaction for the Asset). The value of for any cannot be changed from to .
stores the reference note for the Asset, as defined in the Reference Notes section.
Management of the Global Issuance State
The issuance state, that is, the map, MUST be updated by a node during the processing of any transaction that contains burn information, or an issuance bundle. The issuance state is chained as follows:
The input issuance state for the activation block of the OrchardZSA protocol is the empty map.
The input issuance state for the first transaction of a block is the final issuance state of the immediately preceding block.
The input issuance state of each subsequent transaction in the block is the output issuance state of the immediately preceding transaction.
The final issuance state of a block is the output issuance state of the last transaction in the block.
We describe the consensus rule changes that govern the management of the global issuance state in the Specification: Consensus Rule Changes section. We use and to denote the input issuance state and output issuance state for a transaction, respectively.
Specification: Consensus Rule Changes
Let be the SIGHASH transaction hash of this transaction, as defined in §4.10 ‘SIGHASH Transaction Hashing’ [29] with the modifications described in ZIP 226 [13], using .
For every transaction:
The nActionGroupsOrchard field MUST have a value of either 0 or 1 and the nAGExpiryHeight field MUST have a value of 0.
The output issuance state of the transaction MUST be initialized to be the same as the input issuance state, .
The set MUST satisfy the consensus rules specified in ZIP 226 [12].
It MUST be the case that for all , . The node then MUST update prior to processing the issuance bundle in the following manner. For every , $mathsf{issued_assets}_{mathsf{OUT}}(mathsf{AssetBase}).mathsf{balance} = mathsf{issued_assets}_{mathsf{OUT}}(mathsf{AssetBase}).mathsf{balance} - mathsf{v}$.
If the transaction contains an issuance bundle:
It MUST also contain at least one OrchardZSA Action Group.
The encoding of the issuance key used to validate the issuance authorization signature MUST be taken from the issuer field, and MUST start with the byte value indicating a BIP 340 public key.
The issuance authorization signature, , MUST be a valid signature over , i.e. .
For every issuance action description () in the issuance bundle:
Every IssueNoteDescription in the IssueAction MUST be a valid field encoding as defined in ZIP 230 [16].
Let an Issue Note (with type ) be constructed from the fields of each IssueNoteDescription, with the derived from the assetDescHash field of the IssueAction and the issuer field of the issuance bundle, as described in the Specification: Asset Identifier, Asset Digest, and Asset Base section.
It MUST be the case that .
If , then let be the first Issue Note in the Issuance Action.
The recipient address of MUST be the default diversified payment address derived from the all-zero Orchard spending key, as described in the Reference Notes section.
The value of MUST be .
The node MUST update .
For every Issue Note, for in IssueAction:
The field of the issue note MUST have been computed as described in the Computation of ρ section.
It MUST be the case that , where is the value of . The node then MUST update
$mathsf{issued_assets}_{mathsf{OUT}}.mathsf{balance} = mathsf{issued_assets}_{mathsf{OUT}}.mathsf{balance} + mathsf{v}_j$.The node MUST compute the note commitment, , as defined in the Note Structure and Commitment section of ZIP 226 [11].
If within the flagsIssuance field of IssueAction, the node MUST set .
Addition to the Note Commitment Tree
If the transaction is added to the block chain, the note commitments of all the OrchardZSA Notes and the Issue Notes in the transaction are added to the note commitment tree of the associated treestate. The order of addition to the tree is as specified below:
For each Action Group in the OrchardZSA Bundle:
For every Action in the Action Group, append the note commitment of every new OrchardZSA note in the Action to the note commitment tree.
For each Issue Action in the Issue Bundle:
For every Issue Note in the Issue Action, append the note commitment of the Issue Note to the note commitment tree.
Rationale
The following is a list of rationale for different decisions made in the proposal:
The issuance key structure is independent of the original key tree, but derived in an analogous manner (via ZIP 32). This keeps the issuance details and the Asset Identifiers consistent across multiple shielded pools. It also separates the issuance authority from the spend authority, allowing for the potential transfer of issuance authority without compromising the spend authority.
The Custom Asset is described via a combination of the issuer identifier and an asset description string, to preclude the possibility of two different issuers creating colliding Custom Assets.
The requirement of at least one OrchardZSA Action Group in the presence of an issue bundle is both to allow for the computation of the field of the issue notes, as well as to prevent replay attacks. If a transaction includes only an issue bundle, the SIGHASH transaction hash would be computed solely based on the issue bundle. A duplicate bundle would have the same SIGHASH transaction hash, potentially allowing for a replay attack.
Hash of the asset description
In an earlier version of this ZIP, the asset description was a direct component of the Asset Identifier, and was stored on-chain in each issuance transaction. The Asset Identifier and issuance transactions now instead include a collision-resistant hash of the asset description, for the following reasons:
A hash output (32 bytes per Issue Action) incurs lower average bandwidth costs in issuance transactions than the asset description (previously up to 512 bytes).
The asset description can be longer than 512 bytes without incurring chain costs.
Including an asset description byte string directly in issuance transactions does not ensure that the "user-visible" asset description is consensus-visible, because the byte string could itself be a hash of another off-chain description (even if the consensus rules had required it to be a Unicode string instead of only recommending it).
The lack of key rotation in this issuance protocol means that it is not sufficient to mark an as trusted and then accept whatever asset descriptions are issued by it. Each Asset Identifier needs to be independently verified, which requires some out-of-band protocol that can also convey the corresponding asset description.
If issuance transactions include the asset descriptions directly, wallets will discover them during scanning. This is an "attractive nuisance" because it would result in wallets being more likely to expose the asset description directly to users without any verification that the received asset has the value that a user might expect from that description. By instead using a collision-resistant hash of an asset description, wallets are forced to look up the corresponding asset description when a payment is received in an unknown asset. That lookup can be mediated by a trusted party or common trusted registry of known assets, or else will need to be approved directly by a user who can personally assert their interest in that specific asset.
Rationale for Global Issuance State
It is necessary to ensure that the balance of any issued Custom Asset never becomes negative within a shielded pool, along the lines of ZIP 209 [8]. However, unlike for the shielded ZEC pools, there is no individual transaction field that directly corresponds to both the issued and burnt amounts for a given Asset. Therefore, we require that all nodes maintain a record of the current amount in circulation for every issued Custom Asset, and update this record based on the issuance and burn transactions processed. This allows for efficient detection of balance violations for any Asset, in which case we specify a consensus rule to reject the transaction or block.
We limit the total issuance of any Asset to a maximum of . This is a practical limit that also allows an issuer to issue the complete supply of an Asset in a single transaction.
Nodes also need to reject transactions that issue Custom Assets that have been previously finalized. The map allows nodes to store whether or not a given Asset has been finalized.
Concrete Applications
Asset Features
By using the boolean and the burning mechanism defined in [10], issuers can control the supply production of any Asset associated to their issuer keys. For example,
by setting from the first issuance action for that Asset Identifier, the issuer is in essence creating a one-time issuance transaction. This is useful when the max supply is capped from the beginning and the distribution is known in advance. All tokens are issued at once and distributed as needed.
Issuers can also stop the existing supply production of any Asset associated to their issuer keys. This could be done by
issuing a last set of tokens of that specific , for which , or by
issuing a transaction with a single note in the issuance action pertaining to that , where the note will contain a . This can be used for application-specific purposes (NFT collections) or for security purposes to revoke the Asset issuance (see Security and Privacy Considerations).
The issuance and burn mechanisms can be used in conjunction to determine the supply of Assets on the Zcash ecosystem. This allows for the bridging of Assets defined on other chains.
Furthermore, NFT issuance is enabled by issuing in a single bundle several issuance actions, where each corresponds to at the fundamental unit level. Issuers and users should make sure that for each of the actions in this scenario.
Modifications relative to ZIP 244 [18]
Relative to the sighash algorithm defined in ZIP 244, the sighash algorithm that applies to v6 transactions differs by including the issuance bundle components within the tree hash. See ZIP 246 [19] for details.
Changes to ZIP 317 [20]
The conventional fee in ZEC is altered to take into account both the presence of issuance actions within a transaction, and the creation of new Custom Assets within the global chain state. See the Fee calculation section of ZIP 317 [21] for details.
Rationale for paying fees in ZEC
Click to show/hide
We choose to maintain the native ZEC Asset as the primary token for the Zcash blockchain, similar to how ETH is needed for ERC20 transactions to the benefit of the Ethereum ecosystem.
An alternative proposal for the OrchardZSA fee mechanism that was not adopted was to adopt a new type of fee, denominated in the custom Asset being issued or transferred. In the context of transparent transactions, such a fee allows miners to “tap into” the ZSA value of the transactions, rather than the ZEC value of transactions. However when transactions are shielded, any design that lifts value from the transaction would also leak information about it.
Security and Privacy Considerations
Displaying Asset Identifier information to users
Wallets need to communicate the names of the Assets in a non-confusing way to users, since the byte representation of the Asset Identifier would be hard to read for an end user. Possible solutions are provided in the Specification: Asset Identifier, Asset Digest, and Asset Base section.
Issuance Key Compromise
The design of this protocol does not currently allow for rotation of the issuance validating key that would allow for replacing the key of a specific Asset. In case of compromise, the following actions are recommended:
If an issuer identifier is compromised, the boolean for all the Assets issued with that key should be set to ; then the issuer should change to a new issuance authorizing key (hence a new issuer identifier), and issue new Assets, each with a new .
Bridging Assets
For bridging purposes, the secure method of off-boarding Assets is to burn an Asset with the burning mechanism in ZIP 226 [10]. Users should be aware of issuers that demand the Assets be sent to a specific address on the Zcash chain to be redeemed elsewhere, as this may not reflect the real reserve value of the specific Asset.
Other Considerations
Implementing Zcash Nodes
Although not enforced in the global state, it is RECOMMENDED that Zcash full validators keep track of the total supply of Assets as a mutable mapping from to in order to properly keep track of the total supply for different Asset Identifiers. This is useful for wallets and other applications that need to keep track of the total supply of Assets.
Test Vectors
LINK TBD
Reference Implementation
LINK TBD
LINK TBD
Deployment
TBD