1

Background

I deployed a ERC20 token to Rinkeby today and have been investigating different ways to do this by reading other popular contracts currently deployed to the Ethereum blockchain. When reading the Tronix contract I noticed it looks pretty close to the generic contract you can find on the web.

In most of these tutorials, to deploy your own token there is often a disclaimer stating,

it's never meant for production level deployment

You can see an example of that here.

There was 1 main difference in the Tronix contract that I would like some clarification on.

Tronix Contract

pragma solidity ^0.4.11;

contract TronToken {

    string public name = "Tronix";      //  token name
    string public symbol = "TRX";           //  token symbol
    uint256 public decimals = 6;            //  token digit

    mapping (address => uint256) public balanceOf;
    mapping (address => mapping (address => uint256)) public allowance;

    uint256 public totalSupply = 0;
    bool public stopped = false;

    uint256 constant valueFounder = 100000000000000000;
    address owner = 0x0;

    modifier isOwner {
        assert(owner == msg.sender);
        _;
    }

    modifier isRunning {
        assert (!stopped);
        _;
    }

    modifier validAddress {
        assert(0x0 != msg.sender);
        _;
    }

    function TronToken(address _addressFounder) {
        owner = msg.sender;
        totalSupply = valueFounder;
        balanceOf[_addressFounder] = valueFounder;
        Transfer(0x0, _addressFounder, valueFounder);
    }

    function transfer(address _to, uint256 _value) isRunning validAddress returns (bool success) {
        require(balanceOf[msg.sender] >= _value);
        require(balanceOf[_to] + _value >= balanceOf[_to]);
        balanceOf[msg.sender] -= _value;
        balanceOf[_to] += _value;
        Transfer(msg.sender, _to, _value);
        return true;
    }

    function transferFrom(address _from, address _to, uint256 _value) isRunning validAddress returns (bool success) {
        require(balanceOf[_from] >= _value);
        require(balanceOf[_to] + _value >= balanceOf[_to]);
        require(allowance[_from][msg.sender] >= _value);
        balanceOf[_to] += _value;
        balanceOf[_from] -= _value;
        allowance[_from][msg.sender] -= _value;
        Transfer(_from, _to, _value);
        return true;
    }

    function approve(address _spender, uint256 _value) isRunning validAddress returns (bool success) {
        require(_value == 0 || allowance[msg.sender][_spender] == 0);
        allowance[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

    function stop() isOwner {
        stopped = true;
    }

    function start() isOwner {
        stopped = false;
    }

    function setName(string _name) isOwner {
        name = _name;
    }

    function burn(uint256 _value) {
        require(balanceOf[msg.sender] >= _value);
        balanceOf[msg.sender] -= _value;
        balanceOf[0x0] += _value;
        Transfer(msg.sender, 0x0, _value);
    }

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

My Contract Via Rinkeby

pragma solidity ^0.4.4;

contract Token {

    function totalSupply() public constant returns (uint256 supply) {}

    function balanceOf(address _owner) public constant 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 constant returns (uint256 remaining) {}

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

}

contract StandardToken is Token {

    function transfer(address _to, uint256 _value) public returns (bool success) {

if (balances[msg.sender] >= _value && _value > 0) {
     balances[msg.sender] -= _value;
     balances[_to] += _value;
     Transfer(msg.sender, _to, _value);
       return true;
      } else { return false; }
 }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
            balances[_to] += _value;
            balances[_from] -= _value;
            allowed[_from][msg.sender] -= _value;
            Transfer(_from, _to, _value);
            return true;
        } else { return false; }
    }

    function balanceOf(address _owner) public constant returns (uint256 balance) {
        return balances[_owner];
    }

    function approve(address _spender, uint256 _value) public returns (bool success) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

    function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
      return allowed[_owner][_spender];
    }

    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;
    uint256 public totalSupply;
}

contract TokenName is StandardToken { 

    string public name;                 
    uint8 public decimals;             
    string public symbol;           
    string public version = 'H1.0';
    uint256 public unitsOneEthCanBuy;   
    uint256 public totalEthInWei;        
    address public fundsWallet;       

    function TokenName() public {
        balances[msg.sender] = 10000000;        
        totalSupply = 10000000;                    
        name = "TokenName";         
        decimals = 2;                           
        symbol = "TOKEN_SYMBOLE_HERE";                               
        unitsOneEthCanBuy = 1000;                                
        fundsWallet = msg.sender;                          
    }

    function() public payable{
        totalEthInWei = totalEthInWei + msg.value;
        uint256 amount = msg.value * unitsOneEthCanBuy;
        if (balances[fundsWallet] < amount) {
            return;
        }

        balances[fundsWallet] = balances[fundsWallet] - amount;
        balances[msg.sender] = balances[msg.sender] + amount;

        Transfer(fundsWallet, msg.sender, amount);

        fundsWallet.transfer(msg.value);
    }

    function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        if(!_spender.call(bytes4(bytes32(keccak256("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData)) { revert(); }
        return true;
    }
}

Question

It is said in the examples I found, that they are not ready for production.

  1. What makes the Tronix contract a production ready contract?

  2. What does address owner = 0x0; mean in the Tronix contract?

1

I don't see anything special about Tronix's contract that would make it any more "production ready" than the others; other than they simply chose NOT to include the best practices disclaimer in their contract.


You can think of 0x0 as null in this case, or simply a black hole. There is a function burn(uint256 _value), which means that they intend to destroy some of their tokens, probably in an attempt to increase the value by decreasing the circulating supply.

  • Thanks for your input on this. Your logic totally makes sense but I can not understand why TRX would be coming into the contract, let alone in to be burned. Would this not only be for people to buy TRX specifically during an ICO and then whatever is left? In that case it would only be going out so how would it be burning coins? But thanks for answering the original question. – wuno Jan 21 '18 at 21:46
  • I would only expect the contract owners to actually use the burn function, maybe to destroy whatever is not sold during the ICO, as you pointed out, anyone else who uses it would be destroying their tokens (I can't think of a good reason to do that). – nyusternie Jan 22 '18 at 14:06
  • Right on thanks man. One more thing, I actually tested my contract last night. I expected it to automatically send 1000 of my token to the address of the person who sends 1ETH into the contract. But that does not happen. It did for sure create the tokens and place them in the address I submitted the contract into the blockchain from. What am I missing here for it to work the way that I was expecting? For the money to be a transaction. Send in 1 ether and get back the 1000 coins. – wuno Jan 22 '18 at 23:54
  • what happened? did the tx fail? uint256 amount = msg.value * unitsOneEthCanBuy; might be a problem, since msg.value is in wei not ether. Also, consider adding SafeMath to protect from overflows. – nyusternie Jan 23 '18 at 11:58
  • I would really like to perfect this contract. I am little confused why you think converting msg.valu to wei could be a problem. Would you mind explaining that a little more to me? Also when you mention overflows you mean a stack overflow? Like if the values add up to be more than uint256? – wuno Jan 28 '18 at 21:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.