SMASH Handbook

PREFACE

The SMASH Handbook (‘Handbook’) compiles all the information currently available about the Stake Pool Metadata Aggregation Server (SMASH), including background, rationale for its introduction, and technical details.

This Handbook is divided into five major sections:

Introduction

An overview of SMASH fundamentals.

Learn about SMASH

This section is a general overview of SMASH functionality, rationale, and use cases.

Installing the SMASH server

This section provides guidelines on how to install the SMASH server, including useful commands and instructions on testing.

Running the SMASH server

This section explains how to run testnet and mainnet nodes, build SMASH, and perform testing.

SMASH metadata management

This section explains the peculiarities of working with the IOHK SMASH server, and provides guidance on how to delist a pool or report any issues to the operator.

Audience

This Handbook is intended for Stake Pool Operators (SPOs) who might want to register their pools' metadata, and anyone who wants to acquire an understanding of what SMASH does, and how it works.

Related documents

For additional information on SMASH, see the following documents:

Acknowledgements

This documentation has been authored by Fernando Sanchez in collaboration with Olga Hryniuk.


INTRODUCTION

Cardano Shelley introduced the concept of stake pools - reliable server nodes that keep an aggregated stake of pool operators and delegators in a single entity. Stake pools are registered on-chain, and their on-chain data (such as information required to calculate rewards) is critical to the operation of the ledger. Stake pools also possess metadata that helps users to make a rational choice of a stake pool to delegate to. This metadata is stored off-chain, as it might reflect sensitive content. Such an approach allows for a certain degree of decentralized censorship.

But on the other hand, off-chain metadata storage poses a challenge of open access by different users. On-chain stake pool registrations contain an URL pointer to the off-chain metadata and a content hash that can be fetched from a specific stake pool. This might cause both performance and privacy issues. Another crucial aspect to address is the stake pool’s “ticker” name, which is the short name a stake pool is recognized by. Ticker names might reflect prominent brands or trademarks that should not be duplicated, as this might lead to confusion. SPOs running multiple pools might want to use the same metadata for all their pools, for example, which might lead to these pools appearing with the same ticker name. This would not be an ideal situation.

To support stake pool operations and provide visibility over the delegation ecosystem, we have created a Stake Pool Metadata Aggregation Server – SMASH. In this Handbook, we overview SMASH’s standardized framework for listing valid stake pools with verified metadata, and provide instructions on working with it.


LEARN ABOUT SMASH

The purpose of SMASH is to aggregate off-chain metadata that stake pools provide when they register on the Cardano blockchain.

This metadata might include:

  • owner
  • pool name
  • pool ticker
  • homepage
  • pledge address
  • short description

The integrity and reputation of Cardano depends on ensuring that registered stake pools are valid, that they do not duplicate ticker names or trademarks, and do not feature content that users are likely to find offensive. SMASH was designed to improve visibility on verified stake pool information for Cardano users and enable convenient navigation options.

The first generation of SMASH was initially deployed by IOHK and is currently used in the Daedalus delegation center, where it enables users to view available stake pools with verified names, ticker symbols, websites, and short descriptions. The functionality provided by SMASH supports stake pool operations and the delegation ecosystem with its standardized framework for listing valid stake pools with verified metadata.

SMASH Rationale

The rationale for introducing a metadata aggregation server in the Cardano architecture is two-fold:

  • to keep the stake pool metadata stored off-chain; and
  • to retain the ability to moderate stake pool metadata, without any centralized censor.

The metadata is hosted off-chain and referred to from the on-chain pool registration. SMASH collects the off-chain data to make it more convenient, performant, and reliable for wallets and other applications to access it.

The SMASH server also addresses a second consideration: the desire to moderate the content of stake pool metadata without a centralized censoring entity. For example, most wallet users and stake pool operators would like to have the ability to treat stake pool ticker names as if they were unique trademarks. It would be too complex to have a fair, on-chain system to resolve ticker name disputes. So instead of enforcing uniqueness on chain, this can optionally be enforced by filtering the metadata as part of metadata aggregation. Multiple aggregation services can be run by different organizations following different policies on filtering stake pool metadata, which enables wallet users and other consumers of stake pool metadata to choose which policy to follow, if any.

SMASH can be configured with policies to filter out metadata based on block lists or reserved ticker names. Daedalus can be configured to use any SMASH server. You can also find more information about the pool metadata (the PoolMetaData record) and read the Design Specification for Delegation and Incentives in Cardano (section 4.2 Stake Pool Metadata, p.30).

SMASH Use Cases

As SMASH is introduced to address metadata performance and privacy issues, delegators, stake pool operators, exchanges, or wallets can deploy and use SMASH to ensure a higher level of metadata accountability and maintenance. Exchanges, wallets, or other SPOs then act as operators and can validate and manage this metadata, or curate it for censorship via the delisting feature.

Exchanges, for example, can use SMASH to fetch stake pool metadata and verify its content against the on-chain registered hash. The exchange can then check existing metadata for correctness (size limits, content, etc.), create new stake pools manually, and reserve their ticker names. If there is a stake pool with a duplicated ticker name, counterfeit, or offensive content, it will be possible to delist this pool.

There are many other use cases for running SMASH servers besides censorship: an operator might choose to list only charity pools or pools from a certain region for ada holders who would prefer to support locally-operated stake pool businesses, for example.

It is expected that more operators will use SMASH servers for metadata curation. As more servers come online, they can be added to a list of preferred SMASH servers within the Daedalus wallet.


INSTALLING A SMASH SERVER

Prerequisites

You can find the most recent installation instructions in the respective SMASH GitHub repository.

The following components must be downloaded and installed before building, installing, and deploying SMASH. It is not necessary to install the Cardano wallet or any other Cardano components.

  • The PostgreSQL library. This can be installed on Linux using e.g., apt install libpq-dev
  • The PostgreSQL server. This can be installed on Linux using e.g., apt install postgresql
  • The cardano-db-sync package. This acts as a library for database support, hence, it is not necessary to install it separately.
  • The cardano-node package. This provides the core Cardano node functionality and runs as a passive node.

Step-by-Step Installation Instructions

Follow these steps to install a SMASH server:

  1. Create a database (DB)

Create a database and provide its path. This installation example uses the default location. Use this command to create the PostgreSQL database:

SMASHPGPASSFILE=config/pgpass ./scripts/postgresql-setup.sh --createdb

To recreate the database (if needed), run the following command:

SMASHPGPASSFILE=config/pgpass ./scripts/postgresql-setup.sh --recreatedb

After that, you can run migrations (if there are any):

SMASHPGPASSFILE=config/pgpass cabal run smash-exe -- run-migrations --mdir ./schema

Run additional migration scripts if they need to be created:

SMASHPGPASSFILE=config/pgpass cabal run smash-exe -- create-migration --mdir ./schema

Useful commands:

  • To show all tables: \dt
  • To show details about a specific table: \d+ TABLE_NAME. For example: \d+ block
  • You can dump the schema with: pg_dump -c -s --no-owner cexplorer > cexplorer.sql
  1. Install SMASH

You can build and install SMASH from the command line using cabal as follows:

cabal build smash
cabal install smash

You can also use stack if you prefer. If you’re already using cabal, replace cabal with stack in the commands above.

Running SMASH with the Cardano node

  1. First, run the Cardano node as a relay, or passive node.

For example:

cardano-node --genesis-file genesis.json --socket-path node.socket --config config.yaml

You can then run SMASH using:

SMASHPGPASSFILE=./config/pgpass cabal run smash-exe -- run-app-with-db-sync --config config.yaml --socket-path node.socket --schema-dir schema/

You can also run a mainnet node using a Nix command:

nix-build -A scripts.mainnet.node -o mainnet-node-local./mainnet-node-local

Useful Commands

From the HTTP API, SMASH supports the fetching of the metadata using:

curl --verbose --header "Content-Type: application/json" --request GET http://localhost:3100/api/v1/metadata/<POOL_ID>/<POOL_HASH>

If you are an administrator, you can delist a pool as follows:

curl --verbose --header "Content-Type: application/json" --request PATCH --data '{"poolId":"<POOL_ID>"}' http://localhost:3100/api/v1/delist

You can use additional commands, which help test the functionality of the SMASH server. You can insert a pool manually, for instance, and the file should be local and not remote:

curl -X POST -v -H 'content-type: application/octet-stream' http://localhost:3100/api/v1/metadata/i<POOL_ID>/<POOL_HASH> --data-binary @<POOL_JSON_FILE_PATH>

To reserve a ticker run:

curl --verbose --header "Content-Type: application/json" --request POST --data '{"poolHash":"<POOL_HASH>"}' http://localhost:3100/api/v1/tickers/<TICKER_NAME>

Testing SMASH

Run commands provided in the example:

curl --verbose --header "Content-Type: application/json" --request GET http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/4b2221a0ac0b0197308323080ba97e3e453f8625393d30f96eebe0fca4cb7335 curl --verbose --user ksaric:cirask --header "Content-Type: application/json" --request PATCH --data '{"poolId":"xyz"}' http://localhost:3100/api/v1/delist

Note: It is critical to work behind HTTPS. Interacting with a server via a regular HTTP protocol is unsafe, since it is using Basic Auth,, which is not protected, and is visible during such interaction. You need an HTTP server (Apache or Nginx, for example) that can be configured post-installation to directly point to the application port.

Getting the Swagger/OpenAPI Information

First, run the application. Then, go to the localhost and copy the content into an editor.

Using SMASH

Inserting pool metadata

This is an example (the hash from Blake2 256), the file should be local and not remote:

curl -X POST -v -H 'content-type: application/octet-stream' http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/4b2221a0ac0b0197308323080ba97e3e453f8625393d30f96eebe0fca4cb7335 --data-binary @test_pool.json

Testing delisting feature

Find a pool hash that has been inserted:

curl -X GET -v http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/4b2221a0ac0b0197308323080ba97e3e453f8625393d30f96eebe0fca4cb7335 | jq

Then, test the delisting by sending a PATCH on the delist endpoint:

curl -X PATCH -v http://localhost:3100/api/v1/delist -H 'content-type: application/json' -d '{"poolId": "8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66"}'

Or, if you have a Basic Auth enabled (replace with the username/pass for your DB) use:

curl -u ksaric:test -X PATCH -v http://localhost:3100/api/v1/delist -H 'content-type: application/json' -d '{"poolId": "8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66"}'

Fetch the pool:

curl -X GET -v http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/4b2221a0ac0b0197308323080ba97e3e453f8625393d30f96eebe0fca4cb7335 | jq .

If you have made a mistake by delisting the wrong pool ID, you can whitelist it (the example with the Basic Auth):

curl -u ksaric:test -X PATCH -v http://localhost:3100/api/v1/enlist -H 'content-type: application/json' -d '{"poolId": "8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66"}'

Fetch the pool:

curl -X GET -v http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/4b2221a0ac0b0197308323080ba97e3e453f8625393d30f96eebe0fca4cb7335 | jq .

Basic AUTH and DB

Before starting, ensure that the Basic Auth flag is disabled. After running the migration scripts (see sections above), you can insert your user and password details in the DB. To do that, you can use command line interface (CLI) commands.

This command creates a new admin user:

SMASHPGPASSFILE=config/pgpass cabal run smash-exe -- create-admin-user --username ksaric --password cirask

This CLI command deletes the admin user (the username and the password must match):

SMASHPGPASSFILE=config/pgpass cabal run smash-exe -- delete-admin-user --username ksaric --password cirask

You will now be able to run your SMASH server with user authentication from DB. If you change your users/passwords, you will need to restart the application, since it takes a full restart for users to reload.

Note: Any changes to the user tables requires the restart of the application.

Test Script

First, ensure that the testing-mode is enabled on all projects.

See an example of how SMASH works:

SMASHPGPASSFILE=config/pgpass ./scripts/postgresql-setup.sh --recreatedb
SMASHPGPASSFILE=config/pgpass cabal run smash-exe -- run-migrations --mdir ./schema
SMASHPGPASSFILE=config/pgpass cabal run smash-exe -- create-migration --mdir ./schema
SMASHPGPASSFILE=config/pgpass cabal run smash-exe -- run-migrations --mdir ./schema

Then, insert the pool; this is what happens when syncing with the blockchain:

curl -X POST -v -H 'content-type: application/octet-stream' http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/4b2221a0ac0b0197308323080ba97e3e453f8625393d30f96eebe0fca4cb7335 --data-binary @test_pool.json

Run SMASH:

SMASHPGPASSFILE=config/pgpass cabal run smash-exe -- run-app

After the server is running, you can check the hash on the localhost to see it return the JSON metadata:

curl -X GET http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/4b2221a0ac0b0197308323080ba97e3e453f8625393d30f96eebe0fca4cb7335

Figuring out the JSON hash

You can use a cardano-cli command to fetch the stake pool metadata hash from a passive node. Also, you can figure out the JSON hash inside GHCi:

ghci
Prelude> import qualified Cardano.Crypto.Hash.Class as Crypto
Prelude> import qualified Cardano.Crypto.Hash.Blake2b as Crypto
Prelude> import qualified Data.ByteString.Base16 as B16
Prelude> poolMetadata <- readFile "test_pool.json"
Prelude> B16.encode $ Crypto.digest (Proxy :: Proxy Crypto.Blake2b_256) (encodeUtf8 poolMetadata)

Note: This assumes that you have a file called "test_pool.json" in your current directory that contains the JSON metadata for the stake pool.

Inserting the reserved ticker name

Currently, SMASH service works by allowing users to insert the ticker name and the hash of the pool they want to be reserved for that ticker name.

There is a CLI utility for doing exactly that. If you want to reserve the ticker name "SALAD" for the specific metadata hash "2560993cf1b6f3f1ebde429f062ce48751ed6551c2629ce62e4e169f140a3524", then you would reserve it like this:

curl --verbose --header "Content-Type: application/json" --request POST --data '{"poolHash":"2560993cf1b6f3f1ebde429f062ce48751ed6551c2629ce62e4e169f140a3524"}' http://localhost:3100/api/v1/tickers/SALAD

If someone adds the ticker name that already exists, it will not be returned, but it will return 404.

Testing the delisting feature

The example we used for testing shows that we can delist the pool ID. If a pool is delisted, its pool ID cannot be used in other pools.

To test delisting, first insert the test_pool.json as in the example:

curl -X POST -v -H 'content-type: application/octet-stream' http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/4b2221a0ac0b0197308323080ba97e3e453f8625393d30f96eebe0fca4cb7335 --data-binary @test_pool.json

You can then change the ticker name of test_pool.json from testy to testo. This changes the pool hash.

curl -X POST -v -H 'content-type: application/octet-stream' http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/3b842358a698119a4b0c0f4934d26cff69190552bf47a85f40f5d1d646c82699 --data-binary @test_pool.json

You will now have two pools from the same pool ID. Run this command to see if they are in the database:

curl -X GET -v http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/4b2221a0ac0b0197308323080ba97e3e453f8625393d30f96eebe0fca4cb7335 | jq .
curl -X GET -v http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/3b842358a698119a4b0c0f4934d26cff69190552bf47a85f40f5d1d646c82699 | jq .
You can try to delist that pool ID and then fetch both pools to see if delisting works on the pool ID level:
curl -X PATCH -v http://localhost:3100/api/v1/delist -H 'content-type: application/json' -d '{"poolId": "8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66"}'
Fetching them again should result in 403:
curl -X GET -v http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/4b2221a0ac0b0197308323080ba97e3e453f8625393d30f96eebe0fca4cb7335 | jq .
curl -X GET -v http://localhost:3100/api/v1/metadata/8517fa7042cb9494818861c53c87780b4975c0bd402e3ed85168aa66/3b842358a698119a4b0c0f4934d26cff69190552bf47a85f40f5d1d646c82699 | jq .

This assumes that you have a file called test_pool.json in your current directory that contains the JSON metadata for the stake pool.

Checking the pool rejection errors

Currently, you can check if there are any errors while trying to download the pool metadata. The hash might sometimes be wrong, or the server URL could return 404, etc.

To check whether anything went wrong, you can add a specific pool ID (c0b0e43213a8c898e373928fbfc3df81ee77c0df7dadc3ad6e5bae17) in the following command:

http://localhost:3100/api/v1/errors/062693863e0bcf9f619238f020741381d4d3748aae6faf1c012e80e7

This shows all the pool errors from the previous day. You can filter these errors by using a date format like DD.MM.YYYY:

http://localhost:3100/api/v1/errors/6b6164af70861c5537cc9c8e50fdae35139ca2c8c6fbb42e8b7e6bfb?fromDate=13.10.2020

The returned list consists of the following objects containing:

  • time - the time formatted in DD.MM.YYYY. HH:MM:SS which is one of the most convenient formats
  • utcTime - the time formatted in the standard UTC format
  • poolId - the pool ID of the pool’s owner
  • poolHash - the hash of the pool’s metadata
  • cause - the cause (reasoning) of the error or failure
  • retryCount - the number of times a user (re)tried to fetch the offline metadata

Unregistering a pool

If a pool is unregistered, all its metadata becomes unavailable. To check which pools have been unregistered, run this command:

curl --verbose --header "Content-Type: application/json" http://localhost:3100/api/v1/retired

RUNNING THE SMASH SERVER

You can find the most recent instructions on running the SMASH server in the respective SMASH GitHub repository.

Running a SMASH server must be done in a certain order. First, you need to run your node, as it fetches the required blocks and online information from the blockchain. A SMASH server also requires the Postgresql database to be running.

Follow these steps to run the SMASH service.

Run the Node

Clone the node and use Nix to build it. You can download specific versions of the node from this release page,

You can also clone the repository and use a specific tag from the release (e.g., 1.14.2):

git clone git@github.com:input-output-hk/cardano-node.git
git checkout 1.14.2 -b tag-1.14.2

Building and running the node on the testnet

Once you have the node version you want, build the node on the testnet using Nix:

nix-build -A scripts.shelley_testnet.node -o shelley-testnet-node

Then, you can run the node with:

./shelley-testnet-node

Building and running the node on the mainnet

After you have the version you wish to work with, build the node on the mainnet ususing Nix: nix-build -A scripts.mainnet.node -o mainnet-node-local

Then, you can run the node with:

./mainnet-node-local

Build SMASH

Download the latest SMASH version.

You can then build the project using Stack, Cabal or Nix:

nix-build -o smash-local

You can now set up the DB schema.

Setting up a Postgresql DB Using SMASH

Follow these steps to set up a Postgresql database to use SMASH.

  1. Create the preferred schema and you can use SMASH to populate it. For this, you will need a connection string.. For example, this is the content for config/pgpass, which can be used to connect to the database:
/var/run/postgresql:5432:smash:*:*
  1. Create a schema, point the schema name, port the number to correct values, and finally, store that information in a file. We will later use the location of that file to connect to the database and populate it.

For example:

SMASHPGPASSFILE=config/pgpass ./scripts/postgresql-setup.sh --createdb
  1. Run the migration required for SMASH to work. Use the database config file:
SMASHPGPASSFILE=config/pgpass ./smash-local run-migrations --mdir ./schema

Once completed, you should have a valid schema and should be able to run SMASH!

Run SMASH

Before running SMASH, ensure that the node is running (see sections above), and use another terminal session to run SMASH. Use the appropriate parameters, since running the server requires it to be in sync with the node.

The socket path should point to a socket that will be used for communication with the node.

For example:

SMASHPGPASSFILE=config/pgpass ./smash-local run-app-with-db-sync --config config/testnet-config.yaml --socket-path ../cardano-node/state-node-shelley_testnet/node.socket --schema-dir schema/ --state-dir ledger-state/shelley-testnet

After this, the SMASH application should start syncing blocks and reflecting pools.

Running Tests

You can run tests using Stack:

stack test --fast -j`nproc` --flag 'smash:testing-mode' --flag 'smash-servant-types:testing-mode'

Or Cabal:

cabal test all -f testing-mode

Checking if it works

When you see that a pool has been registered, you can obtain information about it by running its poolid and hash (the example of the hash here is 93b13334b5edf623fd4c7a716f3cf47be5baf7fb3a431c16ee07aab8ff074873):

curl -X GET -v http://localhost:3100/api/v1/metadata/062693863e0bcf9f619238f020741381d4d3748aae6faf1c012e80e7/93b13334b5edf623fd4c7a716f3cf47be5baf7fb3a431c16ee07aab8ff074873

You can test the delisting by sending a PATCH on the delist endpoint (using the pool id from the example, 062693863e0bcf9f619238f020741381d4d3748aae6faf1c012e80e7):

curl -X PATCH -v http://localhost:3100/api/v1/delist -H 'content-type: application/json' -d '{"poolId": "062693863e0bcf9f619238f020741381d4d3748aae6faf1c012e80e7"}'

If you have Basic Auth enabled (remember to replace the username/password you have in your DB), run:

curl -u ksaric:cirask -X PATCH -v http://localhost:3100/api/v1/delist -H 'content-type: application/json' -d '{"poolId": "062693863e0bcf9f619238f020741381d4d3748aae6faf1c012e80e7"}'

Running a stub server for local testing purposes

If you wish to run a stub server for local testing purposes, build SMASH in testing mode:

stack install --flag 'smash:testing-mode' --flag 'smash-servant-types:testing-mode' --flag 'smash:disable-basic-auth'
smash-exe run-stub-app
curl -X POST -v -H 'content-type: application/octet-stream' --data-binary @test_pool.json \
http://localhost:3100/api/v1/metadata/5ee7591bf30eaa4f5dce70b4a676eb02d5be8012d188f04fe3beffb0/cc019105f084aef2a956b2f7f2c0bf4e747bf7696705312c244620089429df6f
curl -X GET -v \
http://localhost:3100/api/v1/metadata/5ee7591bf30eaa4f5dce70b4a676eb02d5be8012d188f04fe3beffb0/cc019105f084aef2a956b2f7f2c0bf4e747bf7696705312c244620089429df6f

SMASH METADATA MANAGEMENT

This section outlines the peculiarities of working with an existing SMASH server, in particular - the one moderated by IOHK.

How does the IOHK SMASH server work?

The first generation of SMASH is initially deployed by IOHK and is used in the Daedalus delegation center, where it provides the ability to view available stake pools with verified names, ticker symbols, and websites:

Daedalus also allows users to configure any server of their choice and browse custom stake pool lists:

The IOHK SMASH server:

  • runs continuously and autonomously;
  • follows the blockchain data to track the stake pool registration or re-registration;
  • downloads stake pool metadata from on-chain locations;
  • is robust against incorrectly configured or malicious metadata hosting (e.g. timeouts, resource limits);
  • verifies metadata content against the on-chain registered hash;
  • verifies the size is within the limits, and the content matches the necessary JSON scheme;
  • serves requested metadata via an API to wallets and other users in a performant way, including for the case of incremental updates;
  • indicates that metadata is not available in response to requests;
  • serves the requested metadata preserving the content hash to be verified against the hash from the on-chain registration certificate;
  • allows operators to delist stake pools;
  • allows operators to configure, check and adjust their chosen policy via an appropriate interface without service interruptions;
  • follows typical behaviours, e.g. configured via CLI and/or configuration file, stdout/stderr logging.

Delisting a stake pool

Cardano reserves the right to delist pools that, based on their metadata, might be deemed to be harmful, offensive, or contain material that might be objectionable.

Below is a step-by-step description of actions that can be taken when you identify a pool with a duplicated ticker name or offensive content. Note that these actions apply to the SMASH server run and maintained by IOHK only.

Possible reasons for delisting a pool

First, determine that there is a valid reason for a stake pool to be delisted. Certain reasons influence the delisting decision.

These include:

  • illegal or malicious content: a stake pool that features any illegal, abusive, or malicious content as part of the stake pool metadata (for example via the link to the SPO’s homepage).
  • impersonation: stake pools attempting to impersonate individuals, groups, or organizations in a misleading, confusing, or deceptive manner. For example, a successful stake pool called POOL being obviously impersonated by another called P00L (by linking to the same website).
  • previous ‘claim’: ticker names can be registered by stake pool operators (SPOs) on a ‘first come - first served’ basis, however, a ticker name that was registered on the Incentivized Testnet (ITN) can only be registered on the Cardano mainnet by the same SPO that registered such a ticker on the ITN. Ticker names that were registered on the ITN but were not re-registered on the Cardano mainnet by 19th June 2020 will be released and available for registration on the Cardano mainnet.
  • an inappropriate ticker name: a ticker name that might be deemed by others obscene, sexually explicit, offensive, hurtful, profane, or otherwise inappropriate. This is a subjective judgment in some cases, so best efforts will always be made.
  • intellectual property rights (IPR) violations: SPOs that violate the intellectual property rights of others -including copyright and trademarks-, where proof can be supplied.
  • inactive or retired pools: stake pools that are retired or have not produced blocks in a long time, or pools whose operator cannot be contacted. Retired pools on the mainnet have a limit of six months within which to make a request for their ticker name to be re-registered.

How to request a delisting

When you identify a stake pool that you believe should be delisted, you can send an official request for delisting to this email address. Include your rationale and any proof of why a delisting is, in your opinion, warranted. In particular, state one of the above reasons and provide a detailed explanation. Stake pools impersonating trademarks should be reported by the trademark holder or their authorized representative. After sending your request, you will receive an acknowledgement email and the request will be taken into consideration.

A SMASH operator will review the request to ensure that the reasoning and proofs are accurate and will make a decision on whether or not to delist the stake pool. It may also be determined that further arbitration or community consultation is required. However, the ultimate decision will always be reserved by the entity operating the SMASH server in question.

When a decision is made, you will receive an email outlining whether the stake pool will be delisted or whether the ticker listing will be allowed to remain. In either case, we’ll always provide an explanation or justification for the choice. In some cases, a stake pool can be delisted proactively - whether temporarily or permanently. With delisting in active, the stake pool will not be visible on SMASH, and its operator will need to make a case if they want the decision reversed. If an SPO believes that delisting their stake pool has happened by mistake, they can submit an appeal to this email address.

IOHK’s SMASH operator is constantly reviewing all requests from the Cardano community and SPOs to ensure that all the stake pool information is tracked and managed accurately. A request is usually processed in 7 working days.

It is important to note that delisting refers to the display of metadata and listing with SMASH only. As a decentralized network, at no point will stake pool operations themselves be affected.

If you need further information or clarification about delisting, you can contact this email address, or contact Ben O’Hanlon directly via Telegram or Twitter.

© IOHK 2015 - 2021


Cardano Logo

Cardano is an open-source project.

Cardano is a software platform ONLY and does not conduct any independent diligence on, or substantive review of, any blockchain asset, digital currency, cryptocurrency or associated funds. You are fully and solely responsible for evaluating your investments, for determining whether you will exchange blockchain assets based on your own judgement, and for all your decisions as to whether to exchange blockchain assets with Cardano. In many cases, blockchain assets you exchange on the basis of your research may not increase in value, and may decrease in value. Similarly, blockchain assets you exchange on the basis of your research may fall or rise in value after your exchange.

Past performance is not indicative of future results. Any investment in blockchain assets involves the risk of loss of part or all of your investment. The value of the blockchain assets you exchange is subject to market and other investment risks