"ERC-165"의 두 판 사이의 차이

위키원
이동: 둘러보기, 검색
4번째 줄: 4번째 줄:
  
 
  pragma solidity ^0.4.20;
 
  pragma solidity ^0.4.20;
 
 
  interface ERC165 {
 
  interface ERC165 {
 
     /// @notice Query if a contract implements an interface
 
     /// @notice Query if a contract implements an interface
15번째 줄: 14번째 줄:
 
  }
 
  }
  
solidity의 함수들은 모두 selector를 가지고 있습니다. selector는 간단히 생각하시면 함수의 아이디라고 생각하셔도 무방합니다. 이 아이디를 만드는 방법은 함수의 시그니처를 해싱하는 건데요. 예를 들어서
+
solidity의 함수들은 모두 selector를 가지고 있다. selector는 간단히 생각하시면 함수의 아이디라고 생각한다. 이 아이디를 만드는 방법은 함수의 시그니처를 해싱하는 것이다. 예를 들어서
 +
 
 +
function balanceOf(address _owner) external view returns (uint256){
 +
    //...
 +
};
 +
 
 +
위와 같은 함수의 아이디를 얻기 위해서는
 +
 
 +
bytes4(keccak256("balanceOf(address)"))
 +
 
 +
위처럼 keccak256을 이용해서 해싱하거나 혹은
 +
 
 +
this.balanceOf.selector
 +
 
 +
이렇게 컨트랙트 내부에서 각 메소드의 selector를 호출해서 확인하실 수 있습니다. 기본적으로 함수의 시그니처에 따라 다른 해시값이 나오고 이 해시값이 해당 함수의 selector가 됩니다.
 +
ERC-165에선 인터페이스의 구현 여부를 확인하기 위해 이 selector를 사용합니다.
 +
이 때 함수의 selector가 해당 함수의 ID라고 한다면 우리는 인터페이스에서 정의한 함수를 모두 구현했는지 여부를 확인하기 위해 인터페이스의 ID에 해당하는 값이 필요한데요. 이 아이디는 인터페이스를 구성하는 모든 함수의 selector를 비트 단위 xor 연산을해서 구합니다.
 +
 
 +
 
 +
pragma solidity ^0.4.20;
 +
 
 +
import "./ERC165.sol";
 +
 
 +
interface Simpson {
 +
    function is2D() external returns (bool);
 +
    function skinColor() external returns (string);
 +
}
 +
 
 +
contract Homer is ERC165, Simpson {
 +
    function supportsInterface(bytes4 interfaceID) external view returns (bool) {
 +
        return
 +
          interfaceID == this.supportsInterface.selector || // ERC165
 +
          interfaceID == this.is2D.selector
 +
                          ^ this.skinColor.selector; // Simpson
 +
    }
 +
 
 +
    function is2D() external returns (bool){}
 +
    function skinColor() external returns (string){}
 +
}
 +
 
 +
위 코드에서 보시면 Simpson이라는 인터페이스의 인터페이스 id를 구하기 위해
 +
 
 +
this.is2D.selector ^ this.skinColor.selector
 +
 
 +
와 같이 연산하는 것을 보실 수 있습니다. 해당 스마트 컨트랙트 Homer가 Simpson 인터페이스를 구현했는지 여부를 확인하고 싶다면 function supportsInterface(bytes4 interfaceID) {} 에 Simpson의 인터페이스 id를 파라미터로 넣어서 호출합니다. true를 반환한다면 컨트랙트 Homer 는 Simpson 인터페이스를 구현한 것이고, false 를 반환한다면 구현하지 않은 것입니다.

2019년 8월 9일 (금) 10:46 판

ERC-165는 Ethereum Request for Comment165의 약자로서 토큰 대신에 방법에 대한 표준을 지정한다. 인터페이스 확인 구현 후 인터페이스 게시하며 스마트 컨트랙트에 주어진 인터페이스를 언제 사용하는지 감지한다.

개요

ERC-165 인터페이스

pragma solidity ^0.4.20;
interface ERC165 {
   /// @notice Query if a contract implements an interface
   /// @param interfaceID The interface identifier, as specified in ERC-165
   /// @dev Interface identification is specified in ERC-165. This function
   ///  uses less than 30,000 gas.
   /// @return `true` if the contract implements `interfaceID` and
   ///  `interfaceID` is not 0xffffffff, `false` otherwise
   function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

solidity의 함수들은 모두 selector를 가지고 있다. selector는 간단히 생각하시면 함수의 아이디라고 생각한다. 이 아이디를 만드는 방법은 함수의 시그니처를 해싱하는 것이다. 예를 들어서

function balanceOf(address _owner) external view returns (uint256){
   //...
};

위와 같은 함수의 아이디를 얻기 위해서는

bytes4(keccak256("balanceOf(address)"))

위처럼 keccak256을 이용해서 해싱하거나 혹은

this.balanceOf.selector

이렇게 컨트랙트 내부에서 각 메소드의 selector를 호출해서 확인하실 수 있습니다. 기본적으로 함수의 시그니처에 따라 다른 해시값이 나오고 이 해시값이 해당 함수의 selector가 됩니다. ERC-165에선 인터페이스의 구현 여부를 확인하기 위해 이 selector를 사용합니다. 이 때 함수의 selector가 해당 함수의 ID라고 한다면 우리는 인터페이스에서 정의한 함수를 모두 구현했는지 여부를 확인하기 위해 인터페이스의 ID에 해당하는 값이 필요한데요. 이 아이디는 인터페이스를 구성하는 모든 함수의 selector를 비트 단위 xor 연산을해서 구합니다.


pragma solidity ^0.4.20;
import "./ERC165.sol";
interface Simpson {
    function is2D() external returns (bool);
    function skinColor() external returns (string);
}
contract Homer is ERC165, Simpson {
    function supportsInterface(bytes4 interfaceID) external view returns (bool) {
        return
          interfaceID == this.supportsInterface.selector || // ERC165
          interfaceID == this.is2D.selector
                         ^ this.skinColor.selector; // Simpson
    }
    function is2D() external returns (bool){}
    function skinColor() external returns (string){}
}

위 코드에서 보시면 Simpson이라는 인터페이스의 인터페이스 id를 구하기 위해

this.is2D.selector ^ this.skinColor.selector

와 같이 연산하는 것을 보실 수 있습니다. 해당 스마트 컨트랙트 Homer가 Simpson 인터페이스를 구현했는지 여부를 확인하고 싶다면 function supportsInterface(bytes4 interfaceID) {} 에 Simpson의 인터페이스 id를 파라미터로 넣어서 호출합니다. true를 반환한다면 컨트랙트 Homer 는 Simpson 인터페이스를 구현한 것이고, false 를 반환한다면 구현하지 않은 것입니다.