Difference between revisions of "How to create your own TRC20 token on Tron"

From CoinWiki
Jump to: navigation, search
(Configuring TronBox)
(Compile and Deploy your Token)
 
(21 intermediate revisions by the same user not shown)
Line 24: Line 24:
  
  
* Next go [https://www.trongrid.io/shasta/#request here] and paste in your Tron address and click 'Submit'. 10,000 text TRX will then be deposited to your address.
+
* Next go [https://www.trongrid.io/shasta/#request here] and paste in your Tron address and click 'Submit'. 5,000 test TRX will then be deposited to your address.
  
 
== Install TronBox ==
 
== Install TronBox ==
 
We will use [[TRON-BOX | TronBox]] to deploy our [[smart contracts | smart contract]] onto Tron's blockchain.
 
We will use [[TRON-BOX | TronBox]] to deploy our [[smart contracts | smart contract]] onto Tron's blockchain.
* Paste the following lines of code into your [[terminal]]
+
* Paste the following lines of code into your [[terminal]] to install tronbox.
 
<code>npm install -g tronbox</code>
 
<code>npm install -g tronbox</code>
 +
 +
* Make a directory on your computer for tronbox and then enter it
 +
<code>mkdir tron-dev</code>
 +
 +
<code>cd tron-dev</code>
  
 
* Initialize TronBox (this can take some time)
 
* Initialize TronBox (this can take some time)
Line 40: Line 45:
  
 
<code>nano .env</code>
 
<code>nano .env</code>
<code>export PRIVATE_KEY_SHASTA =your_private_key</code>
+
 
 +
<code>export PRIVATE_KEY_SHASTA=your_private_key</code>
  
 
* Press 'control x',  then 'y', and then 'enter' to save.
 
* Press 'control x',  then 'y', and then 'enter' to save.
  
== Modify our token's code==
 
Smart contracts on Tron are built using Solidity, just like on Ethereum. So we will use a modified version of a ERC20 token code created by [https://github.com/ConsenSys/Token-Factory TokenFactory] to create our TRC20 token.
 
  
* Copy the following code into your favorite code editor. I will be using [https://atom.io/ Atom].
+
Now we will have to change the version compiler in <code>tronbox.js</code>.
<code>
 
pragma solidity ^0.4.24;
 
  
contract Token {
+
<code>nano tronbox.js</code>
  
    /// @return total amount of tokens
+
Scroll down to where is says <code>// version: '0.5.4'</code> and uncomment the line (remove the '//') and enter '0.5.10'. Tronbox only supports the following Solidity versions: 0.4.24, 0.4.25, 0.5.4, 0.5.8, 0.5.10.
    function totalSupply() constant returns (uint256 supply) {}
 
  
    /// @param _owner The address from which the balance will be retrieved
+
* When you are done press 'control x',  then 'y', and then 'enter' to save.
    /// @return The balance
 
    function balanceOf(address _owner) constant returns (uint256 balance) {}
 
  
    /// @notice send `_value` token to `_to` from `msg.sender`
+
== Modify our token's code==
    /// @param _to The address of the recipient
+
Smart contracts on Tron are built using [[Solidity]], just like on Ethereum.
    /// @param _value The amount of token to be transferred
 
    /// @return Whether the transfer was successful or not
 
    function transfer(address _to, uint256 _value) returns (bool success) {}
 
  
    /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
+
* Copy the following code into your favorite code editor. I will be using [https://atom.io/ Atom].
    /// @param _from The address of the sender
+
* '''Here's the link to the code shown below''' [https://raw.githubusercontent.com/blockinator/smart-contract-repository/master/TRON/Token/TRC20.sol TRC20 Code]
    /// @param _to The address of the recipient
 
    /// @param _value The amount of token to be transferred
 
    /// @return Whether the transfer was successful or not
 
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}
 
  
    /// @notice `msg.sender` approves `_addr` to spend `_value` tokens
+
<code>
    /// @param _spender The address of the account able to transfer the tokens
+
pragma solidity ^0.5.10;
    /// @param _value The amount of wei to be approved for transfer
 
    /// @return Whether the approval was successful or not
 
    function approve(address _spender, uint256 _value) returns (bool success) {}
 
  
    /// @param _owner The address of the account owning tokens
+
// Safe maths
     /// @param _spender The address of the account able to transfer the tokens
+
contract SafeMath {
     /// @return Amount of remaining tokens allowed to spent
+
    function safeAdd(uint a, uint b) public pure returns (uint c) {
     function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
+
        c = a + b;
 +
        require(c >= a);
 +
    }
 +
    function safeSub(uint a, uint b) public pure returns (uint c) {
 +
        require(b <= a);
 +
        c = a - b;
 +
    }
 +
     function safeMul(uint a, uint b) public pure returns (uint c) {
 +
        c = a * b;
 +
        require(a == 0 || c / a == b);
 +
     }
 +
     function safeDiv(uint a, uint b) public pure returns (uint c) {
 +
        require(b > 0);
 +
        c = a / b;
 +
    }
 +
}
  
     event Transfer(address indexed _from, address indexed _to, uint256 _value);
+
/**
     event Approval(address indexed _owner, address indexed _spender, uint256 _value);
+
  ERC Token Standard #20 Interface
 +
  https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
 +
*/
 +
contract ERC20Interface {
 +
     function totalSupply() public view returns (uint);
 +
    function balanceOf(address tokenOwner) public view returns (uint balance);
 +
    function allowance(address tokenOwner, address spender) public view returns (uint remaining);
 +
    function transfer(address to, uint tokens) public returns (bool success);
 +
    function approve(address spender, uint tokens) public returns (bool success);
 +
     function transferFrom(address from, address to, uint tokens) public returns (bool success);
  
 +
    event Transfer(address indexed from, address indexed to, uint tokens);
 +
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
 
}
 
}
  
 +
// Contract function to receive approval and execute function in one call
 +
contract ApproveAndCallFallBack {
 +
    function receiveApproval(address from, uint256 tokens, address token, bytes memory data) public;
 +
}
  
contract StandardToken is Token {
+
// Owned contract
 +
contract Owned {
 +
    address public owner;
 +
    address public newOwner;
  
     function transfer(address _to, uint256 _value) returns (bool success) {
+
     event OwnershipTransferred(address indexed _from, address indexed _to);
  
        if (balances[msg.sender] >= _value && _value > 0) {
+
    constructor() public {
            balances[msg.sender] -= _value;
+
        owner = msg.sender;
            balances[_to] += _value;
 
            Transfer(msg.sender, _to, _value);
 
            return true;
 
        } else { return false; }
 
 
     }
 
     }
  
     function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
+
     modifier onlyOwner {
 +
        require(msg.sender == owner);
 +
        _;
 +
    }
  
        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
+
    function transferOwnership(address _newOwner) public onlyOwner {
            balances[_to] += _value;
+
        newOwner = _newOwner;
            balances[_from] -= _value;
 
            allowed[_from][msg.sender] -= _value;
 
            Transfer(_from, _to, _value);
 
            return true;
 
        } else { return false; }
 
 
     }
 
     }
 +
    function acceptOwnership() public {
 +
        require(msg.sender == newOwner);
 +
        emit OwnershipTransferred(owner, newOwner);
 +
        owner = newOwner;
 +
        newOwner = address(0);
 +
    }
 +
}
  
     function balanceOf(address _owner) constant returns (uint256 balance) {
+
// ERC20 Token, with the addition of symbol, name and decimals and assisted token transfers
         return balances[_owner];
+
contract CoinWiki is ERC20Interface, Owned, SafeMath {
 +
    string public symbol;
 +
    string public  name;
 +
    uint8 public decimals;
 +
    uint public _totalSupply;
 +
 
 +
     mapping(address => uint) balances;
 +
    mapping(address => mapping(address => uint)) allowed;
 +
 
 +
    // Constructor
 +
    constructor() public {
 +
        name = "CoinWiki Token";
 +
        symbol = "CWT";
 +
        decimals = 18;
 +
        _totalSupply = 1000000000 * (10 ** uint256(decimals));
 +
         balances[msg.sender] = _totalSupply;
 +
        emit Transfer(address(0), msg.sender, _totalSupply);
 
     }
 
     }
  
     function approve(address _spender, uint256 _value) returns (bool success) {
+
    // Total supply
         allowed[msg.sender][_spender] = _value;
+
     function totalSupply() public view returns (uint) {
        Approval(msg.sender, _spender, _value);
+
         return _totalSupply  - balances[address(0)];
        return true;
 
 
     }
 
     }
  
     function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
+
    // Get the token balance for account tokenOwner
      return allowed[_owner][_spender];
+
     function balanceOf(address tokenOwner) public view returns (uint balance) {
 +
        return balances[tokenOwner];
 
     }
 
     }
  
     mapping (address => uint256) balances;
+
     // Transfer the balance from token owner's account to to account
    mapping (address => mapping (address => uint256)) allowed;
+
    function transfer(address to, uint tokens) public returns (bool success) {
    uint256 public totalSupply;
+
        balances[msg.sender] = safeSub(balances[msg.sender], tokens);
}
+
        balances[to] = safeAdd(balances[to], tokens);
 +
        emit Transfer(msg.sender, to, tokens);
 +
        return true;
 +
    }
  
 +
    /**
 +
    Token owner can approve for spender to transferFrom(...) tokens
 +
    from the token owner's account
  
contract CoinWiki is StandardToken {
+
    https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
 +
    recommends that there are no checks for the approval double-spend attack
 +
    as this should be implemented in user interfaces
 +
    */
 +
    function approve(address spender, uint tokens) public returns (bool success) {
 +
        allowed[msg.sender][spender] = tokens;
 +
        emit Approval(msg.sender, spender, tokens);
 +
        return true;
 +
    }
  
     function () {
+
    /**
         //if ether is sent to this address, send it back.
+
    Transfer tokens from the from account to the to account
         throw;
+
    The calling account must already have sufficient tokens approve(...)-d
 +
    for spending from the from account and
 +
    - From account must have sufficient balance to transfer
 +
    - Spender must have sufficient allowance to transfer
 +
    - 0 value transfers are allowed
 +
    */
 +
     function transferFrom(address from, address to, uint tokens) public returns (bool success) {
 +
         balances[from] = safeSub(balances[from], tokens);
 +
        allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
 +
        balances[to] = safeAdd(balances[to], tokens);
 +
        emit Transfer(from, to, tokens);
 +
         return true;
 
     }
 
     }
  
     string public name;                     
+
     // Returns the amount of tokens approved by the owner that can be transferred to the spender's account
     uint8 public decimals;               
+
     function allowance(address tokenOwner, address spender) public view returns (uint remaining) {
    string public symbol;                  
+
        return allowed[tokenOwner][spender];
     string public version = 'H1.0';     
+
     }
  
     function CoinWiki(
+
    // Token owner can approve for spender to transferFrom(...) tokens from the token owner's account.
        ) {
+
     function approveAndCall(address spender, uint tokens, bytes memory data) public returns (bool success) {
         balances[msg.sender] = 160000000000000000000000000;               // Give the creator all initial tokens (100000 for example)
+
         allowed[msg.sender][spender] = tokens;
         totalSupply = 160000000000000000000000000;                                // Update total supply (100000 for example)
+
         emit Approval(msg.sender, spender, tokens);
        name = "CoinWiki Token";                                                                         // Set the name for display purposes
+
         ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, address(this), data);
         decimals = 18;                                                                                           // Amount of decimals for display purposes
+
         return true;
         symbol = "CWT";                                                                                       // Set the symbol for display purposes
 
 
     }
 
     }
  
     // Approves and then calls the receiving contract
+
     // Send back ETH
     function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
+
     function () external payable {
         allowed[msg.sender][_spender] = _value;
+
         revert();
        Approval(msg.sender, _spender, _value);
+
    }
  
        if(!_spender.call(bytes4(bytes32(sha3("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData)) { throw; }
+
    // Owner can transfer out any accidentally sent ERC20 tokens
        return true;
+
    function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
 +
        return ERC20Interface(tokenAddress).transfer(owner, tokens);
 
     }
 
     }
 
}
 
}
 +
 
</code>
 
</code>
  
* Change your token's supply on line 99 and 100
+
'''Now let's configure your token:'''
* Name your token on line 101
+
* Name your token on line 83
* Set your token's decimal on line 102 (Most tokens have 18 decimal places but you can have any number you like)
+
* Change your token's symbol on line 84
* Change your token's symbol on line 103
+
* Set your token's decimal on line 85 (Most tokens have 18 decimal places but you can have any number you like)
* Change the contract name on line 85 and the function name on line 97 to whatever you like (I just used my token's name)
+
* Change your token's supply on line 86
 +
* Change the contract name on line 72
  
Now we are going to add our code to TronBox.  
+
'''Now we are going to add our code to TronBox.'''
 
* Enter contracts directory
 
* Enter contracts directory
 
<code>cd tronbox/contracts</code>
 
<code>cd tronbox/contracts</code>
Line 183: Line 249:
  
 
* Modify '2_deploy_contracts.js' to match your token
 
* Modify '2_deploy_contracts.js' to match your token
 +
 
<code>cd ..</code>
 
<code>cd ..</code>
  
 
<code>nano migrations/2_deploy_contracts.js</code>
 
<code>nano migrations/2_deploy_contracts.js</code>
  
* Delete existing code and then copy and paste the following code into '2_deploy_contracts.js' and change variable and contract names to match your token
+
* Uncommit both lines that have commits and replace all instances of 'MyContract' with the name of your contract
  
<code>
+
* Press 'control x',  then 'y', and then 'enter' to exit and save your file
var Migrations = artifacts.require("./Migrations.sol");
 
var CoinWiki = artifacts.require("./CoinWiki.sol");
 
  
module.exports = function(deployer) {
+
== Compile and Deploy your Token ==
  deployer.deploy(Migrations);
+
* Input the following code into your terminal to compile and deploy your smart contract to the Tron testnet.
  deployer.deploy(CoinWiki);
 
};
 
</code>
 
 
 
* Press 'control x',  then 'y', and then 'enter' to save your file
 
  
== Compile and Deploy your Token ==
 
 
<code>cd ..</code>
 
<code>cd ..</code>
  
 
<code>tronbox compile --compile-all</code>
 
<code>tronbox compile --compile-all</code>
  
<code>tronbox migrate --reset --network development</code>
+
<code>source .env && tronbox migrate --reset --network shasta</code>
 +
 
 +
* After you migrate your smart contract to the Shasta testnet you will see two variables: base58 and hex. The base58 value is your 'contract address'. To see your new token, paste the value into the search bar on [https://shasta.tronscan.org Shasta Tronscan].
 +
 
 +
<code>
 +
(base58) TMRAvTVVnCvkPjQMYJrEqeKUtqiwqn65ZN
 +
</code>
 +
 
 +
<code>
 +
(hex) 417d92767fbb81cfcc604e452dd6558039181fb33d
 +
</code>

Latest revision as of 22:47, 28 October 2020

TRON is a decentralized blockchain content delivery platform to allow creators to publish and own their uploaded content. TRON originally existed as an ERC20 token (TRX) operating on Ethereum's blockchain but now exists as its own blockchain. TRON has its own set of token standards called TRC10 and TRC20. In this guide I will walk you through creating your own TRC20 token.

Download TronLink

  • TronLink is a browser based extension for interacting with the TRON blockchain. It is available for chrome based browsers like Google Chrome and Brave. Add the extension to your browser by clicking the 'Add to Chrome' button.

Tronlink.png


  • Once the extension is added, click on it in the upper right hand corner. You will then be walked through some steps to create your wallet. First you are going to create a password then press 'Continue'. Then click on 'Create Wallet' like so:

Tronlinkpass.png Tronlinkcreate.png


  • Now name your wallet and press 'Continue'. Next copy the mnemonic phrase to a safe place and press 'Continue'. The last step is to confirm the mnemonic phrase by selecting the words in order and press 'Confirm' to finish. You have now created a wallet!

Tronlinkwallet.png


Get test TRX coins

  • Click the 'Settings' tab in TronLink and select 'Shasta Testnet' in the 'Node selection' box.

Tronlinktest.png


  • Next go here and paste in your Tron address and click 'Submit'. 5,000 test TRX will then be deposited to your address.

Install TronBox

We will use TronBox to deploy our smart contract onto Tron's blockchain.

  • Paste the following lines of code into your terminal to install tronbox.

npm install -g tronbox

  • Make a directory on your computer for tronbox and then enter it

mkdir tron-dev

cd tron-dev

  • Initialize TronBox (this can take some time)

tronbox init

Configuring TronBox

We will need to copy your private key from our Tron wallet and place it in a .env file. Go to your TronLink extension and click 'Export' and copy your private key.

Next create a '.env' file and paste in the following code with your private key.

nano .env

export PRIVATE_KEY_SHASTA=your_private_key

  • Press 'control x', then 'y', and then 'enter' to save.


Now we will have to change the version compiler in tronbox.js.

nano tronbox.js

Scroll down to where is says // version: '0.5.4' and uncomment the line (remove the '//') and enter '0.5.10'. Tronbox only supports the following Solidity versions: 0.4.24, 0.4.25, 0.5.4, 0.5.8, 0.5.10.

  • When you are done press 'control x', then 'y', and then 'enter' to save.

Modify our token's code

Smart contracts on Tron are built using Solidity, just like on Ethereum.

  • Copy the following code into your favorite code editor. I will be using Atom.
  • Here's the link to the code shown below TRC20 Code

pragma solidity ^0.5.10;

// Safe maths contract SafeMath {

   function safeAdd(uint a, uint b) public pure returns (uint c) {
       c = a + b;
       require(c >= a);
   }
   function safeSub(uint a, uint b) public pure returns (uint c) {
       require(b <= a);
       c = a - b;
   }
   function safeMul(uint a, uint b) public pure returns (uint c) {
       c = a * b;
       require(a == 0 || c / a == b);
   }
   function safeDiv(uint a, uint b) public pure returns (uint c) {
       require(b > 0);
       c = a / b;
   }

}

/**

 ERC Token Standard #20 Interface
 https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
  • /

contract ERC20Interface {

   function totalSupply() public view returns (uint);
   function balanceOf(address tokenOwner) public view returns (uint balance);
   function allowance(address tokenOwner, address spender) public view returns (uint remaining);
   function transfer(address to, uint tokens) public returns (bool success);
   function approve(address spender, uint tokens) public returns (bool success);
   function transferFrom(address from, address to, uint tokens) public returns (bool success);
   event Transfer(address indexed from, address indexed to, uint tokens);
   event Approval(address indexed tokenOwner, address indexed spender, uint tokens);

}

// Contract function to receive approval and execute function in one call contract ApproveAndCallFallBack {

   function receiveApproval(address from, uint256 tokens, address token, bytes memory data) public;

}

// Owned contract contract Owned {

   address public owner;
   address public newOwner;
   event OwnershipTransferred(address indexed _from, address indexed _to);
   constructor() public {
       owner = msg.sender;
   }
   modifier onlyOwner {
       require(msg.sender == owner);
       _;
   }
   function transferOwnership(address _newOwner) public onlyOwner {
       newOwner = _newOwner;
   }
   function acceptOwnership() public {
       require(msg.sender == newOwner);
       emit OwnershipTransferred(owner, newOwner);
       owner = newOwner;
       newOwner = address(0);
   }

}

// ERC20 Token, with the addition of symbol, name and decimals and assisted token transfers contract CoinWiki is ERC20Interface, Owned, SafeMath {

   string public symbol;
   string public  name;
   uint8 public decimals;
   uint public _totalSupply;
   mapping(address => uint) balances;
   mapping(address => mapping(address => uint)) allowed;
   // Constructor
   constructor() public {
       name = "CoinWiki Token";
       symbol = "CWT";
       decimals = 18;
       _totalSupply = 1000000000 * (10 ** uint256(decimals));
       balances[msg.sender] = _totalSupply;
       emit Transfer(address(0), msg.sender, _totalSupply);
   }
   // Total supply
   function totalSupply() public view returns (uint) {
       return _totalSupply  - balances[address(0)];
   }
   // Get the token balance for account tokenOwner
   function balanceOf(address tokenOwner) public view returns (uint balance) {
       return balances[tokenOwner];
   }
   // Transfer the balance from token owner's account to to account
   function transfer(address to, uint tokens) public returns (bool success) {
       balances[msg.sender] = safeSub(balances[msg.sender], tokens);
       balances[to] = safeAdd(balances[to], tokens);
       emit Transfer(msg.sender, to, tokens);
       return true;
   }
   /**
    Token owner can approve for spender to transferFrom(...) tokens
    from the token owner's account
    https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
    recommends that there are no checks for the approval double-spend attack
    as this should be implemented in user interfaces
   */
   function approve(address spender, uint tokens) public returns (bool success) {
       allowed[msg.sender][spender] = tokens;
       emit Approval(msg.sender, spender, tokens);
       return true;
   }
   /**
    Transfer tokens from the from account to the to account
    The calling account must already have sufficient tokens approve(...)-d
    for spending from the from account and
    - From account must have sufficient balance to transfer
    - Spender must have sufficient allowance to transfer
    - 0 value transfers are allowed
   */
   function transferFrom(address from, address to, uint tokens) public returns (bool success) {
       balances[from] = safeSub(balances[from], tokens);
       allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
       balances[to] = safeAdd(balances[to], tokens);
       emit Transfer(from, to, tokens);
       return true;
   }
   // Returns the amount of tokens approved by the owner that can be transferred to the spender's account
   function allowance(address tokenOwner, address spender) public view returns (uint remaining) {
       return allowed[tokenOwner][spender];
   }
   // Token owner can approve for spender to transferFrom(...) tokens from the token owner's account.
   function approveAndCall(address spender, uint tokens, bytes memory data) public returns (bool success) {
       allowed[msg.sender][spender] = tokens;
       emit Approval(msg.sender, spender, tokens);
       ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, address(this), data);
       return true;
   }
   // Send back ETH
   function () external payable {
       revert();
   }
   // Owner can transfer out any accidentally sent ERC20 tokens
   function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
       return ERC20Interface(tokenAddress).transfer(owner, tokens);
   }

}

Now let's configure your token:

  • Name your token on line 83
  • Change your token's symbol on line 84
  • Set your token's decimal on line 85 (Most tokens have 18 decimal places but you can have any number you like)
  • Change your token's supply on line 86
  • Change the contract name on line 72

Now we are going to add our code to TronBox.

  • Enter contracts directory

cd tronbox/contracts

  • Make new file for our token and paste in the modified code from your text editor. Name the file like so: <name_of_token>.sol

nano CoinWiki.sol

  • Press 'control x', then 'y', and then 'enter' to save your file

Modify Migrations

  • Modify '2_deploy_contracts.js' to match your token

cd ..

nano migrations/2_deploy_contracts.js

  • Uncommit both lines that have commits and replace all instances of 'MyContract' with the name of your contract
  • Press 'control x', then 'y', and then 'enter' to exit and save your file

Compile and Deploy your Token

  • Input the following code into your terminal to compile and deploy your smart contract to the Tron testnet.

cd ..

tronbox compile --compile-all

source .env && tronbox migrate --reset --network shasta

  • After you migrate your smart contract to the Shasta testnet you will see two variables: base58 and hex. The base58 value is your 'contract address'. To see your new token, paste the value into the search bar on Shasta Tronscan.

(base58) TMRAvTVVnCvkPjQMYJrEqeKUtqiwqn65ZN

(hex) 417d92767fbb81cfcc604e452dd6558039181fb33d