23

I want to know how to instantiate an existing contract deployed on the blockchain using its address. e.g:

contract A {
    function f1()
    {}
}

A is deployed on the blockchain, and in contract B I want to call the function f1() and get its return. e.g:

contract B {
    address contrac_A=0x123456;

    //call f1 from A
}

How should I call it using the address of A?

15

If the deployed contract doesn’t adhere to the ABI, but you know the contract signature (name and argument types) You could use :

contract_address.call(bytes4(sha3("function_name(types)")),parameters_values)

for example : contrac_A.call(bytes4(sha3("f()")) while there is no input no parameters in your exemple.

replace contract_address,function_name,parameters_values by your credentials.

Edit : as sha3 has been deprecated it's better to use instead keccak256 as following: bytes4(keccak256("f()")).

Furthermore, since solidity 0.4.22, the global functions abi.encode(), abi.encodePacked(), abi.encodeWithSelector() and abi.encodeWithSignature() have been defined to encode structured data and therefore helping us to build valid call (they return the needed 4 bytes) as follow :

contract_address.call.value(1 ether).gas(10)(abi.encodeWithSignature("register(string)", "MyName"));

Documentation:

https://github.com/ethereum/wiki/wiki/Solidity-Features#generic-call-method

https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#function-selector

  • I have seen a function as follows. function transfer(address _to, uint _value, bytes _data, string _custom_fallback) returns (bool success) { ContractReceiver receiver = ContractReceiver(_to); receiver.call.value(0)(bytes4(sha3(_custom_fallback)), msg.sender, _value, _data); return true; } .....What's the use of value(0) here?? – Crissi Mariam Robert Oct 12 '17 at 11:52
  • 1
    f.call.value(X) is calling f with X wei check ethereum.stackexchange.com/questions/6707/… – Badr Bellaj Oct 12 '17 at 13:18
21

Use an abstract contract (preferred)

Further clarifications to @Edmund's answer:

contract A { // This doesn't have to match the real contract name. Call it what you like.
   function f1(bool arg1, uint arg2) returns(uint); // No implementation, just the function signature. This is just so Solidity can work out how to call it.
}

contract YourContract {
  function doYourThing(address addressOfA) returns(uint) {
    A my_a = A(addressOfA);
    return my_a.f1(true, 3);
  }
}

This shows using the return value from f1.

Also, if f1 encounters an exception (imagine its implementation is function f1(bool arg1, uint arg2) returns(uint) { throw; }), the exception is propagated and my_a.f1 will also throw and it will revert a transaction that invoked doYourThing.

In practice, you'll have 3 files.

AbstractA.sol contains:

contract A {
   function f1(bool arg1, uint arg2) returns(uint); // No implementation, just the function signature. This is just so Solidity can work out how to call it.
}

YourContract.sol contains:

import "AbstractA.sol"

contract YourContract {
  function doYourThing(address addressOfA) returns(uint) {
    A my_a = A(addressOfA);
    return my_a.f1(true, 3);
  }
}

A.sol contains:

contract A {
   // implementation of f1
   function f1(bool arg1, uint arg2) returns(uint) {
       if (arg1) {
           throw;
       } else {
           return arg2;
       }
   }
}

Limitations of using call

call is suggested in @Badr's answer but should be used very carefully. Solidity docs state:

All three functions call, delegatecall and callcode are very low-level functions and should only be used as a last resort as they break the type-safety of Solidity.

Also, the return value of f1 can't be obtained by using call like addressOfA.call(bytes4(keccak256("f1(bool, uint256)")), true, 3) because call only returns a bool (false if the call encounters an exception).

This means that the exception must be propagated manually like:

if (!addressOfA.call(bytes4(keccak256("f1(bool, uint256)")), true, 3)) {
    throw;
}
2
contract A { // This doesn't have to match the real contract name. Call it what you like.
   function f1(){} // No implementation, just the function signature. This is just so Solidity can work out how to call it.
}

contract YourContract 
  function doYourThing() {
    A my_a = A(contract_A);
    my_a.f1();
  }
}
  • they are not in the same contract file the compiler will not recongnise the contract A so no A my_a = A(contract_A); – Sig Touri Oct 31 '16 at 14:47
  • Put them in the same file. You don't need the full implementation, just the function signatures. – Edmund Edgar Oct 31 '16 at 14:51
  • I am asking about an alredy deployed contract. – Sig Touri Oct 31 '16 at 14:58
  • You don't need the full source code. You must know the name of the method you're calling and what parameters it takes, so stick that in a contract definition called A, leave the function body empty and plonk it above the contract that's going to call it. – Edmund Edgar Oct 31 '16 at 15:33
  • Edited my answer to provide context. That really is all you need, it doesn't matter whether the contract is already deployed or not. If your original code won't compile, check the spelling of "function". – Edmund Edgar Oct 31 '16 at 22:48

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.