Sound recently launched with its first round of artists. The reception has wildly exceeded our expectations and we couldn't be more happy with the outpouring of support for artists exploring web3 music.
Now that we've introduced the protocol to the world, we want to provide insights into how it’s designed and the thought process behind those decisions. This post will be an aerial-perspective, lightly technical, and mainly focused on the smart contract design. Future posts will drill down into more intricate application details that developers might be interested in.
We started with two main objectives:
- Create tools that put artists in control
- Make music patronage more fun
Create tools that put artists in control
One of the big problems with the web2 creator economy is that creators are beholden to platform risk, or as crypto hodlers call it, centralization. Although they can often find a huge amount of value in using those platforms, there are countless stories of companies pulling the rug out from under them in different ways.
At Sound, we want to give artists control and minimize this risk, while building an approachable and engaging experience. Striking the right balance involves tradeoffs and we will reexamine those with the community over time. For the first version of the protocol, we landed on:
- Enable each artist to deploy a smart contract that they control, that will govern their entire catalog of Sound NFTs. This is the bedrock of our architecture and puts artists in the driver seat. One clear benefit of this is that it enables every artist to create and manage their own collection on secondary markets like OpenSea.
- Make the contracts upgradable so new features can be added, but with minimum friction for the artist.
- Manually white-list and onboard the first batch of artists, but forge a path toward making this process completely determined by the Sound community.
- Serve the metadata through our API, with a plan for enabling artists to freeze it in permanent storage in the future.
Make music patronage fun
Some music fans might love being at a concert where they're the only person in the audience, but that isn't sustainable for the artist nor is it a fun experience for most genres (imagine a dance club with one attendee). For that reason, we knew we wanted sound NFTs to be released as editions rather than 1-of-1 unique tokens.
The community of token holders serves as the foundation for rich social features that can be built on top.
Starting from that premise, we explored existing NFT protocols. We drew considerable inspiration from the edition contracts of Mirror and Zora and evaluated tradeoffs around ownership, composability, upgradeability, and secondary market. Prioritizing community building and gas efficiency, we landed on:
- An artist deploys a single smart contract which enables minting multiple songs.
- Each song can be minted with multiple edition counts
- Editions are minted as they are purchased to minimize gas costs
Now that we have all that preamble out of the way, let's dig into some details.
(っ◔◡◔)っ ♥ Sound Protocol ♥
This is the brain of the Sound protocol. Its a pretty simple brain, as its only responsibilities are to authorize who can deploy an artist contract and perform the deployment. It also has some code that enables upgradability of itself and the artist contracts. Any curious developers can view its source code here.
If ArtistCreator is the brain, Artist is the heart. Its source code can be viewed here. It is a customized version of the 721 NFT standard and each Sound artist deploys one before they can start minting songs. The artist gets to choose the contract's name and token symbol, as well as the parameters of each song edition like quantity, price, secondary-sales royalty, auction start time and end time. For simplicity, season 1 NFTs have all been 25 edition counts at 0.1 eth, but this will change over time.
We inherit a lot of functionality from OpenZepplin contracts and have a couple tiny support contracts, but that's basically the protocol. It's pretty simple, but there are a few other things worth explaining.
After a lot of internal debate, we ultimately decided to serve NFT metadata from our own API, as opposed to putting it on a permanent decentralized storage network like IPFS or Arweave. The media itself gets stored on IPFS, but it is linked to from the metadata, and the NFT contract links to it by pointing to our API.
The main benefit is the flexibility it affords while we explore creative possibilities. We're currently taking advantage of this in a couple ways:
- Golden Egg game: when a song sells out, one of the buyers' NFTs is selected at random and upgraded. The artist can also optionally define additional rewards for the winner.
- Evolving the metadata in lockstep with the community. An example: a community member suggested that the first song minted by an artist should have a special trait, so we added the “Genesis” attribute.
- Song comments: while we could just store all the comments in our database, we thought it would be more interesting to store them on IPFS. As comments update, we update the IPFS hash. The NFT metadata points to the updated IPFS hash.
In the future, we will provide artists the ability to freeze the metadata. We want to do this after the metadata format has matured and in a way that preserves the fun of artist and fan interactions. We will get feedback from the community and implement this thoughtfully in the future.
In addition to dynamic vs static metadata, we struggled with the decision of whether or not to make the artist contracts upgradable. On one hand, when a contract can be upgraded it introduces security risk and trust assumptions. On the other hand, unforeseen bugs or vulnerabilities can potentially be fixed with an upgrade, and new features can be added to the protocol over time. We believe this is incredibly important for a community of creatives, which is why we ultimately opted for upgradable contracts.
The specific upgrade pattern we landed on is called the Beacon Proxy. It was developed by 0age at Dharma Wallet (huge shout out to 0age, who helped us a ton over the past couple months). The beacon proxy works like this:
- A factory contract (in our case, ArtistCreator), deploys an implementation (Artist.sol) that all the artist owned proxies use for their functionality.
- The factory also deploys a beacon contract that controls any upgrades of the implementation.
- When one of the Artist proxies is called, it asks the beacon for the current implementation.
- All the data for each proxy is stored on the proxy itself. Only the functionality is delegated.
This beacon pattern enables upgrading all the proxies with a single transaction. The benefit is that all artist contracts can be updated seamlessly with new features and bug fixes. It also has the risk of being a single point of failure and an attack vector for a malicious actor to compromise the protocol.
We understand concerns, and want to be transparent about our security: the beacon is currently protected by a Gnosis Safe which requires a total of 5 signatures from 7 hardware wallets spread between the 3 Sound cofounders. Additionally, any upgrade will require buy-in from the Sound community, and we plan to decentralize the upgrade governance control as we scale up.
There is a long list of improvements and features we’d like to add in the next several months. In no particular order, some of the top priorities are:
- The ability to define song credits and surfacing this information in the NFT metadata
- Splitting revenue among collaborators
- User-led curation and onboarding of new artists
- A page for song supporters to showcase their catalog
- Native support for collaborations, albums, and playlists
- An iframe song embed widget
That's the conclusion of the first official Sound engineering blog post. Please reach out on our Discord if you have any further questions. Thanks for reading, and thanks for supporting musicians!