How to capture the revert from the calle contract?

I have a Logic contract(caller), which calls a another contract named StorageContract (calle). I’m call a function of Storage contract through the LogicContract and I have put a require inside that function, which doesnt satistfy. But im unable to get thet require message in my Logic Contract

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import "hardhat/console.sol";

error InsufficientBalance(string data);


contract Storagecontract{
    address public owner;
    
    function set(string memory _name)public view {
        console.log(owner,msg.sender);
        revert InsufficientBalance({data: "Nothing"});

       
    }
}


contract Logiccontract{
    string public stat;

    function changename(address add, string memory name)public {
         (bool send, bytes memory data)=add.call(abi.encodeWithSignature("set(string)", name));
         console.log("status",send);


    }
   
}

Please elaborate!

For example:

  • What is your execution flow?
  • What is the outcome of that flow?
  • How is it different from the outcome that you’re expecting?

Also, there seems to be a lot of code which is irrelevant to your question.

For example - onlyOwner, changeOwner, etc.

Please include only the relevant information, so that your question is easier for readers to address.

I have updated the above code, please have a look. All i want is when i make a call from logicContract to StorageContract (set func). I need that custom error back in my Logic contract

Revert is not a state-changing operation.

Perhaps you’re confusing it with emitting an event (similar spelling in a way)?

1 Like

This doesn’t look like a valid question for Language Design topic and sorry for dead post bump but let me try to answer the question

Retrieving error parameters of call result to another SC is quite challenging and usually unreasonable but not impossible

For example, StringError(string data) with parameter "Go Back" is encoded as follows
0xd842448a ← error signature
0000000000000000000000000000000000000000000000000000000000000020 ← pointer to string (because string is dynamic type)
0000000000000000000000000000000000000000000000000000000000000007 ← string length
476f204261636b + some trailing zeros ← string itself

Though, you need to validate the error data you’ve received matches the error signature, dynamic data pointer is set correctly, error data length is not exceeded by dynamic parameter length, and only then get the string by the calculated pointer

Here is the whole code

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

// contract which reverts with custom error with a string parameter
contract Destination {
    constructor() {}
    error StringError(string data); // error signature is 0xd842448a
    fallback() external {
        revert StringError("Go Back");
    }
}

// contract to deploy and execute
contract Target {
    // prepare contract to call internally
    address destination;
    constructor() {
        destination = address(new Destination());
    }

    function exec() external returns (string memory) {
        // execute call to some contractt
        (bool success, bytes memory data) = destination.call("");

        // process the error if execution was not successful
        if (!success) {
            // get the string parameter from error
            string memory errorData;

            // some safe checks that can be omitted (not recommended)
            {
                // get error signature
                bytes4 errorSignature;
                if (data.length < 4) revert();
                assembly {
                    errorSignature := mload(add(data, 32))
                }
                // validate the signature is the expected one
                if (errorSignature != bytes4(0xd842448a)) revert();

                uint256 pointer;
                uint256 length;
                // validate data has place for pointer and string length
                if (data.length < 4 + 32 * 2) revert();
                // load string length and pointer
                assembly {
                    pointer := mload(add(data, 36))
                    length := mload(add(data, 68))
                }
                // validate pointer is abi compliant
                if (pointer != 32) revert();
                // validate data provides all the string bytes
                if (data.length < 4 + 32 * 2 + length) revert();
            }

            // set pointer for error string
            assembly {
                errorData := add(68, data) 
            }

            // return the error string if call errored with StringError
            return errorData;
        }

        // return nothing if execution was successful
        return "";
    }
}