본문 바로가기
프로그래밍/solidity

ERC-20 ( Ethereum Request for Comment 20 ) : 대체 가능한 토큰

by 한코코 2022. 11. 2.

솔리디티 파일을 이더리움 네트워크에 배포한 상태에서 시작한다.

만약 배포할 줄 모른다면 다음 글을 참고해서 따라하면 된다.

 

[220713] 스마트 컨트랙트 구현하기 - 1) 트러플로 구현하기

개발환경 설치&세팅하기 // truffle 설치&세팅 $ npm init -y $ mkdir truffle $ cd truffle $ npm install -g truffle $ npx truffle init // react를 사용하는 front 디렉토리 만들기 $ npx create-react-app front // ganache 네트워크 실

hancoco.tistory.com

 

 


오픈제플린 라이브러리 설치

솔리디티 기반의 스마트 계약을 개발하는 표준 프레임워크인 오픈제플린 라이브러리를 설치해준다.

$ npm install @openzeppelin/contracts

 

node_modules 디렉토리 안에 오픈제플린 관련 폴더가 생긴다.

 

 

ERC20 디렉토리를 열어보면 ERC20과 IERC20 파일이 있다.

 

 

IERC20.sol은 IERC20이라는 인터페이스를 정의하는 코드로 이루어져있다.

// IERC20
pragma solidity ^0.8.0;

// ^0.8.15버전에서는 contract로 선언하지 않고 interface라고 선언한다.
interface IERC20 { ... }

 

solidity 공식 사이트 설명을 보면, 상호작용하기 위해서 만들어진게 인터페이스라고 정의하고 있고, 다음과 같은 속성을 가진다.

  • 어떤 기능도 구현할 수 없다
  • 다른 인터페이스에서 상속 가능
  • 선언된 모든 함수는 외부에 있어야 한다.
  • 생성자(constructor)를 선언할 수 없다
  • 상태 변수를 선언할 수 없다

이를 따르면 IERC20은 누군가에게 상속 당하기 위한 인터페이스임을 알 수 있다.

ERC20.sol을 간단히 코드로 보면 ERC20 컨트랙트를 정의하는 코드로 이루어져 있다.

또한 Context, IERC20, IERC20Metadata를 상속 받는 것을 알 수 있다.

// ERC20
pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

// 상속받을때 사용하는 is
// 상속받음 is 상속함
contract ERC20 is Context,IERC20,IERC20Metadata { ... }

 

 

 


IERC20 주요 함수들

function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);

event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
  • totalSupply : 발행한 토큰의 총량을 반환함
  • balanceOf : 해당 계정 account가 보유한 토큰 잔액을 반환함
  • transfer : 토큰의 생성자가 계정 소유자와 같을때, 계정 to에게 amount개의 토큰을 전달한다.
  • transferFrom : 토큰의 생성자가 계정 소유자와 같지 않을때,  권한을 위임받은 계정 from은 위임받은 계정 to에게 토큰 amount개를 전달한다.
  • approve : 계정 소유자가 특정 계정 spender에게 amount개의 토큰을 위임한다.
  • allowance : 계정 소유자 owner가 특정 계정 spender에게 어느정도의 토큰을 위임했는지 값을 반환해준다.
  • Transfer : 토큰 전송이 일어날때 실행되는 이벤트.
  • Approval : approve 함수가 성공적으로 실행되면 실행되는 이벤트.

 

 

 


토큰 생성하기

ERC20.sol에 있는 _mint()함수를 사용해서 토큰을 생성했다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract Token is ERC20{
  // 구조체 이름 생략
  constructor() ERC20("test","testToken") {
    _mint(msg.sender, 1000*10**decimals());
  }

  // mint 함수 정의
  function mint(address to, uint amount) public {
    _mint(to,amount);
  }
}

 

$ truffle compile
$ truffle migration --reset

코드를 네트워크에 무사히 배포가 되었다.

그런데 토큰 CA를 가져와서 메타마스크에 토큰을 추가해보려고하는데 토큰이 추가되지 않았다.

 

토큰 CA를 입력했을때 내가 지정한 토큰기호와 토큰 십진수도 자동으로 입력이 되고, 잔액도 인식을 하는데 토큰이 추가가 안된다.

뭔가 잘못했나 싶어서 remix를 연결해 자세히 확인해보기로 했다.

 

 

무사히 Mint 컨트랙트가 실행된것도 확인할 수 있는데 대체 왜 안되는 것인가....

 

 

// test/token.js
const Token = artifacts.require("Token");

describe("Token Test", () => {
  let token;
  let owner;
  let mintToken;

  it("Token deployed", async () => {
    token = await Token.deployed();
    owner = token.address;
    mintToken = await token.mint(owner,100)
    console.log('token CA : ',owner)
    console.log('토큰 민트 결과 : ',mintToken)
  });
});
$ truffle test

테스트 코드를 통해서 토큰을 생성한 과정을 출력해보았다.

정상적으로 생성된걸 확인할 수 있다.

메타마스크에 연결되어서 보이지는 않지만 일단 생성은 잘 됨.

댓글