I have ERC20 contract

pragma solidity ^0.5.7;

library SafeMath {
     * @dev Multiplies two unsigned integers, reverts on overflow.
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;

     * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;

     * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;

     * @dev Adds two unsigned integers, reverts on overflow.
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;

     * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
     * reverts when dividing by zero.
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;

contract ERC20 {

    using SafeMath for uint256;

    mapping (address => uint256) public balances;

    mapping (address => mapping (address => uint)) public allowed;

    //Fix for short address attack against ERC20
    modifier onlyPayloadSize(uint size) {
        assert(msg.data.length == size + 4);

    function balanceOf(address _owner) public view returns (uint256) {
        return balances[_owner];

    function transfer(address _recipient, uint256 _value) public onlyPayloadSize(2*32){
        require(balances[msg.sender] >= _value && _value > 0);
        emit Transfer(msg.sender, _recipient, _value);        

    function transferFrom(address _from, address _to, uint256 _value) public {
        require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0);
            emit Transfer(_from, _to, _value);

    function  approve(address _spender, uint _value) public {
        allowed[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);

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

    //Event which is triggered to log all transfers to this contract's event log
    event Transfer(
        address indexed _from,
        address indexed _to,
        uint _value

    //Event which is triggered whenever an owner approves a new allowance for a spender.
    event Approval(
        address indexed _owner,
        address indexed _spender,
        uint _value

contract yMTCZ is ERC20 {

    string public constant name = "MyCoinZy";

    string public constant symbol = "yMTCZ";

    uint8 public constant decimals = 6;

    uint256 public totalSupply = 1000000 * 10**6;

    uint256 public constant unitsOneEthCanBuy = 200;     // How many units of your coin can be bought by 1 ETH

    uint256 public totalEthInWei;  

    address payable public fundsWallet = msg.sender;

    string public  version = "1.0";

    constructor() yMTCZ() public {

        balances[msg.sender] = totalSupply;


    function () external payable {
        totalEthInWei = totalEthInWei + msg.value;
        uint256 amount = msg.value * unitsOneEthCanBuy;
        require(balances[fundsWallet] >= amount && allowed[fundsWallet][msg.sender] >= amount && amount > 0);
            emit Transfer(fundsWallet, msg.sender, amount);


I can't buy token using ETH. I use payable function to accept ETH and send tokens to user wallet.

1 Answer 1


I think it is too much for a fallback function


In the worst case, the fallback function can only rely on 2300 gas being available (for example when send or transfer is used), leaving little room to perform other operations except basic logging. The following operations will consume more gas than the 2300 gas stipend: Writing to storage, Creating a contract, Calling an external function which consumes a large amount of gas, Sending Ether

So you should have a separated buy function

  • you mean make empty function () external payable {} , and separate function buy() public {here code}
    – Alex
    May 7, 2019 at 14:51
  • no you dont need to use the fallback function. You should write a new function buy(..) public payable {code here}, and who want to buy your token should call this function and send ether with it
    – Majd TL
    May 7, 2019 at 15:18

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