336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

이번 포스팅에선 이더리움 기반 토큰을 만들기 위한 Solidity 문법과 토큰 표준인 EIP20(ERC20)에 대해 알아보겠습니다.


첫 번째로 살펴볼 내용은 mapping 데이터 타입입니다.


예제 출처: http://solidity.readthedocs.io/en/develop/types.html#mappings


mapping은 일종의 key-value 스토리지 타입입니다. 기존 범용 프로그래밍 언어에서 흔히 볼 수 있는 Map<Key, Value>와 다른 점은 모든 키에 대해 Value가 존재하는 것처럼 동작합니다. 즉, 특정 키에 값을 쓰기 전에도 읽기가 가능하고, mapping 생성 시 초기화는 모든 키에 대해 값이 0인 것과 같습니다. 이런 특성 때문에 mapping 타입 자체에는 key에 대한 순회 방법이 존재하지 않습니다. key를 순회하기 위해서는 순회하려는 key의 리스트를 별도로 관리해야 합니다.


msg.sender는 transfer()를 호출한 이더리움 계정의 주소입니다. 즉, 위의 예제는 해당 이더리움 계정을 가진 사람만이 자신의 balance를 업데이트 할 수 있습니다.


이 mapping(address => uint) 타입이 이더리움 기반 토큰의 핵심을 담고 있습니다. 우리가 비트코인이나 이더리움의 이더를 생각해보면 어떤 암호화폐의 소유란 결국 내가 소유한 주소(공개키)에 얼마가 있는지가 공개되어 있다는 것입니다. 만약 우리가 이더리움 주소를 생성하면 그 주소에는 0 ETH가 들어있는 것으로 취급됩니다. 누군가 입금을 하기 전까지는요. mapping와 같지요. 이제 토큰 보내는 함수를 보겠습니다.



require(bool condition)는 조건이 만족하지 않으면 해당 트랜잭션을 취소합니다. 예제 구현에서는 자신이 가진 토큰보다 더 많은 토큰을 보내려 할 때 이를 막기 위해 쓰여졌습니다. 내 이더리움 계정을 가지고 transfer(address to, uint value) 함수를 호출함으로써 to 주소로 value 만큼 토큰을 보낼 수 있습니다. to는 다른 이더리움 계정이겠지요. 이러한 원리로 이더리움 계정은 ETH를 소유함과 동시에 이더리움 기반 토큰을 소유할 수 있습니다. 이제 남은 것은 토큰의 발행 정도이군요. 아주 간단한 예제를 하나 보겠습니다.



InitialSupplyExample은 생성자를 두어 생성자를 호출한 사람에게 10만 토큰을 넣습니다. 즉, 토큰을 만든 사람에게 10만 토큰을 발행한 것이지요. 위 예제의 경우 해당 토큰은 10만 개가 총 발행량이 되고, 더 이상 발행될 수 없습니다. 추후에 더 발행할 수 있는 토큰을 만들고 싶다면 아래처럼 작성해야 합니다.




mint 함수는 owner가 토큰을 새로 생성할 수 있는 함수입니다. 생성자를 호출한 사람을 owner로 기억해두기 때문에 해당 토큰을 만든 사람만이 토큰을 생성할 권리를 가지게 됩니다. 물론 위의 예제처럼 아무런 제약없이 토큰을 생성할 수 있다면 아무도 이 토큰에 가치를 신뢰하지 않을 겁니다.


토큰을 owner가 찍어내는 방식이 아닌 payable 함수를 두어 ETH를 받고 토큰을 발행해주는 방식도 생각해볼 수 있겠습니다. 스마트 컨트랙트 코드를 어떻게 짜느냐가 그 토큰의 특성을 정의하게 됩니다.


여기까지 간단한 이더리움 기반 토큰 구현에 대해 살펴보았고, 이제 ERC20 인터페이스에 대해 살펴보겠습니다. ERC20 토큰 표준안은 각종 토큰을 구현하는 스마트 컨트랙트가 지켜야 할 인터페이스입니다. EIP20 표준으로 채택되어 이 인터페이스를 지킨다면 지갑 앱이나 explorer 앱에서 이 토큰과 관련된 정보를 보여줍니다. 아래 스크린샷은 etherscan.io에서 Bread TOKEN 정보를 보여주는 예입니다.



아래는 EIP20 토큰이 지켜야 할 contract 인터페이스입니다.




여기서 Approval과 관련된 transferFrom/approve/allowance 함수는 설명이 필요할 것 같습니다. 이더리움 토큰은 토큰을 직접 보내는 방법도 있지만, 다른 사람이 내가 가진 토큰 사용을 허가하는 방법도 있습니다.


A라는 이더리움 계정이 approve(B, 100)을 호출하면 B 계정이 A 계정에 있는 토큰 100개를 사용할 수 있습니다. B는 transferFrom(A, C, 60)을 호출해서 C 계정에 60 토큰을 보낼 수 있습니다.

allowance는 balanceOf의 approval 버전입니다. A가 B에게 100을 approve하고, B가 C에게 transferFrom으로 60을 보내고 나면 allowance(A, B)는 40이 반환됩니다.


직접 transfer대신 approve하는 방식은 수수료 문제로 자주 쓰입니다. 예를 들어 어떤 토큰이 transfer 함수 내에서 msg.sender에게 1토큰의 수수료를 부과한다고 가정해 봅시다.


transfer 방식

A calls transfer(B, 100)

이 경우 A에서 101 토큰이 출금되고 B에 100이 입금됩니다.


approve 방식

A calls approve(B, 100)

B calls transferFrom(A, B, 100)

이 경우 A에서 100 토큰이 출금되고 B에 99가 입금됩니다.


수수료를 내는 주체가 달라집니다. 물론 이는 transfer에 수수료가 있다는 가정 하에 그렇습니다. 앞서 토큰 발행 시에 payable 함수를 두어 ETH를 토큰으로 바꾸는 예를 살짝 소개했는데, 토큰을 ETH로 바꾸는 환불의 경우 트랜잭션 수수료가 강제되기 때문에 ETH 출금같은 경우에는 거의 이 방식이 쓰입니다. 물론 이는 보내는 사람의 수수료 비용을 줄여주기도 하지만 ETH를 보낼 때 발생할 수 있는 보안 위협을 줄일 수 있는 방법이기도 합니다. 자세한 내용은 다른 보안 이슈 관련 포스팅에서 소개할 기회가 있으면 좋겠습니다.


지금까지 이더리움 기반의 토큰과 그 표준인 EIP20에 대해 알아보았습니다. 토큰에 관한 구체적인 구현이 궁금하신 분들은 OpenZeppelin의 라이브러리를 살펴보시면 도움이 될 것 같습니다.


https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts/token


20분만에 이더리움 토큰 발행하기라는 재미있는 포스팅도 있어 소개합니다. 이미 짜여진 라이브러리를 수정하면 이름 붙이고 어떻게 발행할 지만 결정하면 되는 정도라 매우 간단합니다.


https://medium.com/bitfwd/how-to-issue-your-own-token-on-ethereum-in-less-than-20-minutes-ac1f8f022793


+ Recent posts