ERC-5679 토큰 발행과 소각 확장 표준 (Token Minting and Burning)

Final · 토큰 · 2022-09-17 작성

EIP-20, EIP-721, EIP-1155 토큰에 발행(mint)과 소각(burn) 함수를 같은 방식으로 더하는 확장입니다. 토큰을 만들고 없애는 기본 생애주기를 표준 함수로 마무리합니다.

왜 필요한가

토큰 표준인 EIP-20, EIP-721, EIP-1155는 토큰을 주고받는 방법은 정하지만 새 토큰을 만들거나 없애는 방법은 따로 정하지 않습니다. 그래서 EIP-721과 EIP-1155의 일부 구현은 전송(transfer) 함수나 비슷한 방법을 빌려 발행과 소각을 처리해 왔습니다. 그러나 발행과 소각은 토큰의 총공급을 바꾸는 일이고 누가 할 수 있는지를 정하는 접근 제어 규칙도 보통 전송과 다릅니다. 전송 함수에 발행과 소각을 섞어 두면 구현이 복잡해지고 권한 설정에서 실수가 생기기 쉽습니다. 또 일관된 방법이 없으면 토큰의 기본 생애주기인 만들기, 옮기기, 없애기가 표준으로 완성되지 않은 상태로 남습니다. 이 표준은 세 토큰 표준 각각에 맞는 발행과 소각 전용 함수를 정해 구현을 단순하게 하고 보안 오류를 줄이는 것을 목표로 합니다.

구현해야 하는 것

심층 설명

적용 범위: 세 표준에 각각 다른 인터페이스

이 표준은 EIP-20, EIP-721, EIP-1155 토큰을 확장합니다. 어느 표준을 따르는 컨트랙트가 이 확장을 채택하면 그 표준에 대응하는 인터페이스를 반드시(MUST) 구현해야 합니다. EIP-20 용 IERC5679Ext20 의 EIP-165 식별자는 0xd0017968, EIP-721 용 IERC5679Ext721 은 0xcce39764, EIP-1155 용 IERC5679Ext1155 는 0xf4cedd5a 입니다. 인터페이스마다 함수 시그니처가 다르기 때문에 식별자를 하나로 합치지 않고 따로 둡니다. 클라이언트가 이 식별자들을 EIP-165 로 구현하는 것을 권장(RECOMMENDED)합니다. EIP-777 은 자체적으로 발행과 소각을 다루므로 확장 대상에서 제외했습니다.

EIP-20 확장: mint 와 burn

EIP-20 토큰은 mint(address _to, uint256 _amount, bytes calldata _data) 와 burn(address _from, uint256 _amount, bytes calldata _data) 를 구현합니다. 수량은 EIP-20 의 방식대로 _amount 하나로 나타내며 토큰 ID 는 없습니다. _data 는 함께 넘기는 바이트열이며 원문은 그 쓰임을 따로 정하지 않습니다. EIP-721, EIP-1155 와 달리 발행 함수 이름이 safeMint 가 아니라 mint 이고 배치 함수도 없습니다. 발행 시에는 0x0 에서 _to 로 _amount 만큼 전송된 것처럼 전송 이벤트를 내고 총공급을 늘려야 합니다. 소각 시에는 0x0 로 전송된 것처럼 이벤트를 내고 총공급을 줄여야 합니다.

EIP-721 확장: safeMint 와 burn

EIP-721 토큰은 safeMint(address _to, uint256 _id, bytes calldata _data) 와 burn(address _from, uint256 _id, bytes calldata _data) 를 구현합니다. 수량 대신 토큰 ID 인 _id 하나를 받습니다. 이는 EIP-721 이 토큰을 _id 로 나타내는 방식을 그대로 따른 것입니다. 원문은 세 인터페이스를 EIP-1155 처럼 항상 _amount 를 갖는 형태로 통일하는 방안도 검토했지만 각 토큰 표준이 원래 쓰는 _id 와 _amount 표현을 유지하기로 했습니다. EIP-721 에는 safeMintBatch 나 burnBatch 같은 배치 함수를 두지 않습니다. 이 역시 EIP-721 의 관례를 따른 결정입니다.

EIP-1155 확장: 단건과 배치 함수

EIP-1155 토큰은 네 함수를 구현합니다. safeMint(address _to, uint256 _id, uint256 _amount, bytes calldata _data) 는 한 종류의 토큰을 발행합니다. safeMintBatch(address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) 는 여러 종류를 한 번에 발행합니다. burn(address _from, uint256 _id, uint256 _amount, bytes[] calldata _data) 는 한 종류를, burnBatch(address _from, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata _data) 는 여러 종류를 한 번에 소각합니다. 토큰 ID 와 수량을 함께 받는 것은 EIP-1155 의 _id 와 _amount 표현을 따른 것이고 배치 함수를 둔 것도 EIP-1155 의 관례를 따른 결과입니다. 원문 선언에서 safeMintBatch 의 매개변수는 밑줄 없이 to, ids, amounts, data 로 적혀 있고 단건 burn 의 _data 는 bytes 가 아니라 bytes[] 배열형입니다. 구현할 때는 원문 선언의 타입을 그대로 따라야 합니다.

발행 시 이벤트와 총공급

토큰을 발행할 때는 전송 이벤트를 반드시(MUST) 내야 합니다. EIP-20 과 EIP-1155 는 _amount 만큼의 토큰이, EIP-721 과 EIP-1155 는 토큰 ID _id 가 0x0 주소에서 _to 가 가리키는 받는 주소로 전송된 것처럼 기록합니다. 총공급(total supply)도 그만큼 반드시 늘어나야 합니다. 이 표준은 새 이벤트를 만들지 않고 EIP-20, EIP-721, EIP-1155 가 이미 요구하는 전송 이벤트를 그대로 씁니다. 호환성을 최대한 지키기 위한 선택입니다.

소각 시 이벤트와 총공급

토큰을 소각할 때도 전송 이벤트를 반드시(MUST) 내야 합니다. 이번에는 보유 주소에서 0x0 주소로 _amount 만큼의 토큰이(EIP-20, EIP-1155) 또는 토큰 ID _id 가(EIP-721, EIP-1155) 전송된 것처럼 기록하고 총공급을 그만큼 반드시 줄여야 합니다. 원문 명세 5항은 보내는 쪽을 _to 가 가리키는 받는 주소라고 적고 있지만 burn 과 burnBatch 함수 선언에서 토큰을 잃는 주소의 매개변수 이름은 _from 입니다. 발행과 마찬가지로 새 이벤트를 정의하지 않고 각 토큰 표준의 기존 전송 이벤트를 씁니다.

safeMint 의 수신자 제한

EIP-721 과 EIP-1155 의 safeMint 는 각 표준의 safeTransferFrom 이 정한 것과 같은 수신자 제한을 반드시(MUST) 적용해야 합니다. EIP-721 과 EIP-1155 에서 safeTransferFrom 은 받는 쪽이 컨트랙트일 때 토큰을 받을 수 있는지 확인하는 절차를 둡니다. 발행도 결국 토큰이 새 주소로 들어가는 일이므로 전송에서 하던 안전 확인을 발행에서도 빠뜨리지 않도록 한 규정입니다. EIP-1155 의 safeMintBatch 도 이름에 safe 가 붙어 있으며 같은 인터페이스에 속합니다.

상태, 의존 표준, 호환성

이 제안은 최종(Final) 상태이며 2022년 9월 17일에 만들어졌습니다. EIP-20, EIP-165, EIP-721, EIP-1155 를 전제로 합니다(requires). 원문은 이 확장이 EIP-20, EIP-721, EIP-1155 각각과 호환되도록 설계되었다고 밝힙니다. 새 이벤트를 정의하지 않고 각 표준의 기존 전송 이벤트를 요구하는 것, 수량과 ID 의 표현을 각 표준 방식 그대로 두는 것, 배치 함수를 EIP-1155 에만 두는 것 모두 기존 표준과의 호환을 우선한 선택입니다. 지원 여부 확인은 인터페이스별 EIP-165 식별자로 합니다.

쓸 때 주의할 점

ERC 원문 · ← ERCs