Soulbound NFT
Soulbound non-fungible 토큰(NFT)은 전송할 수 없는 NFT이다. NFT가 Sui 계정에 민트된 뒤에는 해당 NFT가 그 계정에 bound되어 전송할 수 없다. 이 implementation은 Sui 프레임워크 transfer 함수의 커스텀 로직을 사용한다. sui::transfer 모듈에는 객체를 전송하는 두 함수인 transfer::transfer와 transfer::public_transfer가 있다.
일반적으로 Sui 에서 새 NFTs 또는 객체 타입s를 정의할 때 transfer 함수를 만들 필요는 없다. Sui 프레임워크가 누구나 객체를 전송하는 데 사용할 수 있는 transfer::public_transfer를 제공하기 때문이다. transfer::public_transfer는 transferred 객체가 key와 store abilities를 가져야 한다. 따라서 key ability는 있지만(Sui 객체라는 뜻) store ability는 없는 새 NFT 타입을 정의하면 holders는 transfer::public_transfer를 사용할 수 없다. 그 결과 soulbound NFT가 된다.
Sui에서 NFTs에 대한 커스텀 전송 로직도 만들 수 있다. transfer::transfer 함수에는 transferred 객체가 전송이 invoke되는 모듈에서 정의되었는지 보장하는 Sui Move bytecode verifier의 커스텀 규칙이 있다. Struct definition에서 store ability를 제거하면 transfer::public_transfer는 사용할 수 없지만, 해당 객체 타입을 정의한 모듈 안에서 invoke하는 한 transfer::transfer는 계속 사용할 수 있다. 이를 통해 모듈 소유자는 soulbound NFTs에 대한 커스텀 전송 로직을 제공할 수 있다.
다음 예시는 Sui에서 soulbound NFT를 만든다. TestnetSoulboundNFT struct는 id, name, description, url 필드로 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::transfer를 사용한다.
이 예시는 transfer::transfer 함수를 사용해 커스텀 전송 로직을 제공하는 방법도 보여준다. 이 위치에 NFT stats reset 또는 결제 요구 사항 같은 추가 로직을 추가할 수 있다. NFT가 완전히 soulbound라면 이 기능을 제공하지 않는다:
/// 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)
}