ERC-5269 ERC 번호로 지원 표준 조회 (ERC Detection and Discovery)

Review · 기타 · 2022-07-15 작성

컨트랙트가 어떤 ERC 표준을 지원하는지 사람이 읽는 ERC 번호로, 그리고 호출자 주소별로 조회할 수 있게 하는 감지 인터페이스입니다.

왜 필요한가

지금까지 컨트랙트가 어떤 표준을 지원하는지 확인하는 데는 ERC-165가 쓰였습니다. 그런데 ERC-165는 함수 서명의 해시를 모아 인터페이스를 식별하기 때문에 함수가 최소 하나는 있어야 하고 데이터 형식이나 서명 방식처럼 함수가 없는 표준이나 전송 호출을 그냥 거부하는 소울바운드(Soul-Bound) 성격의 표준은 표현할 수 없습니다. 또 bytes4 해시값은 사람이 읽기 어려워서 어떤 ERC 번호에 해당하는지 알려면 컨트랙트 안에 변환표를 두어야 합니다. 마지막으로 ERC-165는 누가 묻든 같은 답을 주기 때문에, 투명 업그레이드 프록시처럼 관리자 계정과 일반 계정을 다르게 대하는 컨트랙트에 대해 특정 호출자 기준의 지원 여부를 물어볼 방법이 없습니다. 이 표준은 ERC 번호와 호출자 주소를 받아 지원 여부와 상태를 돌려주는 조회 함수를 정의해 이런 한계를 풀려고 합니다.

심층 설명

두 가지 식별자: majorERCIdentifier와 minorERCIdentifier

majorERCIdentifier는 보통 ERC 번호라고 부르는 값입니다. ERC-721이면 721, 이 표준 자신이면 5269입니다. supportERC 호출에서 이 값은 (0, 2^32-1] 범위여야 하고(SHOULD), 2^32 이상은 ERC가 아닌 다른 표준 모음을 지원할 경우를 대비해 예약되어 있습니다. ERCNumber 대신 majorERCIdentifier라는 이름을 쓴 것은 미래에 번호가 아닌 방식의 표준이 나올 가능성에 대비한 것입니다. minorERCIdentifier는 bytes32 값으로 각 ERC의 저자가 정의하도록 남겨 둔 공간입니다. 예를 들어 ERC-721 저자는 keccak256("ERC721Metadata")나 keccak256("ERC721Metadata.tokenURI")를 지정할 수 있고 ERC-712의 V1~V4처럼 버전 구분에도 쓸 수 있습니다. 값 0은 해당 ERC의 주 동작 전체를 가리키는 것으로 예약되어 있습니다.

반환값 ercStatus의 규칙

supportERC는 지원 상태를 bytes32로 돌려줍니다. 조회 대상 ERC가 FINAL 상태라면 반드시 keccak256("FINAL")을 반환해야 하고(MUST), FINAL이 아닌 ERC에 대해서는 keccak256("DRAFT")를 반환하는 것이 권장됩니다(SHOULD). ERC 저자는 keccak256("DRAFTv1")이나 keccak256("DRAFT-option1")처럼 자체 상태값을 정할 수 있지만 그 값은 해당 ERC 본문에 문서화되어야 합니다. Final이 아닌 ERC-XXX를 조회했을 때 keccak256("FINAL")을 반환해서는 안 되며(MUST NOT), 이때는 0 반환이 권장됩니다. 호출자는 keccak256("FINAL") 이외의 모든 값을 최종이 아닌 것으로, 0은 엄격히 미지원으로 취급해야 합니다. supportERC는 view 함수여야 하며 EVM의 전역 상태를 바꿔서는 안 됩니다.

호출자(caller)를 입력으로 받는 이유

ERC-165와 달리 이 표준은 address caller를 입력으로 받습니다. 같은 컨트랙트라도 호출 계정에 따라 동작이 다를 수 있기 때문입니다. 대표 사례가 투명 업그레이드 패턴(Transparent Upgradable Pattern)으로, 프록시 컨트랙트는 관리자 계정과 일반 계정의 호출을 다르게 처리합니다. msg.sender를 쓰지 않고 인자로 받는 것은, 트랜잭션을 보내지 않고도 특정 발신자에게 해당 인터페이스가 제공될지 미리 조회할 수 있게 하기 위해서입니다. ERC-1967 같은 프록시 패턴이 널리 쓰이는 상황을 고려한 설계입니다.

OnSupportERC 이벤트로 하는 선언

규격을 따르는 컨트랙트는 생성자나 업그레이드 시점에 OnSupportERC(address(0), 5269, 0, ERC_5269_STATUS, []) 이벤트를 내보내는 것이 권장됩니다(SHOULD). 여기서 caller가 address(0)이면 모든 호출자에게 적용된다는 뜻입니다. 또 지원하는 다른 ERC의 주 동작이나 하위 동작을 같은 이벤트로 선언할 수 있고(MAY), 특정 호출자 또는 모든 호출자에 대한 지원 여부가 바뀔 때도 이벤트를 낼 수 있습니다. 참조 구현의 ERC-721 예시는 배포 시 721 전체, ERC721Metadata, ERC721Enumerable을 각각 FINAL 상태로 선언합니다.

ERC-165와의 차이와 경쟁 관계

이 표준은 ERC-165의 경쟁 표준으로 만들어졌습니다. ERC-165는 함수 서명 해시로 인터페이스를 선언하므로 함수가 최소 하나 존재해야 하지만 이 표준은 함수가 없는 표준도 번호로 선언할 수 있습니다. 또 ERC 번호를 그대로 쓰면 사람이 읽기 좋고 ENS 같은 이름 기반 컨트랙트와 다루기 쉽습니다. 실제로 ERC-5267의 extensions 목록, ERC-600과 ERC-601의 파생 경로, ERC-5568의 instruction_id, ERC-6120의 uint eip 필드처럼 ERC 번호로 표준을 지정하는 사례가 늘고 있습니다. 번호 기반 감지 인터페이스가 있으면 bytes4 식별자를 ERC 번호로 바꾸는 조회 테이블이 필요 없어집니다. 설계 논의에서는 번호의 해시나 ERC-165 식별자를 쓰는 대안도 검토했지만 해시는 역으로 읽기 어렵다는 이유로 원래 번호를 그대로 쓰는 쪽을 택했습니다.

이 표준 자신에 대한 조회와 extraData

이 문서 시점에서 ERC_5269_STATUS는 keccak256("DRAFTv1")로 정해져 있습니다. 현재 스냅숏 기준으로 supportERC((any caller), 5269, 0, []) 호출은 반드시 ERC_5269_STATUS를 반환해야 하며 이 표준이 FINAL이 되면 같은 호출에 대해 ERC_5269_STATUS를 반환해야 합니다. 마지막 인자 extraData는 ERC-5750에 따른 미래 확장용 bytes 파라미터입니다. 참조 구현은 majorERCIdentifier가 5269이고 minorERCIdentifier가 0일 때 ERC_STATUS를 반환하고 그 외에는 0을 반환하는 단순한 구조입니다.

아직 Review 단계인 제안

이 표준의 상태는 Review입니다. 아직 확정되지 않아 내용이 바뀔 수 있고 명세 안의 상태값 정의(DRAFTv1 등)도 표준이 진행되면서 달라질 수 있습니다.

쓸 때 주의할 점

ERC 원문 · ← ERCs