무지개곰
article thumbnail

이더리움에서 가장 유명하면서도 널리 사용되는 토큰 표준 중 하나로 ERC20이 있습니다. ERC20을 따르면 자산을 보다 쉽게 교환할 수 있고 다양한 Dapp끼리 동일한 표준에 따라 상호 연동할 수 있습니다. ERC20 토큰을 생성하기 위하여 어떠한 규칙을 따라야 하는지 알아보겠습니다.

ERC20 표준

ERC20 토큰은 대체 가능 토큰(fungible token)으로 고유하지 않으면서 동일한 가치의 다른 토큰으로 완벽히 대체할 수 있는 토큰입니다. 따라서 ERC20 기반 토큰을 생성하려면 아래의 함수를 반드시 제공해야 합니다.

totalSupply()
balanceOf(address _owner)
transfer(address _to, uint256 _value)
transferFrom(address _from, address _to, uint256 _value)
approve(address _spender, uint256 _value)
allowance(address _owner, address _spender)

위에서부터 각 함수의 역할을 설명하자면 아래와 같습니다.

totalSupply는 토큰의 총 발행량

balanceOf는 _owner가 소지하고 있는 토큰의 수량 확인

transfer은 _to에게 _value만큼 토큰을 전송

transferFrom은 _from으로부터 _to에게 _value만큼 토큰 전달

approve는 _spender에게 _value만큼 토큰의 권한을 부여

allowance는 _owner가 _spender에게 권한을 부여한 토큰 수량 확인

 

또한 위의 함수 이외에도 사용되는 이벤트는 아래와 같습니다.

transfer(address indexed _from, address indexed _to, uint256 _value)
approval(address indexed _owner, address indexed _spender, uint256 _value)

토큰 전송 및 권한 부여를 하게 되면 두 이벤트를 발생시켜 로그에 기록합니다. 이를 통하여 토큰을 전송하였는지 권한을 부여하였는지 이벤트의 로그를 통하여 확인할 수 있습니다.


mint와 burn

mint 함수는 새로운 토큰을 발행하는 기능을 구현할 때 사용될 수 있습니다.

burn 함수는 특정 주소가 소유한 토큰을 감소시키는 역할을 합니다.

mint와 burn함수는 ERC-20 표준에서는 제공되지 않고, 프로젝트의 특정 요구에 따라 사용자 정의 함수로 구현되어야 합니다. 따라서 mint와 burn 기능이 필요한 경우, ERC-20 토큰을 개발하는 프로젝트에서는 해당 기능을 자체적으로 추가하여 스마트 계약을 구현해야 합니다. 이러한 기능을 구현하기 위해서는 프로젝트의 개발자가 토큰의 로직을 수정하고, mint와 burn 기능을 구현하는 함수를 추가하여야 합니다.

 

*Openzeppelin에서 제공하는 ERC20의 경우 _mint함수와 _burn함수가 존재합니다.

_mint

function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

_burn

function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

최대 발행량 제한

bitcoin의 경우 총발행량이 2100만 개로 제한되어 있습니다. ERC-20을 이용하여 총발행량을 제한하려면 스마트 계약에서 해당 로직을 구현해야 합니다. 일반적으로 ERC-20 토큰의 총공급량은 totalSupply() 함수를 통해 조회하므로 다음과 같은 방법으로 토큰의 총발행량을 제한할 수 있습니다.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;

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

contract RainbowBearToken is ERC20 {
	uint256 public maxSupply;

	constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol)  {
  	    maxSupply = 1000000; // 총 발행량을 1,000,000으로 설정
	}

	function mint(address _to, uint256 _amount) public {
	    require(totalSupply() + _amount <= maxSupply, "Max supply exceeded");
	    _mint(_to, _amount);
 	   emit Transfer(address(0), msg.sender, _amount);
	}
}
  1. openzeppelin을 이용하여 ERC20을 import 합니다.
  2. import 한 ERC20을 is를 이용하여 RainbowBearToken에 상속합니다.
  3. constructor를 이용하여 maxSupply를 설정해 줍니다.
  4. 상속받은 ERC20도 선언을 하기 위하여 constructor의 매개변수인 _name과 _sybol을 ERC20(_name, _sybol)을 통하여 전달합니다.
  5. mint라는 함수를 만들고 require문을 통하여 총발행량을 확인 후 상속받은 ERC20의 함수인 _mint를 통하여 토큰을 발행합니다.

'BlockChain > solidity' 카테고리의 다른 글

[Solidity] ERC-2771이란? (ERC-2771Context란?)  (0) 2023.07.02
[Solidity] EIP-712란?  (0) 2023.07.02
[Solidity] ERC20 Permit이란?  (0) 2023.06.17
[Solidity] ERC-1155란?  (0) 2023.05.18
[Solidity] ERC-721이란?  (0) 2023.05.18
profile

무지개곰

@무지개곰

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!