ERC-5380 ERC-721 사용권 부여 확장 (ERC-721 Entitlement Extension)
Final · NFT·멀티토큰 · 2022-03-11 작성
NFT(ERC-721) 소유자가 토큰을 넘기지 않고도 그 토큰의 특정 속성을 쓸 권리를 다른 주소에 부여할 수 있게 하는 표준입니다.
왜 필요한가
NFT는 소유자가 한 명뿐이어서 토큰이 가진 쓸모를 다른 사람과 나누려면 토큰 자체를 보내는 방법밖에 없었습니다. 예를 들어 온체인 트레이딩 카드 게임(TCG)의 카드를 직접 사지 않고 게임에서만 써 보고 싶은 사람이 있어도, 이를 표준화된 방식으로 허락할 수단이 없었습니다. 또 권리의 성격에 따라 요구가 다릅니다. 게임 카드처럼 한 번에 한 사람만 써야 하는 속성이 있는가 하면, 미디어 사용권처럼 토큰만큼 희소할 필요가 없어 여러 사람에게 줘도 되는 속성도 있습니다. 이 표준은 토큰별로 부여 가능한 인원 수를 정해 두고 소유자가 원하는 주소에 사용권(entitlement)을 나눠 줄 수 있는 공통 인터페이스를 정의합니다.
구현해야 하는 것
event EntitlementChanged(address indexed user, address indexed contract, uint256 indexed tokenId);: 어떤 사용자가 가진 사용권 수량이 바뀔 때 발생하는 이벤트입니다. user가 0 주소이면 소유자 본인을 뜻합니다.function entitle(address user, address contract, uint256 tokenId) external;: 호출자가 해당 ERC-721 토큰의 소유자일 때, 지정한 사용자에게 그 토큰의 사용권을 부여합니다.function maxEntitlements(address contract, uint256 tokenId) external view (uint256 max);: 해당 토큰의 사용권을 받을 수 있는 최대 사용자 수를 조회합니다.function entitlementOf(address user, address contract, uint256 tokenId) external view returns (uint256 amt);: 특정 사용자가 해당 컨트랙트와 tokenId에 대해 가진 사용권 수량을 조회합니다.function entitlementOfUserByIndex(address user, uint256 index) external view returns (address contract, uint256 tokenId);: 사용권을 하나 이상 가진 사용자의 보유 목록을 인덱스로 하나씩 열거합니다.function tokenURI() external view returns (string);: ERC-1046 방식의 토큰 메타데이터 URI를 돌려줍니다.
심층 설명
기본 인터페이스와 entitle의 동작
표준을 따르는 사용권 컨트랙트는 ERC5380Entitlement 인터페이스를 반드시(MUST) 구현해야 합니다. entitle(user, contract, tokenId)는 msg.sender가 해당 ERC-721 토큰의 소유자일 때 지정한 user에게 사용권을 부여합니다. 다만 소유자가 아닌 주소가 호출해도 되돌리지(revert) 않아야 한다(SHOULD NOT)는 권고가 있으니 주의해야 합니다. 즉 실패를 예외가 아니라 조용한 무시로 처리하는 설계입니다.
maxEntitlements와 entitlementOf의 기본값
maxEntitlements(contract, tokenId)는 그 토큰의 사용권을 받을 수 있는 최대 사용자 수를 돌려줍니다. 게임 카드처럼 한 번에 한 명만 써야 하는 속성과, 여러 명에게 줘도 되는 속성을 이 값으로 구분합니다. entitlementOf(user, contract, tokenId)는 특정 사용자의 사용권 수량(amt)을 돌려주며 기본값은 maxEntitlements(contract, tokenId) 전량이 contract.ownerOf(tokenId), 즉 토큰 소유자에게 배정된 상태입니다. 아무에게도 빌려주지 않았다면 모든 권리가 소유자에게 있다는 뜻입니다.
EntitlementChanged 이벤트
사용자가 가진 사용권 수량이 바뀔 때 EntitlementChanged(user, contract, tokenId) 이벤트가 발생합니다. user, contract, tokenId 세 인자가 모두 indexed여서 로그 필터링이 쉽습니다. user가 0 주소이면 그 사용자는 소유자를 가리킨다고 원문이 명시합니다.
ERC-165 인터페이스 감지
이 표준은 ERC-165를 요구합니다. supportsInterface는 ERC5380Entitlement의 인터페이스 ID로 호출될 때 반드시 true를 돌려줘야 합니다. 선택 확장인 ERC5380EntitlementEnumerable과 ERC5380EntitlementMetadata도 각자의 인터페이스 ID에 대해 같은 요구가 있으므로, 호출자는 온체인에서 어떤 기능까지 구현됐는지 미리 확인할 수 있습니다.
열거 확장(Enumerable Extension)
선택 사항(OPTIONAL)이지만 권장(RECOMMENDED)되는 확장입니다. entitlementOfUserByIndex(user, index)는 0이 아닌 사용권을 가진 토큰을 사용자별로 인덱스를 늘려 가며 열거해 그 사용자가 어떤 (contract, tokenId) 조합의 권리를 가졌는지 돌려줍니다. 인덱스가 범위를 벗어나거나 user가 0 주소이면 예외를 던집니다(Throws).
메타데이터 확장과 ERC-1046 스키마
역시 선택이지만 권장되는 확장으로, ERC-1046 호환 tokenURI()를 제공합니다. URI가 가리키는 메타데이터의 interop 필드에는 erc5380 항목을 두는데, ERC-5380 토큰 메타데이터라면 반드시 true로 설정하고 아니면 생략해야 합니다. 이 표시는 지갑이 해당 주소를 ERC-5380 사용권으로 다루라는 신호입니다. 메타데이터에는 name, symbol, description, images, icons를 선택적으로 담을 수 있습니다. 이미지가 비트맵이면 가로 320~1080픽셀을 권장하고 images는 가로세로 비율 1.91:1에서 4:5 사이를 권장합니다. icons는 비율이 반드시 1:1이어야 하고 투명 배경을 써야 하며 비트맵이면 높이가 너비와 같아야 합니다.
ERC-20과 ERC-1155를 지원하지 않는 이유
이 표준은 ERC-721 전용입니다. 원문 근거(Rationale)에 따르면 ERC-20과 ERC-1155는 지원하지 않는데, 부분 소유권(partial ownership)은 소유 여부만 따지는 불리언 소유권보다 추적이 훨씬 복잡하기 때문입니다. 참고로 이 표준은 ERC-4907(대여 표준)의 대안 설계로 논의됐으며 상태는 Final로 확정됐습니다.
쓸 때 주의할 점
- 기반 표준의 보안 고려사항 승계: 원문은 ERC-721과 ERC-1046의 보안 고려사항이 그대로 적용된다고 명시합니다. 사용권 컨트랙트를 구현하거나 연동할 때 두 표준의 주의점을 함께 검토해야 합니다.