18

I have 2 contracts, Parents and Child which has a public string variable - name.

contract Child {
    string public name;
    function child (string _name){
       name = _name;
    }
}

Parents needs to get that name:

contract Parents {
    string public childName;
    Child child;
    function Parents(address _childAddress){
        child = Child(_childAddress);
        childName = child.name();  // I also tried child.name
    }
}

But I'm getting the following error:

Error: Type tuple() is not implicitly convertible to expected type string storage ref.
        childName = child.name();

So I've tried to create another function in Child that will return a string:

function getName() returns (string name) {
    return name;
}

And in Parents I've changed

childName = child.name();  into--->  childName = child.getName();

But I keep getting the same error. Any ideas? As always, your help is appreciated.

2 Answers 2

12

Variable-sized data that is returned by one contract, cannot be read by another contract.

Parents is trying to read a string from Child and thus the error.

Reference:

The EVM is unable to read variably-sized data from external function calls... Note that on the other hand, it is possible to return variably-sized data, it just cannot be read from within the EVM.

EIP 5 is a proposed update of the EVM that's needed to allow contracts to read dynamically-sized data returned by other contracts.

1
  • is this still the case as i think this works now. i am in solidity 0.8.17. can you confirm?
    – user566245
    Feb 18 at 21:16
3

Here is a version that compiles.

As the address type is more easily converted into the string type, I've stored the original addresses as the address types, and added a function to convert from address to string when required.

contract Child {
    address public addr;

    function child (address _addr) {
        addr = _addr;
    }    

    function getAddress() returns (address) {
        return addr;
    }

    function toBytes(address x) returns (bytes b) {
        b = new bytes(20);
        for (uint i = 0; i < 20; i++) {
            b[i] = byte(uint8(uint(x) / (2**(8*(19 - i)))));
        }
    }

    function getName() returns (string) {
        return string(toBytes(addr));
    }
}

contract Parents {
    address public childAddr;
    Child child;

    function Parents(address _childAddress) {
        child = Child(_childAddress);
        childAddr = child.getAddress();
    }
}

I have stored all addresses as the address type.

I have added the function toBytes(...) to convert from the address type to the bytes type (from How to convert an address to bytes in Solidity?).

And you can easily convert from bytes to string by casting using string(...).

1
  • This will not work if your string has more than 20 bytes. But you can use bytes32, for 32 bytes!
    – Ismael
    Jun 13, 2016 at 17:58

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.