Soulbound NFT
Soulbound non-fungible token(NFT)은 transfer할 수 없는 NFT이다. NFT가 Sui account에 mint된 뒤에는 해당 NFT가 그 account에 bound되어 transfer할 수 없다. 이 implementation은 Sui framework transfer functions의 custom logic을 사용한다. sui::transfer module에는 objects를 transfer하는 두 functions인 transfer::transfer와 transfer::public_transfer가 있다.
일반적 으로 Sui에서 새 NFTs 또는 object types를 정의할 때 transfer function을 만들 필요는 없다. Sui framework가 누구나 objects를 transfer하는 데 사용할 수 있는 transfer::public_transfer를 제공하기 때문이다. transfer::public_transfer는 transferred objects가 key와 store abilities를 가져야 한다. 따라서 key ability는 있지만(Sui object라는 뜻) store ability는 없는 새 NFT type을 정의하면 holders는 transfer::public_transfer를 사용할 수 없다. 그 결과 soulbound NFT가 된다.
Sui에서 NFTs에 대한 custom transfer logic도 만들 수 있다. transfer::transfer function에는 transferred objects가 transfer가 invoke되는 module에서 정의되었는지 보장하는 Sui Move bytecode verifier의 custom rules가 있다. Struct definition에서 store ability를 제거하면 transfer::public_transfer는 사용할 수 없지만, 해당 object type을 정의한 module 안에서 invoke하는 한 transfer::transfer는 계속 사용할 수 있다. 이를 통해 module owner는 soulbound NFTs에 대한 custom transfer logic을 제공할 수 있다.
다음 예시는 Sui에서 soulbound NFT를 만든다. TestnetSoulboundNFT struct는 id, name, description, url fields로 NFT를 정의한다:
public struct TestnetSoulboundNFT has key {
id: UID,
name: string::String,
description: string::String,
url: Url,
}
TestnetSoulboundNFT struct는 key ability를 가지지만 store ability는 없다. 이는 transfer::public_transfer로 transfer할 수 없다는 뜻이다. 대신 같은 module에 구현된 custom transfer logic과 함께 transfer::transfer를 사용한다.
이 예시는 transfer::transfer function을 사용해 custom transfer logic을 제공하는 방법도 보여준다. 이 위치에 NFT stats reset 또는 payment requirement 같은 additional logic을 추가할 수 있다. NFT가 완전히 soulbound라면 이 functionality를 제공하지 않는다:
/// Transfer `nft` to `recipient`
/// Do not include this if you want the NFT fully soulbound
public fun transfer(nft: TestnetSoulboundNFT, recipient: address, _: &mut TxContext) {
// Add custom logic for transferring the NFT
transfer::transfer(nft, recipient)
}