0

So, I'm trying to test an underflow of test ERC20 tokens, but even if I remove all the require checks of the EIP20 (ERC20) file, when I transfer 1 test token from the contract to an address (the contract has 0 tokens), it fails anyways and reverts, does anyone know why? (By the way, the message that appears before sending the transaction is: "gas estimation failed" and more text, then "execution reversed") These are the codes:

pragma solidity 0.4.21;

import "./EIP20.sol";

contract TransferTokens {
  function transferTokens (address _tokenAddress, address _to, uint256 _value) public returns (bool) {
        EIP20 token = EIP20 (_tokenAddress);

        return token.transfer(_to, _value);
    }
} 
 /*
Implements EIP20 token standard: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
.*/


pragma solidity ^0.4.21;

import "./EIP20Interface.sol";


contract EIP20 is EIP20Interface {

    uint256 constant private MAX_UINT256 = 2**256 - 1;
    mapping (address => uint256) public balances;
    mapping (address => mapping (address => uint256)) public allowed;
    /*
    NOTE:
    The following variables are OPTIONAL vanities. One does not have to include them.
    They allow one to customise the token contract & in no way influences the core functionality.
    Some wallets/interfaces might not even bother to look at this information.
    */
    string public name;                   //fancy name: eg Simon Bucks
    uint8 public decimals;                //How many decimals to show.
    string public symbol;                 //An identifier: eg SBX

    function EIP20(
        uint256 _initialAmount,
        string _tokenName,
        uint8 _decimalUnits,
        string _tokenSymbol
    ) public {
        balances[msg.sender] = _initialAmount;               // Give the creator all initial tokens
        totalSupply = _initialAmount;                        // Update total supply
        name = _tokenName;                                   // Set the name for display purposes
        decimals = _decimalUnits;                            // Amount of decimals for display purposes
        symbol = _tokenSymbol;                               // Set the symbol for display purposes
    }

    function transfer(address _to, uint256 _value) public returns (bool success) {
        balances[msg.sender] -= _value;
        balances[_to] += _value;
        emit Transfer(msg.sender, _to, _value); //solhint-disable-line indent, no-unused-vars
        return true;
    }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        uint256 allowance = allowed[_from][msg.sender];
        balances[_to] += _value;
        balances[_from] -= _value;
        if (allowance < MAX_UINT256) {
            allowed[_from][msg.sender] -= _value;
        }
        emit Transfer(_from, _to, _value); //solhint-disable-line indent, no-unused-vars
        return true;
    }

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

    function approve(address _spender, uint256 _value) public returns (bool success) {
        allowed[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value); //solhint-disable-line indent, no-unused-vars
        return true;
    }

    function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }
}
// Abstract contract for the full ERC 20 Token standard
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
pragma solidity ^0.4.21;


contract EIP20Interface {
    /* This is a slight change to the ERC20 base standard.
    function totalSupply() constant returns (uint256 supply);
    is replaced with:
    uint256 public totalSupply;
    This automatically creates a getter function for the totalSupply.
    This is moved to the base contract since public getter functions are not
    currently recognised as an implementation of the matching abstract
    function by the compiler.
    */
    /// total amount of tokens
    uint256 public totalSupply;

    /// @param _owner The address from which the balance will be retrieved
    /// @return The balance
    function balanceOf(address _owner) public view returns (uint256 balance);

    /// @notice send `_value` token to `_to` from `msg.sender`
    /// @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 transfer(address _to, uint256 _value) public returns (bool success);

    /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
    /// @param _from The address of the sender
    /// @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) public returns (bool success);

    /// @notice `msg.sender` approves `_spender` to spend `_value` tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @param _value The amount of tokens to be approved for transfer
    /// @return Whether the approval was successful or not
    function approve(address _spender, uint256 _value) public returns (bool success);

    /// @param _owner The address of the account owning tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens allowed to spent
    function allowance(address _owner, address _spender) public view returns (uint256 remaining);

    // solhint-disable-next-line no-simple-event-func-name
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

2
  • 1
    It would be helpful if you add information on how you test, what exactly do you test, which function do you call, with what parameters, what is the state before that, etc... Commented Jul 29, 2023 at 20:43
  • What I'm trying to do is test underflow with a test ERC20 token by sending 1 token from 0 tokens in the contract, I was using the transfer function (not TransferFrom) to test underflows with uint256, but even if I remove the require checks and changed the all the functions in the interface from public to external, it still doesn't work, I see that in opcode, 069 - revert" it fails.
    – 19216811
    Commented Jul 30, 2023 at 6:00

2 Answers 2

0

Functions in interfaces must be declared external.

Change the visibility of all your functions in your interface to external and it'll work.

From Solidity docs:

All declared functions must be external in the interface, even if they are public in the contract.

2
  • 1
    Well this is Solidity 0.4.21. I don't think this requirement applies there. And in any case the OP indicated that it compiles just fine. Commented Jul 29, 2023 at 20:41
  • It doesn't work @ChefAharoni
    – 19216811
    Commented Jul 30, 2023 at 6:02
0

Since you're using version 0.4.x there is no underflow protection by default. So things underflow unless checks are added explicitly.

So something like this underflows just fine:

pragma solidity 0.4.21;

contract A {
  uint public thing;
  function do_underflow() public {
    thing -= 1;
  }
}

I'm not sure why you experience a revert. My guesses are either 1) you accidentally use the wrong compiler somehow 2) there is some code left which reverts

8
  • I'm using the remix.ethereum.org website to do this, does that have to do with anything?
    – 19216811
    Commented Jul 30, 2023 at 11:39
  • No, that should be fine. I also wrote and tested the above snippet in Remix Commented Jul 30, 2023 at 13:37
  • Can you test my codes with a test ERC20 token that you have laying around in your wallet, and if you have discord or Whatsapp, can you send me a screenshot if it worked for you? You can just tell me here if you want
    – 19216811
    Commented Jul 30, 2023 at 13:39
  • Btw, normal underflows not involving ERC20 or in this case EIP20 works just fine. It underflows fine.
    – 19216811
    Commented Jul 30, 2023 at 14:13
  • (when I say test my code, I mean test underflowing test ERC20 tokens)
    – 19216811
    Commented Jul 30, 2023 at 14:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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