8

Code A Minimalistic NFT Smart Contract in Solidity On Ethereum: A How-To Guide

 3 years ago
source link: https://hackernoon.com/code-a-minimalistic-nft-smart-contract-in-solidity-on-ethereum-a-how-to-guide-kl3u34l6
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Code A Minimalistic NFT Smart Contract in Solidity On Ethereum: A How-To Guide

6
heart.pngheart.pngheart.pngheart.png
light.pnglight.pnglight.pnglight.png
boat.pngboat.pngboat.pngboat.png
money.pngmoney.pngmoney.pngmoney.png

@thebojdaLaszlo Fazekas

Freelancer developer, ENVIENTA activist, blogger

NFT is a new/old buzzword of the blockchain world. The NFT standard (EIP-721) was created in 2018, but after CrptoKitties this field was relatively silent.

0 reactions
heart.png
light.png
money.png
thumbs-down.png

Nowadays NFTs are back in fashion, and everybody wants to make NFT from everything. You can sell your arts or tweets, or anything that you can imagine in form of NFTs. But what is this mystic NFT thing?

0 reactions
heart.png
light.png
money.png
thumbs-down.png

NFT is not a big deal. As ERC20 (fungible) tokens, NFT (non-fungible tokens) are also simple “databases” on the blockchain.

0 reactions
heart.png
light.png
money.png
thumbs-down.png

While an ERC20 token contract stores balances of Ethereum addresses, the NFT contract stores unique ID -> Ethereum address assignments. When you mint an NFT to yourself, the token contract assigns the unique token ID to your Ethereum address.

0 reactions
heart.png
light.png
money.png
thumbs-down.png

Technically this unique ID is the NFT itself.

You can sell it, or buy other NFTs which is a reassignment of the ID. Metadata can be assigned to the ID (by a URI) that represents the thing behind the NFT (ex.: an image, a tweet, etc.). That’s all. Easy, right? I told, NFT is not a big deal…

0 reactions
heart.png
light.png
money.png
thumbs-down.png

Although an NFT is not a complicated thing, an NFT contract can be quite complex. If you take a look at 0xcert’s implementation, you will find a complex token logic and many internal state variables.

0 reactions
heart.png
light.png
money.png
thumbs-down.png

The problem with complexity is the high transaction cost. In this article, I will show how can you create a minimalistic but fully functional NFT contract on the Ethereum blockchain.

0 reactions
heart.png
light.png
money.png
thumbs-down.png

First of all, take a look at some of the state variables of 0xcert’s implementation:

0 reactions
heart.png
light.png
money.png
thumbs-down.png
mapping (address => uint256[]) internal ownerToIds;
mapping (uint256 => uint256) internal idToOwnerIndex;
mapping (uint256 => address) internal idToOwner;
mapping (address => uint256) private ownerToNFTokenCount;

The

ownerToIds
mapping contains the token IDs that are assigned to the Ethereum address,
idToOwner
is a token ID -> Ethereum address mapping,
idToOwnerIndex
assigns the token ID to the index of the owner’s token array, and finally,
ownerToNFTokenCount
assigns the owners Ethereum address to the token count (how many NFT are owned by the owner).
0 reactions
heart.png
light.png
money.png
thumbs-down.png

As you see, this data structure is strongly redundant, because every mapping could be calculated from the first ownerToIds structure.

All of these mappings are stored on the blockchain, and all of them have to be managed in the contract’s methods. Unfortunately, all of them are needed if we want to implement the ERC-721 token standard. So, what we can do to reduce the complexity and the transactional cost of method calls?

0 reactions
heart.png
light.png
money.png
thumbs-down.png

If ERC-721 compatibility is not needed then we can do a simple trick. In this case, we can store on the blockchain only the things that are absolutely necessary.

0 reactions
heart.png
light.png
money.png
thumbs-down.png

Every other thing can be stored in an external database. If we store the token balances, token lists, etc. in an external (non-blockchain) storage then we don’t need the redundant mappings. The contract will be simpler and the transactions will be cheaper. After the theory, let’s take a look at the code:

0 reactions
heart.png
light.png
money.png
thumbs-down.png

Only 24 lines of code. Not bad. But is it really a fully functional NFT contract? Let’s see. It has 2 methods: mint and transfer. The mint method creates a new NFT token. It has 2 parameters

_to
and
_ipfsHash
. The first parameter is the target Ethereum address that will own the newly minted token.
0 reactions
heart.png
light.png
money.png
thumbs-down.png

The second parameter is a unique hash that points to the metadata on IPFS. In the original ERC-721 specification metadata is pointed by a

tokenURI
. Why do we use an IPFS hash instead? There are many reasons.
0 reactions
heart.png
light.png
money.png
thumbs-down.png

An IPFS hash is only 32 bytes, so writing it to the blockchain is cheaper than a URI string. The second reason is that IPFS is immutable. The content cannot be changed, because if it changes the IPFS hash would also change. So, storing the data on IPFS and writing the hash to the blockchain is something like writing the data itself to the blockchain, but much cheaper.

0 reactions
heart.png
light.png
money.png
thumbs-down.png

The mint method reads the current value of the

tokenCounter
variable to get a unique token ID. The method increments this variable by every call, so the token ID will be absolutely unique. The method stores the token ID - Ethereum address assignment into the
idToOwner
mapping, which is the only one mapping what we store on the blockchain. In the last step, the method emits a Mint event, which will be very important later.
0 reactions
heart.png
light.png
money.png
thumbs-down.png

The transfer method has two parameters

_to
and
_tokenId
. The first parameter is the target address that will own the NFT, and the second parameter is the ID of the token. The first line of the method checks the ownership of the token using the
idToOwner
mapping. Only the token owner can call the transfer method. If the token owned by the caller, then the method modifies the assignment in the mapping and emits a Transfer event.
0 reactions
heart.png
light.png
money.png
thumbs-down.png

This two method is enough for a fully functional NFT. But what about the balances, ownership queries, etc.? Here comes the external database. When a contract emits an event, it will be stored on the blockchain in the logs.

0 reactions
heart.png
light.png
money.png
thumbs-down.png

These logs are available through the JSON-RPC API directly, or you can use the JavaScript API to read them. These logs contain the full transaction history, so they contain every piece of information that is needed. Since they are stored on the blockchain, at every point in time a database can be built from them that contains the token ownership, balances, and every other data that is needed.

0 reactions
heart.png
light.png
money.png
thumbs-down.png

To show this, let’s check the ERC-721 methods and how an external database can provide the data.

0 reactions
heart.png
light.png
money.png
thumbs-down.png
balanceOf
,
ownerOf
- These can be easily calculated from Mint and Transfer events
0 reactions
heart.png
light.png
money.png
thumbs-down.png
approve
,
setApprovalForAll
,
getApproved
,
isApprovedForAll
- Our minimalistic NFT doesn’t provide approval logic, only the owner can transfer the tokens. If needed, this feature can be implemented by a second mapping.
0 reactions
heart.png
light.png
money.png
thumbs-down.png
safeTransferFrom
,
transferFrom
- Transfer safety can be checked externally, and from parameter is meaningless here, because our tokens can be transferred only by the owner.
0 reactions
heart.png
light.png
money.png
thumbs-down.png
tokenURI
- The URI of the token can be generated from the IPFS hash part of the Mint event.
0 reactions
heart.png
light.png
money.png
thumbs-down.png
totalSupply
,
tokenByIndex
,
tokenOfOwnerByIndex
- These can be calculated easily from the Mint and Transfer events.
0 reactions
heart.png
light.png
money.png
thumbs-down.png

As you can see, our minimalistic NFT token can do everything that an ERC-721 token can do except the approval logic, but it can be implemented if needed.

0 reactions
heart.png
light.png
money.png
thumbs-down.png
6
heart.pngheart.pngheart.pngheart.png
light.pnglight.pnglight.pnglight.png
boat.pngboat.pngboat.pngboat.png
money.pngmoney.pngmoney.pngmoney.png
by Laszlo Fazekas @thebojda. Freelancer developer, ENVIENTA activist, bloggerRead my stories
Join Hacker Noon

Create your free account to unlock your custom reading experience.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK