"The creator community will be equally as important to this next crypto boom as the developer community was to the DeFi boom SS 2020. The goal of tools in the creator boom should be the same: maximize liquidity optimization for market suppliers and reward community. The suppliers aka market makers in this case, however, are the creators." - https://zora.co/blog/creative-composability
This hack is an attempt to get closer to that goal.
A common theme among recent conversations with middle-class / emerging artists is that many want their art in as many hands as possible.
Fractional.art helps this -- but long-term I think it'd be great to embed fractionalization (or something similar) into Zora's protocol itself.
After tinkering inside ourzora/core, I discovered a way to build similar functionality without touching the contracts at all, but through the ZDK.
First I'll show the complete minting process then explain the changes.
import { Zora } from '@zoralabs/zdk'
import { Wallet } from 'ethers'
import {
constructBidShares,
constructCollectionData,
constructCollectionMediaData,
mintCollection,
generateMetadata,
sha256FromBuffer,
} from '@zoralabs/zdk'
const wallet = Wallet.createRandom()
const zora = new Zora(wallet, 4)
const contentHash = sha256FromBuffer(Buffer.from('testing zora collections ...'))
const collectionSupply = 4
const collectionData = constructCollectionData(contentHash, collectionSupply)
const metadataJSON = generateMetadata('zora-20210101', {
version: 'zora-20210101',
name: 'testing zora collections ...',
description: collectionData['mediaTree'],
mimeType: 'text/plain',
})
const metadataHash = sha256FromBuffer(Buffer.from(metadataJSON))
const metadataURI = 'https://ipfs.io/ipfs/QmaipCiN95UGEHRkxVWYmj8bcAYeyxL9LqjHACpvWzcHAt'
const contentURI = 'https://ipfs.io/ipfs/QmXxUwtS2HaCGpY3kKDs7ncy79pu92YZ1KtawQjmox6naf'
const collectionMediaData = constructCollectionMediaData(
collectionData,
contentURI,
metadataURI,
metadataHash
)
const bidShares = constructBidShares(
10, // creator share
90, // owner share
0 // prevOwner share
)
mintCollection(collectionMediaData, bidShares, zora)
/** Rinkeby Transaction Hashes
* 0x824e8147861840abc105023e2af161c5b72bfb39c8478541c2102704a2160161 (ZORA Token ID 3565)
* 0x5af4b4214d6d29bd1ea4e8ea0d6def373a4f8cfcf4469ab2520c6a03f2422b32 (ZORA Token ID 3566)
* 0x3e4d8cf7eb2e04cc2910267e3713d39503fa69e57a6b2dea0ddbbdd276fa0f09 (ZORA Token ID 3567)
* 0xc4b9ef87a3d6a6a896f78808f25cae06f63b91b6991dba0715095c2ba9488913 (ZORA Token ID 3568)
*/
Collections invert fractionalization by allowing a creator to create "copies" of their NFT, instead of dividing it to pieces. Each "copy" still contains all the properties of cryptomedia.wtf, but what makes it a part of a collection is it points to a merkle tree proving its relation to the rest of the supply.
I see this is a building block towards a platform enabling creators to exercise features like "anyone who holds a piece of collection X will receive Y amounts of Z in the future" on Zora.
A few features/TODOs for this initial MVP:
- A metadata scheme for collections to ensure the merkle tree is stored upon minting
- Utility functions to verify an NFT's existence in a collection
- Allow multiple content hashes so creators can create a collection of different NFTs (eg. Punks) natively on Zora
*ik you guys already use the term 'collection' but since its a cool term and this is just a mvp im rolling with it
A CollectionData
type composed of four fields:
type CollectionData = {
mediaSupply: number // Number of media files in collection
mediaContentHashes: BytesLike[] // Content hashes of media in collection
collectionHash: BytesLike // Root of collection's merkle tree
mediaTree: string // JSON representation of collection's merkle tree
}
CollectionData
is generated by the constructCollectionData
function, which expects two parameters: contentHash
and supply
This function utilizes three custom helper functions:
validateSupply
ensures the number provided forsupply
is an integerconstructCollectionContentHashes
uses the providedcontentHash
to generate unique content hashes for each media in the collectionconstructCollectionTree
uses the new content hashes to construct a merkle tree of the collection
Returns a populated CollectionData
type
Wraps constructMediaData
by taking
- a populated
CollectionData
type, and - existing ZDK properties
tokenURI
,metadataURI
, andmetadataHash
to construct MediaData
for each media in a collection.
Returns an array of populated MediaData
types
Wraps zora.mint
by taking
- a
MediaData
array returned byconstructCollectionMediaData
BidShares
returned byconstructBidShares
, and- an instance of
Zora
and mints each media in a collection.
hmu kulk#3357
on Discord