-
Notifications
You must be signed in to change notification settings - Fork 7
ICRC-152: Standardizing Privileged Mint & Burn #156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
f7aa013
16a1bfb
d1b21a4
39b00f3
7ad7b94
4eec90b
2536650
38f722e
465698d
ad57946
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,388 @@ | ||||||||||||||||||||||||||
| # `ICRC‑152`: Privileged Mint & Burn API | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| | Status | | ||||||||||||||||||||||||||
| |:------:| | ||||||||||||||||||||||||||
| | Draft | | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ## Introduction & Motivation | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Most ICRC-based ledgers (e.g., ICRC-1, ICRC-2) treat minting and burning as | ||||||||||||||||||||||||||
| system-only operations that occur indirectly. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - Minting is represented as a transfer from the minting account. | ||||||||||||||||||||||||||
| - Burning is represented as a transfer into the minting account. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| This approach works for decentralized tokens but is insufficient for | ||||||||||||||||||||||||||
| administrator-controlled or regulated assets, such as: | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - Stablecoins, which must allow an issuer to adjust circulating supply. | ||||||||||||||||||||||||||
| - Real-World Asset (RWA) tokens, where compliance requires explicit | ||||||||||||||||||||||||||
| mint and burn actions. | ||||||||||||||||||||||||||
| - Other managed ledgers (NFTs, reward points, internal credits). | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Without a standardized API, integrators and tooling cannot reliably | ||||||||||||||||||||||||||
| distinguish user-initiated supply changes from privileged supply | ||||||||||||||||||||||||||
| management actions. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ICRC-152 addresses this gap by introducing: | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - Two privileged methods, `icrc152_mint` and `icrc152_burn`, callable only by authorized principals. | ||||||||||||||||||||||||||
| - A canonical mapping from method inputs to block `tx` fields, including optional metadata and caller tracking. | ||||||||||||||||||||||||||
| - Recording of these operations using the typed block kinds **defined in ICRC-122**: | ||||||||||||||||||||||||||
| `btype = "122mint"` for mints and `btype = "122burn"` for burns. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ## Overview | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ICRC-152 standardizes privileged supply management in ICRC-based ledgers. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Specifically, it defines: | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - **APIs** for minting and burning tokens under ledger authorization. | ||||||||||||||||||||||||||
| - **Canonical `tx` mapping** rules ensuring deterministic block content. | ||||||||||||||||||||||||||
| - **Use of ICRC-122 block kinds** to record privileged supply actions | ||||||||||||||||||||||||||
| (`btype = "122mint"` and `btype = "122burn"`). | ||||||||||||||||||||||||||
| - **Compliance reporting** through ICRC-10 methods. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| This allows wallets, explorers, and auditors to: | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - Reliably distinguish privileged supply changes from user-initiated transfers. | ||||||||||||||||||||||||||
| - Verify compliance with external requirements (e.g., MiCA). | ||||||||||||||||||||||||||
| - Interoperate across ledgers that adopt the same API and block semantics. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ## Dependencies | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| This standard does not introduce new block kinds. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - **ICRC-3** — Provides the block log format, hashing, certification, and rules | ||||||||||||||||||||||||||
| for canonical `tx` mapping. | ||||||||||||||||||||||||||
| - **ICRC-122** — Defines the typed block kinds used by this standard: | ||||||||||||||||||||||||||
| - `btype = "122mint"` (authorized mint block) | ||||||||||||||||||||||||||
| - `btype = "122burn"` (authorized burn block) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| A ledger implementing ICRC-152 MUST: | ||||||||||||||||||||||||||
| - Emit `122mint` for successful `icrc152_mint` calls and `122burn` for successful | ||||||||||||||||||||||||||
| `icrc152_burn` calls. | ||||||||||||||||||||||||||
| - Populate `tx.mthd` with namespaced values **introduced by this standard**: | ||||||||||||||||||||||||||
| `"152mint"` and `"152burn"`. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ## Common Elements | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| This standard inherits core conventions from **ICRC-3** (block log format, Value encoding, hashing, certification) and **ICRC-122** (typed block kinds). | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - **Accounts** | ||||||||||||||||||||||||||
| Encoded as ICRC-3 `Value` `variant { Array = vec { V1 [, V2] } }` where | ||||||||||||||||||||||||||
| `V1 = variant { Blob = <owner_principal_bytes> }` and optionally | ||||||||||||||||||||||||||
| `V2 = variant { Blob = <32-byte_subaccount_bytes> }`. | ||||||||||||||||||||||||||
| If no subaccount is provided, the array contains only the owner principal. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - **Principals** | ||||||||||||||||||||||||||
| Encoded as `variant { Blob = <principal_bytes> }`. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - **Timestamps** | ||||||||||||||||||||||||||
| Caller-supplied `created_at_time` is in **nanoseconds since Unix epoch**. | ||||||||||||||||||||||||||
| Encoded as `Nat` in ICRC-3 `Value` and **MUST** fit in `nat64`. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - **Blocks & Parent Hash** | ||||||||||||||||||||||||||
| Resulting blocks for these APIs use `btype = "122mint"` and `btype = "122burn"` (per ICRC-122). | ||||||||||||||||||||||||||
| Standard metadata (e.g., `phash`, `ts`) follows ICRC-3. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ## Methods | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ### `icrc152_mint` | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| This method allows a ledger controller (or other authorized principal) to mint | ||||||||||||||||||||||||||
| tokens. It credits the specified account, increases total supply, and records | ||||||||||||||||||||||||||
| the action on-chain. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #### Arguments | ||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||
| type MintArgs = record { | ||||||||||||||||||||||||||
| to : Account; | ||||||||||||||||||||||||||
| amount : nat; | ||||||||||||||||||||||||||
| created_at_time : nat64; | ||||||||||||||||||||||||||
| reason : opt text; | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| type MintError = variant { | ||||||||||||||||||||||||||
| Unauthorized : text; // caller not permitted | ||||||||||||||||||||||||||
| InvalidAccount : text; // target account invalid | ||||||||||||||||||||||||||
| Duplicate : record { duplicate_of : nat }; | ||||||||||||||||||||||||||
| GenericError : record { error_code : nat; message : text }; | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| icrc152_mint : (MintArgs) -> (variant { Ok : nat; Err : MintError }); | ||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #### Semantics | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| **Authorization** | ||||||||||||||||||||||||||
| - The method **MUST** be callable only by a **controller** of the ledger or other explicitly authorized principals. | ||||||||||||||||||||||||||
| - Unauthorized calls **MUST** fail with `Unauthorized`. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| **Effect (on success, non-retroactive)** | ||||||||||||||||||||||||||
| - **Credit** `amount` to `to`. | ||||||||||||||||||||||||||
| - **Increase** total supply by `amount`. | ||||||||||||||||||||||||||
| - **Append** a block with `btype = "122mint"`. | ||||||||||||||||||||||||||
| - The block’s top-level `tx` **MUST** be constructed **exactly** as in **Canonical `tx` Mapping** (keys, types, encodings), and embedded in the block. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| **Return value** | ||||||||||||||||||||||||||
| - On success, **MUST** return `variant { Ok : nat }` where the `nat` is the index of the created block. | ||||||||||||||||||||||||||
| - On failure, **MUST** return `variant { Err : MintError }`. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| **Deduplication & idempotency** | ||||||||||||||||||||||||||
| - The ledger **MUST** perform deduplication (e.g., using `created_at_time` and any implementation-defined inputs). | ||||||||||||||||||||||||||
| - If a duplicate is detected, the ledger **MUST NOT** append a new block and **MUST** return `Err(Duplicate { duplicate_of = <index> })`. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| **Error cases (normative)** | ||||||||||||||||||||||||||
| - `Unauthorized` — caller not permitted. | ||||||||||||||||||||||||||
| - `InvalidAccount` — malformed/invalid target account (e.g., minting account, anonymous principal, invalid subaccount bytes). | ||||||||||||||||||||||||||
| - `Duplicate { duplicate_of }` — a semantically identical transaction was already accepted. | ||||||||||||||||||||||||||
| - `GenericError { error_code, message }` — any other failure preventing a valid `122mint` block. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| **Clarifications** | ||||||||||||||||||||||||||
| - Optional fields **MUST be omitted** from `tx` if not supplied in the call (no null placeholders). | ||||||||||||||||||||||||||
| - Representation-independent hashing (ICRC-3) applies; field presence and values matter, not map ordering. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #### Canonical `tx` Mapping | ||||||||||||||||||||||||||
| A successful call to `icrc152_mint` produces a block of type `122mint`. | ||||||||||||||||||||||||||
| The `tx` field is derived deterministically as follows: | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #### Canonical `tx` Mapping (normative) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
| #### Canonical `tx` Mapping | |
| A successful call to `icrc152_mint` produces a block of type `122mint`. | |
| The `tx` field is derived deterministically as follows: | |
| #### Canonical `tx` Mapping (normative) | |
| #### Canonical `tx` Mapping (normative) | |
| A successful call to `icrc152_mint` produces a block of type `122mint`. | |
| The `tx` field is derived deterministically as follows: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed — collapsed into a single heading.
Copilot
AI
Apr 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The supported-standards example uses an ICRC-3 Value-style encoding (variant { Vec = ... } / variant { Text = ... }), but per ICRC-10 these methods return Candid vec record { name : text; url : text } (see ICRCs/ICRC-10/ICRC-10.md:13-16). Please update the example to the correct Candid shape, and ensure the URL matches this repo path (likely .../ICRCs/ICRC-152/ICRC-152.md).
| variant { Vec = vec { | |
| record { | |
| "name"; variant { Text = "ICRC-152" }; | |
| "url"; variant { Text = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-152.md" }; | |
| } | |
| }}; | |
| vec { | |
| record { | |
| name = "ICRC-152"; | |
| url = "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-152/ICRC-152.md"; | |
| } | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed — updated to use Candid vec record { name: text; url: text } format, and corrected the URL to include the /ICRC-152/ subdirectory.
Copilot
AI
Apr 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The mint call example passes to = [principal "..."], which looks like the ICRC-3 Value account encoding, but the method signature defines to : Account in Candid. In this repo Account is a Candid record { owner : principal; subaccount : opt blob } (e.g., ICRCs/ICRC-7/ICRC-7.did:3). Please rewrite the example to use the Candid Account record and a valid principal textual form (the hex-like string shown isn’t a valid Candid principal literal).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed — the method call example now uses the Candid Account record format (record { owner = principal "..."; subaccount = null }) with a valid principal textual form.
Copilot
AI
Apr 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The block example encodes the block timestamp as variant { Nat64 = ... }, but the ICRC-3 Value type used in this repo does not define a Nat64 constructor (see ICRCs/ICRC-7/ICRC-7.did:6-13); it uses Nat. Please change the example to use variant { Nat = ... } (keeping the "must fit nat64" constraint if desired).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed — changed all Nat64 to Nat in the block examples. The constraint that values must fit in nat64 is documented in the canonical mapping table.
Copilot
AI
Apr 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the tx map example, amt and the caller-supplied ts are encoded as variant { Nat64 = ... }, but this repo’s ICRC-3 Value only supports Nat (no Nat64; see ICRCs/ICRC-7/ICRC-7.did:6-13). This also contradicts the canonical mapping table where amt/ts types are Nat. Please update these to variant { Nat = ... }.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed — changed Nat64 to Nat for both amt and ts in the mint tx map example.
Copilot
AI
Apr 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The burn call example passes from = [principal "..."], which doesn’t match the Candid Account record type used by ICRC ledgers in this repo (e.g., ICRCs/ICRC-7/ICRC-7.did:3 / ICRCs/ICRC-106/ICRC-106.md:75-78). Also, the principal string shown is hex-like and not a valid Candid principal literal. Please update the example to use a Candid Account record with a valid principal text form.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed — same as the mint example, now uses Candid Account record format with a valid principal.
Copilot
AI
Apr 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The burn block example encodes the block timestamp as variant { Nat64 = ... }, but the ICRC-3 Value type used in this repo does not define Nat64 (see ICRCs/ICRC-7/ICRC-7.did:6-13); it uses Nat. Please change this to variant { Nat = ... }.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed — changed Nat64 to Nat in the burn block timestamp.
Copilot
AI
Apr 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the burn tx map example, amt and the caller-supplied ts are encoded as variant { Nat64 = ... }, but this repo’s ICRC-3 Value only supports Nat (no Nat64; see ICRCs/ICRC-7/ICRC-7.did:6-13). Please update these to variant { Nat = ... } to match the canonical mapping.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed — changed Nat64 to Nat for both amt and ts in the burn tx map example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR description/title references ICRC-522 and
icrc522_mint/icrc522_burn, but this document defines ICRC-152 andicrc152_mint/icrc152_burn. Please align the PR metadata with the spec number and method names (or rename the spec if 522 was intended).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed — the PR metadata was stale from an earlier numbering. The spec is ICRC-152.