Skip to content

Commit 223a162

Browse files
authored
TIP-4.6 (Upgradeable NFT) standard documentation (#358)
1 parent f51ecbe commit 223a162

File tree

2 files changed

+184
-0
lines changed

2 files changed

+184
-0
lines changed

src/standard/TIP-4/6.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
---
2+
title: 4.6. Upgradeable NFT
3+
sidebar_position: 6
4+
slug: /standard/TIP-4.6
5+
---
6+
7+
# Upgradeable NFT (TIP-4.6)
8+
Requires: [TIP-4.1](1.md)
9+
Requires: [TIP-6.1](./../TIP-6/1.md)
10+
11+
## Abstract
12+
13+
This standard describes the operation of upgradeable NFT contracts. This is based on [TIP-4.1](1.md) and does not describe the functionality proposed there.
14+
15+
The only difference in the minting process is that the Collection deploys an NftPlatform contract rather than an NFT.
16+
17+
Immediately after deployment to the network, the NftPlatform contract calls the `tvm.setcode()`, `tvm.setCurrentCode()`, and `onCodeUpgrade` functions, changing its code to NFT code.
18+
19+
## Motivation
20+
21+
The standard allows the NFT code to be changed in case an error is found in it or there is a need to add new functionality.
22+
23+
## Specification
24+
25+
The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119).
26+
27+
28+
## Collection
29+
30+
The NFT collection contract serves as a repository for the most up-to-date version of the NFT code, including its current version number. When an individual NFT contract seeks to upgrade its own codebase, it can initiate a request to the NFT collection contract. Upon receiving this request, the collection contract will automatically update the requesting NFT with the latest version of the code.
31+
32+
Code update functions are not standardized.
33+
34+
```solidity
35+
interface ITIP4_6Collection {
36+
event UpgradeNftRequested(uint32 oldVersion, uint32 newVersion, address nft, address initiator);
37+
event NftCodeUpdated(uint32 oldVersion, uint32 newVersion, uint256 oldCodeHash, uint256 newCodeHash);
38+
39+
function nftVersion() external view responsible returns (uint32);
40+
41+
function platformCode() external view responsible returns (TvmCell);
42+
43+
function platformCodeInfo() external view responsible returns (uint256 codeHash, uint16 codeDepth);
44+
}
45+
```
46+
47+
### TIP4_6Collection.nftVersion()
48+
```solidity
49+
function nftVersion() external view responsible returns (uint32);
50+
```
51+
52+
Returns the current version of the NFT. The Collection stores only the latest version, update history is stored in events.
53+
54+
### TIP4_6Collection.platformCode()
55+
```solidity
56+
function platformCode() external view responsible returns (TvmCell);
57+
```
58+
59+
Returns the NftPlatform code containing the `collection`(`address`) salt. The NftPlatform code is non-upgradeable.
60+
61+
### TIP4_6Collection.platformCodeInfo()
62+
```solidity
63+
function platformCodeInfo() external view responsible returns (uint256 codeHash, uint16 codeDepth);
64+
```
65+
66+
Returns the hash and depth of the NftPlatform code. These can be used to calculate the NFT address in third-party contracts. The hash is taken from the NftPlatform code containing the `collection`(`address`) salt.
67+
68+
### Events
69+
```solidity
70+
event UpgradeNftRequested(uint32 oldVersion, uint32 newVersion, address nft, address initiator);
71+
event NftCodeUpdated(uint32 oldVersion, uint32 newVersion, uint256 oldCodeHash, uint256 newCodeHash);
72+
```
73+
**UpgradeNftRequested**
74+
75+
You MUST emit it when an update is requested from the NFT and upgrade is available (the NFT version at the time of the upgrade request is less than the current NFT version in the collection).
76+
77+
**NftCodeUpdated**
78+
79+
You MUST emit it when NFT code is updated in a collection. The function of code update is not standardized.
80+
81+
### Mint
82+
83+
The functions implementing minting are not standardized. The process itself differs from the one proposed in [TIP-4.1](1.md) (see Abstract).
84+
85+
### Upgrade
86+
87+
When NFT code is updated in a collection, the latter changes the NFT version and emits the `NftCodeUpdated` event.
88+
89+
## Nft
90+
```solidity
91+
interface ITIP4_6Nft {
92+
event NftUpgraded(uint32 oldVersion, uint32 newVersion, address initiator);
93+
94+
function requestUpgrade(address sendGasTo) external;
95+
96+
function version() external view responsible returns (uint32);
97+
}
98+
```
99+
100+
### TIP4_6Nft.requestUpgrade()
101+
```solidity
102+
function requestUpgrade(address sendGasTo) external;
103+
```
104+
105+
- `sendGasTo (address)` - the address to which the remaining gas will be sent
106+
107+
Calls the Сollection function, checking if there is an upgrade. If a new version is available, the Сollection upgrades the NFT by calling the appropriate function (this function is not included in the standard, implementations may vary).
108+
109+
### TIP4_6Nft.version()
110+
```solidity
111+
function version() external view responsible returns (uint32);
112+
```
113+
114+
Returns the current version of NFT.
115+
116+
### Events
117+
```solidity
118+
event NftUpgraded(uint32 oldVersion, uint32 newVersion, address initiator);
119+
```
120+
121+
**NftUpgraded**
122+
123+
You MUST emit it after the NFT upgrade.
124+
125+
### Upgrade
126+
127+
The NFT upgrade scenario is as follows:
128+
129+
1. The user (in the general case, the NFT manager) calls the NFT `requestUpgrade` function.
130+
2. The NFT requests an upgrade from the collection, passing information about itself (`id`, `version`).
131+
3. The Collection compares the version it holds with the one passed by the NFT.
132+
4. If the version in the collection is larger, then an upgrade is available. The collection emits the `UpgradeNftRequested` event, calls the NFT function and passes it the new code, version and other necessary data
133+
1. If the versions are equal, the process aborts and remaining gas is returned to the owner.
134+
5. NFT sets the new code, emits `NftUpgraded` event
135+
136+
## NftPlatform
137+
138+
NftPlatform's static variables MUST contain `_id`(`uint256`) and nothing else.
139+
140+
The code and interface of the contract are not standardized, except for the previously mentioned static `_id`(`static uint256`) (similar to the NFT contract). As described above, when minting, the collection deploys this contract instead of the NFT, then it upgrades its code to **TIP4_6Nft.**
141+
142+
This approach allows the collection to accept messages from NFTs of any version without retaining all the NFT code used.
143+
144+
An example of this contract is shown below. The NftPlatform code is salted with the address of the Collection that deployed it (similar to the NFT contract) so that the codehash is unique for each Collection.
145+
146+
```solidity
147+
contract NftPlatform {
148+
uint8 constant value_is_empty = 101;
149+
uint8 constant sender_is_not_collection = 102;
150+
uint8 constant value_is_less_than_required = 104;
151+
152+
uint256 static _id;
153+
154+
constructor(TvmCell nftCode, TvmCell data, uint128 remainOnNft) public {
155+
optional(TvmCell) optSalt = tvm.codeSalt(tvm.code());
156+
require(optSalt.hasValue(), value_is_empty);
157+
address collection = optSalt.get().toSlice().decode(address);
158+
require(msg.sender == collection, sender_is_not_collection);
159+
require(remainOnNft != 0, value_is_empty);
160+
require(msg.value > remainOnNft, value_is_less_than_required);
161+
162+
initialize(nftCode, data);
163+
}
164+
165+
function initialize(
166+
TvmCell nftCode,
167+
TvmCell data
168+
) private {
169+
tvm.setcode(nftCode);
170+
tvm.setCurrentCode(nftCode);
171+
172+
onCodeUpgrade(data);
173+
}
174+
175+
function onCodeUpgrade(TvmCell data) private {}
176+
}
177+
```

src/standard/TIP-4/core-description.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ Using the Storage contract, you can store NFT-related bytes in blockchain. [TIP-
3939
## (Status:Draft) [Don't Be Evil NFT licensing (TIP-4.5)](./../TIP-4/5.md)
4040
The standard adds the support of [Can't Be Evil NFT licenses](https://github.com/a16z/a16z-contracts) [introduced](https://a16zcrypto.com/introducing-nft-licenses/) by [Andreessen.Horowitz](https://a16z.com). [TIP-4.5](./../TIP-4/5.md) is optional, but can be used for clarifying the legal basis of NFT usage by the owner.
4141

42+
## (Status:Draft) [Upgradeable NFT (TIP-4.6)](./../TIP-4/6.md)
43+
The standard describes the operation of upgradeable NFT contracts. [TIP-4.6](./../TIP-4/6.md) is optional, but can be used for changing NFT code in case an error is found in it or there is a need to add new functionality.
44+
45+
**Implementation**
46+
47+
[grandbazar.io](https://github.com/grandbazar-io/everscale-tip4.6-contracts) implementation
48+
4249

4350
## Authors
4451
| Author | Command |

0 commit comments

Comments
 (0)