# ZTP-721

| Method   | Description                                           |
| -------- | ----------------------------------------------------- |
| name     | Token Name. Example: “Global Coin”                    |
| symbol   | Token Symbol. Example: GCN                            |
| describe | Token description: “Global coin token issued  by XYZ” |
| version  | Token version                                         |

## Simple Summary

A standard interface for non-fungible tokens, also known as deeds.

## Abstract

The following standard allows for the implementation of a standard API for NFTs (non-fungible tokens) within smart contracts. This standard provides basic functionality to track and transfer NFTs.

We considered use cases of NFTs being owned and transacted by individuals as well as consignment to third party brokers/wallets/auctioneers (“operators”). NFTs can represent ownership over digital or physical assets. We considered a diverse universe of assets, and we know you will dream up many more:

* Physical property — houses, unique artwork
* Virtual collectibles — unique pictures of kittens, collectible cards
* “Negative value” assets — loans, burdens and other responsibilities

In general, all houses are distinct and no two kittens are alike. NFTs are *distinguishable* and you must track the ownership of each one separately.

## Motivation

A standard interface allows wallet/broker/auction applications to work with any NFT on Zetrix. Additional applications are discussed below.

## Specification Token Methods

#### balanceOf

Count all NFTs assigned to an  `owner` , and returns the number of NFTs owned by `owner` , possibly zero.

```javascript
self.balanceOf = function (paramObj) {
    Utils.assert(Utils.addressCheck(paramObj.owner), "ERC721: Invalid owner address: " + paramObj.owner);
    let balance = BasicOperationUtil.loadObj(BasicOperationUtil.getKey(BALANCES_PRE, paramObj.owner));
    if (balance === false) {
        return '0';
    }
    return balance;
};
```

#### ownerOf

Find the owner of an NFT, and returns the address of the owner of the NFT.

```javascript
self.ownerOf = function (paramObj) {
    return _requiredOwned(paramObj.tokenId);
};
```

#### safeTransferFrom

Transfers the ownership of an NFT from one address to another address. This function SHOULD also enforce the `onZTP721Received` check to ensure that if the receiver is a contract address, it is able to receive NFTs.

```javascript
self.safeTransferFrom = function (paramObj) {
    self.transferFrom(paramObj);
    /*
     if(paramObj.data !== "") {
         // Implement checkOnZTP721Received
     }
    */
};
```

#### transferFrom

Transfers the ownership of an NFT from one address to another address.&#x20;

Note: THE CALLER IS RESPONSIBLE TO CONFIRM THAT THE RECEIVER IS CAPABLE OF RECEIVING NFTS OR ELSE THEY MAY BE PERMANENTLY LOST.

```javascript
self.transferFrom = function (paramObj) {
    Utils.assert(Utils.addressCheck(paramObj.to), "ERC721: Invalid receiver address.");
    let previousOwner = self.p.update(paramObj.to, paramObj.tokenId, Chain.msg.sender);
    Utils.assert(previousOwner === paramObj.from, "ERC721: Incorrect owner");
};
```

#### approve

Change or reaffirm the approved address for an NFT.

```javascript
self.approve = function (paramObj) {
    return self.p.approve(paramObj.to, paramObj.tokenId, Chain.msg.sender);
};
```

#### setApprovalForAll

Enable or disable approval for a third party ("operator") to manage all of `Chain.msg.sender`'s assets.

```javascript
self.setApprovalForAll = function (paramObj) {
    return self.p.setApprovalForAll(Chain.msg.sender, paramObj.operator, paramObj.approved);
};
```

#### getApproved

Get the approved address for a single NFT, and returns the approved address for this NFT.

```javascript
self.getApproved = function (paramObj) {
    _requiredOwned(paramObj.tokenId);
    return self.p.getApproved(paramObj.tokenId);
};
```

#### isApprovedForAll

Query if an address is an authorized operator for another address, and returns true if `operator` is an approved operator for `owner`, false otherwise.

```javascript
self.isApprovedForAll = function (paramObj) {
    return BasicOperationUtil.loadObj(BasicOperationUtil.getKey(OPERATOR_APPROVAL_PRE, paramObj.owner, paramObj.operator));
};
```

#### Note: A wallet/broker/auction application MUST implement the **wallet interface** (ZTP721Receiver interface with the onERC721Received function) if it will accept safe transfers.

## [Zetrix Ecosystem Proposals](https://github.com/Zetrix-Chain/zetrix-protocol)

Sample ZTP721 contract can be found [here](https://github.com/Zetrix-Chain/zetrix-protocol/blob/main/ZTP/ZTP-721.js).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.zetrix.com/en/developer-resources/smart-contract/ztp-standard/ztp-721.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
