AccessControlEnumerable 컨트랙트를 구현하다가 ERC165에 대한 내용을 접하게 되어서 작성하게 되었다.
배포한 컨트랙트가 해당 배포한 컨트랙트의 표준을 따르고 있는지 확인하는 표준
(ERC721을 만들었는데 ERC721 표준을 정확히 따르고 있는가…? 에 대한걸 확인하는 표준)
우리는 해당 컨트랙트가 어떤 표준을 실제로 구현했는지 확인 할수있는 방법이 없다. 이를 확인 할수있게 해주는 것이 ERC165 표준이다.
solidity 함수는 모두 selector(함수 시그니처 해싱값)라고 하는 함수 아이디를 들고있다.
그렇다면 ‘표준 인터페이스에 구현된 함수아이디’와 ‘작성한 컨트랙트의 함수아이디’를 비교하면 인터페이스를 구현하고 있구나를 확인할 수 있을 것이다.
하지만 각 함수 아이디를 일일히 비교하는 것은 비효율적이기 때문에 표준 인터페이스의 함수들을 XOR 연산하여 인터페이스 아이디를 만들어 내고 이와 내가 작성한 컨트랙트 인터페이스 아이디를 비교한다.
//ERC165
abstract contract ERC165 is IERC165 {
function supportsInterface(
bytes4 interfaceId
) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
//ERC165를 상속 받는 AccessControl
abstract contract AccessControl is Context, IAccessControl, ERC165 {
function supportInterface(
bytes4 interfaceId
) public view virtual returns (bool) {
return
interfaceId == type(IAccessControl).interfaceId ||
super.supportsInterface(interfaceId);
}
}
//AccessControl을 상속받는 AccessControlEnumerable
abstract contract AccessControlEnumerable is
IAccessControlEnumerable,
AccessControl
{
function supportsInterface(
bytes4 interfaceId
) public view virtual override returns (bool) {
return
interfaceId == type(IAccessControlEnumerable).interfaceId ||
super.supportsInterface(interfaceId);
}
}
위 코드는 ERC165를 상속받는 AccessControl을 상속 받는 AccessControlEnumerable 컨트랙트이다.
IAccessControlEnumerable가 구현되었는지 확인하고 싶다면 IAccessControlEnumerable의 아이디를 supportsInterface 에 넣어보고 구현되었다면 True값을 반환한다.
만약 IERC165가 구현되었는지를 확인 하고 싶다면 super를 통해 상속받은 IERC165 인터페이스 아이디와 비교하여 True를 반환할것이다.