Where should you develop your blockchain app?
→ Download our guide to Web3 ecosystemsClose Icon

A Look Inside Gamma’s Create Portal and How It Empowers NFT Creators

Hey, this is Nick Sainato, Co-Founder and COO of Gamma.io. Gamma aims to become the home for the world’s Web3 social identity, centered around NFTs. Today, I’m going to walk you through our creator launchpad, the Create Portal, which allows artists and creatives to launch NFT collections and support NFT-gated communities.

Type
Tutorial
Topic(s)
Published
August 31, 2022
Author(s)
Co-Founder & COO of Gamma
Gamma's Create Portal
Contents
Copy link

I first discovered Stacks in early 2021 through a tweet about CityCoins from BoredElonMusk. The idea of using Web3 to democratize civil engagement fascinated me. As I dug deeper, I found the value proposition to be even stronger, as I discovered how CityCoins was building on top of Stacks, which settled the outcome of its transactions on Bitcoin. Using Bitcoin as a secure, decentralized settlement layer—independent from its use as a money layer—seemed like a massive (and, in hindsight, obvious) unlock.

The thing that impressed me more than anything about the Stacks ecosystem was its community—one that was focused on building genuinely interesting and useful things. While I wasn’t a developer, I wanted to join the space in a more active way.

In September 2021, over several weeks on nights and weekends, I crafted an NFT project that embodied this community’s spirit. It combined a story-driven puzzle with the concept of trading cards, requiring community members to work together towards a common goal. While I had the creative mindset to conceptualize this project and the semi-technical background to understand what smart contracts were, I lacked the developer resources to make it a reality.

One of the NFTs From the Project

It was right around this time that my Co-Founder, Jamil, was working on launching the first open NFT marketplace on Stacks (then stxnft.com). We worked together to create a smart contract for my idea, and within two weeks it was launched as one of the first projects on the platform. The project had solid traction, but it was clear that we’d be able to serve even more community members by working together on Gamma rather than me focusing my efforts on this side project (don’t worry, I didn’t rug… but that’s a story for another time).

Fast forward to today, Jamil’s concept of an open marketplace on Stacks is a reality, and creators like me can make their idea a reality in a matter of minutes. The Gamma launchpad empowers creators with simple, accessible tools that compose smart contracts based on their specific needs, so they can focus on their true talents instead of the code.

Our open marketplace makes it easy to find, buy, and sell NFTs. Our launchpad and creator tooling reduce barriers to entry and offer a seamless community management suite to creators. And user profiles and social features bring together buyers, sellers, artists, and collectors into a single hub for community and social identity. These offerings are integral to Gamma’s overall experience.

What Is Gamma’s Launchpad?

In a few words, our creator launchpad makes it possible for artists and non-technical creators to deploy a custom NFT smart contract in less than five minutes for less than $1. Importantly, this is a contract that they own, and only they have the “keys” to control.

The process works like this: a creator is first guided through the basic concepts of a smart contract, then they upload their assets (usually some multimedia along with other metadata), and finally, they select features to be added to their contract and deploy it to the network.

Our creator launchpad makes it possible for artists and non-technical creators to deploy a custom NFT smart contract in less than five minutes for less than $1.

Our launchpad has seen a ton of traction, with nearly 900 contracts deployed using the portal since its launch in February of this year. What’s more, creators really seem to find value in the offering, with an average of 2.1 collections deployed per unique address.

This is really exciting to us, as it represents nearly 15% of all smart contracts on the Stacks network at the time of writing.

Gamma Puts Creators First

The need for a tool like this one was clear: the first marketplace on Stacks charged a 40% commission for creating NFT smart contracts and required weeks of lead time, if you could even get in touch. Not to mention, you didn’t own your own smart contract if you went this route, meaning there was significant counterparty risk in the event that the platform stopped serving your collection, an unfortunate reality for early artists given the platform has since been deprecated.

Artists should be able to keep a larger share of the revenues from their collection, and they certainly shouldn’t have to give up control over their smart contract in the process.

In fairness to this (now defunct) platform, there simply weren’t other options available at the time, and their developer resources were likely stretched quite thin. That said, it was clear that artists should be able to keep a larger share of the revenues from their collection, and they certainly shouldn’t have to give up control over their smart contract in the process.

What’s interesting about this is that this problem is not properly solved even on more “mature” NFT ecosystems like Ethereum or Solana. For example, minting with Open Sea’s no-code solution, all NFTs are minted to a single “Open Sea Shared Storefront” contract where you aren’t the ultimate owner and it’s impossible to get verified.

Other platforms like Manifold provide smart contract builders, but they can be limited in what contract types or features you can add, and they lack a marketplace and artist profiles to tie the experience together. Moreover, their process doesn’t seem like it’s made for somebody brand new to Web3, which can limit accessibility to newcomers. We felt there had to be a better way.

How the Create Portal Works

The Gamma Create Portal offers three main solutions in a single offering:

  1. Smart Contract Builder: The core offering, empowering a non-technical creator to launch a custom NFT contract in a few minutes.
  2. IPFS Pinning and Storage: NFT metadata is only as decentralized as its storage method, so we include IPFS pinning and lifetime storage for files associated with collections deployed on our platform. What’s great about IPFS is that anyone else with a vested interest in the files’ existence (say, the creator or a holder) can store their own copy of the files in a permissionless way, reducing counterparty risk and decentralizing asset storage and delivery.
  3. Custom Mint Page and Marketplace Onramp: Once deployed, a creator can use their contract anywhere. One common path is using Gamma’s custom mint pages. We also automatically populate collection-level metadata onto Gamma’s core marketplace, so you’re guaranteed to have a compatible contract with complying standards from the moment you launch. Finally, we ask creators to provide details about themselves and their collection, which we use to vet, verify, and promote unique projects, giving creators a platform to speak and share their creative process.

Diving Into the Code

Let’s dive into a few examples of the Clarity smart contract code that is produced when you deploy a collection using Gamma’s Create Portal. Full disclosure: As I said earlier, I’m not a developer. But that’s actually what makes Clarity such a brilliant smart contract language—it’s human readable if you have even an entry-level understanding of the code. This is especially important when you’re trusting the code with your money or other assets.

We begin each contract with some basic information that allows Gamma and other platforms to identify the contract type and its features. Next, we define constants, which are essentially definitions for certain aspects of the contract that will never change. In this case, we’re defining the deployer’s address, Gamma’s mint commission percentage (10% of primary sales), and the address where these mint commissions will be assigned. Constants also include the contract’s error codes, which will be referenced in the Stacks Explorer in the event that a user attempts a transaction that fails for one of these reasons. Let’s take a look:


(define-constant ERR-NO-MORE-NFTS u100)
(define-constant ERR-NOT-ENOUGH-PASSES u101)
(define-constant ERR-PUBLIC-SALE-DISABLED u102)
(define-constant ERR-CONTRACT-INITIALIZED u103)
(define-constant ERR-NOT-AUTHORIZED u104)
(define-constant ERR-INVALID-USER u105)
(define-constant ERR-LISTING u106)
(define-constant ERR-WRONG-COMMISSION u107)
(define-constant ERR-NOT-FOUND u108)
(define-constant ERR-PAUSED u109)
(define-constant ERR-MINT-LIMIT u110)
(define-constant ERR-METADATA-FROZEN u111)
(define-constant ERR-AIRDROP-CALLED u112)
(define-constant ERR-NO-MORE-MINTS u113)
(define-constant ERR-INVALID-PERCENTAGE u114)

Next, we define the contract’s variables. These are also definitions, but instead are changeable through smart contract calls (e.g. mint or airdrop) or other state changes of the contract like the ID of the last minted NFT. By design, some of these variables can only be changed once, and only in one direction.

For example, the ipfs-root string defines where the NFT metadata (e.g. the images and descriptive attributes) is hosted. By default, a contract admin can call the set-base-uri function to update the metadata referenced within the contract. However, once it is clear that the metadata is error-free and unchanging, it’s a best practice to freeze the metadata, in other words, lock this variable into a final state that can never be changed in the future. This ensures that the NFT a collector purchases will always present the same metadata in the future. Here’s a look at this contract’s internal variables:


(define-data-var mint-limit uint u15)
(define-data-var last-id uint u1)
(define-data-var total-price uint u32000000)
(define-data-var artist-address principal 'SP1X6M947Z7E58CNE0H8YJVJTVKS9VW0PHD4Q0A5F)
(define-data-var ipfs-root (string-ascii 80) "ipfs://ipfs/QmQDXepX6skZWU7RJn1gW9bsKnQi5hsiuGj9cSeJwJNdDD/json/")
(define-data-var mint-paused bool false)
(define-data-var premint-enabled bool false)
(define-data-var sale-enabled bool false)
(define-data-var metadata-frozen bool false)
(define-data-var airdrop-called bool false)
(define-data-var mint-cap uint u1)

To try to prevent this blog from becoming too complicated, we’ll skip past the actual mint functions of the contract and explore one final area of the contract, the non-custodial marketplace functions. These functions are especially important and interesting, because they allow users to list NFTs on a marketplace without having to relinquish custody of their NFTs. Let’s break down what that means.

In a custodial marketplace, a user is effectively transferring ownership over their NFT into the custody of the marketplace’s smart contract. While the NFT is owned by the marketplace’s smart contract, there exists a (small) possibility that a bug or malicious attack or contract design could result in the user losing their NFT.

Clarity’s decidability and published source code makes the risk here quite low—you or other community members can independently audit marketplace contracts and verify that their admins do not hold powers to steal NFTs, and battle-tested code poses less of a risk against exploits. Even still, the objectively lowest risk method of listing an asset for sale is one in which it remains owned by its current owner until a sale is completed, and only then is it transferred to its new owner. Non-custodial marketplace functions and immutable smart contract code allow for this to happen. Here’s a look at this portion of the Gamma NFT contracts:


(define-read-only (get-listing-in-ustx (id uint))
  (map-get? market id))

(define-public (list-in-ustx (id uint) (price uint) (comm-trait ))
  (let ((listing  {price: price, commission: (contract-of comm-trait), royalty: (var-get royalty-percent)}))
    (asserts! (is-sender-owner id) (err ERR-NOT-AUTHORIZED))
    (map-set market id listing)
    (print (merge listing {a: "list-in-ustx", id: id}))
    (ok true)))

(define-public (unlist-in-ustx (id uint))
  (begin
    (asserts! (is-sender-owner id) (err ERR-NOT-AUTHORIZED))
    (map-delete market id)
    (print {a: "unlist-in-ustx", id: id})
    (ok true)))

(define-public (buy-in-ustx (id uint) (comm-trait ))
  (let ((owner (unwrap! (nft-get-owner? stella id) (err ERR-NOT-FOUND)))
      (listing (unwrap! (map-get? market id) (err ERR-LISTING)))
      (price (get price listing))
      (royalty (get royalty listing)))
    (asserts! (is-eq (contract-of comm-trait) (get commission listing)) (err ERR-WRONG-COMMISSION))
    (try! (stx-transfer? price tx-sender owner))
    (try! (pay-royalty price royalty))
    (try! (contract-call? comm-trait pay id price))
    (try! (trnsfr id owner tx-sender))
    (map-delete market id)
    (print {a: "buy-in-ustx", id: id})
    (ok true)))
    

;; Non-custodial SIP-009 transfer function
(define-public (transfer (id uint) (sender principal) (recipient principal))
  (begin
    (asserts! (is-eq tx-sender sender) (err ERR-NOT-AUTHORIZED))
    (asserts! (is-none (map-get? market id)) (err ERR-LISTING))
    (trnsfr id sender recipient)))

(define-private (trnsfr (id uint) (sender principal) (recipient principal))
  (match (nft-transfer? stella id sender recipient)
    success
      (let
        ((sender-balance (get-balance sender))
        (recipient-balance (get-balance recipient)))
          (map-set token-count
            sender
            (- sender-balance u1))
          (map-set token-count
            recipient
            (+ recipient-balance u1))
          (ok success))
    error (err error)))

You’ll notice above that quite a bit is happening. We’ll call out just a few important aspects in this explainer.

First, you’ll notice the transfer function. The transfer function is SIP-009 compliant (a public function, with matching name and parameters for token id, sender, and recipient) but the body of the function first checks to see if the token is listed for sale (if the token is for sale then it will have an entry in the market map at which point the transfer call terminates).

Within the SIP-009 transfer function, we call the trnsfr function (a private function), which then transfers the NFT from the sender to the recipient. We then update the token count map for each party so that the contract knows how many tokens any given principal owns at one time.

Next, we’ll review the list/buy in ustx (micro STX) functions. To list an NFT for sale, the owner calls list-in-ustx, which adds the token to the market map. The market map sets a price, commission (via commission-trait), and a royalty percentage.

When buy-in-ustx is called the contract checks that the listing exists in the market map and then proceeds to calculate and transfer STX to the seller, as well as pay royalties and commissions based on the set values. The contract then deletes the listing from the market map.

Finally, let’s explore the commissions and royalties functions in greater detail. For commission payouts, the contract calls the pay function of the passed commission trait, which then calculates and transfers the funds based on the sale amount.

For royalties, this amount (represented as a percentage of the total sale) is set in the contract when it is deployed, with a default of 5%. There is a set-royalty-percent function which allows the artist and contract owner to change the royalty to anywhere between 0% and 10%.

These functions enable NFT holders to list and sell NFTs without a smart contract needing to take custody over their NFTs. In other words, they don’t need to trust humans or code to custody their NFTs.

Conclusion

Smart contracts secured by Bitcoin just make sense. For artists, there’s a clear value proposition to leverage the most secure, trusted, time-tested, and decentralized settlement layer to record and protect ownership records and ensure royalty payments are respected for decades to come.

Yet, artists don’t always have the technical expertise to write contracts from scratch or manage all of the maintenance and supporting aspects following a collection’s deployment. At Gamma, we’re trying to remove this complexity so creators can get back to creating.

Learn more about our Create Portal at create.gamma.io.

Want to get in touch? Find Gamma or me on Twitter, or join the conversation on Discord.

Copy link
Hiro news & product updates straight to your inbox
Only relevant communications. We promise we won’t spam.

Related stories