Story Protocol (Story Network) is a purpose-built Layer-1 blockchain for intellectual property (IP), designed to make IP registration, licensing, and royalty distribution enforceable through smart contracts. The network is EVM-equivalent and built with the Cosmos SDK, with execution-level optimizations for working with graph-like relationship data (e.g., original works and their derivatives) so these relationships can be stored, traversed, and queried efficiently.
At the protocol level, IP is represented as an IP Asset implemented as an ERC-721 NFT. When an IP Asset is registered, it is paired with an IP Account based on a modified ERC-6551 (token-bound account) design. This account acts as the programmable container for the asset’s permissions and economic logic-such as licensing terms, royalty configuration, and links to derivative works.
Core protocol modules typically include:
-
A Licensing module that attaches a programmable license (commonly referred to as a Programmable IP License / PIL) to an IP Asset and enables issuance of License Tokens (ERC-721) to grant usage rights under defined terms.
-
A Derivative workflow where creating or registering a derivative can require consuming/burning the relevant License Token, establishing parent–child relationships on-chain.
-
A Royalty module that automates revenue sharing across related IP assets according to the configured rules.
-
A Dispute module (and supporting components) for handling challenges/flags and related governance processes.
In practice, Story Protocol positions itself as an IP-native L1 where ownership records, licensing permissions, derivative relationships, and royalties are managed on-chain through standardized assets and protocol modules-reducing reliance on manual, off-chain enforcement for these workflows.
Public Endpoints
Cosmos
Ethereum Virtual Machine (EVM)
Guide
This guide provides a complete, reliable walkthrough for setting up and operating a Story Protocol mainnet node and validator. It covers the full process-from downloading binaries and configuration files to initializing the node, managing keys, applying snapshots, and maintaining a stable validator environment. Follow the steps carefully to ensure a smooth and secure deployment on the Story network.
Recommended Hardware: 8 Cores, 32GB RAM, 400GB of storage (NVME), 100 Mb/s
Prepare
Update and install packages
sudo apt update && sudo apt upgrade -y && \ sudo apt install -y curl git wget htop tmux build-essential jq make lz4 gcc unzip
Installing Go
cd $HOME VER="1.22.5" wget "https://golang.org/dl/go$VER.linux-amd64.tar.gz" sudo rm -rf /usr/local/go sudo tar -C /usr/local -xzf "go$VER.linux-amd64.tar.gz" rm "go$VER.linux-amd64.tar.gz" [ ! -f ~/.bash_profile ] && touch ~/.bash_profile echo "export PATH=$PATH:/usr/local/go/bin:~/go/bin" >> ~/.bash_profile source $HOME/.bash_profile [ ! -d ~/go/bin ] && mkdir -p ~/go/bin
Set vars (replace MONIKER with your own)
echo "export MONIKER="test"" >> $HOME/.bash_profile echo "export STORY_CHAIN_ID="story-1"" >> $HOME/.bash_profile echo "export STORY_PORT="45"" >> $HOME/.bash_profile source $HOME/.bash_profile
Binary
Download prebuilt binary
cd $HOME rm -rf story-geth wget -O story-geth https://github.com/piplabs/story-geth/releases/download/v1.2.0/geth-linux-amd64 chmod +x $HOME/story-geth mv $HOME/story-geth $HOME/go/bin/ [ ! -d "$HOME/.story/story" ] && mkdir -p "$HOME/.story/story" [ ! -d "$HOME/.story/geth" ] && mkdir -p "$HOME/.story/geth"
Install Story
cd $HOME rm -rf story git clone https://github.com/piplabs/story cd story git checkout v1.4.2 go build -o story ./client mv $HOME/story/story $HOME/go/bin/
Initialization
Initialize the node (replace $MONIKER with your own)
story init --moniker $MONIKER --network $STORY_CHAIN_ID
Genesis
Download genesis
wget -O $HOME/.story/story/config/genesis.json https://storage.crouton.digital/mainnet/story/files/genesis.json
Addrbook
Download addrbook
wget -O $HOME/.story/story/config/addrbook.json https://storage.crouton.digital/mainnet/story/files/addrbook.json
Configuration
SEEDS="8db87ee67cdf4c098d023e8f96d6156f098f0ae1@story-mainnet-crouton.digital:45656" PEERS="[email protected]:26656,ef8d211e08ca33193c2dff535ec5a29902e2b3f4@story-mainnet-peer.itrocket.net:45656,[email protected]:26656,[email protected]:26656,[email protected]:26656,[email protected]:26656,[email protected]:26656,[email protected]:26656,[email protected]:27656,[email protected]:26656,[email protected]:59456,[email protected]:26656" sed -i -e "/^\[p2p\]/,/^\[/{s/^[[:space:]]*seeds *=.*/seeds = \"$SEEDS\"/}" \ -e "/^\[p2p\]/,/^\[/{s/^[[:space:]]*persistent_peers *=.*/persistent_peers = \"$PEERS\"/}" $HOME/.story/story/config/config.toml
Сreate geth servie file
sudo tee /etc/systemd/system/story-geth.service > /dev/null <<EOF [Unit] Description=Story Geth daemon After=network-online.target [Service] User=$USER ExecStart=$(which story-geth) --story --syncmode full \ --http --http.api eth,net,web3,engine --http.vhosts '*' \ --http.addr 0.0.0.0 --http.port ${STORY_PORT}545 \ --authrpc.port ${STORY_PORT}551 \ --ws --ws.api eth,web3,net,txpool \ --ws.addr 0.0.0.0 --ws.port ${STORY_PORT}546 \ --port ${STORY_PORT}303 Restart=on-failure RestartSec=3 LimitNOFILE=65535 [Install] WantedBy=multi-user.target EOF
Сreate story service file
sudo tee /etc/systemd/system/story.service > /dev/null <<EOF [Unit] Description=Story Service After=network.target [Service] User=$USER WorkingDirectory=$HOME/.story/story ExecStart=$(which story) run Restart=on-failure RestartSec=5 LimitNOFILE=65535 [Install] WantedBy=multi-user.target EOF
Restore node from snapshot
sudo systemctl stop story story-geth cp $HOME/.story/story/data/priv_validator_state.json $HOME/.story/story/priv_validator_state.json.backup rm -rf $HOME/.story/story/data rm -rf $HOME/.story/geth/odyssey/geth/chaindata curl https://storage.crouton.digital/testnet/story/snapshots/story_latest.tar.lz4 | lz4 -dc - | tar -xf - -C $HOME/.story mv $HOME/.story/story/priv_validator_state.json.backup $HOME/.story/story/data/priv_validator_state.json sudo systemctl start story-geth sudo systemctl start story sudo journalctl -u story -f
State Sync
Restore node from state sync
SNAP_RPC="https://story-mainnet-cosmos-rpc.crouton.digital:443" && \ sudo systemctl stop story && \ cp $HOME/.story/data/priv_validator_state.json $HOME/.story/priv_validator_state.json.backup && \ story tendermint unsafe-reset-all --home $HOME/.story --keep-addr-book && \ peers="@" && \ sed -i.bak -e "s/^persistent_peers *=.*/persistent_peers = \"$peers\"/" $HOME/.story/config/config.toml && \ LATEST_HEIGHT=$(curl -s "$SNAP_RPC/block" | jq -r .result.block.header.height) && \ BLOCK_HEIGHT=$((LATEST_HEIGHT - 1000)) && \ TRUST_HASH=$(curl -s "$SNAP_RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash) && \ echo "$LATEST_HEIGHT $BLOCK_HEIGHT $TRUST_HASH" && sleep 2 && \ sed -i.bak -E "s|^(enable[[:space:]]+=[[:space:]]+).*$|\1true| ; s|^(rpc_servers[[:space:]]+=[[:space:]]+).*$|\1\"$SNAP_RPC,$SNAP_RPC\"| ; s|^(trust_height[[:space:]]+=[[:space:]]+).*$|\1$BLOCK_HEIGHT| ; s|^(trust_hash[[:space:]]+=[[:space:]]+).*$|\1\"$TRUST_HASH\"| ; s|^(seeds[[:space:]]+=[[:space:]]+).*$|\1\"\"|" $HOME/.story/config/config.toml && \ mv $HOME/.story/priv_validator_state.json.backup $HOME/.story/data/priv_validator_state.json && \ sudo systemctl restart story && \ sudo journalctl -u story -f
Upgrade Node
cd $HOME rm -rf story git clone https://github.com/piplabs/story cd story git checkout v1.4.2 go build -o story ./client sudo mv $HOME/story/story $(which story) sudo systemctl restart story && sudo journalctl -u story -f
Delete Node
sudo systemctl stop story story-geth sudo systemctl disable story story-geth rm -rf $HOME/.story sudo rm /etc/systemd/system/story.service /etc/systemd/system/story-geth.service sudo systemctl daemon-reload
Key management
# This command generates a new wallet with a unique keypair. # Use this to create a secure, brand-new wallet for transactions. # Your wallet name = "wallet" story keys add wallet
Create validator
# View your validator key story validator export # Export EVM private key story validator export --export-evm-key #View EVM private key and make a key backup cat $HOME/.story/story/config/private_key.txt
Before creating a validator, wait for your node to get fully synced. Once "catching_up" is "false", move on to the next step
curl localhost:$(sed -n '/\[rpc\]/,/laddr/ { /laddr/ {s/.*://; s/".*//; p} }' $HOME/.story/story/config/config.toml)/status | jq
story validator create --stake 1024000000000000000000 --moniker $MONIKER --chain-id 1514 --unlocked=false
Remember to backup your validator priv_key from here:
cat $HOME/.story/story/config/priv_validator_key.json


