0

I try to learn solidity and i have a problem. I've created a base token and i want to call the balanceof method from this token in another contract. In Solidity Remix i get :

call to BaseTokenBet.getTokenBalance errored: VM error: revert.
revert  The transaction has been reverted to the initial state.
Note: The constructor should be payable if you send value.  Debug the transaction to get more information. 

My BaseToken :

pragma solidity >=0.4.22 <0.6.0;

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

contract BaseToken {
// 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 generates a public event on the blockchain that will notify 
 clients
event Approval(address indexed _owner, address indexed _spender, 
uint256 _value);

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

/**
 * Constructor function
 *
 * Initializes contract with initial supply tokens to the creator of 
 the contract
 */
constructor() public {
    totalSupply = 10000 * 10 ** uint256(decimals);  // Update total 
    supply with the decimal amount
    balanceOf[msg.sender] = totalSupply;                // Give the 
    creator all initial tokens
    name = "BaseToken";                                   // Set the 
   name for display purposes
    symbol = "BASETOKEN";                               // Set the 
 symbol for display purposes
}

function getBalance() public pure returns (string memory){
   return  "some string";
}

/**
 * Internal transfer, only can be called by this contract
 */
function _transfer(address _from, address _to, uint _value) internal {
    // Prevent transfer to 0x0 address. Use burn() instead
    require(_to != address(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 recipient
    balanceOf[_to] += _value;
    emit 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 returns (bool 
 success) {
    _transfer(msg.sender, _to, _value);
    return true;
}

/**
 * Transfer tokens from other address
 *
 * Send `_value` tokens to `_to` on behalf of `_from`
 *
 * @param _from The address of the sender
 * @param _to The address of the recipient
 * @param _value the amount to send
 */
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;
}

/**
 * Set allowance for other address
 *
 * Allows `_spender` to spend no more than `_value` tokens on your 
  behalf
 *
 * @param _spender The address authorized to spend
 * @param _value the max amount they can spend
 */
function approve(address _spender, uint256 _value) public
    returns (bool success) {
    allowance[msg.sender][_spender] = _value;
    emit Approval(msg.sender, _spender, _value);
    return true;
}

/**
 * Set allowance for other address and notify
 *
 * Allows `_spender` to spend no more than `_value` tokens on your 
 behalf, and then ping the contract about it
 *
 * @param _spender The address authorized to spend
 * @param _value the max amount they can spend
 * @param _extraData some extra information to send to the approved 
  contract
 */
function approveAndCall(address _spender, uint256 _value, bytes memory 
 _extraData)
    public
    returns (bool success) {
    tokenRecipient spender = tokenRecipient(_spender);
    if (approve(_spender, _value)) {
        spender.receiveApproval(msg.sender, _value, address(this), 
   _extraData);
        return true;
    }
}

/**
 * Destroy tokens
 *
 * Remove `_value` tokens from the system irreversibly
 *
 * @param _value the amount of money to burn
 */
function burn(uint256 _value) public returns (bool success) {
    require(balanceOf[msg.sender] >= _value);   // Check if the sender 
 has enough
    balanceOf[msg.sender] -= _value;            // Subtract from the 
 sender
    totalSupply -= _value;                      // Updates totalSupply
    emit Burn(msg.sender, _value);
    return true;
}

/**
 * Destroy tokens from other account
 *
 * Remove `_value` tokens from the system irreversibly on behalf of 
 `_from`.
 *
 * @param _from the address of the sender
 * @param _value the amount of money to burn
 */
function burnFrom(address _from, uint256 _value) public returns (bool 
 success) {
    require(balanceOf[_from] >= _value);                // Check if the 
 targeted balance is enough
    require(_value <= allowance[_from][msg.sender]);    // Check 
    allowance
    balanceOf[_from] -= _value;                         // Subtract 
     from the targeted balance
    allowance[_from][msg.sender] -= _value;             // Subtract 
    from the sender's allowance
    totalSupply -= _value;                              // Update 
    totalSupply
    emit Burn(_from, _value);
    return true;
}

}

In my second contract i try to call balanceOf:

pragma solidity >=0.4.22 <0.6.0;

import "./BaseToken.sol";

contract BaseTokenBet {

BaseToken public baseToken;

address public owner;

constructor() public {
    owner = msg.sender;
    baseToken = BaseToken(owner);
}

function getOwner() public view returns (address)  {
  return owner ;
}

function getBaseToken() public view returns (BaseToken)  {
  return baseToken ;
}


function getTokenBalance() public view returns (uint256){
    return baseToken.balanceOf(owner);
}

 }

When i call getTokenBalance i get the error posted above.

Can someone put on the right track with this?

1 Answer 1

1

With this:

baseToken = BaseToken(owner);

You are setting baseToken to point to a BaseToken contract at the address given by owner.

Needless to say, there is no BaseToken contract deployed at that address.

So to begin with, you need to change it to:

baseToken = new BaseToken();

Or to:

baseToken = BaseToken(someAddr);

Where someAddr is the address of an already deployed BaseToken contract.

You can, for example, pass someAddr to the constructor of the BaseTokenBet contract.

7
  • When i deploy my BaseToken the amount in the constructor is sent to the owner that created the contract (if i call directly the balanceOf method from Remix Ide with the current address i see the amount generated by the constructor). if i call new baseToken = new BaseToken(); will not this generate a new token contract everytime? The BaseToken will be deployed in advance. The address calling getTokenBalance should have already some tokens or should have 0 tokens.
    – user978123
    Mar 3, 2019 at 17:45
  • @user978123: "to the owner who created the contract" - well, that owner is NOT the address that you pass in baseToken = BaseToken(owner). That owner (msg.sender) is the contract which executes this statement (i.e., the BaseTokenBet instance). Mar 3, 2019 at 17:56
  • Yes, i understand that owner is the one executing the contract. But also this is the owner that deployed the BaseToken contract. This owner has the supply of my BaseToken. If i call the method balanceOf from the deployed BaseToken passing the current's owner address i get the value of the supply. I want to get the same value, calling the balanceOf method from my second contract. Sorry for my noob questions.
    – user978123
    Mar 3, 2019 at 17:56
  • @user978123: That will deploy a new BaseToken instance (whose owner will be your BaseTokenBet instance, as I mentioned in the previous comment). I am therefore guessing that you probably want to use the other option that I have suggested. Mar 3, 2019 at 17:57
  • Tried second approach : baseToken = new BaseToken(0xfd6681fffbedfe8bb69efdf62898dfabbf1ad406); browser/BaseTokenBet.sol:13:21: TypeError: Wrong argument count for function call: 1 arguments given but expected 0. baseToken = new BaseToken(0xfD6681fffBEDFE8bb69eFdf62898dfAbbF1Ad406); ^-------------------------------------------------------^
    – user978123
    Mar 3, 2019 at 18:03

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.