Skip to main content
2nd param to f1 became a uint
Source Link
eth
  • 86.5k
  • 53
  • 287
  • 411
contract A { // This doesn't have to match the real contract name. Call it what you like.
   function f1(bool arg1, intuint 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);
  }
}

Also, if f1 encounters an exception (imagine its implementation is function f1(bool arg1, intuint 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;
       }
   }
}

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

if (!addressOfA.call(bytes4(sha3keccak256("f1(bool, int256uint256)")), true, 3)) {
    throw;
}
contract A { // This doesn't have to match the real contract name. Call it what you like.
   function f1(bool arg1, int 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);
  }
}

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

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

if (!addressOfA.call(bytes4(sha3("f1(bool, int256)")), true, 3)) {
    throw;
}
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);
  }
}

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;
       }
   }
}

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).

if (!addressOfA.call(bytes4(keccak256("f1(bool, uint256)")), true, 3)) {
    throw;
}
Source Link
eth
  • 86.5k
  • 53
  • 287
  • 411

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, int 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, int arg2) returns(uint) { throw; }), the exception is propagated and my_a.f1 will also throw and it will revert a transaction that invoked doYourThing.

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(sha3("f1(bool, int256)")), 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(sha3("f1(bool, int256)")), true, 3)) {
    throw;
}