Skip to content

IP‑On‑Chain Pallet

Mission: Bring canonical, on‑chain lifecycle management of music IP—tracks, stems, samples, even generative assets—directly into the Polkadot runtime. The pallet stores authoritative metadata, ownership, royalty splits and cross‑asset links so that dApps can build licensing, remix and revenue products without off‑chain silos.


Features

  • Track & Sample Registration
    Register unique digital assets (e.g. tracks, stems, loops, generative tracks, generative loops, etc) on-chain as verifiable entities.

  • Ownership Management
    Assign and transfer ownership of assets with full traceability.

  • Metadata Support
    Attach rich metadata to each asset. We also introduce MM25 standard for Music IP-Onchain Metadata

  • On-Chain Provenance
    Maintain an immutable record of asset origin and its derivative relationships.

Use Cases

  • Royalty distribution with transparency
  • Sample reuse and attribution
  • Licensing automation
  • Creative provenance for AI-generated or collaborative works

Why This Pallet Exists

Challenge What MM25 Solves
IP data scattered off‑chain Every critical field lives on‑chain, queryable via RPC and light‑client‑friendly.
No canonical IDs for samples / tracks Deterministic EntityId sequence; linked to content hash in dApps.
Royalty splits are opaque Authors & Authorities are first‑class objects with verifiable provenance.
Difficult attribution Runtime API exposes lineage (related_to) for sample/derivative tracking.

Core Domain Types

Authority

/// Alias used across the pallet
pub type AuthorityDetailsFor<T, I = ()> = AuthorityDetails<
    <T as frame_system::Config>::AccountId,
    <T as Config<I>>::MaxShortStringLength,
>;

#[derive(Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo, Clone, PartialEq, Eq)]
pub enum AuthorityKind { Musician, Label }

pub struct AuthorityDetails<AccountId, Short> {
    pub authority_kind: AuthorityKind,
    pub owner: AccountId,
    pub name: BoundedVec<u8, Short>,
}

Author

pub type AuthorFor<T, I = ()> = AuthorDetails<
    <T as Config<I>>::AuthorityId,
    <T as Config<I>>::MaxShortStringLength,
    <T as Config<I>>::MaxLongStringLength,
>;

pub struct AuthorDetails<AuthorityId, Short, Long> {
    pub nickname: BoundedVec<u8, Short>,
    pub real_name: Option<BoundedVec<u8, Long>>,
    pub owner: AuthorityId,
}

Entity (track / sample / etc.)

pub type EntityDetailsFor<T, I = ()> = EntityDetails<
    <T as Config<I>>::AuthorityId,
    <T as Config<I>>::AuthorId,
    <T as Config<I>>::EntityId,
    Wallet<<T as frame_system::Config>::AccountId>,
    Metadata<<T as Config<I>>::MaxLongStringLength>,
    <T as Config<I>>::MaxEntityAuthors,
    <T as Config<I>>::MaxRoyaltyParts,
    <T as Config<I>>::MaxRelatedEntities,
>;

pub enum IPEntityKind { Sample, Track, GenerativeTrack, GenerativeSample }

Metadata & Wallet

pub enum MetadataStandard { M25 }

pub struct Metadata<Long> {
    pub url: BoundedVec<u8, Long>,
    pub standard: MetadataStandard,
}

pub struct Wallet<AccountId> {
    pub address_id: AccountId,
    pub weight: u32,        // percentage (0–10000 = 0–100%)
}

Dispatchable Calls

Index Call Purpose Access (Origin)
 0 create_author Register a new author profile Signed & whitelisted
 1 edit_author Update real‑name / owner Signed & whitelisted
 2 create_authority Register a label / musician authority Signed & whitelisted
 3 edit_authority Edit authority data / transfer owner Signed & whitelisted
 4 create_entity Mint new track / sample entity with URL metadata Signed & whitelisted
 5 edit_entity Update metadata, authors, royalty parts, relations Signed & whitelisted

All extrinsics emit the corresponding *Added or *Edited event.


Runtime API Surface

fn entity(id: EntityId) -> Result<EntityDetails>;
fn entities(from: EntityId, to: EntityId) -> Result<Vec<(EntityId, EntityDetails)>>;
fn author(id: AuthorId) -> Result<AuthorDetails>;
fn authors(from: AuthorId, to: AuthorId) -> Result<Vec<(AuthorId, AuthorDetails)>>;
fn authority(id: AuthorityId) -> Result<AuthorityDetails>;
fn authorities(from: AuthorityId, to: AuthorityId) -> Result<Vec<(AuthorityId, AuthorityDetails)>>;

The RPC facade (see rpc.md).


Events & Errors

Events

  • AuthorAdded, AuthorEdited
  • AuthorityAdded, AuthorityEdited
  • EntityAdded, EntityEdited

Errors

Error Variant Category Description
AuthorAlreadyExists Author Attempted to create an author whose ID (auto‑increment) or nickname already exists.
AuthorNotFound Author Supplied AuthorId does not match any stored author.
AuthorIdIncrementFailed Author Next author ID overflowed (NextAuthorId could not be incremented).
AuthorityAlreadyExists Authority Attempted to register an authority that already exists.
AuthorityNotFound Authority Supplied AuthorityId not present in storage.
AuthorityIdIncrementFailed Authority Next authority ID overflowed (NextAuthorityId increment failed).
EntityAlreadyExists Entity An entity with the given EntityId already exists.
EntityNotFound Entity No entity found for the provided EntityId.
EntityIdIncrementFailed Entity Overflow while incrementing NextEntityId.
EntityTooManyAuthors Entity authors vector exceeds MaxEntityAuthors constant.
EntityAuthorNotFound Entity One of the supplied author IDs is not registered.
EntityTooManyRoyaltyParts Entity royalty_parts vector exceeds MaxRoyaltyParts constant.
EntityTooManyRelatedEntities Entity related_entities vector exceeds MaxRelatedEntities constant.
EntityRelatedEntityNotFound Entity A referenced related entity does not exist.
Overflow General Arithmetic overflow (typically checked_add failure).
LimitExceeded General A BoundedVec or string length exceeded its compile‑time limit.
BadFormat General Metadata or URL failed validation (invalid UTF‑8 or schema mismatch).
NoPermission Permissions Caller lacks the required ownership or role for this operation.
NotWhitelisted Permissions Origin account is not whitelisted by WhiteListChecker.

References