ERC-5289 이더리움 공증 인터페이스 (Ethereum Notary Interface)
Review · 서명·인증 · 2022-07-16 작성
스마트 컨트랙트가 법적 문서를 가리키는 링크를 제공하고 사용자의 서명 기록을 온체인에 남겨, 컨트랙트 이용에 법적 구속력을 더할 수 있게 하는 표준입니다.
왜 필요한가
스마트 컨트랙트는 코드로는 실행되지만 그 자체로 법적 구속력이 있는 계약은 아닙니다. 원문은 NFT를 예로 듭니다. NFT는 흔히 저작권을 보유하고 증명하는 수단으로 알려졌지만 실제로는 거의 그렇지 않습니다. 대부분의 NFT는 법적으로 아무 의미가 없고 드물게 의미가 있는 경우에도 최초 보유자에게 제한된 이용 허락을 줄 뿐 이후 보유자에게는 어떤 허락도 이어 주지 못합니다. 이 표준은 컨트랙트가 법적 문서를 가리키는 변하지 않는 링크를 제공하고 사용자가 그 문서에 서명했는지와 언제 서명했는지를 컨트랙트가 검증하고 기록하게 해서 컨트랙트 사용자와 법적 문서 사이에 직접적인 계약 관계(privity)를 만들려고 합니다. 다만 원문 저자들은 변호사가 아니며 이 제안은 법률 자문이 아니라고 밝힙니다.
구현해야 하는 것
event DocumentSigned(address indexed signer, uint16 indexed documentId);: signDocument가 호출되어 서명이 이뤄질 때 발생하는 이벤트입니다.function legalDocument(uint16 documentId) external view returns (string memory);: 법적 문서를 가리키는 변하지 않는 링크를 돌려줍니다. IPFS 호스팅이 권장되고 PDF, HTML 같은 일반 파일 형식이어야 합니다.function documentSigned(address user, uint16 documentId) external view returns (bool signed);: 해당 사용자가 그 문서에 서명했는지 여부를 돌려줍니다.function documentSignedAt(address user, uint16 documentId) external view returns (uint64 timestamp);: 해당 사용자가 그 문서에 서명한 시각을 돌려줍니다. 서명하지 않았다면 값은 아무 것이나 될 수 있습니다.function signDocument(address signer, uint16 documentId) external;: 문서에 서명합니다. 컨트랙트가 반드시 검증해야 하고 DocumentSigned 이벤트를 내거나 실패해야 합니다.
심층 설명
법적 문서 라이브러리 인터페이스
IERC5289Library는 ERC-165를 상속합니다. legalDocument(uint16 documentId)는 법적 문서로 가는 변하지 않는(immutable) 링크를 돌려주며 IPFS 호스팅이 권장(RECOMMENDED)되고 PDF, HTML, TeX, Markdown 같은 일반 파일 형식을 반드시(MUST) 써야 합니다. documentSigned(address user, uint16 documentId)는 서명 여부를, documentSignedAt은 서명 시각을 uint64로 돌려줍니다. 사용자가 서명하지 않은 경우 documentSignedAt의 timestamp는 어떤 값이든 될 수 있으므로 반드시 documentSigned로 서명 여부를 먼저 확인해야 합니다. signDocument(address signer, uint16 documentId)는 컨트랙트가 반드시 검증해야 하고 DocumentSigned 이벤트를 내거나 실패(throw)해야 합니다.
ERC-5568 신호로 서명을 요청하는 방식
컨트랙트가 특정 문서의 서명을 요구하려면 ERC-5568 신호로 리버트합니다. 신호의 instruction_data는 ABI 인코딩된 (address, uint16) 쌍이고 address는 라이브러리 주소, uint16은 문서의 documentId입니다. 원문은 throw WalletSignal24(0, 5289, abi.encode(라이브러리 주소, 12345)) 형태의 예시를 보여 줍니다. 즉 트랜잭션을 일부러 실패시키면서 그 실패 데이터에 어떤 문서에 서명해야 하는지를 담아 지갑에 알리는 구조입니다.
지갑이 지켜야 하는 동작
서명 요청을 받은 지갑은 반드시(MUST) legalDocument를 호출해 문서를 가져오고 그 문서를 사용자에게 표시한 뒤 서명 또는 취소를 묻는 화면을 띄워야 합니다. 사용자가 동의하면 지갑은 반드시 signDocument를 호출해야 합니다. 문서를 보여 주지 않고 서명만 처리하는 구현은 표준을 따르지 않는 것입니다.
타입과 설계 선택의 근거
서명 시각의 반환 타입으로 uint64를 고른 이유는 64비트 시간 레지스터가 표준이기 때문입니다. 문서 ID에 uint16을 고른 이유는 65536개 문서면 어떤 용도에도 충분할 가능성이 높기 때문입니다. 부족하면 컨트랙트를 다시 배포하면 됩니다. signDocument가 ECDSA 서명을 인자로 받지 않는 것은 계정 추상화(account abstraction)와의 미래 호환성을 위해서이고 필요한 경우 이후 확장이 그 기능을 더할 수 있습니다. IPFS를 의무로 둔 것은 서명된 문서의 진본성을 증명할 수 있기 때문입니다.
검토 단계의 제안이며 법률 자문이 아님
이 제안의 상태는 검토(Review)로, 아직 최종 확정되지 않았고 내용이 바뀔 수 있습니다. 또한 원문 저자들은 자신들이 변호사가 아니며 이 제안이 법률 자문이 아니라고 명시합니다. 실제 법적 효력은 각 관할의 법에 따라 달라질 수 있다는 점을 전제로 읽어야 합니다.
쓸 때 주의할 점
- 문서는 허용형이어야 합니다: 사용자는 개인 키를 도난당해 누군가 자기 명의로 서명했다고 주장할 수 있습니다. 그래서 서명 대상 문서는 반드시 권리를 주는 허용(permissive) 성격이어야 하고 의무를 지우는 제한(restrictive) 성격이어서는 안 됩니다. 예를 들어 NFT에 붙은 이미지의 이용 허락을 주는 문서는 서명자가 서명을 부인할 이유가 없으므로 괜찮습니다.