ERC-8426 is an Ethereum standard that lets an NFT contract say "this token has a pass". Wallets and marketplaces can find it, add it to Apple Wallet or Google Wallet, and know when it needs refreshing. ERC8426 is the first token built on it.
Three small pieces on chain. The rest happens off it.
ERC-8426 doesn't put passes on Ethereum. It adds one view function and two events to an ERC-721 contract, then sets the rules for the server those point to. Pass generation, signing and push delivery stay with whoever issues the pass.
Discovery
Where's the pass?
The contract exposes passURI(tokenId). It returns a URL for that token's pass manifest, a small JSON file that lists how to get the pass on each platform.
Advertised through ERC-165 with interface id 0xef5f1e71
The URL is the lasting handle, acquisition links can be short-lived
When something about a pass changes, most often because the token moved, the contract emits an event. Issuers and indexers watch for it and push the new version to the phone.
A pass can carry buttons that change things. Holding the pass is never enough to press them. Every action needs a signed, single-use challenge and a fresh on-chain ownership read.
Sign-In with Ethereum (ERC-4361) is the suggested format
Works for normal wallets, ERC-1271 and ERC-6492 accounts
// checked at request time, never cachedownerOf(tokenId) == signer
How it works
From a token to a card on the lock screen.
This is the path a wallet app or marketplace follows when someone taps "add to wallet" on an ERC-8426 token.
Detect
The app calls supportsInterface(0xef5f1e71). True means the contract speaks ERC-8426.
Resolve
It calls passURI(tokenId) and fetches the JSON manifest at that address.
Prove
For a gated pass, the server answers 401 with a challenge. The holder signs it and the server reads ownerOf.
Acquire
The manifest's formats give an Apple .pkpass link and a Google save link. The phone adds the pass.
Refresh
On transfer the contract emits PassUpdate. The issuer rotates links and pushes the new pass.
What sits on Ethereum
One view function, two events and an ERC-165 answer. Nothing about the pass itself, and no personal data.
passURIPassUpdateBatchPassUpdatesupportsInterface
What sits with the issuer
The manifest, the signed pass files, push registrations, challenges and the ownership checks. Any server that follows the rules can be the issuer.
manifest.json.pkpasssave linkchallenge
Interface
The whole on-chain surface.
Two interfaces. The first is required. The second is optional and lets a contract publish which platform signer its passes should carry, so a wallet can tell a genuine pass from a copy.
A pass is a bearer card. It proves nothing on its own.
Anyone can screenshot a pass or forward a link. So ERC-8426 never lets possession of a pass authorize anything. The standard defines two ways to hand passes out, and one floor every action has to clear.
Public configuration
Open manifest
Anyone can read the manifest and add the pass. Fits art, collectibles and anything where seeing the pass is harmless.
Acquisition links aren't proof of anything
The manifest may also be mirrored into tokenURI metadata
Actions on the pass still need the full authorization floor
Gated configuration
Holders only
A request without proof gets a 401 that points to a challenge. The holder signs it, and each entitled account gets its own links.
Links rotate on transfer, or on a new owner's first claim
Fits tickets, memberships and anything with value
Clients send the proof in request headers
The authorization floor
Any action a pass can trigger needs both checks, every time. Each one covers a gap the other leaves open: rotating links doesn't stop a forwarded link, and a fresh owner read alone doesn't stop a forwarded link while the owner hasn't changed.
For custodial or email-onboarded products there's a narrower capability configuration, where an unguessable link can stand in for the signature. It's bound to one token, action and account, can't transfer, burn or approve, and the fresh ownership read still applies. The standard says plainly that forwarding isn't prevented in this mode.
1Control proof
A signed challenge naming the chain, contract, token, action and verifier, with a single-use nonce and an expiry. Valid for EOAs, ERC-1271 and ERC-6492 accounts.
2Fresh ownership read
An on-chain check of the current owner at request time, ideally at the latest block. Never served from a cache.
Refusal code
Status
When
proof_required
401
A gated request came without a control proof
nonce_invalid
401
The challenge was used before, expired or never issued
not_owner
403
The signer doesn't hold the token right now
rate_limited
429
Too many requests, retrying later can help
read_failed
503
The server couldn't read the chain, so it refused rather than guess
Checker
Does a contract speak ERC‑8426?
Paste any ERC-721 contract. This reads the chain directly from your browser: it asks for both interface ids, calls passURI for the token you pick, and tries to load the manifest it points to.
result
Enter a contract address and press Check contract. Nothing is sent from your wallet, these are read-only calls to a public Ethereum node.
The token
ERC8426, the first token on ERC‑8426.
A standard needs a first implementation people can hold. ERC8426 carries the standard's name and answers its interface, so it doubles as a live reference that wallets and marketplaces can test against.
$ERC8426
The token contract reports support for 0xef5f1e71, returns a manifest from passURI, and emits PassUpdate when a token moves, so the pass on the old holder's phone goes stale and the new holder's goes live.
$ERC8426pending
Network
Ethereum
Interface
0xef5f1e71
Pass
Apple, Google
Sign a pass challenge
This builds the kind of Sign-In with Ethereum message an ERC-8426 issuer sends before a pass action, and asks your wallet to sign it. Signing is free and moves nothing.
The challenge names the token, the action, a one-time nonce and a five minute expiry.
Security
What the standard asks issuers to watch for.
Bearer artifacts
Passes can be copied. Possession must never authorize an action.
Bounded freshness
A reorg or a lagging node can briefly let a sold token act. Issuers should read from current, trusted nodes.
Leaked stores
A dump of the issuer's database shouldn't hand out working links or capabilities.
Push fan-out
Device registrations for updates need limits so one token can't be used to flood phones.
Approvals after a sale
Authority granted from a token-controlled account can outlive the sale. Refuse it or revoke it on transfer.
Stale, not gone
Old passes should stay reachable so their holders can see that the content is out of date.
FAQ
Questions.
Who wrote ERC-8426?
Hunt (@huntclubhero), in August 2026. It's discussed on Ethereum Magicians and its text is CC0, so anyone can build on it.
Do I need a crypto wallet on my phone to use a pass?
Not to carry it. The pass lives in Apple Wallet or Google Wallet like any boarding pass. You need your Ethereum wallet when an issuer asks you to prove you hold the token, for a gated pass or an action.
Can someone use my pass if they copy it?
They can show a copy, but they can't act with it. Every action needs a fresh signature from the current holder and an on-chain ownership check.
What happens to my pass when I sell the token?
The contract emits PassUpdate. The issuer rotates the links and pushes an update, so your pass shows it's out of date and the buyer can claim a fresh one.
Does it work with ERC-1155?
ERC-8426 is written for ERC-721 and leaves ERC-1155 out of scope.
Is there code I can start from?
Yes. The standard links a CC0 reference contract and server, and there's an open-source SDK with contracts, an issuer, Apple and Google delivery, a client, React hooks and a conformance suite.
Where's the $ERC8426 contract?
0x53c7aafd56922c89d7456f282d961d7d6e6dbd51 on Ethereum. It's also shown under the main buttons, in the token section and in the footer.
Everything about ERC-8426 and the $ERC8426 token, for people who hold passes, teams who want to ship one, and wallets that want to show them. Start with the overview, or jump to the part you need.
ERC-8426, Wallet Pass Extension for NFTs, is an Ethereum standard that lets an ERC-721 contract advertise that its tokens can be delivered as native mobile wallet passes: the cards that live in Apple Wallet on iPhone and Google Wallet on Android, next to boarding passes and loyalty cards.
The standard is deliberately small. On chain it adds one view function, passURI(tokenId), and two events, PassUpdate and BatchPassUpdate. Everything else, building the pass, signing it for Apple or Google, pushing updates to phones and checking who is allowed to do what, happens off chain at the address the contract points to. ERC-8426 sets the rules for that address so that every wallet, marketplace and issuer can work with every contract the same way.
It covers three things:
DiscoveryHow an app finds out a token has a pass, and where to get it.
FreshnessHow an app learns that a pass is out of date and needs replacing.
AuthorizationWhat has to be true before a pass is allowed to change anything.
It was proposed in August 2026 by Hunt (@huntclubhero), is discussed on Ethereum Magicians, and its text is CC0. $ERC8426 is the first token built on it.
Why it exists
Most people never open a crypto wallet app. Almost everyone opens the wallet app that came with their phone. It already holds tickets, memberships and cards, it shows them on the lock screen at the right moment, and it updates them in the background. That makes it a natural place for an NFT that does something in the real world: an event ticket, a club membership, a game pet, a stored value card.
Until ERC-8426, every team that wanted this built a private bridge between its contract and Apple's or Google's pass systems. Wallets and marketplaces had no way to know which tokens had passes, no shared way to fetch them, and no common rule for keeping them in step with the chain. Each bridge also had to solve the same security problem alone: a pass is just a file, and files get copied.
ERC-8426 turns that into one shared seam. A contract states that it supports passes. An app that understands the standard can then offer "add to wallet" for any such token, without knowing anything about the project behind it.
Key terms
Pass
A card in Apple Wallet or Google Wallet. For Apple it's a signed .pkpass file. For Google it's an object saved through a save link.
Issuer
The server that builds, signs and serves passes for a contract, and checks proofs before it acts.
Manifest
The small JSON document that passURI resolves to. It lists how to get the pass on each platform.
Acquisition URL
A link in the manifest that actually delivers the pass, one per platform.
Control proof
A signed, single-use challenge showing that a request comes from a particular account.
Fresh ownership read
A check of the token's current owner on chain, made at the moment of the request.
Public / gated
The two ways an issuer can hand out passes: to anyone, or only to proven holders.
Capability URL
An unguessable link that grants something on its own. Allowed only in tightly limited cases.
On chain and off chain
The line between the two is the most important design choice in ERC-8426.
Manifest, pass files, save links, challenges, nonces, push registrations
Who can see it
Everyone, forever
Whoever the issuer allows
Personal data
None
Device tokens for push, kept by the issuer
Changes
Only by the contract's own logic
Any time, signalled by events
Because passURI is a public view, anyone can call it. Any privacy or access control has to be enforced by the server behind the URL, never by hoping the URL stays secret.
Holders
Getting a pass
If you hold a token whose contract supports ERC-8426, a wallet or marketplace that understands the standard can show an add to wallet option next to it. The exact button depends on the app, but the steps are the same.
Open the token in an app that supports ERC-8426, on your phone or computer.
Prove it's yours if the pass is gated. Your Ethereum wallet shows a sign-in message naming the token. Signing is free and sends nothing.
Choose your platform. On an iPhone you get the Apple pass, on Android the Google one.
Add it. Your phone shows a preview of the card. Confirm and it joins your other passes.
After that, the pass behaves like any other card in your phone's wallet. It can show on the lock screen, update in the background and be shared or removed like a normal pass.
What's on a pass
The issuer decides the design. ERC-8426 doesn't fix the layout, only how the pass is found and kept fresh. A typical pass shows the collection name and logo, the token's artwork, the token number, a short label for the holder, and any fields that matter for its use: a seat and date for a ticket, a tier for a membership, a balance for a stored value card.
Some passes include buttons or links that do something, like checking in, claiming a reward or refreshing data. Those are covered in Pass actions.
Selling or sending
When a token moves, the contract emits PassUpdate for it. Issuers watch for that event. When they see it they rotate the links tied to the old holder and push an update, so the pass on the seller's phone shows that it's out of date. The buyer can then add a fresh pass of their own.
The old pass isn't deleted. The standard asks issuers to keep superseded passes reachable so the person holding one can see that it's stale, rather than having a card silently stop working.
Remember: deleting the pass from your phone doesn't affect the token, and keeping the pass after a sale gives you nothing. The token on Ethereum is what counts.
Pass actions
An action is anything a pass can trigger that changes something: checking in at a door, redeeming a perk, topping up a balance. ERC-8426 sets a floor for all of them: before an action runs, the issuer has to see a fresh signature from the account that holds the token and confirm on chain that it still holds it.
So when you press a button on a pass, expect your Ethereum wallet to ask you to sign a short message. Read it. It should name the token, the action, the site asking and an expiry a few minutes away.
Staying safe
Never type your recovery phrase anywhere to get a pass. No part of ERC-8426 needs it.
Read sign-in messages. A pass challenge names one token and one action. If a request asks to approve, transfer or sign something you don't understand, decline it.
Treat a pass like a printed ticket. Anyone can copy it, but a copy can't act, because actions need your signature.
Check the contract. The $ERC8426 address is published on this site and on X. Use the checker to confirm any contract supports the standard.
Contracts
The interface
An ERC-8426 contract is an ERC-721 contract that also implements IERC721WalletPass and says so through ERC-165.
That's all a contract has to add. It must return true from supportsInterface(0xef5f1e71), alongside the usual ERC-721 and ERC-165 ids.
Interface ids
Interface
Id
How it's derived
IERC721WalletPass
0xef5f1e71
Selector of passURI(uint256)
IERC721WalletPassIssuer
0x470be7e9
Selector of passIssuer()
ERC-721
0x80ac58cd
Required base
ERC-165
0x01ffc9a7
Required base
Events don't count toward an ERC-165 id, which is why the main id equals the single function's selector. In Solidity you can write type(IERC721WalletPass).interfaceId and get the same value.
When to emit events
Events are how the outside world learns a pass is stale. Emit them whenever anything that a pass shows, or anything that decides who may use it, changes.
Transfers. Emit PassUpdate(tokenId) on every transfer, including mints and burns. This is the one nearly every contract needs.
Token data. If the pass shows on-chain values like a level, a balance or an expiry, emit when they change.
Rentals and roles. If someone other than the owner can use the token, for example an ERC-4907 user, emit when that changes.
Collection-wide changes. A new design or a new issuer affects many tokens. Emit BatchPassUpdate(fromTokenId, toTokenId). The range is inclusive at both ends.
Emitting too often is cheap and harmless. Missing an event leaves stale passes on phones.
passURI rules
It returns a URL for the token's manifest. In practice this is an https URL, often a base string plus the token id.
It's the lasting handle. Acquisition links inside the manifest can expire or rotate. passURI itself should keep working.
It's public. Anyone can call it, so it must never contain secrets or per-holder tokens.
For a token that doesn't exist, revert as tokenURI would, so clients don't fetch manifests for nothing.
The issuer interface
A second, optional interface lets a contract commit to the platform identity its passes are signed under, so a wallet can tell a genuine pass from one made by someone else.
If you implement it, return true for 0x470be7e9 as well, and keep the value in step with the identity in your manifests.
Example contract
A minimal implementation on OpenZeppelin's ERC-721. It serves every token's manifest from one base URL and emits PassUpdate on every mint, transfer and burn.
MyPassCollection.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {IERC721WalletPass} from "./IERC721WalletPass.sol";
contract MyPassCollection is ERC721, IERC721WalletPass {
string private _passBase;
constructor(string memory passBase) ERC721("My Pass", "PASS") {
_passBase = passBase;
}
function passURI(uint256 tokenId) external view returns (string memory) {
_requireOwned(tokenId);
return string.concat(_passBase, Strings.toString(tokenId));
}
function supportsInterface(bytes4 id) public view override returns (bool) {
return id == type(IERC721WalletPass).interfaceId || super.supportsInterface(id);
}
function _update(address to, uint256 tokenId, address auth)
internal override returns (address from)
{
from = super._update(to, tokenId, auth);
emit PassUpdate(tokenId);
}
}
Hooking _update covers mints, transfers and burns in one place. The open-source ERC-8426 SDK ships a tested base contract that does the same, plus examples for tickets, memberships, rentals and stored value cards.
Manifest version. Currently 1. Clients ignore versions they don't know.
formats
Yes
Platform key to https acquisition URL. At least one entry. apple and google are defined. Clients ignore keys they don't know.
updatedAt
No
Unix time of the last change, so clients can tell old from new.
issuer
No
Platform identities, such as the Google issuer id, a wallet can compare with what it receives.
Serving it
Serve it as application/json. Clients shouldn't act on a manifest with a media type they don't expect.
Send CORS headers on the manifest, the challenge endpoint and refusal responses, so browser-based wallets and sites can read them.
Use https for every acquisition URL.
In the gated configuration, answer unproven requests with 401 and a pointer to the challenge endpoint instead of a manifest.
Mirroring into metadata
A contract may copy the manifest into the token's tokenURI metadata so marketplaces that only read metadata still find it. Only do this in the public configuration. In a gated setup the manifest belongs to the holder, and metadata is visible to everyone.
Issuers
What an issuer does
The issuer is the server at the other end of passURI. One issuer can serve one contract or many. Its jobs:
Serve manifests for every token, in the public or gated configuration.
Build and sign passes: .pkpass bundles for Apple, pass objects and save links for Google.
Issue challenges and check proofs before handing out gated passes or running actions.
Read the chain at request time to confirm ownership.
Watch events and push updates to registered devices when a pass goes stale.
ERC-8426 leaves the internals to you: language, hosting, storage and design are your call. The SDK's issuer package runs on Next.js, Hono, Workers, Bun, Deno, Node and Express if you'd rather not start from nothing.
Public configuration
The manifest is open to anyone who asks. Good for art, collectibles and anything where showing the pass harms no one.
Acquisition URLs aren't proof of ownership. Treat them as hygiene only.
Anyone may add the pass, including people who don't hold the token.
Only holders get the pass. Good for tickets, memberships and anything with value.
A client fetches the manifest without proof and gets 401 with a reference to the challenge endpoint.
It requests a challenge, has the holder sign it, and retries with the proof attached.
The issuer checks the signature, burns the nonce and reads ownerOf on chain.
If everything matches, it returns a manifest with acquisition URLs made for that account.
Link rotation
Acquisition URLs should be capability URLs: long, random and unguessable. In the gated configuration they're issued per entitled account and rotate when the token transfers, or when a new owner claims for the first time. The old links stop delivering current passes. Rotation limits how long a leaked or forwarded link is useful, but it doesn't replace the authorization checks.
Apple and Google
Apple Wallet
Passes are .pkpass bundles signed with a pass type certificate from an Apple developer account. Updates go through the PassKit web service: devices register for a pass, the issuer pings them through APNs, and they fetch the new version.
Google Wallet
Passes are objects under a class in the issuer's Google Wallet account. A save link adds the object to a user's wallet. Updating the object on Google's side updates every saved copy.
The manifest hides this difference from clients. They pick the format for the platform they're on and follow the link.
Pushing updates
When a PassUpdate or BatchPassUpdate lands, the issuer rebuilds the affected passes and pushes them. Keep device registrations bounded. A single token shouldn't be able to register an unlimited number of devices, or it becomes a way to flood phones with pushes.
Authorization
The two checks
A pass is a bearer artifact: whoever has the file can show it. So ERC-8426 never lets possession of a pass authorize anything. Every state-changing action, and every gated delivery, needs both of these:
1. Control proof
A signed, single-use, time-limited challenge from the account making the request.
2. Fresh ownership read
An on-chain check, at request time, that this account holds the token.
They cover different gaps. A fresh read alone doesn't stop someone forwarding a working link while the owner hasn't changed. A signature alone doesn't stop a seller from using an old signature after the sale. Together they mean only the current holder, acting now, gets through.
Control proof
The challenge the holder signs must bind:
the chain, contract and token id
the action being authorized
the verifier's identity, so a signature for one issuer can't be replayed at another
the account claiming control
a single-use nonce, burned on first use
an expiry, kept short
Challenge message
Sign-In with Ethereum (ERC-4361) is the recommended format. Wallets already know how to display it clearly. A pass challenge looks like this:
ERC-4361 challenge
issuer.example wants you to sign in with your Ethereum account:
0x1234...abcd
Authorize pass action "claim" for token #1.
URI: https://issuer.example
Version: 1
Chain ID: 1
Nonce: k3v9q2m8x1p7
Issued At: 2026-11-01T12:00:00.000Z
Expiration Time: 2026-11-01T12:05:00.000Z
Resources:
- eip155:1/erc721:0xContract/1
The domain must match the issuer. The resource line names the exact token in CAIP-19 form.
Signature types
Account
How to verify
Regular wallet (EOA)
Recover the signer from the message and compare
Smart account
Call isValidSignature on the account, as in ERC-1271
Not yet deployed smart account
Use the ERC-6492 wrapper to verify before deployment
Fresh ownership read
Read ownerOf(tokenId) at request time, ideally at the latest block, from a node you trust. Never serve it from a cache. If the read fails, refuse with read_failed rather than guessing.
Freshness is bounded, not perfect. A chain reorganization or a node that's a few blocks behind can briefly let a token that was just sold still act. Keep that window small and know it exists.
Capability configuration
Some products can't ask for a signature on every action, for example custodial apps or ones where users sign up with email. For them, ERC-8426 allows a capability URL to stand in for the control proof, but only when all of these hold:
The URL is bound to one token, one action and one account.
It rotates on transfer and whenever the owner asks.
The action can't transfer, burn, approve or change who is entitled.
Repeating the action has a bounded, documented effect.
The fresh ownership read still applies on every use.
The standard is upfront that this mode does not stop forwarding. A link passed to someone else works for them while the owner stays the same. The conditions above make sure the damage from that is small and known.
Refusal responses
When an issuer says no, it answers with JSON and a code clients can act on.
Code
Status
Meaning
Retry helps?
proof_required
401
No control proof was sent
Yes, after signing
nonce_invalid
401
Nonce reused, expired or unknown
Yes, with a new challenge
not_owner
403
The signer doesn't hold the token now
No
rate_limited
429
Too many requests
Yes, later
read_failed
503
The chain couldn't be read
Yes, later
Integrations
Wallets and marketplaces
Detect. Call supportsInterface(0xef5f1e71) on the token's contract.
Resolve. Call passURI(tokenId) and fetch the manifest. Ignore unknown versions.
Prove if asked. On 401, fetch the challenge, have the user sign it, retry with the proof.
Offer the right button. Show the Apple link on iOS and the Google link on Android.
Watch. Listen for PassUpdate and BatchPassUpdate and refresh what you show.
Only ask users to sign challenges that match the token and action they asked for. A client that signs whatever an issuer sends defeats the point.
Client code
Detection and resolution need nothing but two JSON-RPC calls and a fetch. This is the same logic the checker on the home page runs.
detect.js
const RPC = "https://ethereum-rpc.publicnode.com";
async function call(to, data) {
const r = await fetch(RPC, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_call", params: [{ to, data }, "latest"] })
});
return (await r.json()).result;
}
const pad = (hex) => hex.replace(/^0x/, "").padStart(64, "0");
export async function passFor(contract, tokenId) {
// supportsInterface(0xef5f1e71)
const ok = await call(contract, "0x01ffc9a7" + "ef5f1e71".padEnd(64, "0"));
if (BigInt(ok) !== 1n) return null;
// passURI(tokenId)
const raw = (await call(contract, "0xef5f1e71" + pad(BigInt(tokenId).toString(16)))).slice(2);
const len = parseInt(raw.slice(64, 128), 16);
const uri = decodeURIComponent(raw.slice(128, 128 + len * 2).replace(/../g, "%$&"));
const res = await fetch(uri, { headers: { accept: "application/json" } });
if (res.status === 401) return { uri, gated: true };
return { uri, manifest: await res.json() };
}
Indexers
Index the two events alongside transfers. A PassUpdate topic plus an indexed token id makes it cheap to answer "which passes changed since block N". For BatchPassUpdate, expand the inclusive range on your side. Record the result of supportsInterface(0xef5f1e71) per contract so apps can filter for pass-enabled collections.
Security
Threats and answers
Risk
What the standard asks
Copied passes
Possession never authorizes an action. Every action needs a proof and a fresh read.
Replayed signatures
Single-use nonces, short expiries, verifier identity in the message.
Forwarded links
Rotation on transfer, plus the authorization floor. In capability mode, bounded effects.
Reorgs and lagging nodes
Read at the latest block from trusted nodes. Accept that a short window exists.
Leaked issuer database
Store links and capabilities so a dump doesn't yield working ones, for example hashed.
Push flooding
Cap device registrations per pass.
Approvals after a sale
Authority granted from token-controlled accounts can outlive a sale. Refuse it, or revoke it on transfer.
Silent breakage
Keep superseded passes reachable so holders see they're stale.
Launch checklist
supportsInterface(0xef5f1e71) returns true
PassUpdate fires on mint, transfer and burn
passURI reverts for tokens that don't exist and contains no secrets
Manifest served as application/json with CORS headers
Every acquisition URL is https and unguessable
Challenges are single-use, expire within minutes and name your domain
Signatures verified for EOAs, ERC-1271 and ERC-6492
Ownership read live on every request, never cached
Refusals use the standard codes
Device registrations capped, stale passes kept reachable
Run the SDK's conformance suite against your contract and server
$ERC8426
The token
$ERC8426 is the first token built on ERC-8426, and it carries the standard's name. Its contract answers the interface, returns a manifest from passURI, and emits PassUpdate when a token moves, so wallets and marketplaces have a live contract to test their support against.
$ERC8426pending
Once the address is published here, you can paste it into the checker to see its interface answers and manifest for yourself.
Using the checker
The checker on the home page reads any contract on Ethereum or Base straight from a public node. It reports whether the contract is ERC-721, whether it supports ERC-8426 and the issuer interface, what passURI returns for the token you chose, and then tries to load that manifest.
If the manifest server doesn't send CORS headers, your browser blocks the read and the checker gives you a link to open it directly. A 401 means the pass is gated. Nothing in the checker uses your wallet.
Signing a challenge
The token section on the home page can build an ERC-4361 challenge for a token id and an action, and ask your wallet to sign it. It shows exactly what a holder sees before a pass action: the domain, the action, a nonce and a five minute expiry. Signing it is free, moves nothing, and isn't sent anywhere.
Reference
Glossary
APNs
Apple's push service, used to tell phones a pass changed.
CAIP-19
A way to name an asset across chains, like eip155:1/erc721:0x.../1.
CORS
Headers that let a web page read a response from another domain.
EOA
A regular Ethereum account controlled by a private key.
ERC-165
How a contract says which interfaces it supports.
ERC-1271
How smart accounts validate signatures.
ERC-4361
Sign-In with Ethereum, a readable message format for signing in.
ERC-4907
Rentable NFTs with a separate user role.
ERC-6492
Signature validation for smart accounts that aren't deployed yet.
.pkpass
Apple's signed pass bundle format.
Nonce
A random value that can be used only once.
Save link
Google's link that adds a pass object to a user's wallet.
FAQ
Do I need a crypto wallet app on my phone?
Not to carry a pass. You use your Ethereum wallet when an issuer asks you to prove you hold the token, which can happen on any device.
Is anything about me stored on chain?
No. The chain holds a URL and events. Device registrations for updates stay with the issuer.
Can the issuer change my pass?
Yes, passes are meant to update. What the issuer can't do is make a pass grant actions on its own: the authorization floor still applies.
What if the issuer goes offline?
Passes already on phones stay there, but they won't update and actions won't run. The token itself is unaffected.
Does it work with ERC-1155?
No. ERC-8426 is written for ERC-721 and leaves ERC-1155 out of scope.
Can one issuer serve many contracts?
Yes. The issuer is just a server. It reads whichever contracts it's set up for.
Which chains does it work on?
Any EVM chain. The challenge carries the chain id, and the checker on this site reads Ethereum and Base.
Where's the $ERC8426 contract address?
0x53c7aafd56922c89d7456f282d961d7d6e6dbd51 on Ethereum. It's also shown on the home page and in the footer.