ERC-5006 렌탈 NFT 사용자 확장 (Rental NFT, NFT User Extension)
Final · NFT·멀티토큰 · 2022-04-12 작성
ERC-1155 토큰에 소유자와 별개의 사용자(user) 역할을 추가해 소유권을 넘기지 않고 정해진 수량과 기한만큼 토큰을 빌려 쓸 수 있게 합니다.
왜 필요한가
ERC-1155 토큰은 게임 아이템처럼 실제 쓰임새가 있는 경우가 많고 토큰을 쓰는 사람과 소유한 사람이 다를 수 있습니다. 대여가 대표적입니다. 소유자와 사용자를 구분하는 역할이 없으면 토큰을 빌려주기 위해 토큰 자체를 상대에게 보내야 하고 받은 사람은 소유자와 똑같이 토큰을 팔거나 다른 곳으로 옮길 수 있습니다. 빌려줬을 뿐인데 소유권까지 넘어가는 셈입니다. 또 프로젝트마다 대여 방식을 제각각 만들면 대여 플랫폼 같은 제3자 서비스가 NFT 발행자의 허락이나 개별 연동 작업 없이는 사용 권한을 다루기 어렵습니다. 그래서 소유자(owner)와 사용자(user) 역할을 나누고 사용자는 소유권 이전 같은 행동을 하지 못하게 막는 공통 규격이 필요합니다.
구현해야 하는 것
event DeleteUserRecord(uint256 recordId): recordId에 해당하는 사용자 레코드가 삭제될 때 발생하는 이벤트입니다.function usableBalanceOf(address account, uint256 tokenId) external view returns (uint256): account가 실제로 사용할 수 있는 tokenId 토큰의 수량을 돌려줍니다.function frozenBalanceOf(address account, uint256 tokenId) external view returns (uint256): account의 토큰 중 동결된(빌려줘서 묶인) 수량을 돌려줍니다.function userRecordOf(uint256 recordId) external view returns (UserRecord memory): recordId에 해당하는 사용자 레코드(UserRecord)의 내용을 돌려줍니다.function deleteUserRecord(uint256 recordId) external: 권한이 있는 호출자가 recordId의 레코드를 한 번에 삭제합니다.
심층 설명
UserRecord 구조체
사용 권한 한 건은 UserRecord 구조체로 기록합니다. 필드는 대상 토큰 종류인 tokenId(uint256), 빌려준 소유자 owner(address), 빌려준 수량 amount(uint64), 권한을 받은 주소 user(address), 만료 시각 expiry(uint64)입니다. 레코드마다 recordId가 부여되고 userRecordOf(recordId)로 내용을 조회합니다. ERC-1155는 같은 종류의 토큰을 여러 개 가질 수 있으므로, 단순히 사용자 한 명을 지정하는 방식이 아니라 수량(amount) 단위로 권한을 쪼개 기록하는 구조입니다.
createUserRecord의 요구 조건
createUserRecord(owner, user, tokenId, amount, expiry)에는 다음 조건이 붙습니다. 호출자가 owner가 아니면 setApprovalForAll을 통해 owner의 토큰을 다룰 권한을 승인받아야 합니다. owner는 해당 종류의 토큰을 amount 이상 보유해야 합니다. user는 제로 주소일 수 없고 amount는 0보다 커야 하며 expiry는 블록 타임스탬프 이후여야 합니다. 성공하면 CreateUserRecord 이벤트가 발생하고 uint256 타입의 레코드 번호를 반환합니다.
잔액 조회와 레코드 삭제
usableBalanceOf(account, tokenId)는 account가 실제로 사용할 수 있는 토큰 수량을 돌려주고 frozenBalanceOf(account, tokenId)는 동결된 토큰 수량을 돌려줍니다. 두 함수로 빌린 쪽의 사용 가능 수량과 빌려준 쪽의 묶인 수량을 각각 확인할 수 있습니다. deleteUserRecord(recordId)는 호출자에게 권한(allowance)이 있어야 하며 레코드를 원자적으로(중간 상태 없이 한 번에) 삭제하고 DeleteUserRecord 이벤트를 발생시킵니다.
인터페이스 식별자
이 표준을 구현한 컨트랙트는 supportsInterface를 0xc26d96cc로 호출했을 때 반드시(MUST) true를 반환해야 합니다. 지갑이나 플랫폼은 이 값 하나로 어떤 ERC-1155 컨트랙트가 사용자 확장을 지원하는지 미리 확인할 수 있습니다. 이 표준은 ERC-165와 ERC-1155를 전제로 합니다(requires: 165, 1155).
설계 의도: 권리 구분과 제3자 통합
소유자와 사용자라는 두 역할을 두면 빌려준 쪽과 빌린 쪽이 무엇을 할 수 있는지 관리하기 쉬워집니다. 예를 들어 소유권 이전 권한은 행동하려는 주소가 소유자인지 사용자인지 확인해서 사용자라면 거부하면 됩니다. 또 허가 없는 상호운용 정신에 따라, 한 프로젝트가 user 역할을 채택하면 다른 프로젝트가 NFT 발행자나 기존 앱의 허락 없이 이 기능과 직접 연동할 수 있습니다. 원문은 같은 PFP NFT가 30일 대여 플랫폼과 할부로 소유권을 사들이는 모기지 플랫폼에 동시에 올라가는 예를 듭니다.
하위 호환성과 표준 상태
이 표준은 기존 ERC-1155에 확장 함수 집합을 더하는 방식이라 ERC-1155와 충돌이 없습니다. 새로 도입된 함수들이 ERC-1155의 기존 함수들과 비슷하게 생겨서 개발자가 빠르게 채택할 수 있다고 원문은 설명합니다. 테스트 케이스와 참조 구현(ERC5006.sol)이 함께 제공되며 표준 상태는 Final로 확정되어 더 이상 내용이 바뀌지 않습니다.
쓸 때 주의할 점
- 소유자 권리 보호: 이 표준은 소유자의 권리를 보호하도록 설계되어 있습니다. 소유자는 NFT의 사용자를 바꿀 수 있고 사용자는 NFT를 다른 곳으로 옮길 수 없습니다.