ERC-6066 NFT 서명 검증 표준 (Signature Validation Method for NFTs)
Final · 서명·인증 · 2022-11-29 작성
일반 계정이나 스마트 컨트랙트가 아니라 NFT 자체가 서명의 주체가 될 수 있게 하고 그 서명이 유효한지 누구나 확인할 수 있는 표준 함수를 정합니다.
왜 필요한가
이더리움에서 일반 계정(EOA, Externally Owned Account)이 만든 서명은 ecrecover()로, 스마트 컨트랙트가 만든 서명은 ERC-1271로 검증할 수 있지만 NFT가 만든 서명을 검증하는 표준 방법은 없었습니다. 예를 들어 어떤 DAO가 CEO, COO 같은 직책을 NFT 배지로 표현하고 분기마다 선거로 사람을 교체한다고 하면, 현직 COO가 서명한 합의나 승인은 'COO 직책'이 아니라 당시 그 사람의 개인 계정에 묶입니다. 사람이 바뀌면 과거 서명이 직책과 함께 넘어가지 않는 것입니다. DAO 전체 다중서명 지갑을 쓰거나 컨트랙트를 COO로 앉히는 우회책도 있지만 책임을 세밀하게 나누기 어렵거나 불필요하게 복잡해집니다. 이 표준은 서명을 양도 가능한 NFT에 묶어 이런 문제를 풉니다.
심층 설명
isValidSignature 함수 요건
함수는 tokenId(서명하는 NFT의 토큰 ID), hash(서명 대상 데이터의 해시), data(검증을 도울 수 있는 선택적 임의 데이터)를 받습니다. 서명이 유효하면 반드시 bytes4 매직 값 0x12edb34f를 반환해야 하고 상태를 수정해서는 안 되며(solc 0.5 미만은 STATICCALL, 이상은 view 한정자), 외부 호출을 허용해야 합니다. 검증 과정에서 임의의 다른 메서드를 호출해 서명을 확인할 수 있습니다.
구현 의무와 호출 의무
이 함수는 토큰 보유자에게 NFT로 서명할 기능을 주고 싶은 ERC-721 또는 ERC-1155 호환 컨트랙트가 구현할 수 있습니다(MAY). 반면 컨트랙트 서명을 지원하려는 호환 호출자는 서명자가 NFT(ERC-721 또는 ERC-1155) 보유자인 경우 반드시 이 메서드를 호출해야 합니다(MUST). 즉 구현은 선택이지만 지원을 표방하는 검증 측의 호출은 의무입니다.
서명 생성 표준을 정하지 않은 이유
이 제안은 서명을 만드는 방법은 일부러 표준화하지 않았습니다. ERC-1271이 스마트 컨트랙트에 서명 방식을 강제하지 않는 것과 같은 이유로, 생성 방식을 고정하면 유연성이 줄기 때문입니다. 검증 방식은 단순하고 충분히 검증된 Gnosis Safe의 컨트랙트 서명 접근을 참고했습니다. bytes calldata data 매개변수는 검증에 추가 데이터가 필요할 때 쓰는 선택 사항이며 향후 확장을 위해 ERC-5750을 따릅니다.
암호학적 서명이 아닌 동의 플래그
이 표준은 암호학적으로 생성된 서명을 검증하지 않는다는 점에서 기존 서명 검증 작업과 호환되지 않습니다. 여기서 서명은 동의를 나타내는 불리언 플래그에 불과합니다. 이는 Gnosis Safe의 컨트랙트 서명 구현과 일치하는 설계입니다.
참조 구현의 구조
참조 구현은 ERC-721 컨트랙트에 mapping(uint256 => mapping(bytes32 => bool)) 저장소를 두고 sign(tokenId, hash) 함수를 onlyTokenOwner 수식어로 보호해 해당 NFT 소유자만 서명을 등록하게 합니다. isValidSignature는 저장된 값이 참이면 MAGICVALUE(0x12edb34f), 아니면 BADVALUE(0xffffffff)를 반환하고 이 예시에서 data 매개변수는 쓰지 않습니다. supportsInterface로 ERC-165 지원도 선언하며 매직 값은 type(IERC6066).interfaceId와 같습니다.
쓸 때 주의할 점
- 서명 철회 가능성: 컨트랙트 기반 서명은 철회될 수 있다는 성질이 이 표준에도 그대로 이어집니다. 개발자와 사용자 모두 이 점을 고려해야 합니다.