Token standards
ICRC-3: the verifiable transaction history of ICP tokens
ICRC-3 standardises how a token ledger on the Internet Computer publishes its transaction history — and how anyone can check that history without trusting the server that sent it. It is what lets wallets and explorers show the past transactions of any compliant token in the same way.
Token data checked on-chain on October 30, 2026 · Sources at the end of the page
ICRC-3 in 30 seconds
- What it is: the standard for accessing a ledger’s block log, accepted by the NNS in proposal 128824.
- What it specifies: how to find the archive canisters, a generic block format that loses no information, a way to verify the log on the client side so it can be downloaded with fast query calls, and how new standards add their own transaction types.
- Why: ICRC-1 intentionally excludes “the block structure and the interface for fetching blocks”. ICRC-3 is that missing piece.
- Adoption: 88 of the 145 tokens listed on ICP Tokens announce ICRC-3 (on-chain, October 30, 2026). The ICP ledger itself does not.
The block log: a hash chain
The ledger records every transaction as a block. Each block stores the hash of its parent in a field called phash: the parent of block i is block i − 1, and block 0 has no parent. Change any old block and its hash changes, so the phash in the next block no longer matches — the chain breaks visibly.
┌─────────────────────────┐ ┌─────────────────────────┐
| Block i | | Block i+1 |
├─────────────────────────┤ ├─────────────────────────┤
◄──| phash = hash(Block i-1) |◄─────────| phash = hash(Block i) |
| ... | | ... |
└─────────────────────────┘ └─────────────────────────┘As a ledger grows, older blocks move to archive canisters. The ledger lists them, and tells the client which block ranges to fetch from which archive.
The Value type and its hash
Candid, the interface language of the Internet Computer, lets clients read data even when their schema lacks some fields — useful for upgrades, but it means a client may silently drop data. For verification that is not acceptable: the client must hash exactly what the ledger sent. So ICRC-3 serves every block as a fixed, generic type that never changes:
type Value = variant {
Blob : blob;
Text : text;
Nat : nat;
Int : int;
Array : vec Value;
Map : vec record { text; Value };
};Its hash is the Internet Computer’s representation-independent hash: blobs and texts are hashed as bytes, natural numbers as their LEB128 encoding and integers as signed LEB128, an array as the hash of its elements’ hashes, and a map as the hash of its key–value hashes sorted lexicographically. The specification links pseudocode and test vectors so every implementation computes the same hash.
How a client verifies the history
- Download the tip certificate with
icrc3_get_tip_certificate. It is signed through the Internet Computer’s certification and contains two values:last_block_indexandlast_block_hash. - Download blocks backwards, starting from
last_block_index. - Check the newest block against
last_block_hash, and every older block i against thephashstored in block i + 1.
Why this is clever
The four endpoints
| Endpoint | What it does |
|---|---|
icrc3_get_archives | Lists the archive canisters with the first and last block each one holds |
icrc3_get_blocks | Returns the total log length, the blocks the ledger still holds, and callbacks for archived ranges |
icrc3_get_tip_certificate | Returns the certificate and hash tree for the latest block index and hash |
icrc3_supported_block_types | Lists every block type (btype) the ledger can produce |
type GetBlocksArgs = vec record { start : nat; length : nat };
type GetBlocksResult = record {
log_length : nat; // total number of blocks
blocks : vec record { id : nat; block : Value }; // blocks still in the ledger
archived_blocks : vec record { // where to fetch the rest
args : GetBlocksArgs;
callback : func (GetBlocksArgs) -> (GetBlocksResult) query;
};
};Block types: 1xfer, 2approve and more
Every ICRC-3 block is a Map. It must contain phash (except the first block) and should contain btype, a unique name for the block type. Data entered by the user sits in the tx field (for example tx.amt, the amount); data set by the ledger sits outside it (for example ts, the time the block was added).
| btype | Older form (tx.op) | Operation | Required fields |
|---|---|---|---|
1xfer | xfer | ICRC-1 transfer | tx.from, tx.to |
2xfer | xfer | ICRC-2 transfer_from | tx.from, tx.to (tx.spender optional) |
2approve | approve | ICRC-2 approval | tx.from, tx.spender |
1mint | mint | New tokens created | tx.to |
1burn | burn | Tokens destroyed | tx.from |
- Transfers and approvals charge a fee. If the user set the fee, it is in
tx.fee; otherwise the ledger records it in a top-levelfeefield. tx.memoandtx.ts(fromcreated_at_time) appear when the user set them.- Older ledgers write the type in
tx.opinstead ofbtype. When both are present,btypewins. - Accounts are stored as an
Arraywith the owner’s bytes and, if present, the subaccount.
How other standards build on it
ICRC-3 is designed to be extended. A new standard that records its own operations must define its block schemas, and name them with its ICRC number followed by the operation — the way 1xfer belongs to ICRC-1. For example, the ICRC-107 draft adds a 107feecol block to record on-chain who receives transaction fees.
Who uses it, and why it matters to you
- Wallets can show your transaction history for any compliant token with one implementation, instead of one per ledger.
- Explorers and indexers can mirror a ledger’s history and prove it matches the certified tip. Many ledgers also run an index canister for per-account history; ICRC-106 tells clients where it is.
- Auditors and projects can check mints, burns and transfers block by block, which helps when verifying supply or treasury movements.
- You get a history that cannot be quietly rewritten: any change breaks the hash chain.
On ICP Tokens, swap data comes from ICPSwap; whale alerts check ICRC-1 ledger transfers. You can look up the ICPSwap swap history of any wallet in the wallet explorer.
Tokens that implement ICRC-3
88 of the 145 tokens listed on ICP Tokens return ICRC-3 from icrc1_supported_standards (checked on-chain on October 30, 2026, ordered by fully diluted market cap).
Show all 88 tokens ↓Show fewer ↑
ALICE
cICP
ICE
TCYCLES
MOTOKO
TAGGR
DCD
SNEED
NUA
SOON
GHOST
OHSHII
DVINITY
ICFC
YUKU
KONG
TACO
MAPTF
PIERRES
CHAI
STK
CLOWN
FUNNAI
NFIDW
DOLR
ANAL
ELNA
ckLINK
ALEX
IAMAI
SPOT
DAMONIC
BURN
SONIC
icUSD
AVCD
HOMELESS
TRAX
CONF
CTZ
DAO
TENDY
PUFFIN
EST
QUOKKA
PHASMA
GOLD
MOTOKOINS
sGLDT
BTON
CRUMB
PIKO
ENGINE
bone
AAA
ckPEPE
TORCH
CCAT
ICG
VILAGE
$UGLY
DARK
RAVEN
TOKO
What about ICP itself?
The ICP ledger (ryjl3-tyaaa-aaaaa-aaaba-cai) returned ICRC-1, ICRC-2 and ICRC-21 — not ICRC-3. You can still follow ICP’s price, pools and large trades on its token page.
FAQ
What is ICRC-3?
Why does ICRC-3 matter if ICRC-1 already has transfers?
How can a block log be verified?
What are archive canisters?
Does the ICP ledger support ICRC-3?
What do btype values like 1xfer and 2approve mean?
Sources
Everything on this page is checked against these primary sources. Token data was read on-chain on October 30, 2026.
- ICRC-3 specification — dfinity/ICRC-1
- NNS proposal 128824 (ICRC-3 accepted) — ICP Dashboard
- Hashing of Value: pseudocode and test vectors — dfinity/ICRC-1
- Internet Computer interface specification: certification
- ICRC-106 index canisters (draft) — dfinity/ICRC
- ICRC-107 fee management (draft) — dfinity/ICRC
Keep exploring
- Token standards on ICP →ICRC-1, -2, -3 and the extensions, chain-key and SNS tokens
- ICRC-1 →The base standard: accounts, transfers, fees
- ICRC-2 →Approve and transfer-from, used by DEXes
- All ICP token prices →Live prices, volume and liquidity of every listed token
- ICPSwap pools →Every active pool, sorted by 24h volume
- ICP wallets →Which wallets hold ICRC tokens
- Free chart widget →A live price chart of any token for your website