8

One great thing about using a library is that the library code can be modified, and as long as the api function prototype stays the same, all we need to do is point to the new address of the updated library.

What happens if we need to add a new function, or change the function prototype of a library? Since the signature needs to be declared in the main contract, is there a trick to update those?

9

There isn't a way to change the ABI, since it is directly compiled in the source code. However, you can call functions manually if you don't mind breaking the type security of your contract.

For example, if your contract named foo is calling the bar method of another contract bazz, and you are concerned about the method name changing, you can implement something like this:

contract Foo {
    address bazz;
    string abiSignature;

    function Foo (address _bazz, string _abi) public {
        bazz = _bazz;
        abiSignature = _abi;
    }

    function updateABI (string _ABI) public {
        abiSignature = _ABI;
    }

    function callBazz(uint256 arg) public returns (bool bazzLib){
        bool bazzCall =  bazz.call(bytes4(sha3(abiSignature)), arg); //calls as a regular transaction
        bool bazzLib  = bazz.callcode(bytes4(sha3(abiSignature)), arg); //calls using "callcode" (like a library)
    }
}

By passing in a new string, such as bar(uint256), to updateABI, you can change the name of the function. By making multiple updateABI functions, each of which takes a different type of argument, you can make as many combinations of function names and arguments as you'd like.

Note that address.call is equivalent to sending a transaction to the address, and allows state changes, whereas callcode is equivalent to calling a library function, and the code is executed in the originating contract's environment.

Return values from call and callcode are boolean, either the call succeeded or the call failed. It is not possible to return a value from call since that would require the contract to know the return type beforehand. You may be able to pass storage pointers to callcode and retrieve data that way, but I need to do some testing.

  • Thank you! My follow-up question is that when we call a library functions whose ABI is declared in our contract, we can use the return values. Is there any way to define and use the return type of the call code in your example? The older version of the documentation says that it is not possible to do that. – shiso Jan 29 '16 at 14:23
  • Updated to address your question, and to note the callcode function as well. – Tjaden Hess Jan 29 '16 at 14:45

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.