ERC20 and ERC721 Standards and Cases

Posted by Big_Ad on Thu, 09 Sep 2021 18:10:36 +0200

ERC-20

Introduction to ERC-20

Digital encrypted currencies can be divided into native and token currencies. ERC (Etherum Request for Comments)It is the agreement proposal submitted by the Taifang developer for tokens, and 20 represents the number of the agreement. All tokens that meet the ERC-20 standard are immediately compatible with the Taifang wallet and reduce the threshold for token development. As long as the ERC-20 protocol is implemented, a new token can be developed quickly. In addition, the interoperability between contracts, toke can be increased by implementing the ERC standard.However, ERC-20 also has some drawbacks, such as the inability to modify the contract after it is published, and the inability to return the token you sent to the contract if it is not an ETH but another token.

This website lists all ERC protocols for reference: https://eips.ethereum.org/erc

ERC-20 currency standard

  • Minimum unit: 6 functions, 2 events
    • TotSupply: Get total token distribution
      function totalSupply() public view returns (uint256)
    • balanceOf: Get the _owner token
      function balanceOf(address _owner) public view returns (uint256 balance)
    • transfer: token to _to into _value
      function transfer(address _to, uint256 _value) public returns (bool success)
    • transferFrom: token to _value from _from
      function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
    • approve: authorize token
      function approve(address _spender, uint256 _value) public returns (bool success)
    • allowance: returns the number of remaining token s used
      function allowance(address _owner, address _spender) public view returns (uint256 remaining)
    • Transfer: Transfer events
      event Transfer(address indexed _from, address indexed _to, uint256 _value)
    • Approval: Authorized withdrawal event
      event Approval(address indexed _owner, address indexed _spender, uint256 _value)
  • Optional unit: 3 functions
    • Name:token name
      function name() public view returns (string)
    • logo Identity of Symbol:token
      function symbol() public view returns (string)
    • Decimals: Return by decimal, e.g. input 360000000 to 3.6
      function decimals() public view returns (uint8)

ERC-20 Cases

//------ERC20.sol
pragma solidity 0.6.0;

abstract contract ERC20{
    function totalSupply() virtual public view returns (uint256);
    function balanceOf(address _owner) virtual public view returns (uint256 balance);
    function transfer(address _to, uint256 _value) virtual public returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) virtual public returns (bool success);
    function approve(address _spender, uint256 _value) virtual public returns (bool success);
    function allowance(address _owner, address _spender) virtual public view returns (uint256 remaining);

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

//-------myERC20.sol
pragma solidity ^0.6.0;

import "./ERC20.sol";

// Implement secure operations
contract SafeMath {
  function safeMul(uint256 a, uint256 b) internal returns (uint256) {
    uint256 c = a * b;
    assert(a == 0 || c / a == b);
    return c;
  }

  function safeDiv(uint256 a, uint256 b) internal returns (uint256) {
    assert(b > 0);
    uint256 c = a / b;
    assert(a == b * c + a % b);
    return c;
  }

  function safeSub(uint256 a, uint256 b) internal returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function safeAdd(uint256 a, uint256 b) internal returns (uint256) {
    uint256 c = a + b;
    assert(c>=a && c>=b);
    return c;
  }

  function assert(bool assertion) internal {
    if (!assertion) {
      revert();
    }
  }
}

contract SafeMath {
  function safeMul(uint256 a, uint256 b) internal returns (uint256) {
    uint256 c = a * b;
    assert(a == 0 || c / a == b);
    return c;
  }

  function safeDiv(uint256 a, uint256 b) internal returns (uint256) {
    assert(b > 0);
    uint256 c = a / b;
    assert(a == b * c + a % b);
    return c;
  }

  function safeSub(uint256 a, uint256 b) internal returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function safeAdd(uint256 a, uint256 b) internal returns (uint256) {
    uint256 c = a + b;
    assert(c>=a && c>=b);
    return c;
  }

  function assert(bool assertion) internal {
    if (!assertion) {
      revert();
    }
  }
}

contract myERC20 is ERC20, SafeMath{
    
    address public payable owner;	// Define contract owner
    uint256 _totalSupply;	// Total token Issues
    
    mapping(address => uint256) _balance;	// Address-owned token
    mapping(address => mapping(address => uint256)) approve;	// Address is authorized to another address token
    
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    
    // Constructor to initialize total token, contract owner.
    constructor(uint256 totalSupply) public {
        _totalSupply = totalSupply;
        _owner = msg.sender;
    }
    
    modifier onlyOwner(){
        require(msg.sender == _owner);
        _;
    }
    
    // Drop a token of _value into _to
    function airDrop (address _to, uint256 _value) onlyOwer public {
    	require(_to != address(0));
        _balance[_to] = SafeMath.safeAdd(_balance[_to], _value);
        _totalSupply = SafeMath.safeAdd(_totalSupply, _value);
    }
    
    // Return total token
    function totalSupply() override public view returns (uint256) { 
        return _totalSupply;
    }
    
    // Returns the number of token s owned by_owner
    function balanceOf(address _owner) override public view returns (uint256 balance) {
        require(owner != address(0));
        return _balance[_owner];
    }
    
    // token to _value in _to
    function transfer(address _to, uint256 _value) override public returns (bool success) {
        require(_to != address(0));
        require(_value > 0);
        require(_balance[msg.sender] >= _value);
        _balance[msg.sender] = SafeMath.safeSub(_balance[msg.sender], _value);
        _balance[_to] = SafeMath.safeAdd(_balance[_to], _value);
        emit Transfer( msg.sender, _to, _value);
        return true;
    }
    
    // token to _value from _from to _to
    function transferFrom(address _from, address _to, uint256 _value) override public returns (bool success) {
        require(_from != address(0));
        require(_to != address(0));
        require(_approve[_from][msg.sender] >= _value);
        
        _approve[_from][msg.sender] = SafeMath.safeSub(_approve[_from][msg.sender], _value);
        _balance[_to] = SafeMath.safeAdd(_balance[_to], _value);
        emit Transfer(_from, _to, _value);
        return true;
    }
    
    // Number of token s authorized to _spender_value
    function approve(address _spender, uint256 _value) override public returns (bool success) {
        require(_spender != address(0));
        require(_balance[msg.sender] >= _value);
       
        
        _approve[msg.sender][_spender] = SafeMath.safeAdd(_approve[msg.sender][_spender], _value);
        _balance[msg.sender] = SafeMath.safeSub(_balance[msg.sender], _value);
        emit Approval(msg.sender, _spender, _value);
        return true;
    }
    
    // Query _owner how many token s are authorized to _spender
    function allowance(address _owner, address _spender) override public view returns (uint256 remaining) {
        require(_owner != address(0));
        require(_spender != address(0));
        return _approve[_owner][_spender];
    }
    
    // Extract token
    function withdrawEther(uint256 _value) public{
		require(msg.sender == owner);
		owner.transfer(_value);
	}
}

ERC-721

Introduction to ERC-721

The official explanation for ERC-721 is: Non-Fungible Tokens (non-homogeneous token s), short for NFT. Tokens that implement the ERC-72 protocol each have their own unique and unique value and are inseparable. Currently they are mainly used in collections, games and other scenarios where unique assets need to be identified.

ERC-721 Currency Standard

  • Minimum unit: 9 functions, 3 events
    • Get the number of NFT s assigned to owner
      function balanceOf(address _owner) external view returns (uint256);
    • Query owner address of NFT with token ID number tokenid
      function ownerOf(uint256 _tokenId) external view returns (address);
    • Transfer NFT with token ID number tokenId from user with _front address to user with _to address
      function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
    • Transfer the NTF with token ID number _tokenId from the user with _front address to the user with _to address and carry data data
      function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
    • Transfer NTF with token ID number _tokenId from user with _front address to user with _to address
      function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
    • Authorize _approved
      function approve(address _approved, uint256 _tokenId) external payable;
    • Get the owner address corresponding to the _tokenId token
      function getApproved(uint256 _tokenId) external view returns (address);
    • ERC721 token assets authorized to third-party_operate s to manage individuals
      function setApprovalForAll(address _operator, bool _approved) external;
    • See if _owner authorizes _operation to manage all ERC721 token assets
      function isApprovedForAll(address _owner, address _operator) external view returns (bool);
    • NFT Asset Transfer Events
      event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
    • NFT Asset Authorization Address Change Event
      event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
    • All NFT Asset Authorization Events
      event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
  • Optional units
    • Describe the name of the NFT collection
      function name() external view returns (string _name);
    • Abbreviation of NTF name in contract
      function symbol() external view returns (string _symbol);
    • Details corresponding to a given asset unique resource identifier (URI)
      function tokenURI(uint256 _tokenId) external view returns (string);
    • Track the number of NFT s in count contracts
      function totalSupply() external view returns (uint256);
    • Enumerate valid NFT s
      function tokenByIndex(uint256 _index) external view returns (uint256);
    • Enumerate NFT s assigned to owners
      function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);

ERC-721 Cases

//---ERC721.sol
pragma solidity ^0.6.0;

abstract contract ERC721{
    function balanceOf(address _owner) virtual external view returns (uint256);
    function ownerOf(uint256 _tokenId) virtual external view returns (address);
    function transferFrom(address _from, address _to, uint256 _tokenId) virtual external payable;
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) virtual external payable;
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, byte data) virtual external payable;
    function approve(address _approved, uint256 _tokenId) virtual external payable;
    function setApprovalForAll(address _operator, bool _approved) virtual external;
    function getApproved(uint256 _tokenId) virtual external view returns (address);
    function isApprovedForAll(address _owner, address _operator) virtual external view returns (bool);
    
    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
}

//-----myArt.sol
pragma solidity ^0.6.0;

import "./ERC721.sol";

contract pcArtCoin is ERC721{
    
    // Contract Owner
    address public fundation;
    
    // Asset structure
    struct asset{
        uint256 _tokenId;	// token ID
        address owner;		// token owner address
        address approver;	// Authorized address for token
        uint256 timestamp;	// time stamp
        byte data;		    // Data contained in token
    }

    
    // Number of NFT s owned by address
    mapping(address => uint256) balances;
    // Asset corresponding to NFT number
    mapping(uint256 => asset) tokens;
    // To grant authorization
    mapping(address => mapping(address => bool)) isAllProved;
    
    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
    
    // Set up assets
    function setAssert(uint256 number, address owner, byte data) onlyFundation public{
        require(owner != address(0));
        // Produce a random token ID
        uint256 tokenId = uint256(keccak256(abi.encodePacked(number, msg.sender, now, owner, data)));
        // Make sure token ID s are different
        require(tokens[tokenId]._tokenId != tokenId);
        // Set up assets
        asset memory Asset = asset(tokenId, owner, address(0), now, data);
        tokens[tokenId] = Asset;
    }
    
    modifier onlyFundation(){
        require(msg.sender == fundation);
        _;
    }
    
    // Returns the number of NFT s owned by_owner
    function balanceOf(address _owner) override external view returns (uint256){
        require(_owner != address(0));
        return balances[_owner];
    }
    
    // Returns the owner of _tokenId
    function ownerOf(uint256 _tokenId) override external view returns (address){
        require(_tokenId != 0);
        return tokens[_tokenId].owner;
    }
    
    // From _from to _to, NFT number is _tokenId
    function transferFrom(address _from, address _to, uint256 _tokenId) override external payable{
        // Security check
        require(tokens[_tokenId].owner == _from);
        require(_from != address(0) && _to != address(0) && _tokenId != 0);
        require(msg.sender == _from || tokens[_tokenId].approver == msg.sender);
        
        tokens[_tokenId].owner = _to;
        tokens[_tokenId].approver = address(0);
        tokens[_tokenId].timestamp = now;
        tokens[_tokenId].data = byte("");
        balances[_from] -= 1;
        balances[_to] += 1;
        
        emit Transfer(_from, _to, _tokenId);
    }
    
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) override external payable{
        require(tokens[_tokenId].approver == _from);
        // Judging that_to is not a contractual address
        require(addrCheck(_to));
        require(_from != address(0) && _to != address(0) && _tokenId != 0);
        require(msg.sender == _from || tokens[_tokenId].approver == msg.sender);
        tokens[_tokenId].owner = _from;
        tokens[_tokenId].approver = address(0);
        tokens[_tokenId].timestamp = now;
        tokens[_tokenId].data = byte("");
        balances[_from] -= 1;
        balances[_to] += 1;
        
        emit Transfer(_from, _to, _tokenId);
    }
    
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, byte data) override external payable{
        require(tokens[_tokenId].owner == _from);
        require(addrCheck(_to));
        require(_from != address(0) && _to != address(0) && _tokenId != 0);
        require(msg.sender == _from || tokens[_tokenId].approver == msg.sender);
       
        tokens[_tokenId].owner = _to;
        tokens[_tokenId].approver = address(0);
        tokens[_tokenId].timestamp = now;
        tokens[_tokenId].data = data;
        balances[_from] -= 1;
        balances[_to] += 1;
        
        emit Transfer(_from, _to, _tokenId);
    }
    
    function approve(address _approved, uint256 _tokenId) override external payable{
        require(tokens[_tokenId].owner == msg.sender);
        require(_tokenId != 0);
        
        tokens[_tokenId].approver = _approved;
        
        emit Approval(msg.sender, _approved, _tokenId);
    }
    
    // Authorize operations to_operator
    function setApprovalForAll(address _operator, bool _approved) override external{
        require(_operator != address(0));
        require(isAllProved[msg.sender][_operator] != _approved);
        isAllProved[msg.sender][_operator] = _approved;
        
        emit ApprovalForAll(msg.sender, _operator, _approved);
    }
    
    // Authorized to get _tokenId token
    function getApproved(uint256 _tokenId) override external view returns (address){
        require(_tokenId != 0);
        return tokens[_tokenId].approver;
    }
    
    function isApprovedForAll(address _owner, address _operator) override external view returns (bool){
        require(_owner != address(0) || _operator != address(0));
        return isAllProved[_owner][_operator];
    }
    
	// Determines whether it is a contract address, returns false, not true    
    function addrCheck(address _addr) private view returns (bool){
        uint256 size;
        assembly{
            size := extcodesize(_addr)
        }
        require(size == 0);
        return true;
    }
}

Last

If there are any deficiencies in the code, please note in the comments section. A github address with many block chain learning resources and technical articles is also recommended. You are also welcome to visit and learn about progress together: https://github.com/mindcarver.

Topics: Blockchain Ethereum