Skip to content

Commit

Permalink
Merge pull request #1156 from lukso-network/docs/contracts-section
Browse files Browse the repository at this point in the history
improve contracts section for Tokens & NFTs (LSP7 + LSP8)
  • Loading branch information
CJ42 authored Oct 21, 2024
2 parents 468cadb + 8c60b71 commit c6992c0
Show file tree
Hide file tree
Showing 15 changed files with 561 additions and 174 deletions.
149 changes: 0 additions & 149 deletions docs/contracts/overview/DigitalAssets.md

This file was deleted.

4 changes: 4 additions & 0 deletions docs/contracts/overview/NFT/_category_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
label: 🖼️ Identifiable Digital Asset (NFT)
position: 5
collapsible: true
collapsed: true
52 changes: 52 additions & 0 deletions docs/contracts/overview/NFT/create-nft-collection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: Create a Non Fungible Token
sidebar_position: 1
---

# Create a Non Fungible Token

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
// modules
import {
LSP8IdentifiableDigitalAsset
} from "@lukso/lsp8-contracts/contracts/LSP8IdentifiableDigitalAsset.sol";
// constants
import {
_LSP8_TOKENID_FORMAT_NUMBER
} from "@lukso/lsp8-contracts/contracts/LSP8Constants.sol";
import {
_LSP4_TOKEN_TYPE_COLLECTION
} from "@lukso/lsp4-contracts/contracts/LSP4Constants.sol";
contract BasicNFTCollection is LSP8IdentifiableDigitalAsset {
constructor(
string memory nftCollectionName,
string memory nftCollectionSymbol,
address contractOwner
)
LSP8IdentifiableDigitalAsset(
nftCollectionName,
nftCollectionSymbol,
contractOwner,
_LSP4_TOKEN_TYPE_COLLECTION,
_LSP8_TOKENID_FORMAT_NUMBER
)
{
// contract logic goes here...
}
}
```

## LSP8 NFT extensions

The `@lukso/lsp8-contracts` package includes token extensions (similarly to OpenZeppelin contracts) that can be added through inheritance. This enables to include specific functionalities for building your token.

| Extension contract | Description |
| :---------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- |
| [`LSP8Burnable.sol`](../../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Burnable.md) | exposes a public `burn(...)` function that allows any NFT holder or operator to burn a specific NFT tokenId. |
| [`LSP8CappedSupply.sol`](../../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8CappedSupply.md) | enable to specify a maximum supply on deployment / initialization, which caps the maximum amount of NFT that can be minted in the collection. |
| [`LSP8Enumerable.sol`](../../contracts/LSP8IdentifiableDigitalAsset/extensions/LSP8Enumerable.md) | functionality to enumerate the list of NFTs in a collection. |
8 changes: 8 additions & 0 deletions docs/contracts/overview/NFT/customise-transfer-behaviour.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: Customize transfer behaviour
sidebar_position: 2
---

# Customize transfer behaviour

The `LSP8IdenfitiableDigitalAsset` contract implementation includes the `_beforeTokenTransfer` and `_afterTokenTransfer` functions that offer the ability to specify custom logic that can run before or after the token transfer has happen (= before or after the balances in the contract state have been updated).
91 changes: 91 additions & 0 deletions docs/contracts/overview/NFT/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
title: 🖼️ Identifiable Digital Asset (NFT)
sidebar_position: 5
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# LSP8 Identifiable Digital Asset

:::danger Deprecation of `LSP8CompatibleERC721`

The `LSP8CompatibleERC721` contracts have been deprecated and deleted from the [`@lukso/lsp-smart-contracts`](https://github.com/lukso-network/lsp-smart-contracts) package since version `0.15.0`, because of their unsafe nature and [security considerations (See PR #845 for more details)](https://github.com/lukso-network/lsp-smart-contracts/pull/845#issuecomment-1888671461).

They are not recommended to be used. However, if you want to still use them, they remain available in the version [`0.14.0`](https://github.com/lukso-network/lsp-smart-contracts/releases/tag/lsp-smart-contracts-v0.14.0).

:::

The **LSP8 Identifiable Digital Asset** contract is the newest advanced version of the existing ERC NFT standards, such as ERC721. LSP8 identifiable digital assets represent **N**on **F**ungible **T**okens (NFTs) that can be uniquely traded. Each NFT is identified with a tokenId, based on **[ERC721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol)** and can also have its own metadata set using the **[`setDataForTokenId(...)`](../../contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatafortokenid)** function.

A **bytes32** value is used for tokenId to allow many uses of token identification, including numbers, contract addresses, and hashed values (i.e., serial numbers).

## Installation & Usage

The LSP8 smart contracts and their ABIs are available are available in their own individual package. To use them, install `@lukso/lsp8-contracts` as a dependency in your project.

<Tabs groupId="provider-lib">
<TabItem value="npm" label="npm" default>

```
npm install @lukso/lsp8-contracts
```

</TabItem>
<TabItem value="yarn" label="yarn" default>

```
yarn add @lukso/lsp8-contracts
```

</TabItem>
<TabItem value="pnpm" label="pnpm" default>

```
pnpm add @lukso/lsp8-contracts
```

</TabItem>
</Tabs>

`LSP8IdentifiableDigitalAsset.sol` is an `abstract` contract that is not deployable as is, because it does not contain any public functions by default to manage token supply (_e.g: no public `mint(...)` or `burn(...)` functions_). You can either:

- use the `LSP8Mintable` preset contract that contains a public `mint(...)` function callable only by the contract's owner.
- or extend the `LSP8IdentifiableDigitalAsset` contract (_see below_) and create your own supply mechanism by defining public methods that use the internal `_mint(...)` and `_burn(...)` functions.

## Comparisons with ERC721

<table>
<tr>
<th>Description</th>
<th>ERC721</th>
<th>LSP8</th>
</tr>
<tr>
<td>Transferring tokens as an owner.</td>
<td rowspan="2">
<code>transferFrom(address,address,uint256)</code><br/>
<code>safeTransferFrom(address,address,uint256)</code><br/>
<code>safeTransferFrom(address,address,uint256,bytes)</code>
</td>
<td rowspan="2"><code>transfer(address,address,bytes32,bool,bytes)</code></td>
</tr>
<tr>
<td>Transferring tokens as an operator.</td>
</tr>
<tr>
<td>Approving an operator to spend tokens on behalf of the owner.</td>
<td><code>approve(address,uint256)</code></td>
<td><code>authorizeOperator(address,bytes32)</code></td>
</tr>
</table>

In comparison ERC721 has:

- `safeTransferFrom(address,address,uint256,bytes)`
- `safeTransferFrom(address,address,uint256)`
- `transferFrom(address,address,uint256)`

All of the above functions can be used by both the owner of the token id or by the operator of the token id in order to transfer the ERC721 token. To be mentioned, both functions `safeTransferFrom(...)` have a hook that calls the recipient contract.

Looking at LSP7 & LSP8 we have unified `transfer(...)` & `transferBatch(...)` functions in both contracts. Those functions contain a hook which is executed conditionally and can be used in any of the above cases.
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
---
title: 🖼️ Identifiable Digital Asset (NFT)
sidebar_position: 5
title: Set NFT Metadata
sidebar_position: 3
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

## LSP8 Identifiable Digital Asset
# Set NFT Metadata

The **LSP8IdentifiableDigitalAsset** contract represents identifiable digital assets (NFTs) that can be uniquely traded and given metadata using the **[ERC725Y Standard](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-725.md#erc725y)**.
Each NFT is identified with a tokenId, based on **[ERC721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol)**.
The function [`setDataBatchForTokenIds(...)`](../../contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatabatchfortokenids) can be used to set multiple [data key-value](/standards/erc725.md#erc725y-generic-data-keyvalue-store) pairs at once for one or multiple tokenIds.

A **bytes32** value is used for tokenId to allow many uses of token identification, including numbers, contract addresses, and hashed values (i.e., serial numbers).
## Examples

### Setting metadata for one or multiple tokenIds
### Set multiple metadata at once on the same tokenId

The function [`setDataBatchForTokenIds(...)`](../../contracts/contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#setdatabatchfortokenids) can be used to set multiple data key-value pairs at once for one or multiple tokenIds.

This function is flexible enough to enable to set one or multiple [data key-value](/standards/erc725).md#erc725y-generic-data-keyvalue-store) pairs for:

#### case 1: a single tokenId

To set for instance 3 x data key-value pairs for the same `tokenId`, the parameters of `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` will be as follow:
To set for instance 3 x data key-value pairs for the same `tokenId`, the parameters of `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` can be used as follow:

<Tabs>

Expand Down Expand Up @@ -123,9 +116,9 @@ async function setMultipleDataForSingleTokenId(

</Tabs>

#### Case 2: different tokenIds
### Set metadata on different tokenIds

To set for instance the same data key-value pair (_e.g: `LSP4Metadata`_) for 3 x different `tokenId`s, the parameters of `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` will be as follow:
To set for instance the same data key-value pair (_e.g: `LSP4Metadata`_) for 3 x different `tokenId`s, the parameters of `setDataBatchForTokenIds(bytes32[],bytes32[],bytes[])` can be used as follow:

<Tabs>

Expand Down Expand Up @@ -227,10 +220,10 @@ async function setMultipleDataForSingleTokenId(

</Tabs>

### Checking if the Metadata of a tokenId changed
## Check if the metadata of a specific NFT (tokenId) has changed

Since LSP8 uses [ERC725Y](/standards/erc725#erc725y-generic-data-keyvalue-store) under the hood, the URI pointing to the metadata of a specific tokenId can be changed inside the ERC725Y storage of the LSP8 contract.

We have seen in the previous section [**how to set metadata for one or multiple tokenIds**](#setting-metadata-for-one-or-multiple-tokenids).

The two functions `setDataForTokenId(...)` and `setDataBatchForTokenIds(...)` emit a [`TokenIdDataChanged`](../contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#tokeniddatachanged) event. You can listen for this event in the LSP8 contract from your dApp, filtering for the `LSP4Metadata` data key to check if the metadata of a tokenId has been changed. You can do so by filtering the first parameter with the `tokenId` and the second parameter with the [bytes32 value of the `LSP4Metadata` data key](../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata).
The two functions `setDataForTokenId(...)` and `setDataBatchForTokenIds(...)` emit a [`TokenIdDataChanged`](../../contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.md#tokeniddatachanged) event. You can listen for this event in the LSP8 contract from your dApp, filtering for the `LSP4Metadata` data key to check if the metadata of a tokenId has been changed. You can do so by filtering the first parameter with the `tokenId` and the second parameter with the [bytes32 value of the `LSP4Metadata` data key](../../../standards/tokens/LSP4-Digital-Asset-Metadata.md#lsp4metadata).
4 changes: 4 additions & 0 deletions docs/contracts/overview/Token/_category_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
label: 🪙 Digital Asset (Token)
position: 4
collapsible: true
collapsed: true
Loading

0 comments on commit c6992c0

Please sign in to comment.