Implement ERC-20 from scratch

Requirements

5 methods

solidity

function name() public view returns (string);
function symbol() public view returns (string);
function decimals() public view returns (uint8);
function totalSupply() public view returns (uint256);
function balanceOf(address _owner) public view returns (uint256 balance);
function transfer(
    address _to, 
    uint256 _value
) public returns (bool success);
function transferFrom(
    address _from, 
    address _to, 
    uint256 _value
) public returns (bool success);
function approve(
    address _spender, 
    uint256 _value
) public returns (bool success);
function allowance(
    address _owner, 
    address _spender
) public view returns (uint256 remaining);

2 Events

solidity

event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);

Code

solidity

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

contract MyFirstToken {
    string public name = "My First Token";
    string public symbol = "MFT";
    uint public decimals = 18;
    uint public totalSupply = 0;

    mapping(address owner => uint amount) public balances;
    mapping(address owner => mapping(address spender => uint amount)) allowances;

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

    function balanceOf(address owner) public view returns (uint amount) {
        return balances[owner];
    }

    function transfer(address to, uint amount) public returns (bool success) {
        // 1. Error
        // 잔액이 충분한가?
        address owner = msg.sender;
        require(balances[owner] >= amount);

        // 2. Data Update
        balances[owner] -= amount;
        balances[to] += amount;
        
        // 3. Event
        emit Transfer(owner, to, amount);
        
        // 4. Return
        return true;
    }

    // 소유자 대신 토큰을 사용하는 spender 가 사용하는 함수
    function transferFrom(address owner, address to, uint amount) public returns (bool success) {
        address spender = msg.sender;
        // 1. Error
        // (1) 잔액이 충분한가?
        // (2) spender 가 권한이 있는가?
        require(balances[owner] >= amount);
        require(allowances[owner][spender] >= amount);

        // 2. Data Update
        // (1) balances
        // (2) allowances
        balances[owner] -= amount;
        balances[to] += amount;
        allowances[owner][spender] -= amount;

        // 3. Event
        emit Transfer(owner, to, amount);

        // 4. Return
        return true;
    }

    function approve (address spender, uint amount) public returns (bool success) {
        address owner = msg.sender;
        
        // 2. Data Update
        allowances[owner][spender] = amount;

        // 3. Event
        emit Approval(owner, spender, amount);

        // 4. Return
        return true;
    }

    function allowance (address owner, address spender) public view returns (uint amount) {
        return allowances[owner][spender];
    }
}

Ressources