6

I want to call the method getdata() and retrieve the returns value to use in another contract. But the call only returns bool on success or failure.

  1. How do I get the return value from getdata() from caller() function in contract extra .

  2. How do I modify the state:- send transaction to setdata(uint,bytes32) from contract extra and change the state of data1 and data2.

Above problem are based on following code.

pragma solidity 0.4.21;
contract Base{
    uint public data1;
    bytes32 public data2;

    function setdata(uint a, bytes32 b){
        data1 = a;
        data2 = b;
    }
    function getdata() public view returns(uint){
        return data1 ;
    }

}
contract extra{
   bool public retrive;
   bool public retrive_setter;
   address public baseaddress = 0xca598f876f79a5f8f479bfa1dcc8f4f2dffbd5c2;
   uint a = 5;
   bytes32 b ="Lina";
   function caller(){
        retrive = baseaddress.call.gas(10000)(bytes8(keccak256("getdata()")));
        retrive_setter = baseaddress.call.gas(1000000)(bytes24(keccak256("setdata(uint, bytes32)")),a,b);
   }
}

Either you can Modify the code and give your answer. I saw this problem on many devs who are newby. Every possible answers are acceptable.

simply on testing using Remix . 

retrive 0:bool: true
retrive_setter 0:bool: false

2 Answers 2

1
pragma solidity 0.4.21;

contract Base {

    uint public dataA;
    bytes32 public dataB;

    function setAB(uint a, bytes32 b) public {
        dataA = a;
        dataB = b;
    }

    function getA() public view returns(uint) {
        return dataA ;
    }

    function getB() public view returns(bytes32) {
        return dataB ;
    }

}

contract Extra {

   Base base;

   function Extra() public {
       base = new Base();
   }

   function getBaseAddres() public view returns(address) {
       return address(base);
   }

   function baseGetA() public view returns(uint) {
        return base.getA();
   }

   function baseGetB() public view returns(bytes32) {
       return base.getB();
   }

   function baseSetAB(uint a, bytes32 b) public returns(bool success) {
       base.setAB(a,b);
       return true;
   }
}

Hope it helps.

UPDATE

The above example just creates a new Base with each deployment of Extra to show them talking in the simplest manner I can think of. Another way to go is to deploy a Base separately. It's location can then be relayed to Extra.

You could pass it into the constructor:

Base base;

function Extra(address baseAddress) public {
  base = Base(baseAddress);
}

It's not checking anything, merely assuming the deployer knows what they're doing. You can also make the address of the base something the owner can change.

Add an owner to the state and the constructor:

address public owner;

function Extra(address baseAddress) public {
  base = Base(baseAddress);
  owner = msg.sender;
}

Add a modifier (after state and before constructor, by convention) to restrict access to the sensitive function.

modifier onlyOwner {
  require(msg.sender == owner);
  _;
}

Add a restricted function to change the base.

function changeBase(address newBase) public onlyOwner returns(bool success) {
  base = Base(newBase);
  return true;
}

You might want to know the address of the Base:

return address(base);

It would be good practice to add event emitters to the state-changing functions in both contracts.

3
  • 1
    thanks for your answer. when you create the new instance of Base then it genetates new address and which is different then actual contract address of base. Now if you set the data to that newly created contract address then how it resides to original contract. I tasted this code but while trying to get the value from base contract where value is set through extra contract. this means it deploy the contract in different address again . To avoid this I want to use sendTransaction and call from extra contract . I think you get that.
    – Gopal ojha
    Apr 11, 2018 at 4:18
  • Sure. I thought you might say that. I didn't want the example overloaded with too many concerns that might distract from the main question. I added way to connect with a deployed Base to my original answer, along with some other concerns I omitted intentionally. Apr 11, 2018 at 4:33
  • There's a little more choreography involved. First deploy a Base, then note the address, then deploy an Extra passing in the address of the Base. If it gets munged up, you can deploy another Base and inform Extra about it. You obviously want to protect that function. In the example, only the same user who deployed the contract would be permitted to do it. Apr 11, 2018 at 4:38
4

First of all, since you know the signatures of the functions you are calling in the Base contract, you can bypass the use of call and directly call them.

pragma solidity 0.4.21;

contract Base{
    uint public data1;
    bytes32 public data2;

    function setdata(uint a, bytes32 b){
        data1 = a;
        data2 = b;
    }
    function getdata() public view returns(uint){
        return data1 ;
    }

}

contract Extra {
   uint public data;
   Base public baseaddress = Base(0xca598f876f79a5f8f479bfa1dcc8f4f2dffbd5c2);

   function caller(){
        data = baseaddress.getdata();
   }

   function setter(uint _integer, bytes32 _bytes) {
       baseaddress.setdata(_integer, _bytes);
   }
}

With this, your two questions have been answered. You will notice I have changed the type of baseaddress. If you simply use address, your contract thinks it's simply a "normal" address and thus, doesn't have functions. So, not only it has to be of the type of the contract you are calling, but regarding its value, you need to do the same thing, and use the "constructor" by passing the address of the contract.

2
  • 1
    thanks, this is one way I used already to transaction with other contract but for huge data there is gas limit issue. If you have way to avoid gas limit issue please proceed.
    – Gopal ojha
    Apr 11, 2018 at 4:21
  • @Gopalojha in that situation one of the best things you can do is work on the efficiency of the contract code itself.
    – CJ Jacobs
    May 15, 2018 at 3:16

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.