Search code examples
try-catchblockchainethereumsoliditysmartcontracts

Solidity try catch to detect an address type


I am not sure to understand the try / catch in solidity. The following code in intentionally wrong and the error should be caught, right?

function GetTest() external view returns (string memory)  {
        
        address _token_addr = 0x0000000000000000000000000000000000000000;
        console.log("here");
        ERC721 candidateContract = ERC721(_token_addr);
        try candidateContract.supportsInterface(0x80ac58cd) {

              console.log("try");
        }
        catch
        {
              console.log("catch");
        }
        return "";
}

What is the way to catch an error and check if the address has the expected type (token, address, contract) ?


Solution

  • The try/catch statement allows you to react on failed external calls and contract creation calls

    When you call candidateContract.supportsInterface(0x80ac58cd) if this function reverts, you will catch the error. For example, if you deploy those testCatch and ERC165 contracts

    contract testCatch{
        function GetTest() public view returns (string memory)  {
            // this is the address of deployed ERC165 contract down below
            address _token_addr = 0x406AB5033423Dcb6391Ac9eEEad73294FA82Cfbc;
           
            ERC165 candidateContract = ERC165(_token_addr);
            try candidateContract.supportsInterface(0x80ac58cd) {
    
                 return "tried";
            }
            catch
            {
                  return "catch";
            }  
    }
    
    }
    interface IERC165 {
        function supportsInterface(bytes4 interfaceId) external view returns (bool);
    }
     
    // this contract originally was abstract but I removed it to be able to deploy
    contract ERC165 is IERC165 {
        function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
            // this require will fail
            require(2==3,"wrong calculation");
            return interfaceId == type(IERC165).interfaceId;
        }
    }
    

    when you call the GetTest() function, it will revert because of require(2==3,"wrong calculation") line

    enter image description here

    However, if you removed the require line from ERC165 contract,

    contract ERC165 is IERC165 {
        function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
            return interfaceId == type(IERC165).interfaceId;
        }
    }
    

    And if you change this bytes4 "0x80ac58cd" to a wrong bytes4 "0x80ac5ccc", if you call the function, catch will not CATCH it. because supportsInterface function will not revert anything. So the code inside try block will run