ERC-7439 암표 거래 방지 티켓 (Prevent ticket touting)

Final · NFT·멀티토큰 · 2023-07-28 작성

공연 티켓을 NFT로 발행하되 소유자 본인도 마음대로 이전하지 못하게 막고 허가된 판매 대행사나 공인 재판매 플랫폼을 통해서만 티켓을 되팔 수 있게 하는 표준입니다.

왜 필요한가

산업 규모의 암표 거래는 오래된 문제입니다. 사기와 범죄가 뒤따르고 사회적 자원이 낭비되며 아티스트와 관련 업계 전반에 큰 피해를 줍니다. 여러 나라 정부가 암표상 규제 법을 만들기 시작했지만 효과는 제한적이어서 재판매가 금지된 공연의 티켓이나 아직 소유하지도 않은 티켓이 투기적으로 팔려 막대한 불법 이익이 생기고 있습니다. 종이 티켓이나 이메일 속 바우처는 위조하거나 돌려 팔기 쉽습니다. 일반 NFT 티켓도 소유자가 자유롭게 전송할 수 있어 암표상이 표를 사재기해 되파는 것을 막지 못합니다. 이 표준은 티켓 소유자를 포함한 모든 당사자의 전송을 금지합니다. 판매 대행사, 매니저, 프로모터, 공인 재판매 플랫폼 같은 특정 계정만 티켓을 옮길 수 있게 해서 암표상이 티켓을 마음대로 넘기지 못하게 합니다. 구매자는 처음 지불한 가격 이하로 공인 창구에서 되팔 수 있습니다.

구현해야 하는 것

심층 설명

ERC-721 확장과 전송 제한

이 표준은 ERC-721의 확장으로, 판매 대행사나 공연 주최자가 암표 시장에서 관객이 착취당하는 것을 막는 예방 조치를 취할 수 있는 함수 범위를 정의합니다. 소유자를 포함한 모든 당사자의 티켓 전송을 금지하고 특정 계정만 전송을 허용합니다. 참조 구현에서는 _beforeTokenTransfer에서 호출자가 PARTNER_ROLE이 아니면 from이나 to가 0 주소인 경우(민트 또는 소각)만 통과시키고 그 외 전송은 "ERC7439: You cannot transfer this NFT!"로 되돌립니다. PARTNER_ROLE은 판매 대행사나 국가 감독 또는 대행사 지정의 합법 2차 판매 플랫폼이 맡을 수 있습니다. 구매자가 암표상인지 구분할 수 없으므로 소유자 본인의 직접 전송은 허용하지 않습니다.

TokenInfo 구조체

티켓마다 TokenInfo 레코드가 붙습니다. signature는 사용자 개인키나 대행사 개인키로 서명한 데이터로, 무엇을 서명할지는 구현자가 스스로 정해 티켓 유효성 증명에 쓰도록 권장합니다. tokenStatus는 티켓의 현재 상태이고 expireTime은 공연 종료 시각으로 설정하도록 권장합니다. 소유자를 제외한 허가된 계정만 이 기록을 수정할 수 있게 해서 기능을 강화했습니다.

TokenStatus 네 가지 상태

enum TokenStatus는 Sold(0), Resell(1), Void(2), Redeemed(3)입니다. 티켓이 판매되면 반드시 Sold로 바꿔야 하며 이 상태에서 티켓은 유효합니다. 2차 시장에 올라가면 반드시 Resell로 바꿔야 하고 역시 유효한 상태입니다. 소유자가 불법 거래에 연루되면 상태를 반드시 Void로 설정해야 하며 이 상태의 티켓은 무효입니다. 티켓이 사용되면 Redeemed로 바꾸는 것을 권장합니다. 주최 측은 토큰 발행량과 TokenStatus를 교차 비교해 실제 판매 상황을 상시 파악할 수 있습니다.

safeMint: 공개 민팅과 투명한 1차 판매

safeMint(address to, bytes memory signature)는 공개 함수로, 누구나 정가에 투명하게 티켓을 직접 민팅할 수 있게 하자는 의도입니다. 민팅 시 TokenInfo에 구매자 계정이나 대행사만 해석할 수 있는 서명이 들어가 티켓 유효성을 증명하고 상태는 Sold가 됩니다. 상태가 바뀌면 TokenStatusChanged 이벤트를 반드시 발생시켜야 합니다. 판매 대행사가 분위기를 띄우려고 암표상과 결탁하거나 공짜 표와 VIP 표를 빼돌리는 관행을 막으려면 공개적이고 투명한 1차 판매 채널이 필요하다는 문제의식에서 나온 설계입니다.

changeState: 재판매 검증과 유동성

changeState(uint256 tokenId, bytes memory signature, TokenStatus tokenStatus, uint256 newExpireTime)는 특정 역할만 호출할 수 있고 상태가 바뀌면 TokenStatusChanged 이벤트를 반드시 발생시켜야 합니다. 참조 구현에서는 onlyRole(PARTNER_ROLE)로 제한합니다. 팔린 티켓을 2차 시장에 내놓으려면 2차 시장에 요청해 Resell 상태로 바꿔야 하며 이 상태 변경 과정 자체가 2차 판매 티켓에 대한 일종의 공식 검증이자 중고 구매자를 위한 보호 장치입니다. 1차 시장에서 직접 민팅하고 필요하면 투명한 2차 시장에서 이전할 수 있어 티켓의 유동성을 뒷받침합니다.

입장 검증과 환불·취소 처리

공연 전 판매 대행사는 서명으로 티켓을 검증해 관객이 진짜인지 확인합니다. TokenStatus가 Sold여야 하고 expireTime으로 관객이 올바른 회차에 왔는지 구분할 수 있습니다. 검증을 통과하면 대행사가 상태를 Redeemed로 바꿉니다. 공연이 취소되는 극단적 상황에서도 환불 처리를 단순하게 진행할 수 있도록 설계했습니다. 참조 구현은 소각 시 해당 토큰의 tokenInfo를 삭제합니다.

인터페이스 식별과 호환성

supportsInterface가 0x15fbb306으로 호출되면 반드시 true를 반환해야 합니다. 이 표준은 ERC-165와 ERC-721을 요구하며 ERC-721과 호환됩니다. 참조 구현은 OpenZeppelin ERC721과 AccessControl을 상속하고 IERC7439 인터페이스 ID와 상위 컨트랙트의 인터페이스 ID를 모두 지원합니다. 원문 상태는 Final로 확정된 표준입니다.

ERC 원문 · ← ERCs