2

I am trying to create contract which can access functions of any ERC-20 standard token contract. At first, I'd like to get balance of given address.

I run private testnet using geth, I have deployed following token contract:

pragma solidity ^0.4.16;

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

contract TokenERC20 {

string public name;
string public symbol;
uint8 public decimals = 18;
uint256 public totalSupply;

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

event Transfer(address indexed from, address indexed to, uint256 value);
event Burn(address indexed from, uint256 value);

constructor(uint256 initialSupply, string tokenName, string tokenSymbol) public {
    totalSupply = initialSupply;
    balanceOf[msg.sender] = totalSupply;
    name = tokenName;
    symbol = tokenSymbol;
}

function _transfer(address _from, address _to, uint _value) internal {
    require(_to != 0x0);
    require(balanceOf[_from] >= _value);
    require(balanceOf[_to] + _value >= balanceOf[_to]);
    uint previousBalances = balanceOf[_from] + balanceOf[_to];
    balanceOf[_from] -= _value;
    balanceOf[_to] += _value;
    emit Transfer(_from, _to, _value);
    assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
}

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

function burn(uint256 _value) public returns (bool success) {
    require(balanceOf[msg.sender] >= _value);
    balanceOf[msg.sender] -= _value;
    totalSupply -= _value;
    emit Burn(msg.sender, _value);
    return true;
}

function burnFrom(address _from, uint256 _value) public returns (bool success) {
    require(_value <= allowance[_from][msg.sender]);
    require(balanceOf[_from] >= _value);
    balanceOf[_from] -= _value;
    allowance[_from][msg.sender] -= _value;
    totalSupply -= _value;
    emit Burn(_from, _value);
    return true;
}

function () public payable {
    revert();
}

}

Everything works fine, I tested it on geth successfuly.

Then I created following contract:

pragma solidity ^0.4.16;

contract ERC20 {
function totalSupply() constant returns (uint256 totalSupply);
function balanceOf(address _owner) constant returns (uint256 balance);
function transfer(address _to, uint _value);
event Transfer(address indexed _from, address indexed _to, uint _value);
}

contract TokenChecker {
address private senderAddress;
address private tokenAddress;

constructor(address _tokenAddress) public {
    senderAddress = msg.sender;
    tokenAddress = _tokenAddress;
}

function bal(address _address) public constant returns (uint256 balance) {
    ERC20 token = ERC20(tokenAddress);
    return token.balanceOf(_address);
}

function getThis() public constant returns (address thisAddress) {
    return address(this);
}

function tokenAdrs() public constant returns (address adrs) {
    return tokenAddress;
}

function () public payable {
    revert();
}
}

This one was deployed using this JavaScript:

var tokenCheckerFactory = eth.contract(COMPILED_WITH_SOLC_ABI)
var tokenCheckerCompiled = "0xCOMPILED_WITH_SOLC_BIN"
var _tokenAddress = "DEPLOYED_TokenERC20_ADDRESS"

var tokenChecker = tokenCheckerFactory.new(_tokenAddress, {from:eth.accounts[0],data:tokenCheckerCompiled,gas:2000000}, function(e, contract){
if(e) {
  console.error(e); // If something goes wrong, at least we'll know.
  return;
}

if(!contract.address) {
  console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");

} else {
  console.log("Contract mined! Address: " + contract.address);
  console.log(contract);
}
})

In geth, getThis() and tokenAdrs() are OK, but theres always 0 returned by bal() with any argument:

// geth console
> token.balanceOf(eth.accounts[0]) // instance of TokenERC20
2.0999984e+25
> tokenChecker.bal(eth.accounts[0])
0
> 

What is wrong with my code? Why can't TokenChecker interact with provided ERC-20 contract? Could it even communicate with random ERC-20 token by given its contract address like this? Thank you in advance.

Edit: When I omit constant at bal(), new transaction is submitted, nothing is returned to console. When i start mining, nothing special happens, only info about mining is shown. And view returns always 0 too.

3
  • I see have this defined in your code: ^0.4.16; but you are using features introduced after that version. Not saying this is your solution, but noting it for reference. They keyword constructor was introduced in 0.4.22 (2018-04-16) github.com/ethereum/solidity/blob/develop/Changelog.md May 30, 2018 at 19:54
  • I've copied and pasted your code into remix for testing via the JS VM. Your bal() worked and returned the proper value. I would assume the problem lies with your JS code, not Solidity. . May 30, 2018 at 20:20
  • @MSwezey Yes, this is my solution, I'm newcommer to solidity. I've changed version and still nothing. Constructor works, because when I pass argument, save it in constructor and return it from some function, passed address is displayed. I think error is at instantiation of ERC20. I've tried to create instance in constructor and function tokenSupply() public constant returns (uint256 totalSupply) { return token.totalSupply(); } and it returns 0 too as if instance of ERC20 didn't exist. May 31, 2018 at 16:27

2 Answers 2

0

Maybe because bal is set as constant? https://solidity.readthedocs.io/en/v0.4.21/contracts.html?highlight=constant#constant-state-variables

2
  • When I omit constant, new transaction is submitted, nothing is returned to console. When i start mining, nothing special happens, only info about mining is shown. May 30, 2018 at 13:22
  • And view returns always 0 too. May 30, 2018 at 13:34
0

function balanceOf(address _owner) constant returns (uint256 balance); is the problem

I think you must use as follows: function balanceOf(address _owner) public view returns (uint256);

Your Answer

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

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