For developers / Tokens
Token list and address tags
One public repository decides which tokens carry the verified mark, which logo and name they show, and what label a contract gets instead of its address. Getting onto it is a pull request.
What the list is
Two files per network. tokenlist.json lists the reviewed tokens, in the standard Uniswap Token Lists format, so any wallet, DEX interface or aggregator can import it as it is. tags.json gives well-known contracts a readable label - a name, a category and a project - so an explorer can show "Pepper router" where it would otherwise show a hexadecimal address.
A listed token gets the verified mark, its logo, its name and its symbol on the explorer, on Pepper, in the Toolkit, on Names and in the Account page. A tagged contract reads by its label in transaction lists, on address pages and in search.
What the mark says, and what it does not
The verified mark says the token was reviewed and that its contract address is the right one for that name. It is not investment advice, not an endorsement and not an audit of the contract.
Nothing is listed automatically. A token launched with Pepper's token launcher is not added because it exists; it is added when someone opens a pull request and it meets the criteria.
Where it lives
The list lives in a public GitHub repository, github.com/PickleChain/token-list, with one folder per network:
| Folder | Holds |
|---|---|
| testnet/ | chain ID 78270the list the Pickle apps read today |
| mainnet/ | empty for nowthe mainnet list and tags are published in this folder when mainnet launches |
| schemas/ | tags.schema.jsonthe JSON Schema of tags.json |
| scripts/ | validate.mjsthe validator run by npm test and by CI |
Inside a network folder:
| Path | What it is |
|---|---|
| tokenlist.json | the tokensUniswap Token Lists format; every entry has chainId 78270 |
| tags.json | the address tagskeyed by checksummed contract address |
| logos/tokens/ | one logo per tokennamed after the token's checksummed address |
| logos/tags/ | project logosthat tags point to; several tags can share one |
The raw URLs, always the latest commit on main:
https://raw.githubusercontent.com/PickleChain/token-list/main/testnet/tokenlist.json https://raw.githubusercontent.com/PickleChain/token-list/main/testnet/tags.json
A token's logo can be a PNG or an SVG, so take the URL from the entry's logoURI (or a tag's logo) rather than assembling it from the address.
For a website, fetch the files server-side and serve them from your own origin instead of hot-linking raw.githubusercontent.com from visitors' browsers: it keeps their IP addresses away from a third party, stays clear of GitHub's rate limits and lets you keep the last good copy when GitHub is unreachable. In a wallet or a DEX interface, add the tokenlist.json raw URL as a custom token list.
How the Pickle apps use it
The explorer API is the only part of the Pickle stack that talks to GitHub for these files. It fetches both about every ten minutes, validates each file as a whole - shape, chain ID, checksums, duplicates - and keeps the last good copy in memory and on disk. A file that fails is rejected entirely and the previous one stays in service, so a bad commit can never blank a label or a logo. Every Pickle site then reads the explorer's copy from its own origin:
| Route | Serves |
|---|---|
| GET /api/tokenlist | tokenlist.json as last validated503 until a first good copy exists |
| GET /api/tags | tags.json as last validated |
| GET /api/tokenlogo/{address} | the token's logo bytes404 when the token is not listed or has no logo |
| GET /api/taglogo/{address} | the tag's logo bytes |
The routes are on https://explorer.picklechain.xyz, behind the explorer's CORS allowlist: they serve the Pickle sites. Your own application reads the raw files above.
About ten minutes after a pull request is merged, the new entry is on every Pickle app; with GitHub's own cache and the sites' caches in the way it can take up to twenty. A logo replaced under the same file name can take up to six hours, because logos are cached by URL.
Add a token
Check the criteria first: a pull request for a token that does not meet them is closed. Then, on your fork of the repository:
- Get the checksummed address. EIP-55 mixed case, not all lowercase. If yours is wrong, the validator prints the expected form.
- Add the logo to
testnet/logos/tokens/, named exactly after that address:testnet/logos/tokens/0x0000…dEaD.png(or.svg). It must follow the logo rules. - Append an entry to
tokensintestnet/tokenlist.json, as in the example below. - Bump the version of
tokenlist.json- adding a token is a minor bump, 1.4.2 becomes 1.5.0 - and settimestampto now, in ISO 8601 UTC. - Run the checks with
npm test. It needs Node 22 or later and nothing else: the validator has no dependencies, so there is nothing to install. - Open a pull request against
main. In its description, link a post from the project's own website or official account that names the contract address.
{
"chainId": 78270,
"address": "0x0000…dEaD",
"name": "Example Token",
"symbol": "EXM",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/PickleChain/token-list/main/testnet/logos/tokens/0x0000…dEaD.png",
"extensions": {
"website": "https://your-project.example",
"explorer": "https://explorer.picklechain.xyz/address/0x0000…dEaD"
}
}0x0000…dEaD stands for your full 42-character checksummed address; it is a placeholder, not a token.
| Field | Rule |
|---|---|
| chainId | 78270the network of the folder; anything else fails |
| address | EIP-55 checksummedunique in the list |
| name | 1-40 characterswhat the apps show beside the logo |
| symbol | 1-20 characters, no spacesunique in the list, case-insensitively |
| decimals | integer 0-255the value the contract's decimals() returns |
| logoURI | a raw URL into testnet/logos/tokens/the file named after the address, .png or .svg |
| tags | optionalids defined in the list's top-level tags, at most 10 |
| extensions | optionalat most 10 values, each a string, number, boolean or null |
The whole round trip on the command line:
# Fork and clone (or fork on the website and clone your fork): gh repo fork PickleChain/token-list --clone cd token-list git checkout -b add-exm # Logo, entry, version and timestamp, then: npm test git add testnet/tokenlist.json testnet/logos/tokens/ git commit -m "Add Example Token (EXM)" git push origin add-exm # ...and open the pull request on GitHub.
Logo rules
| Rule | Requirement |
|---|---|
| Format | PNG or SVGthe type is checked from the bytes, not from the extension |
| PNG size | exactly 256 x 256 pixels |
| File size | 100 KB at most |
| File name | <checksummed address>.png or .svgfor a token; letter case matters on GitHub |
| Location | the same network folder as the lista testnet list may only point at testnet/logos/ |
| Artwork | square, readable at 20 pixelstransparent or solid background; apps usually crop to a circle |
An SVG must be a plain drawing
No <script>, no event-handler attributes, no <foreignObject>, no external href or url(), no DOCTYPE. Only submit artwork you own or are allowed to use.
Every file under logos/ must be referenced by the list or the tags. A logo that nothing points to fails the checks, so remove it in the same pull request as its entry.
Add an address tag
Tags are for contracts that people meet in transactions: protocol contracts, routers, factories, pools, vaults, games, bridges. Personal wallets are never tagged. The project must be live on Pickle Chain, and the address must be checkable in the project's own documentation or deployment files.
- Add an entry to
tagsintestnet/tags.json, keyed by the checksummed address. - Optionally add a logo to
testnet/logos/tags/- same format rules as a token logo, any file name - and pointlogoat its raw URL. Several tags of one project can share one file. - Bump the version of
tags.jsonand itstimestamp, runnpm testand open the pull request.
"0x0000…dEaD": {
"name": "Example vault",
"category": "protocol",
"project": "Example",
"url": "https://your-project.example",
"logo": "https://raw.githubusercontent.com/PickleChain/token-list/main/testnet/logos/tags/example.png",
"note": "Holds deposits and pays out the weekly yield."
}| Field | Rule |
|---|---|
| name | 1-40 characters, unique in the fileshown instead of the address, so keep it short and specific |
| category | a key of categoriessee the list below |
| project | 1-40 charactersthe project the contract belongs to |
| url | an https:// link, or nullrequired: write null when there is none |
| logo | a raw URL into testnet/logos/tags/, or nullrequired: write null when there is none |
| note | optional, at most 200 characterswhat the contract does, in one sentence |
The categories defined today:
| Key | For |
|---|---|
| token | a token contractthe metadata and logo live in tokenlist.json; the tag gives it a label |
| protocol | core contractsfees, staking, burning, faucet, registry |
| bridge | the ETH bridgebetween Pickle Chain and its settlement layer |
| dex | Pepper exchange contractsfactories, routers, quoters and the token launcher |
| pool | a Pepper liquidity pool |
| toolkit | Toolkit contractsmultisend, locker, streams and the deploy factory |
| names | the Pickle Name Service |
| oracle | price feeds |
| arcade | the arcade bank and its games |
If none fits, propose a new category in the same pull request: a lowercase key of up to 20 characters, with a name and a description.
Update or remove an entry
- Change an entry - a name, a note, a website, the decimals - by editing it in place and bumping the patch version. Open the pull request from the token's team, as for an addition.
- Change a logo by replacing the file. Switching between PNG and SVG renames it, so update
logoURIand delete the old file. - Replace a contract by adding the new address. For a tag, keep the old entry and suffix its name with
(previous), so old transactions still read clearly. - Remove an entry by deleting it and its logo file, with a major version bump.
Maintainers can remove a token at any time - after an exploit, a rug pull, a move to a new contract or a misleading change of metadata.
Versions
Each file carries its own version, and the bump follows the Token Lists rules. CI enforces it against the base branch of the pull request, and a changed version needs a newer timestamp.
| Change | Bump |
|---|---|
| An entry removed | major1.4.2 becomes 2.0.0 |
| An entry added | minor1.4.2 becomes 1.5.0 |
| An entry changed | patch1.4.2 becomes 1.4.3 |
npm test # every list and logo, then the validator's own tests node scripts/validate.mjs --base origin/main # also the version bumps, as CI checks them
What review checks
Every pull request runs npm test and the version check in GitHub Actions, then a maintainer reviews it. A token is added when all of these hold:
- It is deployed on the network of that folder, and its source is verified or published.
- The pull request is opened or confirmed by the token's team, with a link to a post on the project's own website or official account that names the contract address.
- Its name and symbol do not imitate another token or project. A new PKL or WETH is refused.
- It has real use: liquidity on Pepper, holders or a live product - not a token launched a few minutes ago.
- The contract has no hidden mint, blacklist or fee switch the team has not disclosed.
A tag is added when the address is a contract, the project is live on Pickle Chain and the address can be checked in the project's own documentation or deployment files.
Common validation errors
npm test prints every problem, not just the first. The ones people meet most, and the fix:
| Message | Fix |
|---|---|
| is not EIP-55 checksummed (expected …) | use the address the message prints |
| logo file must be named after the checksummed address | rename the logo to the exact mixed-case address |
| referenced but missing (case matters on GitHub) | the file name and logoURI differ, often only in letter case |
| PNG is 512x512, it must be 256x256 | resize the image to 256 x 256 |
| … bytes, the limit is 102400 | compress it, or use an SVG |
| not referenced by this network's tokenlist.json or tags.json; remove it | delete the leftover logo, or fix the entry pointing to it |
| symbol "EXM" repeats tokens[3] | the symbol is taken; symbols are unique |
| the file changed but version stayed 1.4.2; bump it | bump the version - see Versions |
| this change needs a minor version bump | an addition is minor and a removal major; a patch is not enough |
| update timestamp when the version changes | set timestamp to the current UTC time |
| "logo" is required (use null for url or logo when there is none) | write "logo": null or "url": null instead of leaving the field out |
| category "vault" is not defined in categories | use an existing key, or add the category in the same pull request |
| SVG must not reference external resources | inline everything; remove external href and url() references |