Skip to content

Commit

Permalink
Merge pull request #1152 from lukso-network/contracts-docs
Browse files Browse the repository at this point in the history
Re-organise sidebar of contracts section + improve LSP25 standard page + improve type of executions in LSP6 standard page + improve the Contracts section for LSP6
  • Loading branch information
CJ42 authored Oct 9, 2024
2 parents b604c81 + 2cd1191 commit 24bec59
Show file tree
Hide file tree
Showing 13 changed files with 606 additions and 452 deletions.
4 changes: 2 additions & 2 deletions docs/contracts/deployed-contracts.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
title: ⛓ Deployed Base Contracts
title: ⛓ Deployed Implementation Contracts
description: List of base implementation and factory contracts addresses deployed on LUKSO Mainnet.
---

import { BaseContractsTable, FactoryContractsTable } from "@site/src/components/DeployedContractsTable"

# Deployed Base Contracts on LUKSO Mainnet
# Deployed Implementation Contracts on LUKSO Mainnet

:::success Deployment Guides

Expand Down
231 changes: 1 addition & 230 deletions docs/contracts/overview/DigitalAssets.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Digital Assets (Token & NFT)
title: 🪙 Digital Asset (Token)
sidebar_position: 4
---

Expand Down Expand Up @@ -120,235 +120,6 @@ contract MyToken is LSP7DigitalAsset {
}
```

## LSP8 Identifiable Digital Asset

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)**.

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).

### Setting metadata for one or multiple tokenIds

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:

<Tabs>

<TabItem value="solidity" label="solidity">

```solidity
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.12;
import {
ILSP8IdentifiableDigitalAsset as ILSP8
} from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol";
import {
_LSP4_METADATA_KEY
} from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol";
bytes32 constant _NFT_ICON_DATA_KEY = keccak256("NFTIcon");
bytes32 constant _NFT_MARKET_PLACE_URLS__DATA_KEY = keccak256("NFTMarketplaceURLs");
bytes32 constant _TOKEN_ID_TO_SET = 0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe;
function setMultipleDataForSingleTokenId(
ILSP8 lsp8Contract,
bytes memory lsp4MetadataValue,
bytes memory nftIconValue,
bytes memory nftMarketPlaceURLsValue
) {
bytes32[] memory tokenIdsToUpdate = new bytes32[](3);
bytes32[] memory dataKeysToSet = new bytes32[](3);
bytes[] memory dataValuesToSet = new bytes[](3);
// we are setting 3 x data key-value pairs for the same tokenid
tokenIdsToUpdate[0] = _TOKEN_ID_TO_SET;
tokenIdsToUpdate[1] = _TOKEN_ID_TO_SET;
tokenIdsToUpdate[2] = _TOKEN_ID_TO_SET;
dataKeysToSet[0] = _LSP4_METADATA_KEY;
dataKeysToSet[1] = _NFT_ICON_DATA_KEY;
dataKeysToSet[2] = _NFT_MARKET_PLACE_URLS__DATA_KEY;
dataValuesToSet[0] = lsp4MetadataValue;
dataValuesToSet[1] = nftIconValue;
dataValuesToSet[2] = nftMarketPlaceURLsValue;
lsp8Contract.setDataBatchForTokenIds(
tokenIdsToUpdate,
dataKeysToSet,
dataValuesToSet
);
}
```

</TabItem>

<TabItem value="ethers-v6" label="ethers v6">

```js
import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts';

const _NFT_ICON_DATA_KEY = keccak256('NFTIcon');
const _NFT_MARKET_PLACE_URLS__DATA_KEY = keccak256('NFTMarketplaceURLs');

const _TOKEN_ID_TO_SET =
'0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe';

async function setMultipleDataForSingleTokenId(
lsp8Contract,
lsp4MetadataValue,
nftIconValue,
nftMarketPlaceURLsValue,
) {
const tokenIdsToUpdate = [
_TOKEN_ID_TO_SET,
_TOKEN_ID_TO_SET,
_TOKEN_ID_TO_SET,
];

const dataKeysToSet = [
ERC725YDataKeys.LSP4.LSP4Metadata,
_NFT_ICON_DATA_KEY,
_NFT_MARKET_PLACE_URLS__DATA_KEY,
];

const dataValuesToSet = [
lsp4MetadataValue,
nftIconValue,
nftMarketPlaceURLsValue,
];

await lsp8Contract.setDataBatchForTokenIds(
tokenIdsToUpdate,
dataKeysToSet,
dataValuesToSet,
);
}
```

</TabItem>

</Tabs>

#### Case 2: 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:

<Tabs>

<TabItem value="solidity" label="solidity">

```solidity
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.12;
import {
ILSP8IdentifiableDigitalAsset as ILSP8
} from "@lukso/lsp-smart-contracts/contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol";
import {
_LSP4_METADATA_KEY
} from "@lukso/lsp-smart-contracts/contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol";
bytes32 constant _FIRST_TOKEN_ID_TO_SET = 0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe;
bytes32 constant _SECOND_TOKEN_ID_TO_SET = 0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef;
bytes32 constant _THIRD_TOKEN_ID_TO_SET = 0xf00df00df00df00df00df00df00df00df00df00df00df00df00df00df00df00d;
function setMultipleDataForSingleTokenId(
ILSP8 lsp8Contract,
bytes memory firstTokenIdLsp4MetadataValue,
bytes memory secondTokenIdLsp4MetadataValue,
bytes memory thirdTokenIdLsp4MetadataValue
) {
bytes32[] memory tokenIdsToUpdate = new bytes32[](3);
bytes32[] memory dataKeysToSet = new bytes32[](3);
bytes[] memory dataValuesToSet = new bytes[](3);
tokenIdsToUpdate[0] = _FIRST_TOKEN_ID_TO_SET;
tokenIdsToUpdate[1] = _SECOND_TOKEN_ID_TO_SET;
tokenIdsToUpdate[2] = _THIRD_TOKEN_ID_TO_SET;
// we are setting the metadata for 3 x different tokenIds
dataKeysToSet[0] = _LSP4_METADATA_KEY;
dataKeysToSet[1] = _LSP4_METADATA_KEY;
dataKeysToSet[2] = _LSP4_METADATA_KEY;
dataValuesToSet[0] = firstTokenIdLsp4MetadataValue;
dataValuesToSet[1] = secondTokenIdLsp4MetadataValue;
dataValuesToSet[2] = thirdTokenIdLsp4MetadataValue;
lsp8Contract.setDataBatchForTokenIds(
tokenIdsToUpdate,
dataKeysToSet,
dataValuesToSet
);
}
```

</TabItem>

<TabItem value="ethers-v6" label="ethers v6">

```js
import { ERC725YDataKeys } from '@lukso/lsp-smart-contracts';

const _FIRST_TOKEN_ID_TO_SET =
'0xcafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe';
const _SECOND_TOKEN_ID_TO_SET =
'0xbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef';
const _THIRD_TOKEN_ID_TO_SET =
'0xf00df00df00df00df00df00df00df00df00df00df00df00df00df00df00df00d';

async function setMultipleDataForSingleTokenId(
lsp8Contract,
firstTokenIdLsp4MetadataValue,
secondTokenIdLsp4MetadataValue,
thirdTokenIdLsp4MetadataValue,
) {
const tokenIdsToUpdate = [
_FIRST_TOKEN_ID_TO_SET,
_SECOND_TOKEN_ID_TO_SET,
_THIRD_TOKEN_ID_TO_SET,
];

const dataKeysToSet = [
ERC725YDataKeys.LSP4.LSP4Metadata,
ERC725YDataKeys.LSP4.LSP4Metadata,
ERC725YDataKeys.LSP4.LSP4Metadata,
];

const dataValuesToSet = [
firstTokenIdLsp4MetadataValue,
secondTokenIdLsp4MetadataValue,
thirdTokenIdLsp4MetadataValue,
];

await lsp8Contract.setDataBatchForTokenIds(
tokenIdsToUpdate,
dataKeysToSet,
dataValuesToSet,
);
}
```

</TabItem>

</Tabs>

### Checking if the Metadata of a tokenId 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).

## Extensions

The smart contracts packages for `@lukso/lsp7-contracts` and `@lukso/lsp8-contracts` include token extensions (similarly to OpenZeppelin contracts) that enables to include functionalities for building your token through inheritance.
Expand Down
64 changes: 18 additions & 46 deletions docs/contracts/overview/ExecuteRelayCall.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,32 @@
---
sidebar_position: 5
title: ⛽️ Execute Relay Call (Meta Transactions)
sidebar_position: 7
---

# Execute Relay Call

## Validity timestamps
## Sequential relay calls in the same channel

:::info
When executing 3 sequential relay calls with sequential nonces in a single channel (= nonces from the KeyManager retrieved via [`getNonce`](../contracts/LSP6KeyManager/LSP6KeyManager.md#getnonce), keep in mind that **if the first transaction does revert, the next 2 will revert in turns**. That happens because a Key Manager nonce is assigned to each relay call.

Use this website to generate validity timestamps for specific date and time.
E.g.:

:::
- First relay call - nonce is 4
- Second relay call - nonce is 5
- Third relay call - nonce is 6

It is possible to make signatures for relay executions valid for specific time periods. This is done by constructing a **validity timestamp** that can be passed as the `uint256 validityTimestamp` parameter to `executeRelayCall` and `executeRelayCallBatch` functions.
One of the requirements for executing a relay call is that **the latest nonce (for a specific signer) stored on-chain in the Key Manager contract must be the same as the one used when signing the executed relay call**. After each successful execution, the on-chain nonce is incremented.

Below are examples of constructing different **validity timestamps**:
Given the example above, the on-chain nonce is 4 and we are executing the relay calls.

### Example 1: from a specific date / time
**If the first relay call pass ✅**

Valid only from the 1st June 2024 (midnight).
- First relay call: nonce was 4 -> incremented to 5
- Second relay call: nonce was 5 -> incremented to 6
- Third relay call: nonce was 6 -> incremented to 7

Timestamp for _1st June 2024_ = `1717200000` (decimal) = `0x665A6480` (hex)
**If the first relay call fails ❌**

```
valid from timestamp 1717200000
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
0x000000000000000000000000665A648000000000000000000000000000000000
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
valid until indefinitely
```

### Example 2: set an expiry date

Valid until 31st January 2025, 5pm CET.

Timestamp for _31st January 2025 (5pm CET)_ = `1738339200` (decimal) = `0x679CF380` (hex)

```
valid from anytime
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
0x00000000000000000000000000000000000000000000000000000000679CF380
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
valid until 31st January 2025 (5pm CET)
```

### Example 3: valid during a specific period

Valid from 1st January 2024 (midnight CET) to 1st April 2024 (midnight CET)

- Timestamp for _1st January 2024 (midnight)_ = `1704063600` (decimal) = `0x6591F270` (hex)
- Timestamp for _1st April 2024 (midnight)_ = `1711926000` (decimal) = `0x6609EAF0` (hex)

```
valid from
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
0x0000000000000000000000006591F2700000000000000000000000006609EAF0
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
valid until
```
- **First relay call reverts ❌** nonce was 4 -> nonce remains 4
- Second relay call: nonce on-chain is 4 -> nonce used to sign was 5 = reverts ❌ with [`InvalidRelayNonce`](../contracts//LSP6KeyManager/LSP6KeyManager.md#invalidrelaynonce)
- Third relay call: nonce on-chain is 5 -> nonce used to sign was 6 = reverts ❌ with [`InvalidRelayNonce`](../contracts//LSP6KeyManager/LSP6KeyManager.md#invalidrelaynonce)
4 changes: 2 additions & 2 deletions docs/contracts/overview/FollowerSystem.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
sidebar_label: 'Follower System'
sidebar_position: 9
sidebar_label: '🔂 Follower System'
sidebar_position: 8
description: How to interact with and implement the LUKSO LSP26 Follower System in your dApps and smart contracts.
---

Expand Down
Loading

0 comments on commit 24bec59

Please sign in to comment.