Reserved IP Address°C
04-14-2025

Failed to fetch data

Getting your Trinity Audio player ready...

This post was first published on Medium. Read DeFi on Bitcoin Part 1: Fungible tokens and token swap and DeFi on Bitcoin Part 3: Uniswap.

In part 2 of the series, we illustrate how to build non-fungible tokens (NFT) and sell them directly on Bitcoin.

Non-Fungible Tokens

In a basic setup, an NFT contract is simply a table with two columns: an ID, uniquely representing a non-fungible asset, and its rightful owner.

NFT Table ID and Owner
NFT Table

The following contract implements such a basic NFT contract, similar to ERC721 token standard in Ethereum.

// a basic ERC721-like non-fungible token
contract ERC721 {
PubKey minter;
@state
HashedMap<int, PubKey> owners;
// mint a new token to receiver
public function mint(PubKey to, int tokenId, Sig minterSig, int keyIndex, SigHashPreimage preimage) {
// token not minted
require(this.owners.has(tokenId, keyIndex));
// authenticate
require(checkSig(minterSig, this.minter));
require(this.owners.set(tokenId, to, keyIndex));
require(this.propagateState(preimage));
}
// burn a token
public function burn(int tokenId, PubKey from, Sig fromSig, int keyIndex, SigHashPreimage preimage) {
// verify ownership
require(this.owners.get(tokenId, from, keyIndex));
// authenticate
require(checkSig(fromSig, from));
require(this.owners.delete(tokenId, to, keyIndex));
require(this.propagateState(preimage));
}
// transfer a token from sender to receiver
public function transferFrom(PubKey from, PubKey to, Sig fromSig, int tokenId, int keyIndex, SigHashPreimage preimage) {
// verify ownership
require(this.owners.get(tokenId, from, keyIndex));
// authenticate
require(checkSig(fromSig, from));
require(this.owners.set(tokenId, to, keyIndex));
require(this.propagateState(preimage));
}
function propagateState(SigHashPreimage preimage): bool {
require(Tx.checkPreimageSigHashType(preimage, SigHash.SINGLE | SigHash.FORKID));
bytes outputScript = this.getStateScript();
bytes output = Utils.buildOutput(outputScript, SigHash.value(preimage));
return hash256(output) == SigHash.hashOutputs(preimage);
}
}
view raw erc721.js hosted with ❤ by GitHub

ERC721 Contract

It is very similar to the fungible token contract we have developed. The most notable difference is the token table at Line 6, mapping ID to its owner, instead of owner to token balance.

Sell NFT

Let us sell some NFTs in exchange for bitcoins. This is akin to swapping fungible tokens. Instead, we swap an NFT for bitcoins.

In the following example, Alice only signs if the payment amount meets her price requirement, in the second output of tx2. Bob only signs if he becomes the new owner of NFT with id 1, in the first output of tx2. Again, the sale is non-custodial and atomic.

NFT Sale chart
NFT Sale

Extensions

There are a variety of ways to extend the sale. We list a few examples:

  • sell NFT in exchange for other tokens: the second output of tx2 should contain the payment to Alice in tokens (fungible or not), not bitcoins, which is funded by a different tx1.
  • platform fee: a third output can be added to tx2 that pays the marketplace a fee, say, 3% of the amount of the second output.

Watch: CoinGeek New York panel, Licensing IP for NFTs: Graphic Novels, Comic Books & Brands

Recommended for you

How AI reshapes programming, building applications
Integrating AI probabilistic thinking with blockchain technology transforms coding practices and sparks a major cultural shift.
April 3, 2025
Developers in Japan can now get hands-on with BSV’s Python SDK
BSV Blockchain Ambassador and YenPoint CEO Ken Sato is co-presenting a session on BSV's Python SDK at Tohoku University on...
March 20, 2025
Advertisement
Advertisement
Advertisement