In Solidity, one can create a bytes array and then use address.call(bytesData) to create a new transaction matching a function signature, as well as passing through the arguments.

One can do address.call(bytes4(bytes32(sha3("someFunction(uint256,address)"))), 10, 0x42) for example. One can dynamically craft the function signature by just passing another bytes variable. But how does one make it possible to have dynamic arguments as well?

Something like this. But functionSig & encoded_params are created IN Solidity.

function doSomething() {
    if(someCondition) {
        bytes memory data = functionSig + encoded_params.

I want to be able to IN Solidity craft this. Not from the outside using web3 or some of the other encoding functions? Is there an easy way to do this? Or should a Solidity encoding function be written that converts the arguments to bytes and creates this message data?

  • Are you aware that you can define abstract contracts that have the signatures you need to call? Doing what you describe is possible, but it's not typesafe, and it's going to cost a lot of gas. May 24 '16 at 10:49
  • I'm aware of abstract contracts, but I want to be able to dynamically call any function with arbitrary amount arguments from within Solidity. It might cost a lot of gas, but I'll do tradeoffs when I get to that point. May 24 '16 at 11:59
  • Can you elaborate on your use-case? Where will you get the ABI of the function from, and in what form? May 24 '16 at 12:01
  • Contract A -> Contract B -> Contract C. Contract A calls function in contract B, but then also has to call a function with specific data in C without hardcoded function names or parameters. Thus when calling contract B, I need send along a raw_data when calling contract C. I can craft this with web3, but I'm using Solidity for testing and thus need to create it in Contract A scope already. May 24 '16 at 14:02
  • 1
    How does contract a learn of the types and values of the parameters to the function in contract C? May 24 '16 at 14:10

To do this you will need to implement the appropriate RLP encoding for the arguments you wish to pass.

RLP Spec: https://github.com/ethereum/wiki/wiki/RLP

For simple non-array fixed length types this is as simple as just concatenating the func_sig + arg_1_as_bytes + arg_2_as_bytes into a single bytes value and passing this into address.call(...).

For complex types like arrays, bytes, string or structs, you will have to do more complex things to construct the appropriate RLP bytes representation for your data.

There is a story in the solidity pivotal tracker to create encode and decode functions that will do this encoding for you.

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.