엘리시아가 OpenZeppelin 코드를 따라가며 이더리움 토큰 표준 ERC20 과 ERC165, ERC721 의 작동 원리를 정리한 글이다. 토큰 보유가 사실은 컨트랙트 안의 매핑 값일 뿐이라는 데서 출발해, ERC20 의 토큰 유실 문제와 그것을 막기 위한 인터페이스 확인 표준으로 이어진다.
핵심 포인트- 토큰을 보유한다는 것은 해당 토큰 컨트랙트의 balance 에 주소와 숫자가 매핑돼 있는 것에 불과하고, 전송은 그 숫자를 바꾸는 과정이다.
- ERC20 의 가장 큰 한계는 토큰 유실이다. 받는 주소에 어떤 인터페이스가 있든 상관없이 전송되기 때문이다.
- 이더는 payable 함수가 없는 컨트랙트로 보내면 트랜잭션이 되돌려지지만, ERC20 토큰은 그대로 들어가 잠긴다.
- 그래서 받는 컨트랙트가 그 토큰을 다룰 인터페이스를 갖고 있는지 전송 전에 확인할 수 있어야 하고, 그 확인 표준이 ERC165 다.
- ERC165 를 상속한 컨트랙트는 자신이 어떤 인터페이스를 구현하는지 선언할 수 있고, 반대로 supportsInterface 호출로 상대 컨트랙트를 확인할 수 있다.
상세 정리- transfer 는 여러 검증을 거친 뒤 보내는 쪽과 받는 쪽의 balances 값을 변경하는 함수다.
- OpenZeppelin 의 확장 기능들을 소개한다. Snapshot 은 특정 시점의 balance 와 totalSupply 에 접근하게 해줘 투표나 에어드랍에 쓸 수 있다.
- Pausable 은 transfer 와 mint, burn 세 함수를 멈출 수 있게 하고, security 항목의 유틸을 쓰면 다른 함수도 멈추게 만들 수 있다.
- Burnable 은 소각을, Capped 는 최대 totalSupply 를 설정해 그 이상 발행되지 않게 한다.
- 모든 토큰 표준에는 전송 전에 끼어드는 훅이 있어, 전송 직전에 여러 장치를 두는 응용이 가능하다.
- ERC20 의 유실 문제를 해결하려 등장한 표준으로 ERC777 을 언급하고 다음 글에서 다루겠다고 예고한다.
- 인터페이스 등록은 함수 선택자를 구하는 것에서 시작한다. 함수 이름과 인자를 해싱해 selector 를 얻고, 여러 selector 에 XOR 을 적용해 인터페이스 하나의 ID 를 만든다.
- ERC721 의 인터페이스 ID 를 생성자에서 등록하면 그 컨트랙트가 해당 인터페이스를 구현한다고 선언하는 셈이 된다.
- 확인 쪽은 EIP165 가 제시한 방식을 OpenZeppelin 이 라이브러리로 만든 ERC165Checker 를 쓴다. 상대가 ERC165 를 구현했는지, 했다면 또 어떤 인터페이스를 구현했는지 알 수 있다.
- ERC721 은 크립토키티 같은 NFT 의 표준으로 디지털 세계의 소유권 주장을 위해 제안됐다. ERC20 과 달리 각 토큰이 고유하며 그 고유성은 token ID 로 표현된다.
- 토큰 표준은 이더리움 재단의 EIP 에 제안돼 있지만, OpenZeppelin 같은 프레임워크가 이를 컨트랙트에 쉽게 적용하도록 돕는다고 짚으며 시작한다.
왜 읽나토큰 표준을 이름만 알고 있던 개발자에게, OpenZeppelin 구현 코드를 근거로 각 표준이 어떤 문제를 풀려고 나왔는지 이어서 설명해주는 글.