Klaytn 문서 아카이브
시작하기스마트 컨트랙트노드 운영dApp 개발자
  • Klaytn 문서
  • -
    • Klaytn Overview
      • 왜 클레이튼일까요?
      • 클레이튼 디자인
        • 합의 메커니즘
        • 계정
        • 트랜잭션
          • 기본
          • 수수료 위임 트랜잭션
          • 수수료 부분 위임 트랜잭션
          • Ethereum
        • 연산
          • 클레이튼 스마트 컨트랙트
          • 실행 모델(Execution Model)
          • Computation Cost
            • 연산 비용 (구 버전 문서)
          • Klaytn 가상머신
            • 클레이튼 가상머신 (구 버전 문서)
        • 스토리지
        • 트랜잭션 비용
          • 트랜잭션 비용 (구 버전 문서)
        • 클레이튼의 네이티브 코인 - KLAY
        • 토큰 이코노미
        • 거버넌스
        • 다중 채널
        • KNI
      • 확장성 솔루션
    • Getting Started
      • Deploying Smart Contract Using Foundry
      • Deploying Smart Contract Using Hardhat
      • Deploying Smart Contract Using KEN
        • Launch an Endpoint Node
        • Top up your Account
        • Install Development Tools
        • Deploy a Smart Contract
        • Check the Deployment
        • Account Management
          • Creating Accounts
          • Managing Accounts
      • Development Environment
      • Getting KLAY
    • 스마트 컨트랙트
      • 솔리디티 - 스마트 컨트랙트 언어
      • 미리 컴파일된 컨트랙트
        • 미리 컴파일된 컨트랙트 (구 버전 문서)
      • IDE 및 도구
        • Truffle
      • 샘플 컨트랙트
        • KlaytnGreeter
        • ERC-20
          • 1. ERC-20 스마트 컨트랙트 작성
          • 2. 스마트 컨트랙트 배포
          • 3. 클레이튼 월렛에서 ERC-20 토큰 사용
        • ERC-721
          • 1. ERC-721 스마트 컨트랙트 작성
          • 2. Deploying Smart Contract
      • 테스트 가이드
      • 배포 가이드
      • 클레이튼 호환 토큰
      • 이더리움 컨트랙트 이식
    • Run a Node
      • 배포
        • Endpoint Node
          • 시스템 요구사항
          • 설치 가이드
            • 다운로드
            • Installation Guide
            • 환경설정
            • EN 실행하기
            • 설치 테스트하기
          • ken CLI 명령어
          • JSON-RPC API
        • 코어 셀
          • System Requirements
          • 네트워크 설정
          • Installation Guide
            • Download
            • 설치하기 전에
            • 컨센서스 노드 설정
              • Installation Guide
              • Configuration
              • CN 실행하기
            • 프록시 노드 설정
              • Installation Guide
              • Configuration
              • PN 실행하기
            • 코어 셀 테스트하기
          • 모니터링 설정
          • H/A 설정
        • Service Chain
          • Getting Started
            • 4개 노드 서비스 체인 설정하기
            • Connecting to Baobab
            • 크로스체인 토큰 전송
            • HA(High Availability) for ServiceChain
            • Nested ServiceChain
            • Value Transfer between Sibling ServiceChains
          • 참조 매뉴얼
            • System Requirements
            • Download
            • SCN User Guide
              • Installation
              • Configuration
              • SCN 실행 및 중지하기
              • 노드 상태 확인하기
              • kscn commands
              • homi commands
            • SPN/SEN User Guide
              • Installation
              • Configuration
              • 노드 실행 및 중지
              • Checking Node Status
            • Bridge Configuration
            • 앵커링
            • KAS 앵커링
            • 토큰 전송
            • Configuration Files
            • 로그 파일
            • Genesis JSON
            • 업그레이드 및 하드포크
          • How-To Guides
        • Download Node Packages
          • v1.11.1
          • v1.11.0
          • v1.10.2
          • v1.10.1
          • v1.10.0
          • v1.9.1
          • v1.9.0
          • v1.8.4
          • v1.8.3
          • v1.8.2
          • v1.8.1
          • v1.8.0
          • v1.7.3
          • v1.7.2
          • v1.7.1
          • v1.7.0
          • v1.6.4
          • v1.6.3
          • v1.6.2
          • v1.6.1
          • v1.6.0
          • v1.5.3
          • v1.5.2
          • v1.5.1
          • v1.5.0
          • v1.4.2
          • v1.4.1
          • v1.4.0
          • v1.3.0
          • v1.2.0
          • v1.1.1
          • v1.0.0
          • v0.9.6
          • v0.8.2
    • 운영 가이드
      • Configuration
      • 노드 로그
      • Log operation
      • 에러 및 문제 해결
      • Klaytn Command
      • Chaindata Change
      • Chaindata Migration
    • dApp Developers
      • JSON-RPC APIs
        • API references
          • eth
            • Caution
            • Account
            • Block
            • Transaction
            • Config
            • Filter
            • Gas
            • Miscellaneous
          • klay
            • Account
            • Block
            • Transaction
              • Working with Klaytn Transaction Types
            • Configuration
            • Filter
            • Gas
            • Miscellaneous
          • net
          • debug
            • Logging
            • Profiling
            • Runtime Tracing
            • Runtime Debugging
            • VM Tracing
            • VM Standard Tracing
            • Blockchain Inspection
          • admin
          • personal
          • txpool
          • governance
        • Service Chain API references
          • mainbridge
          • subbridge
        • Transaction Error Codes
      • RPC Service Providers
        • Public Endpoints
      • SDK & Libraries for interacting with Klaytn Node
        • caver-js
          • Getting Started
          • Sending a sample transaction
          • API references
            • caver.account
            • caver.wallet
              • caver.wallet.keyring
            • caver.transaction
              • Basic
              • Fee Delegation
              • Partial Fee Delegation
            • caver.rpc
              • caver.rpc.klay
              • caver.rpc.net
              • caver.rpc.governance
            • caver.contract
            • caver.abi
            • caver.kct
              • caver.kct.kip7
              • caver.kct.kip17
              • caver.kct.kip37
            • caver.validator
            • caver.utils
            • caver.ipfs
          • caver-js ~v1.4.1
            • Getting Started (~v1.4.1)
            • API references
              • caver.klay
                • Account
                • Block
                • Transaction
                  • Legacy
                  • Value Transfer
                  • Value Transfer Memo
                  • Account Update
                  • Smart Contract Deploy
                  • Smart Contract Execution
                  • Cancel
                • Configuration
                • Filter
                • Miscellaneous
              • caver.klay.net
              • caver.klay.accounts
              • caver.klay.Contract
              • caver.klay.KIP7
              • caver.klay.KIP17
              • caver.klay.abi
              • caver.utils (~v1.4.1)
            • Porting from web3.js
        • caver-java
          • Getting Started
          • API references
          • caver-java ~v1.4.0
            • Getting Started (~v1.4.0)
            • Porting from web3j
        • ethers.js
        • web3.js
      • Tutorials
        • Klaytn Online Toolkit
        • Fee Delegation Example
        • Count DApp
          • 1. Environment Setup
          • 2. Clone Count DApp
          • 3. Directory Structure
          • 4. Write Smart Contract
          • 5. Frontend Code Overview
            • 5-1. Blocknumber Component
            • 5-2. Auth Component
            • 5-3. Count Component
          • 6. Deploy Contract
          • 7. Run App
        • Klaystagram
          • 1. Environment Setup
          • 2. Clone Klaystagram DApp
          • 3. Directory Structure
          • 4. Write Klaystagram Smart Contract
          • 5. Deploy Contract
          • 6. Frontend Code Overview
          • 7. FeedPage
            • 7-1. Connect Contract to Frontend
            • 7-2. UploadPhoto Component
            • 7-3. Feed Component
            • 7-4. TransferOwnership Component
          • 8. Run App
        • Building a Buy Me a Coffee dApp
          • 1. Project Setup
          • 2. Creating a BMC Smart Contract
          • 3. Testing the contract using scripts
          • 4. Deploying BMC Smart contract
          • 5. Building the BMC Frontend with React and Web3Onboard
          • 6. Deploying Frontend code on IPFS using Fleek
          • 7. Conclusion
        • Migrating Ethereum App to Klaytn
        • Connecting MetaMask
        • Connecting Remix
        • Verifying Smart Contracts Using Block Explorers
      • Developer Tools
        • Wallets
          • Kaikas
          • Klaytn Wallet
          • Klaytn Safe
            • Klaytn Safe Design
            • Create a Safe
            • Add assets
            • Send assets
            • Contract Interaction
            • Transaction Builder
            • Points to Note
            • Frequently Asked Questions
          • Wallet Libraries
            • Web3Auth
            • Web3Modal
            • Web3-Onboard
        • Oracles
          • Orakl Network
          • Witnet
          • SupraOracles
        • Block Explorers
          • Klaytnscope
          • Klaytnfinder
        • Klaytn Contracts Wizard
    • Glossary
  • ---
    • Klaytn 하드포크
    • 클레이튼 2.0
      • 메타버스 패키지
      • 완결성과 개선 사항들
      • 이더리움 호환성
      • 거버넌스 탈중앙화
      • 대규모 에코 펀드
    • FAQ
    • 오픈 소스
    • 이용약관
    • 지원 언어
  • ℹ️최신 Klaytn 문서
Powered by GitBook
On this page
  • 1.1 MyERC20의 전체 구조
  • 1.2 중요한 메소드(method) 살펴보기
  • (1) function balanceOf(address account) external view returns (uint256);
  • (2) function transfer(address recipient, uint256 amount) external returns (bool);
  • (3) function approve(address spender, uint256 amount) external returns (bool);
  • (4) function _mint(address account, uint256 amount) internal

Was this helpful?

  1. -
  2. 스마트 컨트랙트
  3. 샘플 컨트랙트
  4. ERC-20

1. ERC-20 스마트 컨트랙트 작성

1.1 MyERC20의 전체 구조

MyERC20.sol의 전체 소스 코드는 아래에서 확인할 수 있습니다. 이 구현체에서 constructor는 컨트랙트 배포 시 미리 정의된 양의 토큰을 발행하기 위해 _mint를 호출합니다.

pragma solidity ^0.5.0;

/**
 * @dev EIP에 정의된 ERC20 표준 인터페이스 추가 함수를 포함하지 않습니다;
 * 이들에 접근하려면 `ERC20Detailed`을 확인하세요.
 */
interface IERC20 {
    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

library SafeMath {
    /**
     * @dev 두 부호 없는 정수의 합을 반환합니다.
     * 오버플로우 발생 시 예외처리합니다.
     *
     * 솔리디티의 `+` 연산자를 대체합니다.
     *
     * 요구사항:
     * - 덧셈은 오버플로우될 수 없습니다.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev 두 부호 없는 정수의 차를 반환합니다.
     * 결과가 음수일 경우 오버플로우입니다.
     *
     * 솔리디티의 `-` 연산자를 대체합니다.
     *
     * 요구사항:
     * - 뺄셈은 오버플로우될 수 없습니다.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev 두 부호 없는 정수의 곱을 반환합니다.
     * 오버플로우 발생 시 예외처리합니다.
     *
     * 솔리디티의 `*` 연산자를 대체합니다.
     *
     * 요구사항:
     * - 곱셈은 오버플로우될 수 없습니다.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // 가스 최적화: 이는 'a'가 0이 아님을 요구하는 것보다 저렴하지만,
        // 'b'도 테스트할 경우 이점이 없어집니다.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev 두 부호 없는 정수의 몫을 반환합니다. 0으로 나누기를 시도할 경우
     * 예외처리합니다. 결과는 0의 자리에서 반올림됩니다.
     *
     * 솔리디티의 `/` 연산자를 대체합니다. 참고: 이 함수는
     * `revert` 명령코드(잔여 가스를 건들지 않음)를 사용하는 반면, 솔리디티는
     * 유효하지 않은 명령코드를 사용해 복귀합니다(남은 모든 가스를 소비).
     *
     * 요구사항:
     * - 0으로 나눌 수 없습니다.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // 솔리디티는 0으로 나누기를 자동으로 검출하고 중단합니다.
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // 이를 만족시키지 않는 경우가 없어야 합니다.

        return c;
    }

    /**
     * @dev 두 부호 없는 정수의 나머지를 반환합니다. (부호 없는 정수 모듈로 연산),
     * 0으로 나눌 경우 예외처리합니다.
     *
     * 솔리디티의 `%` 연산자를 대체합니다. 이 함수는 `revert`
     * 명령코드(잔여 가스를 건들지 않음)를 사용하는 반면, 솔리디티는
     * 유효하지 않은 명령코드를 사용해 복귀합니다(남은 모든 가스를 소비).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}

/**
 * @dev `IERC20` 인터페이스의 구현
 *
 * 이 구현은 토큰이 생성되는 방식과 무관합니다. 이는
 * 파생 컨트랙트에 `_mint`를 이용한 공급 메커니즘이 추가되어야 한다는 의미입니다.
 * 일반적인 메커니즘은 `ERC20Mintable`을 참조하세요.
 *
 * *자세한 내용은 가이드 [How to implement supply mechanisms]
 * (https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226)를 참고하세요.*
 *
 * 일반적인 OpenZeppelin 지침을 따랐습니다: 함수는 실패시 `false`를 반환하는 대신
 * 예외처리를 따릅니다. 그럼에도 이는 관습적이며
 * ERC20 애플리케이션의 기대에 반하지 않습니다.
 *
 * 또한, `transferFrom` 호출 시 `Approval` 이벤트가 발생됩니다.
 * 이로부터 애플리케이션은 해당 이벤트를 수신하는 것만으로
 * 모든 계정에 대한 허용량(allowance)을 재구성 할 수 있습니다. 이는 스펙에서 요구되지 않으므로, EIP에 대한 다른 구현체는
 * 이러한 이벤트를 발생하지 않을 수 있습니다.
 *
 * 마지막으로, 표준이 아닌 `decreaseAllowance` 및 `increaseAllowance`
 * 함수가 추가되어 허용량 설정과 관련해 잘 알려진 문제를
 * 완화했습니다. `IERC20.approve`를 참조하세요.
 */
contract MyERC20 is IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    // https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/token/ERC20/ERC20Detailed.sol 시작 부분을 참고
    string private _name;
    string private _symbol;
    uint8 private _decimals;

    constructor (string memory name, string memory symbol, uint8 decimals) public {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;

        _mint(msg.sender, 100000 * 10 ** uint256(decimals)); // 주의!
    }

    / **
     * @dev 토큰 이름을 반환합니다.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @dev 주로 이름을 줄여서 표현한 토큰 심볼을
     * 반환합니다.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev 사용자 표현을 위한 소수 자릿수를 반환합니다.
     * 예를 들어, `decimals`이  `2`인 경우, 505` 토큰은
     * 사용자에게 `5,05` (`505 / 10 ** 2`)와 같이 표시되어야 합니다.
     *
     * 토큰은 보통 18의 값을 취하며, 이는 Ether와 Wei의 관계를
     * 모방한 것입니다.
     *
     * > 이 정보는 디스플레이 목적으로만 사용됩니다.
     * `IERC20.balanceOf`와 `IERC20.transfer`를 포함해
     * 컨트랙트의 산술 연산에 어떠한 영향을 주지 않습니다.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }
    // https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v2.3.0/contracts/token/ERC20/ERC20Detailed.sol 끝 부분을 참고

    uint256 private _totalSupply;

    /**
     * @dev `IERC20.totalSupply`를 참조하세요.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev `IERC20.balanceOf`를 참조하세요.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev `IERC20.transfer`를 참조하세요.
     *
     * 요구사항 :
     *
     * - `recipient`는 영 주소(0x0000...0)가 될 수 없습니다.
     * - 호출자의 잔고는 적어도 `amount` 이상이어야 합니다.
     */
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    /**
     * @dev `IERC20.allowance`를 참조하세요.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev `IERC20.approve`를 참조하세요.
     *
     * 요구사항:
     *
     * - `spender`는 영 주소가 될 수 없습니다.
     */
    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev `IERC20.transferFrom`를 참조하세요.
     *
     * 업데이트된 허용량을 나타내는 `Approval` 이벤트가 발생합니다. 이것은 EIP에서
     * 요구되는 바가 아닙니다. `ERC20`의 시작 부분에 있는 참고 사항을 참조하세요.
     *
     * 요구사항:
     * - `sender`와 `recipient`는 영 주소가 될 수 없습니다.
     * - `sender`의 잔고는 적어도 `value` 이상이어야 합니다.
     * - 호출자는 `sender`의 토큰에 대해 최소한 `amount` 만큼의 허용량을
     * 가져야 합니다.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
        return true;
    }

    /**
     * @dev 호출자에 의해 원자적(atomically)으로 `spender`에 승인된 허용량을 증가시킵니다.
     *
     * 이것은 `IERC20.approve`에 기술된 문제에 대한 완화책으로 사용될 수 있는
     * `approve`의 대안입니다.
     *
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
        return true;
    }

    /**
     * @dev 호출자에 의해 원자적으로 `spender`에 승인된 허용량을 감소시킵니다.
     *
     * This is an alternative to `approve` that can be used as a mitigation for
     * problems described in `IERC20.approve`.
     *
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender`는 호출자에 대해 최소한 `subtractedValue` 만큼의 허용량을
     * 가져야 합니다.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    /**
     * @dev `amount`만큼의 토큰을 `sender`에서 `recipient`로 옮깁니다.
     *
     * This is internal function is equivalent to `transfer`, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a `Transfer` event.
     *
     * 요구사항:
     *
     * - `sender`는 영 주소가 될 수 없습니다.
     * - `recipient`은 영 주소가 될 수 없습니다.
     * - `sender`의 잔고는 적어도 `amount` 이상이어야 합니다.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev `amount`만큼의 토큰을 생성하고 `account`에 할당합니다.
     * 전체 공급량을 증가시킵니다.
     *
     * `from`이 영 주소로 설정된 `Transfer` 이벤트를 발생시킵니다.
     *
     * 요구사항:
     *
     * - `to`는 영 주소가 될 수 없습니다.
     */
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

     /**
     * @dev `account`로부터 `amount`만큼의 토큰을 파괴하고,
     * 전체 공급량을 감소시킵니다.
     *
     * `to`가 영 주소로 설정된 `Transfer` 이벤트를 발생시킵니다.
     *
     * 요구사항:
     *
     * - `account`는 영 주소가 될 수 없습니다.
     * - `account`는 적어도 `amount`만큼의 토큰이 있어야 합니다.
     */
    function _burn(address account, uint256 value) internal {
        require(account != address(0), "ERC20: burn from the zero address");

    _balances[account] = _balances[account].sub(value);
        _totalSupply = _totalSupply.sub(value);
        emit Transfer(account, address(0), value);
    }

    /**
     * @dev `owner`의 토큰에 대한 `spender`의 허용량을 `amount`만큼 설정합니다.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an `Approval` event.
     *
     * 요구사항:
     *
     * - `owner`는 영 주소가 될 수 없습니다.
     * - `spender`는 영 주소가 될 수 없습니다.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    /**
     * @dev `account`로부터 `amount`만큼의 토큰을 파괴하고,
     * 호출자의 허용량으로부터 `amount`만큼을 공제합니다.
     *
     * `_burn` 및 `_approve`를 참조하세요.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));
    }
}

MyERC20.sol은 IERC20 인터페이스, SafeMath 라이브러리, IERC20를 구현하는 MyERC20 컨트랙트로 구성되었습니다.

  • SafeMath 라이브러리는 솔리디티의 uint256 타입에 대한 안전한 연산을 위해 오버플로우 검사를 추가한 솔리디티 산술 연산에 대한 래퍼(wrapper)를 정의합니다.

    • ERC20에 더하여, constructor가 정의되었으며 이 생성자는 새로운 ERC20 토큰 이름과 심볼, 그리고 사전 정의된 양의 토큰을 발행하기 위해 사용됩니다. constructor는 첫 배포에서 한 번 호출됩니다.

1.2 중요한 메소드(method) 살펴보기

몇 가지 중요한 메소드를 자세히 살펴 봅시다.

(1) function balanceOf(address account) external view returns (uint256);

balanceOf는 ERC-20의 필수 메소드입니다. balanceOf는 주어진 주소의 잔액을 반환합니다.

    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

balanceOf는 아래에 명시된 mapping (address => uint256)인 _balances에 저장된 키 account의 값을 반환합니다.

    mapping (address => uint256) private _balances;

만일 _balances에 대해 유효한 키 account가 없다면, 0을 반환합니다.

(2) function transfer(address recipient, uint256 amount) external returns (bool);

transfer는 ERC-20의 필수 메소드입니다. transfer 는 amount 만큼의 토큰을 recipient에게 전송하고, 반드시 Transfer 이벤트를 촉발해야 합니다. 이 함수는 메시지 호출자의 계정 잔액이 지불하기 위해 충분한 토큰을 가지고 있지 않으면 예외를 발생시켜야 합니다.

transfer는 아래와 같이 실제 전송 및 이벤트를 구현한 내부의 메소드 _transfer을 호출합니다.

    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

_transfer는 ERC-20의 메소드인 transfer의 실제 동작을 구현합니다.

또한, 아래와 같이 require를 사용해 영 주소로 또는 영 주소에서 토큰을 전송하지 못하게 합니다.

    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

(3) function approve(address spender, uint256 amount) external returns (bool);

approve는 ERC-20의 필수 메소드입니다. approve는 spender가 당신의 계정으로부터 amount 한도 하에서 여러 번 출금하는 것을 허용합니다. 이 함수를 여러번 호출하면, 단순히 허용량을 amount으로 재설정합니다.

approve는 실제 approve의 동작을 구현한 내부의 메소드 _approve를 호출합니다. msg.sender 는 계정 owner로써 전달됩니다.

    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    function _approve(address owner, address spender, uint256 value) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

_approve는 특정 address로부터 spender에 대한 허용된 value를 유지하는 2차원 딕셔너리(dictionary)인 _allowances를 업데이트합니다.

    mapping (address => mapping (address => uint256)) private _allowances;

(4) function _mint(address account, uint256 amount) internal

_mint는 ERC-20의 일부가 아닙니다. 그러나 새로운 ERC-20 토큰을 생성할 방법이 필요하며, 이 구현체에서 새 토큰을 생성하기 위해 아래와 같은 _mint가 필요합니다.

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

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

_mint는 컨트랙트 내부의 메소드이며 이 컨트랙트 안에서 호출할 수 있습니다.

MyERC20.sol에서 _mint는 스마트 컨트랙트를 배포할 때 사전 정의된 양의 토큰을 발행하기 위해 constructor에서 한 번만 호출됩니다.

스마트 컨트랙트를 배포한 후 추가 토큰을 발행하려면, mint와 같은 새로운 공개 메소드를 도입해야 합니다. 이 메소드는 오직 권한이 있는 사용자만이 발행할 수 있어야 하므로, 주의해서 구현해야 합니다.

PreviousERC-20Next2. 스마트 컨트랙트 배포

Last updated 2 years ago

Was this helpful?

IERC20 인터페이스는 에 명시된 필수 인터페이스를 정의합니다.

MyERC20는 IERC20 인터페이스를 구현하고 에 명시된 세 개의 추가적인 메서드(method)를 정의합니다.

더 자세한 내용을 위해서는 OpenZeppelin 예제 를 참조하세요.

ERC-20 스펙
ERC-20 스펙
ERC20Mintable.sol