5

In my contract, I have separated my code and data. In the "data contract", I am storing the current version of code. Whenever addEmployee() is called, I am trying to delegate it to Current Version address (with string as parameter) where the actual function code resides. But the problem is string being received by the Current Version is always ' ' regardlessof my input. (See the commented part in the contract Data.)The function works as expected if I use bytes32 instead of string. Can someone explain this behaviour??? Am I missing some concept??

pragma solidity ^0.4.11;

contract EmployeeDir{
    uint public id;
    string public name;
    address public currentVersion;
    address public owner;

    struct employee{
        string name;
        uint days_present;
    }

    mapping (uint => employee) public dir;

    /**
     * Constructor: Sample Input "vishy", "<address of contract Code>"
     * @param _name - Name of the EmployeeDir
     * @param _versionAddr - Address of the Current Version to which Delegate Call is intended to
     **/
    function EmployeeDir(string _name, address _versionAddr){
        dir[id].name = _name;
        currentVersion = _versionAddr;
        owner = msg.sender;
    }

    function updateVersionAddress(address _versionAddr){
        if(msg.sender == owner)
            currentVersion = _versionAddr;
    }

    function addEmployee(string _name){
        if(msg.sender == owner){
            //This is where the string is being passed as empty 
            //To check if the delegatecall is indeed working, a sample var id has been introduced.
            //The var id is getting updated on delegatecall meaning that delegatecall is working but the string is not getting updated.
            currentVersion.delegatecall(bytes4(sha3("addEmployee(string)")), _name);

            dir[id].name = name;
        }
    }
}

contract Code{
    uint public id;
    string public name;

    function addEmployee(string _name){
        id += 1;
        name = _name;
    }
}
  • I don't see any comments. How are you sending data into the contract? – Steve Ellis Jul 16 '17 at 14:35
1

To force the conversion use byte32(_name) instead of just _name.

Solidity provides automatic "type casting" whenever possible. This works when the source type and destination type are both known, and there exists a default transformation from the source type to the destination type.

In the case of delegatecall the expected arguments are specified as (...), meaning a variable number of arguments of unspecified type. This is because when you compile your contract the compiler can have no knowledge about the details of the destination code that you are calling into.

Since the destination type is unknown the automatic type casting feature is disabled for the arguments to delegatecall(...). It is then the responsibility of the programmer to ensure that all arguments are cast into the correct form first. This can be performed inline by the simple addition of an explicit cast.

In your example, you are trying to pass a string argument called '_name' to another contract function that is expecting an argument of type bytes32. If the function call was being made to another function within the same contract then the conversion would happen automatically (See further details here), but, as described above, arguments that are passed to delegatecall (or to any method with who's arguments are specified as (...)), the argument will be passed "as-is".

  • But the function addEmployee() in 'contract Code' is expecting a string datatype. As seen from Remix IDE, the function is intrepreted by EVM as '"2d2d03a6": "addEmployee(string)"' – Viswanath Kapavarapu Dec 27 '17 at 6:15
  • So why do I need to type cast the variable _name to bytes32? – Viswanath Kapavarapu Dec 27 '17 at 6:22

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.