[Mastering Ethereum] 10. Tokens- (2)ERC20 토큰 구현해보기

Woojin Jeong
7 min readFeb 19, 2022

--

이 글은 Mastering Ethereum, by Andreas M. Antonopoulos, Gavin Wood를 참고 및 재구성하여 작성하였습니다.

(1)편에서 토큰의 개념에 대해 알아보았고, (2)편에서는 METoken이라는 ERC20 기반 토큰을 직접 구현해보고자 합니다. 이 예제에 대한 코드는 책의 github repository에 업로드 돼 있고, 솔리디티 v0.8.11 용 수정된 코드는 여기를 참고하시면 됩니다.

$ mkdir METoken 
$ cd METoken
METoken $ truffle init
METoken $ npm init

가장 먼저해야 할 일은 토큰 프로젝트의 디렉토리를 만들고 Truffle 프레임워크를 초기화하는 것입니다. npm(Node Package Manager)은 Node.js로 만들어진 모듈을 설치하고 관리해 주는 프로그램입니다. npm init은 패키지를 초기화해주는 명령어로, 실행 후 계속 엔터를 누르며 디폴트 값으로 설정해줍니다. 초기화 설정이 끝나면 디렉토리 안에 아래와 같은 파일들이 생성된 것을 볼 수 있습니다.

이제, (1)편에서도 잠깐 언급되었던 OpenZeppelin 라이브러리를 설치해줍니다. 이 패키지는 node_modules 디렉토리 아래에 약 250개의 파일을 추가하는데, ERC20 외에도 다양한 것들이 포함되어 있습니다. 여기서는 그 중 일부만을 사용할 것입니다. 솔리디티 버전에 맞게 OpenZeppelin 라이브러리 역시 수정이 필요한데, 다음 깃헙 코드를 참고하여 수정하시면 됩니다.

METoken.sol

METoken.sol

컨트랙트를 배포하기 전에 code editor를 통해 truffle-config.js 파일을 환경에 맞게 수정해 주어야 합니다. (책에 설명된 .env 파일을 이용하는 방법은 사용하지 않았습니다.) 또한, migrations 폴더 안에 2_deploy_contracts.js 파일을 만들어주고 아래의 명령어를 실행합니다. 컨트랙트를 구성하는 각 파일에 대한 설명은 7장의 솔리디티 편을 참고하시길 바랍니다.

$ truffle migrate --network ganache

1_initial_migration.js에서 migration이 배포되었고, 2_deploy_contracts.js에서는 METoken 컨트랙트가 배포된 것을 확인할 수 있습니다. 아래와 같이 가나슈 콘솔 창에도 컨트랙트 배포 결과를 볼 수 있습니다. 첫번째 계정은 컨트랙트 배포에 사용되었던 계정이므로 잔액이 조금 깎여 있습니다.

가나슈의 트랜잭션 탭을 클릭하면 총 4개의 트랜잭션이 생성된 것을 볼 수 있습니다. 맨 아래에 있는 트랜잭션은 위의 migration에 해당하는 트랜잭션 해시와 일치하고, 세번째 트랜잭션은 배포(deploy)한 트랜잭션 해시와 일치합니다. (오른쪽에 ‘contract creation’으로 표기돼 있음) 그렇다면 ‘contract call’에 해당하는 두번째와 네번째 트랜잭션은 어디에서 온 것일까요?

이들은 truffle 내부의 migrations.sol로부터 생긴 트랜잭션입니다. contracts 폴더 안의 migrations.sol 파일을 보면 last_completed_migration 변수가 선언됩니다. 이 변수는 한번 배포된 컨트랙트를 재배포하지 않기 위한 장치로, contract call에 해당하는 트랜잭션들은 이 변수를 업데이트 하기 위한 트랜잭션입니다. 블록체인의 immutability과 연결되는 개념으로, 컨트랙트는 기존에 배포된 주소로 재배포가 불가합니다. 좀 전에 실행한 migrate 커맨드에서 2개의 스크립트가 실행되었기 때문에 이 변수 값은 2로 업데이트 됩니다.

migrations.sol

또한 트러플 콘솔을 사용하여 생성한 컨트랙트를 다룰 수 있습니다. truffle-config.js에서 설정한 네트워크(여기서는 ganache)에 연결하여 커맨드 창에 truffle(ganache)> 표기가 있는지 확인합니다. METoken 컨트랙트는 트러플 환경 안에서 자바스크립트의 객체로 존재하고, address 같은 속성들을 포함하고 있습니다. 배포된 계약에 접근하려면 “deployed” 함수를 이용해서 컨트랙트 인스턴스를 얻고 then 함수 안에서 인스턴스의 totalSupply 함수를 호출해야합니다. 코드는 아래와 같습니다.

결과는 BN(big number) 형식으로 출력되는데, words의 맨 앞에 해당하는 숫자가 balance를 의미합니다. 한편, 아래와 같이 web3 api를 사용하여 계정 정보에 접근할 수 있습니다. web3.eth.accounts를 하여도 동일한 결과를 얻을 수 있습니다.

10000 MET를 첫번째 계좌에서 두번째 계좌로 송금해 봅시다. METoken이 deployed 되면 then 안에 있는 함수를 실행하라는 의미로, 순서대로 첫번째 계좌의 잔액을 확인하고, 두번째 계좌로 10000을 보낸 뒤, 다시 첫번째 계좌의 잔액을 확인하는 코드입니다. 그 결과 아래와 같이 잔액이 10000만큼 줄어든 것을 확인할 수 있습니다.

(1)편에서 설명한 것처럼, ERC20 토큰의 한계는 토큰 유실이었습니다. 이전 장에서 다루었던 Faucet.sol에 해당하는 컨트랙트로 우리가 만든 METoken을 보내면 영원히 잠기게 됩니다. Faucet.sol에는 ERC20의 전송 함수(transfer, approve&transferFrom)를 호출하는 코드가 없기 때문입니다. MET를 Faucet 컨트랙트에 보내려면 Faucet.sol의 수정이 필요한데, 이는 METFaucet.sol 코드를 참고하시길 바랍니다.

Reference

--

--