OpenZeppelin's ERC20: A User Guide

OpenZeppelin's ERC20: A User Guide
⚠️
Version of OpenZeppelin introduced: v5.0.0

In this post, we'll introduce ERC20, a standard often used in the Ethereum blockchain. With ERC20, you can:

  • Easily create a cryptocurrency that follows the ERC20 standard.
  • Implement a secure cryptocurrency.

What is ERC20?

ERC20 is a standard token specification on the Ethereum blockchain. ERC20 tokens are compatible with each other, making it easy to integrate them into wallets, cryptocurrency exchanges, DeFi platforms, etc., and swap them with each other.

However, Ethereum's native currency, ether, was created before the ERC20 standard, so it does not conform to the ERC20 specification.

Inside ERC20

Here's a brief look at the ERC20 implementation:

Here's the translation of your blog post:

OpenZeppelin's ERC20: A User Guide

Version of OpenZeppelin introduced: v5.0.0

In this post, we'll introduce ERC20, a standard often used in the Ethereum blockchain. With ERC20, you can:

Easily create a cryptocurrency that follows the ERC20 standard.
Implement a secure cryptocurrency.
What is ERC20?

ERC20 is a standard token specification on the Ethereum blockchain. ERC20 tokens are compatible with each other, making it easy to integrate them into wallets, cryptocurrency exchanges, DeFi platforms, etc., and swap them with each other.

However, Ethereum's native currency, ether, was created before the ERC20 standard, so it does not conform to the ERC20 specification.

Inside ERC20

Here's a brief look at the ERC20 implementation:

solidity
Copy code
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    uint256 private _totalSupply;
    string private _name;
    string private _symbol;

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    // Other functions and implementations...
}

Now, let's explain some key functions!

_update

function _update(address from, address to, uint256 value) internal virtual {
    if (from == address(0)) {
        _totalSupply += value;
    } else {
        uint256 fromBalance = _balances[from];
        if (fromBalance < value) {
            revert ERC20InsufficientBalance(from, fromBalance, value);
        }
        _balances[from] = fromBalance - value;
    }

    if (to == address(0)) {
        _totalSupply -= value;
    } else {
        _balances[to] += value;
    }

    emit Transfer(from, to, value);
}

The _update function is used mainly for burning, minting, and transferring tokens. Depending on the arguments set, each process is performed, so be careful when using it!

Patternfromtovalue
mintZero addressRecipient's addressAmount of tokens
burnToken owner's addressZero addressAmount of tokens
transferToken owner's addressRecipient's addressAmount of tokens

_transfer

function _transfer(address from, address to, uint256 value) internal {
    if (from == address(0)) {
        revert ERC20InvalidSender(address(0));
    }
    if (to == address(0)) {
        revert ERC20InvalidReceiver(address(0));
    }
    _update(from, to, value);
}

This internal function is used for transferring tokens. If either from or to is the zero address, the transaction will revert.

transferFrom

function transferFrom(
    address from,
    address to,
    uint256 value
) public virtual returns (bool) {
    address spender = _msgSender();
    _spendAllowance(from, spender, value);
    _transfer(from, to, value);
    return true;
}

The transferFrom function is used when a third party transfers tokens from one account to another. It checks the allowance of the spender before executing the transfer.

transfer

function transfer(address to, uint256 value) public virtual returns (bool) {
    address owner = _msgSender();
    _transfer(owner, to, value);
    return true;
}

The transfer function is used to move tokens from the caller's account to another account.

_mint

function _mint(address account, uint256 value) internal {
    if (account == address(0)) {
        revert ERC20InvalidReceiver(address(0));
    }
    _update(address(0), account, value);
}

This internal function is used for minting tokens. It checks that the minting address is not the zero address before executing the update.

_burn

function _burn(address account, uint256 value) internal {
    if (account == address(0)) {
        revert ERC20InvalidSender(address(0));
    }
    _update(account, address(0), value);
}

This internal function is used for burning tokens. It checks that the burning address is not the zero address before executing the update.

Example Code

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

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

contract MyCoin is ERC20, Ownable {
    constructor(
        address initialOwner
    ) ERC20("MyCoin", "MC") Ownable(initialOwner) {}

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }
}

In this example, we've created a simple MyCoin token where only the owner can mint tokens. This provides the minimum functionality required, so try minting some tokens to yourself after deployment!

OpenZeppelin makes it incredibly easy to create your own coin, and you can add various features to customize it to your liking. For example, many coins have a blacklist feature, so feel free to customize it as you wish.

Conclusion

OpenZeppelin's ERC20 provides an easy and standardized way to create and manage coins. The main advantages of using OpenZeppelin are the ease of coin implementation and compliance with the ERC20 standard in a security-verified manner. It is recommended to use OpenZeppelin instead of developing similar implementations individually due to potential security risks. In this post, we introduced a basic implementation where only the contract owner can mint tokens. However, OpenZeppelin offers a wide range of customizations for coin projects. When creating a coin, leverage this secure and flexible ERC20 implementation to efficiently and safely advance your project.