2

I'm building a project which consists of two .sol files -> A.sol and B.sol. Now, A.sol contains an abstract contract definition of B, among other things, like this:

Contract B {
  function fnB() public;
}

similarly B.sol contains an abstract contract definition of A:

Contract A {
  function fnA() public;
}

This is been designed such to attain a certain 'message passing' between the two contracts. There is no inheritance between these two contracts, as the abstract contracts are being used for composition. Now the problem is, while using truffle, the '2_deploy_contracts.js' file imports artifacts for both using their contract name (instead of the .sol file name). An error is being thrown because of that since the truffle migrate command is considering the respective abstract contracts instead of the main contracts. Is there a workaround for this? The exact error thrown by 'truffle migrate' command is this:

"A" is an abstract contract or an interface and cannot be deployed.
   * Import abstractions into the '.sol' file that uses them instead of deploying them separately.
   * Contracts that inherit an abstraction must implement all its method signatures exactly.
   * A contract that only implements part of an inherited abstraction is also considered abstract.
    at Deployer._preFlightCheck 

The deploy js file looks something like this:

var A = artifacts.require("A");
var B = artifacts.require("B");

module.exports = function(deployer, network, accounts) {


    if(network == "ganache") {
        deployer.deploy(A, {gas:400000})
            .then(function(receipt) {
                return deployer.deploy(B, A.address, {from:accounts[0], gas:400000});
            })
            .catch(function(e){
                console.log(e);
            });   }};
8
  • Share your migration scripts please (or at least the 2nd one - 2_deploy_contracts.js). Jan 9, 2019 at 10:54
  • BTW, you should use interfaces there, not contracts. Jan 9, 2019 at 10:55
  • code var A = artifacts.require("A"); var B = artifacts.require("B"); module.exports = function(deployer, network, accounts) { if(network == "ganache") { deployer.deploy(A, {gas:400000}) .then(function(receipt) { return deployer.deploy(B, A.address, {from:accounts[0], gas:400000}); }) .catch(function(e){ console.log(e); }); } };code
    – Kombo
    Jan 9, 2019 at 11:03
  • Good, now share your contracts as well please. Jan 9, 2019 at 11:05
  • The problem here (I believe) is that var A is catching the abstract contract A residing in B, and var B is catching the abstract contract B residing in A, instead of taking the corresponding main definitions.
    – Kombo
    Jan 9, 2019 at 11:06

1 Answer 1

0

This has been solved by giving a different contract name for the constituent abstract contracts in the following manner:

    Contract BInterface {
  function fnB() public;
}

Contract A {
... codes for contract A ...
... codes for contract A ...

BInterface private bInterface;
bInterface = new bInterface(<address of B>);
}

also the same setup for contract B:

Contract AInterface {
      function fnA() public;
    }

    Contract B {
    ... codes for contract B ...
    ... codes for contract B ...

    AInterface private aInterface;
    aInterface = new aInterface(<address of A>);
    }

now there is no collision between the names of abstract contract and the main contracts.

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.