ERC-6454 전송 가능 NFT 판별 인터페이스 (Minimal Transferable NFT detection interface)
Final · NFT·멀티토큰 · 2023-01-31 작성
NFT가 지금 전송될 수 있는 토큰인지 컨트랙트에 직접 물어볼 수 있는 최소한의 표준 함수를 정의합니다. 이를 통해 특정 계정에 묶여 거래할 수 없는 NFT를 만들고 식별할 수 있습니다.
왜 필요한가
NFT(대체 불가능 토큰)는 업적 증명이나 게임 캐릭터의 기술처럼 주인이 바뀌면 의미가 없어지는 용도로도 쓰입니다. 예를 들어 운동 성과나 기부 활동을 증명하는 NFT가 자유롭게 거래된다면, 그 토큰을 가진 사람이 실제로 그 일을 해냈는지 믿을 수 없게 됩니다. 그런데 표준이 없으면 어떤 NFT가 전송 금지인지 밖에서 미리 알 방법이 없습니다. 지갑이나 마켓플레이스는 일단 전송을 시도해 보고 실패해야 알 수 있는데, 그러면 트랜잭션이 실패하고 가스(수수료)가 낭비됩니다. 가스 계산을 흉내 내서 실패 여부를 추측하는 것은 사용자 경험이 나쁩니다. 이 표준은 함수 하나로 전송 가능 여부를 미리 확인하는 공통 방법을 제공합니다.
구현해야 하는 것
function isTransferable(uint256 tokenId, address from, address to) external view returns (bool);: 주어진 토큰이 from 주소에서 to 주소로 전송될 수 있는지 참·거짓으로 알려 줍니다. false를 반환하면 해당 전송은 반드시 실패(리버트)해야 합니다.
심층 설명
isTransferable 함수와 전송 차단 규칙
인터페이스는 isTransferable(uint256 tokenId, address from, address to) 함수 하나로 구성되며 ERC-165 식별자는 0x91a6262f입니다. 이 함수가 false를 반환하면 해당 토큰의 전송은 반드시(MUST) 실행을 리버트해야 합니다. 존재하지 않는 tokenId를 넘기면 민팅 가능 여부를 확인하는 경우를 제외하고 반드시 리버트해야 합니다. 즉 단순한 조회 함수가 아니라, 반환값이 실제 전송 동작과 일치해야 하는 강제 규칙입니다.
일반 전송 가능성 조회 방법
토큰이 전반적으로 전송 가능한지 확인하려면 from과 to 파라미터에 모두 0x0000000000000000000000000000000000000000 주소를 넣어 호출해야(SHOULD) 합니다. 일반 전송 가능성이 false이면 민팅과 소각을 제외한 모든 종류의 전송이 반드시 리버트해야 합니다. 초기 제안에는 tokenId만 받는 단순한 메서드가 있었는데, 토큰이 조건에 따라 전송 불가가 될 수 있다는 논의가 나와 파라미터를 늘리고 영 주소를 넣는 방식으로 원래 기능을 유지했습니다.
민팅·소각 판별과 예외
민팅(발행) 가능 여부를 확인할 때는 from을 영 주소로, to를 영 주소가 아닌 값으로 넣어야 하며 이때는 아직 존재하지 않는 tokenId도 예외적으로 허용해야(SHOULD) 합니다. 소각 가능 여부는 반대로 from을 영 주소가 아닌 값, to를 영 주소로 넣어 확인합니다. 토큰의 일반 전송 가능성은 민팅 가능 여부(from이 영 주소)나 소각 가능 여부(to가 영 주소)의 영향을 받지 않아야 합니다. 전송은 막혀 있어도 발행과 소각은 별개로 다룰 수 있다는 뜻입니다.
from 파라미터의 승인 검증은 선택 사항
구현자는 from 파라미터로 토큰 전송 승인(approval)까지 검증할 수(MAY) 있지만 이 제안이 의무화하지 않으므로 호출자는 그 동작에 의존하지 않아야(SHOULD NOT) 합니다. 승인을 검증하는 구현에서는 from이 토큰을 보내는 소유자가 아니라 트랜잭션 개시자(소유자이거나 전송 권한을 받은 오퍼레이터)를 검증하게 됩니다. 승인 검증을 의무화하지 않은 이유는 승인이 이미 별도로 표준화되어 있고 추가 검사를 강제하면 가스 소비가 커지기 때문입니다.
이벤트와 관리 함수를 뺀 최소 설계
이 표준에는 토큰이 전송 불가가 되었음을 알리는 이벤트가 없습니다. 토큰은 생성 시점, 별도 표시 시점, 또는 특정 조건 충족 시점에 전송 불가가 될 수 있는데, 블록 번호로 결정되는 경우처럼 이벤트를 발생시킬 수 없는 상황이 있기 때문입니다. 전송 가능성을 켜고 끄는 관리 함수도 일부러 명세에서 제외했습니다. 범용적인 최소 제안이라는 목표를 지켜 다양한 커스텀 구현을 허용하기 위해서입니다. 기존의 비슷한 제안들보다 적은 메서드로 전송 불가 NFT에 필요한 최소 인터페이스만 제공하는 것이 이 표준의 설계 방향입니다.
메서드 하나를 표준으로 만든 이유와 호환성
전송 함수를 오버라이드하는 것만으로도 전송을 막을 수는 있지만 컨트랙트 실행 전에 전송 불가 여부를 보장하는 유일한 방법은 표준 인터페이스를 갖추는 것입니다. 이를 통해 다른 스마트 컨트랙트가 전송 불가 토큰에 전송을 시도해 트랜잭션 실패와 가스 낭비를 겪는 일을 피할 수 있습니다. 표준 인터페이스가 없다면 가스 계산을 시도해 리버트 여부를 확인하는 수밖에 없는데 이는 나쁜 사용자 경험입니다. 이 표준은 ERC-721 및 기존 ERC-721 도구·인프라와 완전히 호환되며 상태가 Final로 확정된 표준입니다.
쓸 때 주의할 점
- 거짓 값을 반환하는 컨트랙트: 인터페이스를 구현하면서 실제로는 전송 가능한 토큰에 대해 isTransferable이 false를 반환하는 식으로 속이는 컨트랙트가 있을 수 있습니다. 사기성 ERC-20, ERC-721 컨트랙트처럼 이런 컨트랙트의 존재 자체를 막을 수는 없으므로, 상호작용하는 외부 컨트랙트를 모두 검증하고 신뢰할 수 없는 컨트랙트와는 상호작용하지 않아야 합니다.
- 전송 가능성은 바뀔 수 있음: 전송 가능성 상태는 시간이 지나면서 바뀔 수 있습니다. 따라서 이 인터페이스를 구현하는 디앱, 마켓플레이스, 지갑은 토큰을 표시할 때마다 토큰의 상태를 확인해야 합니다.
- 숨은 로직과 미감사 컨트랙트 주의: ERC-721과 같은 보안 고려 사항이 적용됩니다. 소각, 자산 추가, 자산 수락을 포함한 어떤 함수에도 숨은 로직이 있을 수 있으며 감사받지 않은 컨트랙트를 다룰 때는 주의가 필요합니다.