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

From CoinWiki
Jump to: navigation, search
(Modify our token's code)
(Modify our token's code)
Line 65: Line 65:
  
 
<code>
 
<code>
pragma solidity ^0.4.24;
+
pragma solidity ^0.5.10;
  
contract Token {
+
// 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;
 +
    }
 +
}
  
    /// @return total amount of tokens
+
/**
     function totalSupply() constant returns (uint256 supply) {}
+
  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);
  
     /// @param _owner The address from which the balance will be retrieved
+
     event Transfer(address indexed from, address indexed to, uint tokens);
     /// @return The balance
+
     event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
    function balanceOf(address _owner) constant returns (uint256 balance) {}
+
}
  
    /// @notice send `_value` token to `_to` from `msg.sender`
+
// Contract function to receive approval and execute function in one call
    /// @param _to The address of the recipient
+
contract ApproveAndCallFallBack {
    /// @param _value The amount of token to be transferred
+
     function receiveApproval(address from, uint256 tokens, address token, bytes memory data) public;
    /// @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`
+
// Owned contract
    /// @param _from The address of the sender
+
contract Owned {
     /// @param _to The address of the recipient
+
     address public owner;
     /// @param _value The amount of token to be transferred
+
     address public newOwner;
    /// @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
+
     event OwnershipTransferred(address indexed _from, address indexed _to);
    /// @param _spender The address of the account able to transfer the tokens
 
    /// @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
+
     constructor() public {
    /// @param _spender The address of the account able to transfer the tokens
+
        owner = msg.sender;
     /// @return Amount of remaining tokens allowed to spent
+
     }
    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
 
  
     event Transfer(address indexed _from, address indexed _to, uint256 _value);
+
     modifier onlyOwner {
     event Approval(address indexed _owner, address indexed _spender, uint256 _value);
+
        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;
  
contract StandardToken is Token {
+
    mapping(address => uint) balances;
 +
    mapping(address => mapping(address => uint)) allowed;
  
     function transfer(address _to, uint256 _value) returns (bool success) {
+
     // 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);
 +
    }
  
        if (balances[msg.sender] >= _value && _value > 0) {
+
    // Total supply
            balances[msg.sender] -= _value;
+
    function totalSupply() public view returns (uint) {
            balances[_to] += _value;
+
        return _totalSupply  - balances[address(0)];
            Transfer(msg.sender, _to, _value);
 
            return true;
 
        } else { return false; }
 
 
     }
 
     }
  
     function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
+
    // Get the token balance for account tokenOwner
 +
     function balanceOf(address tokenOwner) public view returns (uint balance) {
 +
        return balances[tokenOwner];
 +
    }
  
         if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
+
    // Transfer the balance from token owner's account to to account
            balances[_to] += _value;
+
    function transfer(address to, uint tokens) public returns (bool success) {
            balances[_from] -= _value;
+
         balances[msg.sender] = safeSub(balances[msg.sender], tokens);
            allowed[_from][msg.sender] -= _value;
+
        balances[to] = safeAdd(balances[to], tokens);
            Transfer(_from, _to, _value);
+
        emit Transfer(msg.sender, to, tokens);
            return true;
+
        return true;
        } else { return false; }
 
 
     }
 
     }
  
     function balanceOf(address _owner) constant returns (uint256 balance) {
+
    /**
         return balances[_owner];
+
    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;
 
     }
 
     }
  
     function approve(address _spender, uint256 _value) returns (bool success) {
+
    /**
         allowed[msg.sender][_spender] = _value;
+
    Transfer tokens from the from account to the to account
         Approval(msg.sender, _spender, _value);
+
    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;
 
         return true;
 
     }
 
     }
  
     function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
+
    // Returns the amount of tokens approved by the owner that can be transferred to the spender's account
      return allowed[_owner][_spender];
+
     function allowance(address tokenOwner, address spender) public view returns (uint remaining) {
 +
        return allowed[tokenOwner][spender];
 
     }
 
     }
  
     mapping (address => uint256) balances;
+
     // Token owner can approve for spender to transferFrom(...) tokens from the token owner's account.
     mapping (address => mapping (address => uint256)) allowed;
+
     function approveAndCall(address spender, uint tokens, bytes memory data) public returns (bool success) {
    uint256 public totalSupply;
+
        allowed[msg.sender][spender] = tokens;
}
+
        emit Approval(msg.sender, spender, tokens);
 
+
        ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, address(this), data);
 
+
         return true;
contract CoinWiki is StandardToken {
 
 
 
    function () {
 
        //if ether is sent to this address, send it back.
 
         throw;
 
 
     }
 
     }
  
     string public name;                     
+
     // Send back ETH
    uint8 public decimals;               
+
     function () external payable {
    string public symbol;                   
+
         revert();
    string public version = 'H1.0';     
 
 
 
     function CoinWiki(
 
        ) {
 
         balances[msg.sender] = 160000000000000000000000000;              // Give the creator all initial tokens (100000 for example)
 
        totalSupply = 160000000000000000000000000;                                 // Update total supply (100000 for example)
 
        name = "CoinWiki Token";                                                                        // Set the name for display purposes
 
        decimals = 18;                                                                                            // Amount of decimals for display purposes
 
        symbol = "CWT";                                                                                      // Set the symbol for display purposes
 
 
     }
 
     }
  
     // Approves and then calls the receiving contract
+
     // Owner can transfer out any accidentally sent ERC20 tokens
     function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
+
     function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
         allowed[msg.sender][_spender] = _value;
+
         return ERC20Interface(tokenAddress).transfer(owner, tokens);
        Approval(msg.sender, _spender, _value);
 
 
 
        if(!_spender.call(bytes4(bytes32(sha3("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData)) { throw; }
 
        return true;
 
 
     }
 
     }
 
}
 
}
 +
 
</code>
 
</code>
  
* Change your token's supply on line 99 and 100
+
* Name your token on line 83
* Name your token on line 101
+
* Change your token's symbol on line 84
* Set your token's decimal on line 102 (Most tokens have 18 decimal places but you can have any number you like)
+
* 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 symbol on line 103
+
* Change your token's supply on line 86
* 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 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.  

Revision as of 22:33, 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'. 10,000 text 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.4.24'. 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. So we will use a modified version of a ERC20 token code created by TokenFactory to create our TRC20 token.

  • Copy the following code into your favorite code editor. I will be using Atom.

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);
   }

}

  • 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 hex value is your 'contract address'. To see your new token, paste the value into the search bar on Shasta Tronscan.

(base58) TVEfcAw4BaGWMzR8HxRszhLZqHTRgru2rx

(hex) 41d356d6a077e97e3f24fd17978b278d285c360ee0