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);
            });   }};
  • Share your migration scripts please (or at least the 2nd one - 2_deploy_contracts.js). – goodvibration Jan 9 at 10:54
  • BTW, you should use interfaces there, not contracts. – goodvibration Jan 9 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 at 11:03
  • Good, now share your contracts as well please. – goodvibration Jan 9 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 at 11:06
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, privacy policy and cookie policy

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