ERC-5169 토큰용 클라이언트 스크립트 URI (Client Script URI for Token Contracts)

Final · 이름·메타데이터 · 2022-05-03 작성

토큰 컨트랙트가 scriptURI() 함수로 그 토큰 전용 공식 클라이언트 스크립트의 내려받기 주소를 알려 주는 표준입니다. 지갑과 앱이 발행자가 지정한 스크립트를 찾아 토큰 기능을 확장할 수 있습니다.

왜 필요한가

토큰에는 전송 말고도 다양한 쓰임새가 있을 수 있습니다. 예를 들어 NFT로 스마트락을 작동하거나, 지갑이 기본으로 지원하지 않는 민트(mint) 같은 컨트랙트 기능을 쓰려면 별도의 클라이언트 스크립트가 필요합니다. 그런데 이 스크립트는 사용자를 대신해 트랜잭션을 만드는 것 같은 민감한 일을 하는데, 토큰 컨트랙트와 스크립트를 공식적으로 연결하는 방법이 없으면 사용자는 지금 쓰는 스크립트가 발행자가 만든 진짜인지 확인할 길이 없습니다. 스크립트를 컨트랙트 안에 통째로 저장하는 방법도 있지만 갱신할 때마다 컨트랙트 서명 키를 써야 해서 키가 노출될 위험이 커지고 클라이언트 스크립트는 보통 컨트랙트보다 훨씬 커서 저장과 갱신 비용도 많이 듭니다. 그렇다고 중앙화된 인증 호스팅을 따로 만드는 것도 부담입니다.

구현해야 하는 것

심층 설명

인터페이스: scriptURI와 setScriptURI

표준은 IERC5169 인터페이스 하나로 구성됩니다. scriptURI()는 현재 저장된 상태인 currentScriptURI를 string[] 형태로 반환해야 하며(MUST), pure나 view로 구현할 수 있습니다(MAY). setScriptURI(string[] memory newScriptURI)는 내부 상태를 currentScriptURI = newScriptURI로 갱신해야 하고(MUST), 갱신이 일어나면 ScriptUpdate 이벤트를 반드시 내보내야 합니다(MUST). URI는 RFC 3986을 따르는 것이면 무엇이든 되며 원문은 IPFS 멀티해시, GitHub gist, 클라우드 저장소 링크를 예로 듭니다. 스크립트의 예로는 토큰 하나에 맞춘 미니댑, 지갑에 없는 mint 같은 기능을 쓰게 하는 TokenScript, Ledger 같은 하드웨어 지갑용 확장, 스마트락을 작동하는 JavaScript 명령을 듭니다.

소유자 검증 규칙

구현 컨트랙트는 상태에 address owner 변수를 저장해야 하고(MUST), 생성자에서 owner = msg.sender로 설정해야 합니다(MUST). setScriptURI는 로직을 실행하고 상태를 바꾸기 전에 먼저 owner == msg.sender를 검증해야 합니다(MUST). 즉 스크립트 주소를 바꿀 수 있는 것은 컨트랙트 소유자뿐입니다. 원문은 이 관리 키(SCPrivKey)가 이 표준을 위해 새로 만드는 키일 필요는 없고 이미 발행된 토큰을 관리하는 기존 관리 키를 그대로 쓸 수 있다고 설명합니다. 테스트 컨트랙트도 OpenZeppelin의 Ownable과 onlyOwner 수식자로 이 규칙을 구현합니다.

스크립트 진위 확인 의무

scriptURI로 알게 된 스크립트를 쓰는 쪽은 다음 중 하나를 반드시 확인해야 합니다(MUST). 스크립트가 바뀔 수 없는 위치(immutable location)에 있거나, URI 자체에 스크립트의 해시 다이제스트가 들어 있거나, 해시 대신 서명으로 진위를 보장하는 별도 표준인 Authenticity for Client Script EIP를 구현해야 합니다. 스크립트는 사용자를 위해 트랜잭션을 만드는 것 같은 신뢰 작업을 수행할 수 있으므로, 내용이 바뀔 수 있는 일반 주소만 믿어서는 안 되기 때문입니다.

왜 온체인이 아니라 외부 저장인가

스크립트를 컨트랙트에 직접 저장하는 방법에는 세 가지 단점이 있습니다. 첫째, 갱신 때마다 컨트랙트 서명 키를 써야 해서 키가 더 자주 노출됩니다. 둘째, 갱신에 컨트랙트 호출이 필요해 갱신이 잦으면 비용 장벽이 됩니다. 셋째, 클라이언트 스크립트는 보통 컨트랙트보다 훨씬 커서 저장료가 많이 듭니다. 그래서 자주 바뀌는 기능은 외부 자원에 두고 주소만 컨트랙트가 알려 줍니다. 외부 자원은 클라우드 같은 중앙 호스팅, 개인 서버, IPFS 같은 탈중앙 저장 어느 쪽이든 됩니다. 완전한 탈중앙 저장은 속도, 가격, 용량에서 불리할 수 있어, 이 표준은 여러 URI를 배열로 돌려줘 중앙·개인·탈중앙 위치를 섞어 쓸 수 있게 했습니다. 스크립트 자체가 다른 스크립트나 데이터 소스를 가리켜 지연 로딩 같은 확장도 할 수 있으며 이런 2차 데이터의 무결성 처리는 스크립트 형식에 맡깁니다.

참조 구현: 사무실 문 NFT

원문은 STL 사무실 문 토큰을 예로 듭니다. 직원에게 NFT를 발행해 전송하고 컨트랙트의 scriptURI()로 연결된 TokenScript에 문을 여는 절차가 담겨 있습니다. 스크립트는 IoT 장치에서 무작위 도전 문자열(예: 'Apples-5E3FA1')을 받아 화면에 보여 주고 개인 서명(Sign Personal)을 요청한 뒤, 서명을 IoT 장치로 돌려보냅니다. 장치는 서명에서 복원한 주소가 그 NFT를 보유하고 있으면 문을 엽니다. 사용자 입장에서는 NFT를 받은 즉시 지갑에서 인증된 기능을 바로 쓸 수 있습니다. 이 구성은 Smart Token Labs 사무실 문과 여러 설치에서 실제로 쓰이고 있다고 원문에 적혀 있습니다.

수명주기와 호환성

수명주기는 간단합니다. 발행 단계에서 발행자는 이 표준을 구현한 컨트랙트와 토큰을 배포하고 setScriptURI로 scriptURI를 등록합니다. 갱신 단계에서는 새 URI 위치들에 스크립트를 먼저 저장한 뒤 새 scriptURI 구조로 setScriptURI를 다시 호출합니다. 원문은 이 표준이 대부분의 기존 토큰 표준과 역호환되며 널리 쓰이는 표준으로 ERC-20, ERC-721, ERC-777, ERC-1155를 든다고 밝힙니다. 이 표준의 상태는 Final로, 내용이 확정되어 더는 바뀌지 않습니다.

쓸 때 주의할 점

ERC 원문 · ← ERCs