0Pricing
Blockchain Smart Contracts with Solidity · レッスン

ERC-20トークンの実装

transfer、approve、allowance関数を含む、ERC-20準拠の独自トークンを開発・デプロイします。

「ERC-20トークンの実装」はCoddyKit上の無料Blockchain Smart Contracts with Solidityレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはBlockchain Smart Contracts with Solidity学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Blockchain Smart Contracts with Solidityコースには全4レッスンが含まれています。

このレッスンの一部はまだ翻訳されておらず、英語で表示されています。

Build Your Own ERC-20 Token

Welcome! In this lesson, you'll learn to implement your very own ERC-20 compliant token. We'll cover the essential functions and variables that make up this widely used standard.

By the end, you'll have a working understanding of how these tokens operate at a fundamental level on the Ethereum blockchain.

Token Identity: Name, Symbol, Decimals

Every ERC-20 token needs basic identifying information: a name, a symbol, and decimals. These are often public state variables.

  • name: The full name of your token (e.g., "MyCoddyToken").
  • symbol: A short ticker symbol (e.g., "MCT").
  • decimals: How many decimal places the token can be divided into (commonly 18, like Ether).

Let's start our contract with these properties:

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

contract MyToken {
  string public name = "MyCoddyToken";
  string public symbol = "MCT";
  uint8 public decimals = 18; // Common for ERC-20
}

Total Supply & Initial Minting

The totalSupply variable keeps track of all existing tokens. We also need a way to store each user's balance, typically using a mapping.

The constructor is a special function that runs only once when the contract is deployed. We use it to set the initial totalSupply and assign all initial tokens to the deployer's address.

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

contract MyToken {
  string public name = "MyCoddyToken";
  string public symbol = "MCT";
  uint8 public decimals = 18;

  uint256 public totalSupply; // Total tokens in existence
  mapping(address => uint256) private _balances; // User balances

  constructor(uint256 initialSupply) {
    totalSupply = initialSupply;
    _balances[msg.sender] = initialSupply; // Mints to deployer
  }
}

Checking Balances: `balanceOf`

The balanceOf function allows anyone to query the token balance of a specific address. It's a view function, meaning it doesn't change the contract's state and costs no gas to call off-chain.

We retrieve the balance from our _balances mapping.

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

contract MyToken {
  string public name = "MyCoddyToken";
  string public symbol = "MCT";
  uint8 public decimals = 18;

  uint256 public totalSupply;
  mapping(address => uint256) private _balances;

  constructor(uint256 initialSupply) {
    totalSupply = initialSupply;
    _balances[msg.sender] = initialSupply;
  }

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

Direct Transfers: `transfer`

The transfer function enables a token holder to send tokens directly to another address. It's a core function of the ERC-20 standard.

Before transferring, we must ensure the sender has sufficient balance. After the transfer, we emit a Transfer event, which is vital for blockchain explorers and dApps to track token movements.

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

contract MyToken {
  string public name = "MyCoddyToken";
  string public symbol = "MCT";
  uint8 public decimals = 18;

  uint256 public totalSupply;
  mapping(address => uint256) private _balances;

  // ERC-20 events
  event Transfer(address indexed from, address indexed to, uint256 value);
  event Approval(address indexed owner, address indexed spender, uint256 value);

  constructor(uint256 initialSupply) {
    totalSupply = initialSupply;
    _balances[msg.sender] = initialSupply;
    emit Transfer(address(0), msg.sender, initialSupply); // Minting event
  }

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

  function transfer(address recipient, uint256 amount) public returns (bool) {
    require(_balances[msg.sender] >= amount, "Insufficient balance");

    _balances[msg.sender] -= amount;
    _balances[recipient] += amount;
    emit Transfer(msg.sender, recipient, amount);
    return true;
  }
}

Delegated Spending: `approve`

The approve function allows a token holder (the owner) to grant another address (the spender) permission to spend a certain amount of their tokens on their behalf.

This is crucial for interacting with decentralized applications (dApps) where you might want a smart contract to manage your tokens (e.g., for staking or trading). We track these approvals in an _allowances mapping.

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

contract MyToken {
  string public name = "MyCoddyToken";
  string public symbol = "MCT";
  uint8 public decimals = 18;

  uint256 public totalSupply;
  mapping(address => uint256) private _balances;
  mapping(address => mapping(address => uint256)) private _allowances; // New: owner => (spender => amount)

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

  constructor(uint256 initialSupply) {
    totalSupply = initialSupply;
    _balances[msg.sender] = initialSupply;
    emit Transfer(address(0), msg.sender, initialSupply);
  }

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

  function transfer(address recipient, uint256 amount) public returns (bool) {
    require(_balances[msg.sender] >= amount, "Insufficient balance");
    _balances[msg.sender] -= amount;
    _balances[recipient] += amount;
    emit Transfer(msg.sender, recipient, amount);
    return true;
  }

  function approve(address spender, uint256 amount) public returns (bool) {
    _allowances[msg.sender][spender] = amount;
    emit Approval(msg.sender, spender, amount);
    return true;
  }
}

Checking Allowance: `allowance`

The allowance function lets you check how many tokens a specific spender is currently permitted to transfer from an owner's balance.

This is a view function, similar to balanceOf, and helps external applications understand the spending limits set by users.

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

contract MyToken {
  string public name = "MyCoddyToken";
  string public symbol = "MCT";
  uint8 public decimals = 18;

  uint256 public totalSupply;
  mapping(address => uint256) private _balances;
  mapping(address => mapping(address => uint256)) private _allowances;

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

  constructor(uint256 initialSupply) {
    totalSupply = initialSupply;
    _balances[msg.sender] = initialSupply;
    emit Transfer(address(0), msg.sender, initialSupply);
  }

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

  function allowance(address owner, address spender) public view returns (uint256) {
    return _allowances[owner][spender];
  }

  function transfer(address recipient, uint256 amount) public returns (bool) {
    require(_balances[msg.sender] >= amount, "Insufficient balance");
    _balances[msg.sender] -= amount;
    _balances[recipient] += amount;
    emit Transfer(msg.sender, recipient, amount);
    return true;
  }

  function approve(address spender, uint256 amount) public returns (bool) {
    _allowances[msg.sender][spender] = amount;
    emit Approval(msg.sender, spender, amount);
    return true;
  }
}

Spending on Behalf: `transferFrom`

The transferFrom function is used by a spender (who has been approved) to move tokens from an owner's balance to a recipient.

It requires checks for both the sender's balance and the allowance granted. After a successful transfer, the allowance is reduced by the transferred amount.

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

contract MyToken {
  string public name = "MyCoddyToken";
  string public symbol = "MCT";
  uint8 public decimals = 18;

  uint256 public totalSupply;
  mapping(address => uint256) private _balances;
  mapping(address => mapping(address => uint256)) private _allowances;

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

  constructor(uint256 initialSupply) {
    totalSupply = initialSupply;
    _balances[msg.sender] = initialSupply;
    emit Transfer(address(0), msg.sender, initialSupply);
  }

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

  function allowance(address owner, address spender) public view returns (uint256) {
    return _allowances[owner][spender];
  }

  function transfer(address recipient, uint256 amount) public returns (bool) {
    require(_balances[msg.sender] >= amount, "Insufficient balance");
    _balances[msg.sender] -= amount;
    _balances[recipient] += amount;
    emit Transfer(msg.sender, recipient, amount);
    return true;
  }

  function approve(address spender, uint256 amount) public returns (bool) {
    _allowances[msg.sender][spender] = amount;
    emit Approval(msg.sender, spender, amount);
    return true;
  }

  function transferFrom(
    address sender,
    address recipient,
    uint256 amount
  ) public returns (bool) {
    require(_balances[sender] >= amount, "Insufficient balance from sender");
    require(_allowances[sender][msg.sender] >= amount, "Insufficient allowance");

    _allowances[sender][msg.sender] -= amount;
    _balances[sender] -= amount;
    _balances[recipient] += amount;
    emit Transfer(sender, recipient, amount);
    return true;
  }
}

Full Minimal ERC-20 Implementation

Here's a complete, minimal ERC-20 token contract. While more advanced implementations (like OpenZeppelin's) include additional features and safety checks, this code covers all the core functions required by the standard.

You can deploy this contract to a testnet to create your own functional token!

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

contract MyToken {
  string public name = "MyCoddyToken";
  string public symbol = "MCT";
  uint8 public decimals = 18;

  uint256 public totalSupply;
  mapping(address => uint256) private _balances;
  mapping(address => mapping(address => uint256)) private _allowances;

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

  constructor(uint256 initialSupply) {
    totalSupply = initialSupply;
    _balances[msg.sender] = initialSupply;
    emit Transfer(address(0), msg.sender, initialSupply);
  }

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

  function allowance(address owner, address spender) public view returns (uint256) {
    return _allowances[owner][spender];
  }

  function transfer(address recipient, uint256 amount) public returns (bool) {
    require(_balances[msg.sender] >= amount, "Insufficient balance");
    _balances[msg.sender] -= amount;
    _balances[recipient] += amount;
    emit Transfer(msg.sender, recipient, amount);
    return true;
  }

  function approve(address spender, uint256 amount) public returns (bool) {
    _allowances[msg.sender][spender] = amount;
    emit Approval(msg.sender, spender, amount);
    return true;
  }

  function transferFrom(
    address sender,
    address recipient,
    uint256 amount
  ) public returns (bool) {
    require(_balances[sender] >= amount, "Insufficient balance from sender");
    require(_allowances[sender][msg.sender] >= amount, "Insufficient allowance");

    _allowances[sender][msg.sender] -= amount;
    _balances[sender] -= amount;
    _balances[recipient] += amount;
    emit Transfer(sender, recipient, amount);
    return true;
  }
}

ERC-20 Core Functions Check

You've learned about the essential functions for an ERC-20 token. Now, let's test your knowledge!

Recap: Your Own Token

Congratulations! You've now implemented the core logic for an ERC-20 token. You learned how to define its properties, manage total supply and individual balances, and enable both direct and delegated token transfers.

Understanding these fundamental building blocks is key to working with any token on the Ethereum blockchain. Next, you might explore how to integrate with existing ERC-20 libraries or add more advanced features!

よくある質問

「ERC-20トークンの実装」レッスンは無料ですか?

はい。「ERC-20トークンの実装」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Blockchain Smart Contracts with Solidityコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Blockchain Smart Contracts with Solidityコースには全4レッスンが含まれています。

「ERC-20トークンの実装」で何を学びますか?

transfer、approve、allowance関数を含む、ERC-20準拠の独自トークンを開発・デプロイします。 ブラウザで直接実行するハンズオンコードでBlockchain Smart Contracts with Solidityを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Blockchain Smart Contracts with Solidityを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのBlockchain Smart Contracts with Solidityは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「ERC-20トークンの実装」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このBlockchain Smart Contracts with Solidityレッスンでコードを書いて実行できますか?

はい。すべてのBlockchain Smart Contracts with Solidityレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ERC-20代替可能トークン標準
  2. ERC-20トークンの実装
  3. ERC-721非代替性トークン(NFT)
  4. ERC-1155マルチトークン規格
← Blockchain Smart Contracts with Solidityに戻る