0

There are two smart contracts, A and B. The addDev() function in contract A is called from contract B using the targetContractAddress.call() method. However, despite the call being successful, the state of contract A is not updated. I mean when I execute the newDev() function in contract B, the contract call is completed successfully, and the newDevAdd event is emitted. Nevertheless, when I subsequently attempt to execute the viewDev() function in contract A, the returned data is null.

I don't know how to fix this problem!

The whole code:

// SPDX-License-Identifier: MIT`
pragma solidity ^0.5.16;
contract A{

    enum field{Ethereum,NodeJS,Go,Python}

    struct developer{
        bytes name;
        field track;
        uint salary;
    }

    mapping(bytes => developer) public devList;

    event listUpdated(string devName,field devField,uint devSalary);

    function addDev(string calldata n,field t,uint s) external {
        devList[bytes(n)].name=bytes(n);
        devList[bytes(n)].track=t;
        devList[bytes(n)].salary=s;
        emit listUpdated(string(devList[bytes(n)].name),devList[bytes(n)].track,devList[bytes(n)].salary);
    }

    function viewDev(string calldata n) external view returns(string memory,field,uint){
        return (string(devList[bytes(n)].name),devList[bytes(n)].track,devList[bytes(n)].salary);
    }

    function() external payable{}
}

contract B{

    enum field{Ethereum,NodeJS,Go,Python}

    event newDevAdd(string name,field track,uint salary);

    function newDev(address targetContract,string calldata n,field t,uint s) external {
        (bool status,bytes memory message)=targetContract.call.gas(1500000)(abi.encodeWithSignature("addDev(string,field,uint256)",n,t,s));
        require(status,string(message));
        emit newDevAdd(n,t,s);
    }
}

1 Answer 1

1

encodeWithSignature doesn’t recognise custom types like enum and struct directly, so they’ve to be passed as uint8 and tuple respectively.

So, in your case, it should be:

(bool status, bytes memory message) = targetContract.call.gas(1500000)(abi.encodeWithSignature("addDev(string,uint8,uint256)",n,uint8(t),s));

2
  • Yes, that worked! Thanks. If encodeWithSignature method can't recognize custom types, what abi's methods can I try so that it can recognize custom types?
    – Alireza
    Commented May 17 at 6:35
  • Actually, none of the encoding methods recognise custom types of other contracts. However, you can easily convert the types or get the function selectors from the contract whose function you’re calling, like if you’re importing that contract and creating its instance, then you can use encodeWithSelector by passing (new A()).addDev.selector as first param followed by the params required by addDev() function like: abi.encodeWithSelector((new A()).addDev.selector, n,uint8(t),s)). But still, for the params you still have to use values typecasted in primitive types. Commented May 17 at 8:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.