I have a special contract with few extra functions. In the transfer wei function I want to send it to the special method or if receiver doesn't have it (because is a wallet or doesn't inherit from my abstract or interface), via normal transfer. How can I check if addressTo inherits from my special interface or abstract contract that contain my payable function?

  • Does this interface contain non-constant functions? Apr 8, 2019 at 8:46
  • It contains canHoldWei external view, receiveWei external payable, getBalance public view, transfer public
    – Radek_pl
    Apr 8, 2019 at 8:55

2 Answers 2


If all the functions in your special interface are constant (either pure or view), then you can call function external_call (see Gnosis MultiSigWallet) for each one of the functions in your special interface, and then determine that to is the address of a special contract if and only if all the calls have returned true.

For example, suppose that you have:

interface SpecialInterface {
    function func1(uint256) external pure returns (bool);
    function func2(uint256, bool) external pure returns (uint256);
    function func3(uint256, uint256) external pure returns (bool);

Then in your transfer function, you can check the to address as follows:

contract MyErc20Contract {
    function transfer(address to, uint256 value) public returns (bool) {
        bytes32 data1 = keccak256("func1(uint256)");
        bytes32 data2 = keccak256("func2(uint256,bool)");
        bytes32 data3 = keccak256("func3(uint256,uint256)");
        bool result1 = external_call(to, 0, data1.length, abi.encodePacked(data1));
        bool result2 = external_call(to, 0, data2.length, abi.encodePacked(data2));
        bool result3 = external_call(to, 0, data3.length, abi.encodePacked(data3));
        if (result1 && result2 && result3) {
            // `to` is the address of a special contract
        else {
            // `to` is not the address of a special contract

    function external_call(address destination, uint value, uint dataLength, bytes data) private returns (bool) {
        bool result;
        assembly {
            let x := mload(0x40)   // "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention)
            let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that
            result := call(
                sub(gas, 34710),   // 34710 is the value that solidity is currently emitting
                                   // It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) +
                                   // callNewAccountGas (25000, in case the destination address does not exist and needs creating)
                dataLength,        // Size of the input (in bytes) - this is what fixes the padding problem
                0                  // Output is ignored, therefore the output size is zero
        return result;
  • Wouldn't this consume a lot of gas?
    – Juanu
    Apr 15, 2021 at 19:45
  • this will fail because 1) encodePacked shouldn't be used with encoding function arguments and 2) the argument values are missing altogether in this example. also, to be thorough the return values will need to be checked, which only provides partial validation on the negative cases, eg., bool cannot be greater than 1, but cannot ensure valid typing May 19, 2022 at 21:15

Smart contract inheritance and interfaces are a syntactic sugar in Solidity. They cannot be recognized from byte code. So the only thing you may probably check is that byte code of a smart contract you are calling is exactly the one you need. To do so you should use assembly instructions extcodesize and extcodecopy.

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.