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:

FolderHolds
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:

PathWhat it is
tokenlist.jsonthe tokensUniswap Token Lists format; every entry has chainId 78270
tags.jsonthe 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:

text
https://raw.githubusercontent.com/PickleChain/token-list/main/testnet/tokenlist.json
https://raw.githubusercontent.com/PickleChain/token-list/main/testnet/tags.json
Read logoURI, do not build it

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:

RouteServes
GET /api/tokenlisttokenlist.json as last validated503 until a first good copy exists
GET /api/tagstags.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.

How long until a merge shows

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:

  1. Get the checksummed address. EIP-55 mixed case, not all lowercase. If yours is wrong, the validator prints the expected form.
  2. 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.
  3. Append an entry to tokens in testnet/tokenlist.json, as in the example below.
  4. Bump the version of tokenlist.json - adding a token is a minor bump, 1.4.2 becomes 1.5.0 - and set timestamp to now, in ISO 8601 UTC.
  5. 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.
  6. 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.
testnet/tokenlist.json - one entry of tokens
{
  "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.

FieldRule
chainId78270the network of the folder; anything else fails
addressEIP-55 checksummedunique in the list
name1-40 characterswhat the apps show beside the logo
symbol1-20 characters, no spacesunique in the list, case-insensitively
decimalsinteger 0-255the value the contract's decimals() returns
logoURIa raw URL into testnet/logos/tokens/the file named after the address, .png or .svg
tagsoptionalids defined in the list's top-level tags, at most 10
extensionsoptionalat most 10 values, each a string, number, boolean or null

The whole round trip on the command line:

bash
# 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

RuleRequirement
FormatPNG or SVGthe type is checked from the bytes, not from the extension
PNG sizeexactly 256 x 256 pixels
File size100 KB at most
File name<checksummed address>.png or .svgfor a token; letter case matters on GitHub
Locationthe same network folder as the lista testnet list may only point at testnet/logos/
Artworksquare, 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.

  1. Add an entry to tags in testnet/tags.json, keyed by the checksummed address.
  2. Optionally add a logo to testnet/logos/tags/ - same format rules as a token logo, any file name - and point logo at its raw URL. Several tags of one project can share one file.
  3. Bump the version of tags.json and its timestamp, run npm test and open the pull request.
testnet/tags.json - one entry of tags
"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."
}
FieldRule
name1-40 characters, unique in the fileshown instead of the address, so keep it short and specific
categorya key of categoriessee the list below
project1-40 charactersthe project the contract belongs to
urlan https:// link, or nullrequired: write null when there is none
logoa raw URL into testnet/logos/tags/, or nullrequired: write null when there is none
noteoptional, at most 200 characterswhat the contract does, in one sentence

The categories defined today:

KeyFor
tokena token contractthe metadata and logo live in tokenlist.json; the tag gives it a label
protocolcore contractsfees, staking, burning, faucet, registry
bridgethe ETH bridgebetween Pickle Chain and its settlement layer
dexPepper exchange contractsfactories, routers, quoters and the token launcher
poola Pepper liquidity pool
toolkitToolkit contractsmultisend, locker, streams and the deploy factory
namesthe Pickle Name Service
oracleprice feeds
arcadethe 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 logoURI and 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.

ChangeBump
An entry removedmajor1.4.2 becomes 2.0.0
An entry addedminor1.4.2 becomes 1.5.0
An entry changedpatch1.4.2 becomes 1.4.3
bash
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:

MessageFix
is not EIP-55 checksummed (expected …)use the address the message prints
logo file must be named after the checksummed addressrename 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 256x256resize the image to 256 x 256
… bytes, the limit is 102400compress it, or use an SVG
not referenced by this network's tokenlist.json or tags.json; remove itdelete 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 itbump the version - see Versions
this change needs a minor version bumpan addition is minor and a removal major; a patch is not enough
update timestamp when the version changesset 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 categoriesuse an existing key, or add the category in the same pull request
SVG must not reference external resourcesinline everything; remove external href and url() references