ERC-4400 ERC-721 소비자 역할 확장 (EIP-721 Consumable Extension)
Final · NFT·멀티토큰 · 2021-10-30 작성
ERC-721 NFT에 소유자와 별개로 토큰을 이용만 하는 소비자(consumer) 주소를 지정하고 조회하는 표준 인터페이스를 더합니다. NFT 대여나 스테이킹처럼 소유와 이용을 나누는 서비스의 기반이 됩니다.
왜 필요한가
ERC-721 NFT에는 소유자(owner), 운영자(operator), 승인 주소(approved address)라는 역할만 정의되어 있습니다. 그런데 NFT에는 소유 말고도 이용이라는 쓰임새가 있습니다. 예를 들어 메타버스의 땅 NFT는 소유자가 다른 주소에 씬(장면) 배포를 맡길 수 있어야 하고 스테이킹 컨트랙트에 NFT를 맡긴 사람은 소유권이 컨트랙트로 넘어간 뒤에도 토큰의 유틸리티 혜택을 계속 누리고 싶어 합니다. 표준이 없으면 각 컨트랙트가 저마다 다른 이름과 방식으로 이용 권한 역할을 만들게 되고 지갑이나 다른 컨트랙트가 그 역할을 일관되게 읽거나 다룰 수 없습니다. 그 결과 여러 프로젝트를 아우르는 범용 NFT 대여 마켓플레이스 같은 서비스를 만들기 어려워집니다.
구현해야 하는 것
event ConsumerChanged(address indexed owner, address indexed consumer, uint256 indexed tokenId);: 소유자가 NFT의 소비자를 바꿀 때 발생하는 이벤트입니다. 소비자가 영 주소면 소비자가 없다는 뜻입니다.function consumerOf(uint256 _tokenId) view external returns (address);: 해당 NFT의 현재 소비자 주소를 돌려줍니다. 소비자가 없으면 영 주소를 반환합니다.function changeConsumer(address _consumer, uint256 _tokenId) external;: NFT의 소비자 주소를 바꾸거나 다시 확인합니다. 소유자, 운영자, 승인 주소만 호출할 수 있습니다.
심층 설명
IEIP721Consumable 인터페이스와 ERC-165 식별자
이 확장을 따르는 컨트랙트는 IEIP721Consumable 인터페이스를 반드시(MUST) 구현해야 합니다. 확장 자체는 ERC-721 컨트랙트에 선택 사항(OPTIONAL)입니다. 인터페이스의 ERC-165 식별자는 0x953c8dfa이며 supportsInterface를 이 값으로 호출하면 반드시 true를 반환해야 합니다. 이를 통해 지갑이나 마켓플레이스 같은 외부 코드가 어떤 NFT 컨트랙트가 소비자 확장을 지원하는지 온체인에서 미리 확인할 수 있습니다. 인터페이스는 이벤트 하나와 함수 두 개로만 구성되어 있습니다.
consumerOf: 소비자 조회
consumerOf(uint256 _tokenId)는 해당 NFT의 현재 소비자 주소를 돌려줍니다. 영 주소는 소비자가 지정되지 않았다는 뜻으로 쓰이며 _tokenId가 유효한 NFT가 아니면 실행이 중단(throw)됩니다. 이 함수는 pure 또는 view로 구현할 수 있습니다(MAY). 상태를 바꾸지 않는 조회 전용 함수이므로, 외부 서비스가 특정 토큰의 이용 권한자를 확인하는 표준 입구 역할을 합니다.
changeConsumer와 ConsumerChanged 이벤트
changeConsumer(address _consumer, uint256 _tokenId)는 NFT의 소비자 주소를 바꾸거나 다시 확인(reaffirm)합니다. msg.sender가 현재 소유자, 소유자가 승인한 운영자, 또는 승인 주소가 아니면 실행이 중단되고 _tokenId가 유효한 NFT가 아니어도 중단됩니다. 영 주소를 넘기면 소비자가 없다는 뜻입니다. 함수는 public 또는 external로 구현할 수 있습니다(MAY). 소비자가 바뀔 때는 ConsumerChanged(owner, consumer, tokenId) 이벤트를 반드시(MUST) 발생시켜야 합니다.
소비자 권한의 금지선
소비자가 시스템 안에서 무엇을 할 수 있는지는 각 구현 컨트랙트가 자유롭게 정합니다. 단 하나의 예외가 있습니다. 소비자는 ERC-721 명세상의 소유자, 운영자, 승인 주소로 간주되어서는 안 되며(MUST NOT) 따라서 전송과 승인을 실행할 수 없어야 합니다. 원문 Rationale은 이 제한의 이유를 분명히 밝힙니다. 소유자 권한이 없는 별도 역할이 필요한 사용 사례가 많은데, 소비자에게 소유자 권한을 주는 구현은 이 표준의 존재 의미를 없애 버리기 때문입니다.
전송 시 소비자 초기화
NFT가 전송(transfer)될 때마다 소비자는 반드시(MUST) 기본 주소로 바뀌어야 하며 기본 주소로는 영 주소 address(0)를 쓰는 것이 권장(RECOMMENDED)됩니다. ConsumerChanged 이벤트 주석도 같은 내용을 담습니다. Transfer 이벤트가 발생하면 그 NFT에 소비자가 있었더라도 없음으로 재설정됩니다. 즉 이용 권한은 소유권을 따라가지 않으며 새 소유자가 원하면 changeConsumer로 소비자를 다시 지정해야 합니다.
설계 원칙과 이름 선택
표준 설계에 영향을 준 요소로 원문은 네 가지를 듭니다. 컨트랙트 비대화를 막기 위해 함수 수를 최소로 유지하는 것, 단순함, 가스 효율, 그리고 소유자, 운영자, 승인 주소 같은 기존 역할을 재사용하거나 덧씌우지 않는 것입니다. 역할 이름으로는 operator도 검토되었지만 ERC-721에서 이미 정의되어 쓰이고 있어 consumer가 선택되었습니다. consumer는 소유권 없이 토큰 인스턴스를 이용하는 주체라는 뜻과 맞닿아 있습니다. 이 표준은 Final 상태로 확정되었고 기존 ERC-721과 호환되며 비슷한 역할을 정의한 다른 표준은 없습니다.
쓸 때 주의할 점
- 소비자에게 줄 권한을 신중히 설계: 표준을 올바르게 구현해 NFT의 전송과 소각을 막았더라도, 소비자에게 원래 소유자에게만 허용해야 할 권한을 무심코 부여할 수 있습니다. 구현자는 소비자에게 주는 권한의 범위를 철저히 검토하고 소유자 전용으로 제한해야 할 동작은 소비자가 쓸 수 없게 해야 합니다.