R5 is fully compatible with standard token protocols, including ERC20 and ERC721, along with other token standards available on Ethereum. This document provides technical guidance on developing and deploying tokens and non-fungible tokens (NFTs) on the R5 network. The following examples illustrate minimal implementations of both ERC20 and ERC721 contracts.
ERC20 Tokens
The ERC20 token standard defines a standard interface for fungible tokens. Contracts adhering to ERC20 allow for the transfer of tokens between addresses and enable applications to manage token balances consistently.
Below is an example of a basic ERC20 token contract written in Solidity (version 0.8.x):
Deployment:
Deploy the contract by specifying the initial supply. The total supply is allocated to the deployer’s address.
Standard Interface:
The functions transfer, approve and transferFrom adhere strictly to the ERC20 specification.
Events:
Emitted events allow external applications to track token transfers and approvals.
ERC721 Tokens (NFTs)
The ERC721 token standard is used for non-fungible tokens, which represent unique assets. Each token has a unique identifier, and the standard provides methods for transferring ownership and managing token metadata.
Below is an example of a minimal ERC721 contract written in Solidity (version 0.8.x):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC721 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function transferFrom(address from, address to, uint256 tokenId) external;
}
contract ERC721Token is IERC721 {
string public name = "R5NFT";
string public symbol = "R5N";
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
// Mint a new NFT to an address.
function mint(address to, uint256 tokenId) public {
require(to != address(0), "Invalid recipient");
require(_owners[tokenId] == address(0), "Token already minted");
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
// Return the balance of an address.
function balanceOf(address owner) public view override returns (uint256) {
require(owner != address(0), "Invalid address");
return _balances[owner];
}
// Return the owner of a given token.
function ownerOf(uint256 tokenId) public view override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "Token not minted");
return owner;
}
// Transfer a token from one address to another.
function transferFrom(address from, address to, uint256 tokenId) public override {
require(ownerOf(tokenId) == from, "Not the token owner");
require(to != address(0), "Invalid recipient");
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
}
Technical Notes
Minting:
The mint function creates a new token and assigns it to an address. Ensure that token IDs are unique.
Standard Compliance:
Functions such as balanceOf, ownerOf, and transferFrom are implemented according to the ERC721 standard.
Events:
The Transfer event is emitted upon minting and transferring tokens, allowing external tracking of NFT ownership.