0

I apologize if it is a simple question. I tried to create a simple contract interaction. I've tried to follow instructions on https://ethereum.stackexchange.com/questions/51760/contract-interaction, docs, and another examples to create a simple contract interaction in solidity 0.5.16. There are two contracts, one is a hello-world contract, called con_H (H of "hello") and owns the helloworld() function. The other one is a contract "A" that calls the helloworld function of con_H. The point is that remix-ide throws an error that I find strange: call to con_A.fun_A1 errored: VM error: revert. revert The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information.

The code is the following one:

pragma solidity ^0.5.16;

contract con_H {
  function helloWorld() external pure returns (string memory) {
    return "Hello, World!";
  }
}


contract con_A {
    con_H ins_H;
    
    function fun_A1() external view returns (string memory) {
        return ins_H.helloWorld();
    }
}

I've also tried for initial lines of con_A:

contract con_A {
    con_H ins_H = con_H(msg.sender);
    ...
}

with msg.sender address with enough balance of 100 test-ETH.

The only way I manage it to work is deploying aside con_H at a given direction 0x..123 and then force the instance H inside con_A with that exact address: con_H ins_H = con_H(0x..123);

How should be done? suggestions..?

2
  • In your first example, the con_H ins_H variable is not initialized, i.e., it is pointing to address 0. In your second example, it is wrongfully initializing, i.e., it is not pointing to an address where a con_H instance has been previously deployed. Commented Nov 19, 2020 at 7:19
  • You can do something like con_H ins_H = new con_H();, which will deploy a con_H instance internally when you deploy con_A. Alternatively, you can deploy a con_H instance yourself, and then pass its address to con_A when you deploy it. Commented Nov 19, 2020 at 7:20

1 Answer 1

1

This (below) casts ins_H as Type: con_H but it doesn't instantiate it at an address. In case that isn't clear, it follows the same semantics as uint x; where x will always be cast as a uint but its value is still 0 because we haven't set it to anything else.

contract con_A {
    con_H ins_H;
    
    function fun_A1() external view returns (string memory) {
        return ins_H.helloWorld();
    }
}

So, far so good, but we have to assign an address to ins_H because it could be anywhere and there could be more than one. AS @goodVibration notes, your contract doesn't do it, so it's address(0) and that won't do. You can:

Pass it in when con_A is deployed (useful for deploying many con_A to connect to one con_H:

constructor (address h) public { // runs once on deployment
  ins_H = con_H(h); // notice we, again, cast the right-hand side as `con_H` to match the left
}

Kill two birds with one stone by deploying con_H when con_A is deployed. That works if there is 1:1 con_A:con_H.

constructor (address h) public {
  ins_H = new con_H(); // one-liner deploys AND stores the address of the instance
}

You can even change it:

function newCon_H(con_H h) public {
  ins_H = h;
}

You can also let your con_H be the hub in a hub & spoke arrangement and let it deploy as many con_A as it likes, and have them use the msg.sender to figure it out. I took the liberty of renaming a few things to make it closer to the style guide.

pragma solidity 0.5.16;

contract ConH {
 
  event newConADeployed(ConA conA);
  
  function helloWorld() external pure returns (string memory) {
    return "Hello, World!";
  }
  
  function newConA() external returns(ConA a) {
      a = new ConA();
      emit newConADeployed(a);
  }
}

contract ConA {
    ConH insH;
    
    constructor () public {
        insH = ConH(msg.sender); // it's the hub
    }
    
    function fun_A1() external view returns (string memory) {
        return insH.helloWorld();
    }
}

You only need to "deploy" ConH. Then, use its newConA() function to deploy one of those from this simple "Factory" and then, in Remix, do ConA "At Address" where you give it the address of the contract the hub/factory made. That sort of structure can deploy lots of "spokes" that talk to one "hub."

I added the event emitter so you have a way to see that address - the little down arrow right of the blue transaction "Debug" button in the console output.

Hope it helps.

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.