1

I am using code from the ethereum docs "https://www.ethereum.org/token". I've set the price from the owner account to 1 ether. Owner has all the tokens. When I send 1 ether from another account to the "buy" function I get the standard error "Constructor should be payble...". I am doing this through remix by switching account, entering 1 ether and clicking the buy function. I am currently just learning to program smart contracts. I know I am breaking the single resp principle.

Why I am not able to use the buy function?

    pragma solidity ^0.4.18;

contract Owned {
    address public owner;

    function Owned() public {
        owner = msg.sender;
    }

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    function transferOwnership(address newOwner) onlyOwner public {
        owner = newOwner;
    }
}

interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }

contract TokenERC20 {
    // Public variables of the token
    string public name;
    string public symbol;
    uint8 public decimals = 18;
    // 18 decimals is the strongly suggested default, avoid changing it
    uint256 public totalSupply;

    // This creates an array with all balances
    mapping (address => uint256) public balanceOf;
    mapping (address => mapping (address => uint256)) public allowance;

    // This generates a public event on the blockchain that will notify clients
    event Transfer(address indexed from, address indexed to, uint256 value);

    // This notifies clients about the amount burnt
    event Burn(address indexed from, uint256 value);

    function TokenERC20(
        uint256 initialSupply,
        string tokenName,
        string tokenSymbol
    ) public {
        totalSupply = initialSupply; // Update total supply with the decimal amount
        balanceOf[msg.sender] = totalSupply;                // Give the creator all initial tokens
        name = tokenName;                                   // Set the name for display purposes
        symbol = tokenSymbol;                               // Set the symbol for display purposes
    }

    function _transfer(address _from, address _to, uint _value) internal {
        // Prevent transfer to 0x0 address. Use burn() instead
        require(_to != 0x0);
        // Check if the sender has enough
        require(balanceOf[_from] >= _value);
        // Check for overflows
        require(balanceOf[_to] + _value > balanceOf[_to]);
        // Save this for an assertion in the future
        uint previousBalances = balanceOf[_from] + balanceOf[_to];
        // Subtract from the sender
        balanceOf[_from] -= _value;
        // Add the same to the recipientA
        balanceOf[_to] += _value;
        Transfer(_from, _to, _value);
        // Asserts are used to use static analysis to find bugs in your code. They should never fail
        assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
    }

    /**
     * Transfer tokens
     *
     * Send `_value` tokens to `_to` from your account
     *
     * @param _to The address of the recipient
     * @param _value the amount to send
     */
    function transfer(address _to, uint256 _value) public {
        _transfer(msg.sender, _to, _value);
    }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        require(_value <= allowance[_from][msg.sender]);     // Check allowance
        allowance[_from][msg.sender] -= _value;
        _transfer(_from, _to, _value);
        return true;
    }


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


    function approveAndCall(address _spender, uint256 _value, bytes _extraData)
        public
        returns (bool success) {
        tokenRecipient spender = tokenRecipient(_spender);
        if (approve(_spender, _value)) {
            spender.receiveApproval(msg.sender, _value, this, _extraData);
            return true;
        }
    }
}

/******************************************/
/*       Lucky TOKEN STARTS HERE       */
/******************************************/

contract MyToken is Owned, TokenERC20 {

    uint256 public buyPrice;

    mapping (address => bool) public frozenAccount;

    /* This generates a public event on the blockchain that will notify clients */
    event FrozenFunds(address target, bool frozen);

    function MyToken(
        uint256 initialSupply,
        string tokenName,
        string tokenSymbol
    ) TokenERC20(initialSupply, tokenName, tokenSymbol) public {}

    /* Internal transfer, only can be called by this contract */
    function _transfer(address _from, address _to, uint _value) internal {
        require (_to != 0x0);                               // Prevent transfer to 0x0 address. Use burn() instead
        require (balanceOf[_from] >= _value);               // Check if the sender has enough
        require (balanceOf[_to] + _value > balanceOf[_to]); // Check for overflows
        require(!frozenAccount[_from]);                     // Check if sender is frozen
        require(!frozenAccount[_to]);                       // Check if recipient is frozen
        balanceOf[_from] -= _value;                         // Subtract from the sender
        balanceOf[_to] += _value;                           // Add the same to the recipient
        Transfer(_from, _to, _value);
    }

    function mintToken(address target, uint256 mintedAmount) onlyOwner public {
        balanceOf[target] += mintedAmount;
        totalSupply += mintedAmount;
        Transfer(0, this, mintedAmount);
        Transfer(this, target, mintedAmount);
    }

    /// @notice `freeze? Prevent | Allow` `target` from sending & receiving tokens
    /// @param target Address to be frozen
    /// @param freeze either to freeze it or not
    function freezeAccount(address target, bool freeze) onlyOwner public {
        frozenAccount[target] = freeze;
        FrozenFunds(target, freeze);
    }

    function setPrice(uint256 newBuyPrice) onlyOwner public {
        buyPrice = newBuyPrice;
    }

    /// @notice Buy tokens from contract by sending ether
    function buy() payable public {
        uint amount = msg.value / buyPrice;               // calculates the amount
        _transfer(owner, msg.sender, amount);              // makes the transfers
    }
}

Using a second account and sending 1 ether to the buy function

1

Well, first, you should copy/paste the Owned and TokenERC20 code so we have an idea of what they do.

But based on your description of the problem,

I get the standard error "Constructor should be payble..."

It seems you are trying to send ETH in the deployment transaction. If this is the desired outcome, add payable to the constructor, otherwise, however you are deploying, set to 0 the field concerning the ETH.

Now, beside that, if you want to send ETH to the contract and call the buy function, you have to either use the ABI through a platform like MEW, or send a transaction to the contract with the function's hash in the data field.

  • How would one get the function hash? – Will Tate Mar 23 '18 at 20:26
  • 1
    Well, you could go on remix, open the contract there, and see in "Details". The functions' hashes are precised there. Or you can go the hard way, and hash yourself the function, and get the first 4 bytes. – Eli Drion Mar 23 '18 at 20:40
  • @ElishaDrion I have edited the post and added source code and screenshot. I am using remix to test those. Sending 1 ethere to the buy function from the second account. The owner has all the balance. – Nikolay Tsvetanov Mar 24 '18 at 8:16
0

The problem was that I was sending 1 ether. My initial supply was 777 but it was not updated to wei using this code I removed:

totalSupply = initialSupply * 10 ** uint256(decimals); // Update total supply with the decimal amount

So when transfering the owner had 777 but because of this calculation:

uint amount = msg.value / buyPrice;               // calculates the amount

the sender had to receive not 1 token but 100000000000000000 because the calculation above uses WEI not ether which is way above the balance of the owner.

TLDR;

The error was given because the Owner didn't have enough token balance to send to the Buyer due to miscalculation in the buy function which uses wei not ether.

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.