0

So, I have a contract, let's call it contract A, that needs to make call to the Dai contract (referred to as Cash). This contract already exists on Kovan, so in 2deploy_contracts.js I simply set its address and pass it to my contract as a constructor variable:

var contractA = artifacts.require("./contractA.sol");
var cashAddress = 0x..;

module.exports = function(deployer, network) {
 if(network === "kovan") {
 deployer.deploy(contractA, cashAddress);
 }
}

contractA.sol, in addition to the contractA contract, has a Cash interface which describes all the functions of this already existing contract:

interface Cash 
{
    function approve(address _spender, uint256 _amount) external returns (bool);
    function balanceOf(address _ownesr) external view returns (uint256);
    function faucet(uint256 _amount) external;
    function transfer(address _to, uint256 _amount) external returns (bool);
    function transferFrom(address _from, address _to, uint256 _amount) external returns (bool);
}

And within the contractA constructor we have:

Cash cash = Cash(cashAddress);

The cash variable is then interacted with at various times, for example:

cash.transfer(_to,_amount);) 

All well and good. The problem is that for local ganache testing, there is not an already deployed Cash contract, so I need to deploy it myself. I have created Cash.sol: (Im aware its shitty and not ERC20, Im only using it for local testing):

pragma solidity ^0.5.0;

contract Cash 
{

mapping (address => uint256) balances;
mapping (address => mapping (address => uint256 ) ) allowances;

function approve(address _spender, uint256 _amount) external returns (bool)
{
    allowances[_spender][msg.sender] = _amount;
    return true;
}

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

function faucet(uint256 _amount) external
{
    balances[msg.sender] = _amount;
}

function transfer(address _to, uint256 _amount) external returns (bool)
{   
    require (balances[msg.sender] >= _amount, "Insufficient balance");
    balances[msg.sender] = balances[msg.sender] - _amount;
    balances[_to] = balances[_to] + _amount;
    return true;
}

function transferFrom(address _from, address _to, uint256 _amount) external returns (bool)
{
    require (allowances[msg.sender][_from] >= _amount, "Insufficient approval");
    require (balances[_from] >= _amount, "Insufficient balance");
    balances[_from] = balances[_from] - _amount;
    balances[_to] = balances[_to] + _amount;
    return true;
}

}

And in my 2deploy_contracts.js I need to pass the address of the newly created contract to contractA as follows:

var Cash = artifacts.require("./Cash.sol");
var contractA = artifacts.require("./contractA.sol");
var cashAddress = 0x..;

module.exports = function(deployer, network) {
 if(network === "development") {
 deployer.deploy(Cash).then((deployedCash) => {
      return deployer.deploy(ContractA, deployedCash.address)
 }
}

But when I try and do development deploy, I get the "Cash is an abstract contract or an interface and cannot be deployed" error.

I'm aware that Cash is an abstract contract (because its just an interface) within contractA.sol. But in 2deploy_contracts.js the object 'Cash' points to Cash.sol, NOT to the interface within contractA.sol. So why is truffle making a fuss?

I thought maybe the problem was that there are two different contracts with the same name- Cash. So for the 'local' version I changed the contract name to localCash (both the file name, and the name of the contract). Then it deploys fine, but since contractA has an interface for Cash and not localCash it can't find the contract at the given address. So it would seem that the name of the interface MUST match the name of the full deployed contract.

Wat do?

0

Change this:

contract Cash

To this:

import './Cash.sol';
contract CashMockup is Cash

And this

var Cash = artifacts.require("./Cash.sol");

To this:

var Cash = artifacts.require("CashMockup");

For future reference, keep in mind that while the Solidity's import statement imports one or more contracts by file-name, the Truffle's artifacts.require statement imports a single contract by contract-name.

| improve this answer | |
  • Thanks buddy for your rapid response!! First of all, do you mean var Cash = artifacts.require("./CashMockup"); instead of var Cash = artifacts.require("CashMockup"); (for the sake of consistency :) )? Anyway I have tried this and the error I get is "Cash not found on network ID: 1579607485454" – Andrew Stanger Jan 21 at 12:11
  • Also, I'm a bit confused as to what should go in the rest of the CashMockup.sol file after contract CashMockup is Cash- the same as what is in Cash.sol? Nothing? Something in between? – Andrew Stanger Jan 21 at 12:13
  • @AndrewStanger: You're welcome. With regards to your first question - please read the paragraph at the bottom of my answer. – goodvibration Jan 21 at 12:15
  • @AndrewStanger: With regards to your second question - it's hard to answer it when you haven't specified any of your file names, leaving the reader to guess which piece of code is located where. Personally, I have guessed that interface Cash is located inside file Cash.sol. Did I guess wrong? In any case, I wrote "replace contract Cash with contract CashMockup is Cash", so you obviously need to add under contract CashMockup is Cash everything that you originally had under contract Cash. – goodvibration Jan 21 at 12:18
  • @goodvibrations Re first question- apologies, my question made no sense, I had not acknowledged the lack of .sol on the end, I thought you had just omitted the "./" accidentally. However, still a bit confused- the line var Cash = artifacts.require("CashMockup") - where does truffle look for the contract named CashMockup if I'm not specifying a filename? – Andrew Stanger Jan 21 at 13:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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