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 . |