[Ethereum] Error calling a function from another contract: Member “*” not found or not visible after argument-dependent lookup in type

soliditytruffle

I'm having trouble compiling a contract that calls a function of an imported contract.

SilverCoin.sol:

pragma solidity ^0.4.11;

contract SilverCoin {
    function abc() constant returns (uint) {
        return 0;
    }
}

Banker.sol:

pragma solidity ^0.4.11;

import "./SilverCoin.sol";

contract Banker {
    function abc_1() constant returns (uint) {
        return SilverCoin.abc();
    }
}

Migration script for truffle:

var SilverCoin = artifacts.require("./SilverCoin.sol");
var Banker = artifacts.require("./Banker.sol");

module.exports = function(deployer) {
  deployer.deploy(SilverCoin);
  deployer.deploy(Banker);
};

Error:

$ truffle compile
Compiling ./contracts/Banker.sol...
Compiling ./contracts/SilverCoin.sol...

/path/to/file/contracts/Banker.sol:7:16: : Member "abc" not found or not visible after argument-dependent lookup in type(contract SilverCoin)
        return SilverCoin.abc();
               ^------------^
Compiliation failed. See above.

How do I fix this?

Best Answer

You are making a reference to the contract itself while you should refer to the contract instance (deployed to a given address).

First of all, you need to store the contract instance address into the Banker contract. For example, you can pass the SilverCoin instance address into the Banker constructor:

contracts/Banker.sol

contract Banker {
    address silverCoinAddress;

    function Banker(address _silverCoinAddress) {
        silverCoinAddress = _silverCoinAddress;
    }

(...)

Then you have to refer to this particular instance when you make the call

contracts/Banker.sol

(...)
    function abc_1() constant returns (uint) {
        SilverCoin instanceSilverCoin = SilverCoin(silverCoinAddress);
        return instanceSilverCoin.abc();
    }
}

Finally, when you deploy SilverCoin and Banker, you can pass the SilverCoin contract address in the Bank contract deployment:

migrations/2_deploy_contracts.js

var SilverCoin = artifacts.require("./SilverCoin.sol");
var Banker = artifacts.require("./Banker.sol");

module.exports = function(deployer) {
    deployer.deploy(SilverCoin).then(function() {
        return deployer.deploy(Banker, SilverCoin.address);
    }).then(function() { })
};

And finally, a quick test to validate all of that

test/test.js

var Banker = artifacts.require("./Banker.sol");
contract('Banker', function(accounts) {
    it("should return 0", function() {
            return Banker.deployed().then(function(instance) {
                return instance.abc_1.call();
            }).then(function (result) {
                assert.equal(result.toNumber(), 0, " must be 0");
            });
    });
});

Command Result:

$ truffle migrate --compile-all --reset
Compiling .\contracts\Banker.sol...
Compiling .\contracts\Migrations.sol...
Compiling .\contracts\SilverCoin.sol...
Writing artifacts to .\build\contracts

Using network 'development'.

Running migration: 1_initial_migration.js
  Replacing Migrations...
  Migrations: 0xc85d4eaed6a61b5879176d9a833f1efdb8427024
Saving successful migration to network...
Saving artifacts...
Running migration: 2_deploy_contracts.js
  Replacing SilverCoin...
  SilverCoin: 0x65a26284f2a38a624270990f19b153c9edd6497a
  Replacing Banker...
  Banker: 0x733349e85343d15f151e16f413541f6e8c963792
  Replacing SilverCoin...
  SilverCoin: 0x5cec7be3d232d59a7e7eb89a5f0cfaebd15125b4
  Replacing Banker...
  Banker: 0x4baa2e28a7670e434bf1cca3732fffb0e9b21a38
Saving successful migration to network...
Saving artifacts...

$ truffle test
Using network 'development'.
  Contract: Banker
    √ should return 0 (234ms)
  1 passing (297ms)

I pushed the code in Git: https://github.com/gjeanmart/stackexchange/tree/master/20750

Related Topic