> For the complete documentation index, see [llms.txt](https://docs.kubchain.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kubchain.com/quickstart/launching-a-token-on-kub/kap-token-interfaces/kap-721.md).

# KAP-721

The following standard outlines a smart contract interface and logic for non-fungible tokens on KUB that supports an `adminTransfer` function designed to create transactions on behalf of NFT holders if they have been a victim of a fraudulent transaction. It is proposed by deriving the ERC-721 standard of Ethereum with additional functions related to `adminTransfer`.

## Token Interface

### IAdminProjectRouter

#### isSuperAdmin

Check whether `_addr` is the Super Admin role in `_project`.

```solidity
function isSuperAdmin(address _addr, string calldata _project) external view returns (bool)
```

#### isAdmin

Check whether `_addr` is the Admin role in `_project`.

```solidity
function isAdmin(address _addr, string calldata _project) external view returns (bool)
```

### IKYCBitkubChain

#### kycsLevel

Returns the KYC Level of `_addr`.

```solidity
function kycsLevel(address _addr) external view returns (uint256)
```

### IKAP165

#### supportsInterface

Check whether the contract implements `interfaceID` and the `interfaceID` is not `0xffffffff`.

```solidity
function supportsInterface(bytes4 interfaceId) external view returns (bool)
```

{% hint style="info" %}
NOTE: Query if the contract implements an interface
{% endhint %}

### IKAP721

#### balanceOf

Returns the number of NFTs owned by the address `owner`, possibly zero.

```solidity
function balanceOf(address owner) external view returns (uint256 balance)
```

{% hint style="info" %}
NOTE: NFTs assigned to the zero address are considered invalid, and this function `throw` for queries about the zero address.
{% endhint %}

#### ownerOf

Returns the address `owner` of the owner of the NFT `tokenID`.

```solidity
function ownerOf(uint256 tokenId) external view returns (address owner);
```

{% hint style="info" %}
NOTE: NFTs assigned to the zero address are considered invalid, and this function `throw` for queries about the zero address.
{% endhint %}

#### safeTransferFrom

Transfers the ownership of NFT `tokenID` from address `from` to address `to`.

* `throw` unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT `tokenID`.
* `throw` if `from` is not the current owner.
* `throw` if `to` is the zero address.
* `throw` if `tokenID` is not a valid NFT.

When the transfer is complete, this function checks if `to` is a smart contract (code size > 0). If so, it calls `onKAP721Received` on `to` and `throw` if the return value is not `bytes4(keccak256("onKAP721Received(address,address,uint256,bytes)"))`.

```solidity
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external
```

#### transferFrom

Transfers the ownership of NFT `tokenID` from address `from` to address `to`.

* `throw` unless ‘msg.sender‘ is the current owner, an authorized operator, or the approved address for this NFT `tokenID`.
* `throw` if `from` is not the current owner.
* `throw` if `to` is the zero address.
* `throw` if `tokenID` is not a valid NFT.

```solidity
function transferFrom(address from, address to, uint256 tokenId) external
```

{% hint style="info" %}
NOTE: The caller is responsible to confirm that `to` address is capable of receiving NFTs, or else they may be permanently lost.
{% endhint %}

#### adminTransfer

Transfers NFT `tokenID` from address `from` to address `to`, and MUST fire the `Transfer` event.

```solidity
function adminTransfer(address from, address to, uint256 tokenId) external
```

{% hint style="info" %}
NOTE: This function can only be called by the Committee address required in the constructor. This function is designed to create transactions automatically on behalf of NFT holders if they have been a victim of a fraudulent transaction. This method works similarly to the `transferFrom` method.
{% endhint %}

#### internalTransfer

Transfers NFT `tokenID` to address `to` internally from address `from`, and MUST fire the `Transfer` event. The function SHOULD `throw` if the message caller’s account balance does not have the specify NFT `tokenID`. NFTs can be transferred between internal addresses that have completed KYC for both the address `from` and the address `to` using the `internalTransfer` function.

```solidity
function internalTransfer(address from, address to, uint256 tokenId) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Super Admin and the Transfer Router.
{% endhint %}

#### externalTransfer

Transfers NFT `tokenID` to address `to` externally from address `from`, and MUST fire the `Transfer` event. The function SHOULD `throw` if the message caller’s account balance does not have the specified NFT `tokenID`. The function `externalTransfer` allows NFTs to be transferred between addresses that have only passed the sender’s KYC verification process.

```solidity
function externalTransfer(address from, address to, uint256 tokenId) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Super Admin and the Transfer Router.
{% endhint %}

#### approve

Change or reaffirm the approved address for an NFT `tokenID` to the address `to`. The zero address indicates there is no approved address.

`throw` unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.

```solidity
function approve(address to, uint256 tokenId) external
```

#### getApproved

Returns the approved address `operator` for this NFT `tokenID`, or the zero address if there is none.

`throw` if `tokenID` is not a valid NFT.

```solidity
function getApproved(uint256 tokenId) external view returns (address operator)
```

#### setApprovalForAll

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

`approve` true if the `operator` is approved, false to revoke approval.

Emits the `ApprovalForAll` event. The contract MUST allow multiple operators per owner.

```solidity
function setApprovalForAll(address operator, bool approved) external
```

#### isApprovedForAll

Check whether `operator` is an approved operator for `owner`.

```solidity
function isApprovedForAll(address owner, address operator) external view returns (bool)
```

{% hint style="info" %}
NOTE: Query if an address `operator` is an authorized operator for another address `owner`.
{% endhint %}

#### safeTransferFrom

Transfers the ownership of NFT `tokenID` from address `from` to address `to`. This works identically to the other function with an extra data parameter, except this function sets data to “”.

```solidity
function safeTransferFrom(address from, address to, uint256 tokenId) external
```

### Events

#### Transfer

This event emits when ownership of any NFT `tokenID` changes by any mechanism, when NFTs are created (`from` == `0`), and when NFTs are destroyed (`to` == `0`).

```solidity
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)
```

{% hint style="info" %}
EXCEPTION: During contract creation, any number of NFTs may be created and assigned without emitting `Transfer`. At the time of any transfer, the approved address for that NFT (if any) is reset to none.
{% endhint %}

#### Approval

This event emits when the `approved` address for an NFT `tokenID` is changed or reaffirmed. The zero address indicates there is no approved address. When a transfer event emits, this also indicates that the approved address for that NFT (if any) is reset to none.

```solidity
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId)
```

#### ApprovalForAll

This event emits when `operator` is enabled or disabled for `owner`. The `operator` can manage all NFTs of the `owner`.

```solidity
event ApprovalForAll(address indexed owner, address indexed operator, bool approved)
```

### IKAP721V2

#### tokenOfOwnerByPage

Returns the list of token identifier for the NFT from `page` to `limit` assigned to `owner`, (sort order not specified).

* `throw` if `limit` is greater than or equals to `balanceOf(owner)`
* `throw` if `page` is less than `0`&#x20;
* `throw` if `limit` is less than `0`
* `throw` if `owner` is the zero address, representing invalid NFTs.

```solidity
function tokenOfOwnerByPage(address owner, uint256 page, uint256 limit) external view returns (uint256[] memory)
```

#### tokenOfOwnerAll

Returns the array of all token identifiers for the NFT assigned to `owner`, (sort order not specified).

```solidity
function tokenOfOwnerAll(address owner) external view returns (uint256[] memory)
```

#### adminApprove

Change or reaffirm the approved address for an NFT `tokenID` to the address `to`. The zero address indicates there is no approved address. This method works similarly to the `approve` method.

`throw` unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.

```solidity
function adminApprove(address to, uint256 tokenId) external
```

{% hint style="info" %}
NOTE: This function can only be called by the Admin and Super Admin. This function is designed to create transactions automatically on behalf of token holders if they have been victims of a fraudulent transaction.
{% endhint %}

#### adminSetApprovalForAll

Enable or disable approval for a third party `operator` to manage all of `msg.sender` assets. `approve` true if the `operator` is approved, false to revoke approval. This method works similarly to the `setApprovalForAll` method.

Emits the `ApprovalForAll` event. The contract MUST allow multiple operators per owner.

```solidity
function adminSetApprovalForAll(address owner, address operator, bool approved) external
```

{% hint style="info" %}
NOTE: This function can only be called by the Admin and Super Admin. This function is designed to create transactions automatically on behalf of token holders if they have been victims of a fraudulent transaction.
{% endhint %}

### IKAP721Metadata

#### name

A descriptive name for a collection of NFTs in this contract.

```solidity
function name() external view returns (string memory)
```

#### symbol

An abbreviated name for NFTs in this contract

```solidity
function symbol() external view returns (string memory)
```

#### tokenURI

A distinct Uniform Resource Identifier (URI) for a given asset.

`throw` if `tokenID` is not a valid NFT. URIs are defined in RFC 3986. The URI may point to a JSON file that conforms to the “KAP721 Metadata JSON Schema”.

```solidity
function tokenURI(uint256 tokenId) external view returns (string memory)
```

### IKAP721Enumerable

#### totalSupply

Returns a count of valid NFTs tracked by this contract, where each one of them has an assigned and queryable owner not equal to the zero address.

```solidity
function totalSupply() external view returns (uint256)
```

#### tokenOfOwnerByIndex

Returns the token identifier for the `index` NFT assigned to `owner`, (sort order not specified).

`throw` if `index` is greater than or equal to `balanceOf(owner)` or if `owner` is the zero address, representing invalid NFTs.

```solidity
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId)
```

#### tokenByIndex

Returns the token identifier for the `index` NFT, (sort order not specified).

`throw` if `index` is greater than or equal to `totalSupply()`

```solidity
function tokenByIndex(uint256 index) external view returns (uint256)
```

### IKAP721Receiver

#### onKAP721Received

The KAP721 smart contract calls this function on the recipient after a `Transfer`. This function MAY `throw` to revert and reject the transfer. Return of other than the magic value `bytes4(keccak256("onKAP721Received(address,address,uint256,bytes)"))` MUST result in the transaction being reverted.

```solidity
function onKAP721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4)
```

{% hint style="info" %}
NOTE: The contract address should always be the message sender.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.kubchain.com/quickstart/launching-a-token-on-kub/kap-token-interfaces/kap-721.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
