Skip to main content

Gear Rentable Non-Fungible Token

Introduction

This is an extension of the standard Non-Fungible Token (NFT). It introduces an additional role (user) that can be granted to addresses, along with a predefined expiration time for this role. The user role grants permission to "use" the NFT, but it does not allow the ability to transfer it or set other users. The source code of the smart contract example is available on GitHub.

Motivation

Some NFTs serve specific utilities. For instance, virtual land can be utilized to create scenes, and NFTs representing in-game assets can be used within the game. In some cases, the NFT's owner and user may not always be the same person. There might be an NFT owner who rents it out to a "user." The actions that a "user" can perform with an NFT differ from those of the "owner" (for example, "users" typically shouldn't have the ability to sell ownership of the NFT). In such situations, it is logical to establish distinct roles that determine whether an address represents an "owner" or a "user," and to manage permissions accordingly.

Some projects already implement this design concept under various names, such as "operator" or "controller." However, as it becomes more widespread, there is a need for a standardized approach to encourage collaboration among all applications.

Moreover, applications of this model, such as renting, often require that user addresses have only temporary access to use the NFT. Typically, this means the owner needs to execute two on-chain transactions: one to designate a new address as the user role at the beginning of the duration and another to reclaim the user role at the end. This process is inefficient in terms of both labor and gas costs. Therefore, an "expires" function is introduced to facilitate the automatic termination of a usage term without the need for a second transaction.

Details

The default implementation of the NFT contract is provided in the gear library: gear-lib/non_fungible_token.

To use the default implementation you should include the packages into your Cargo.toml file:

gear-lib = { git = "https://github.com/gear-foundation/dapps", tag = "0.3.3" }

Rentable NFT contains regular NFT (gnft-721) and additional field users_info:

rentable-nft/src/lib.rs
pub struct Contract {
#[NFTStateField]
pub token: NFTState,
pub token_id: TokenId,
pub owner: ActorId,
pub transactions: HashMap<H256, NFTEvent>,
pub collection: Collection,
pub config: Config,
pub users_info: HashMap<TokenId, UserInfo>,
}

In all other cases, everything also corresponds to the usual non-fungible-token contract, except additional specific actions:

rentable-nft/io/src/lib.rs
pub enum NFTAction {
// ... like a usual NFT contract
SetUser {
token_id: TokenId,
address: ActorId,
expires: u64, // unix timestamp
transaction_id: u64,
},
UserOf {
token_id: TokenId,
},
UserExpires {
token_id: TokenId,
},
}

And features specific events:

rentable-nft/io/src/lib.rs
pub enum NFTEvent {
// ... like a usual NFT contract
UpdateUser {
token_id: TokenId,
address: ActorId,
expires: u64,
},
UserOf {
address: ActorId,
},
UserExpires {
expires: u64,
},
}

Conclusion

Gear provides a reusable library with core functionality for the gNFT-4907 protocol. By using object composition, the library can be utilized within a custom NFT contract implementation in order to minimize duplication of community available code.

A source code of the Gear NFT smart contract example based on gear-lib is available on GitHub: gear-foundation/dapps-non-fungible-token.

See also an example of the smart contract testing implementation based on gtest: gear-foundation/dapps/non-fungible-token/tests.

For more details about testing smart contracts written on Gear, refer to this article: Program Testing.