Fracada: A protocol for fractionalizing NFTs

Nico Arq
dcSpark
Published in
4 min readSep 28, 2021

Introduction

Non fungible tokens (NFTs) have found a very popular application as on-chain representation of different assets, particularly artwork.

A natural step is fractioning the NFT: what if you have a NFT you want to share with your friends, or if you buy an NFT together, how do you indicate shared ownership?

Here we present a protocol where you can fraction your NFT and get back a limited amount of of tokens representing fractions of that NFT (and they can be traced back to it).

Design

The contract will either receive the NFT to lock and a number in the redeemer indicating how many fractions (tokens) of the NFT to mint or receive all the fraction tokens and pay back the NFT while burning the tokens.

Fractionating the NFT

Fractioning is done in two steps:

  1. Lock the NFT in the contract.
  2. Mint the tokens and pay to the public key that locked the NFT in the previous step.

Locking the NFT

This step locks the NFT in the contract with the datum containing the nft asset class and the owner, we set the amount of fractions to 0 (no fractions yet)

Off-chain

We build the datum and lock it in the script:

Minting the tokens

To mint and pay the fraction tokens, we use the minting policy and the fraction validator together:

The minting policy will allow minting if the token is paid from the validator to the validator again and the specified amount of tokens are actually minted.

The validator will check that the fraction count in the datum changes from 0 to the actual number, the owner is preserved in the datum, and the correct number of tokens are minted.

Off-chain

The offchain code will look for the UTxO containing the NFT, update the total fraction in the datum (thus spending and paying the NFT back to the validator) and use the minting script to mint the fraction tokens:

On-chain validator

The minting spending path in the validator will check that the NFT has’t been fractioned yet (the fraction counter in the input datum is 0), that the new count matches the requested amount of tokens, that the requested amount is minted and the owner is preserved in the datum.

Minting script

The minting script should check the requested amount of tokens is minted and the NFT is spent and locked from the fractionNFT validator

Returning the NFT

To return the NFT:

User: has to provide all the minted tokens.

Off-chain: the contract has to burn the tokens and pay the NFT

On-chain validator: verify the NFT is paid to the user and the correct tokens are burned.

Minting script: Burn the requested amount of tokens

Off-chain

To get the NFT back, the signer has to collect all the fraction tokens and burn them while spending the NFT from the contract.

When returning the NFT, we look for the NFT in the UTxOs locked by the contract, extract the datum to find the tokens to burn, and pay back the NFT to the signer:

On-chain validator

The validator will only release the NFT to the signer if the fraction tokens are burned.

Minting script

The minting script should check only the requested amount of tokens are burned and the NFT is paid back to the signer.

Conclusion

This is a simple contract that showcases a few useful techniques for developing smart contracts in Plutus: minting & burning, using the datum to keep protocol state, interrelate minting and validator scripts, utxo filtering and selection, multiple spending path validators, and more.

Although the initial application of fractionating an NFT to share with friends is almost a novelty, the core protocol of locking a token and issue a number of special tokens, returning the initial token after the special tokens are burned can be integral part of other protocols like governance (where you lock your governance tokens in exchange of voting tokens), access control/initialization of processes (locking a control token will give you back tokens/NFTs to start dApp state machines), etc. After all, Every eUTxO dApp will use NFTs.

The full project can be found at https://github.com/dcSpark/fracada

As a reminder, the code of this project is not audited, but we present it with the goal of sharing smart contract knowledge and collaborating with the community.

Thanks to our lead Plutus developer for writing the blogpost and coding the project!

--

--