[Ethereum] Get method signature from contract rather than manually constructing

pythonsignatureweb3.py

Is there a way to get a method signature from the contract object (using Web3.py) rather than manually constructing it? I don't see a function in there that accomplishes this. It seems like something should be built-in.

I have always calculated the method signature manually using Web3.sha3 as seen below, but this requires me to manually type out the function params.

params = 'uint256,uint256,bytes,address[]'
method_signature = Web3.sha3(text=f"functionNameGoesHere({params})")[0:4]

The contract object already knows the ABI JSON, so shouldn't it be able to generate it for me?

It would be nice if I could do this:

function.method_signature

Since I can already do this:

function.abi

Note, I'm NOT trying to build a transaction to broadcast to the network. I'm trying to generate lots of function hashes from contracts given the contract object an ABI. And these contracts will change over time so I don't want to hard code anything.

Edit: I wrote this myself to do the job. It supports regular types as well as tuples. Would still prefer to use something built-in though.

def GetMethodSignature_GivenAbi(methodName, abi):
    params = ''
    for index, input in enumerate(abi['inputs']):
        if index > 0:
            params += ','

        if input['type'] == 'tuple':
            params += '('
            for index2, tupleComponent in enumerate(input['components']):
                if index2 > 0:
                    params += ','

                params += tupleComponent['type']

            params += ')'

        else:
            params += input['type']

    methodSignature = GetMethodSignature(methodName, params)
    return methodSignature

ABI simple example:

{
  'constant': False,
  'inputs': [
    {
      'name': 'name1',
      'type': 'uint256'
    },
    {
      'name': 'name2',
      'type': 'uint256'
    }
  ],
  'name': 'simpleFunction',
  'outputs': [

  ],
  'payable': False,
  'stateMutability': 'nonpayable',
  'type': 'function'
}

ABI tuple example:

{
  'constant': False,
  'inputs': [
    {
      'name': 'name1',
      'type': 'uint256'
    },
    {
      'name': 'name2',
      'type': 'uint256'
    },
    {
      'name': 'name3',
      'type': 'uint256'
    },
    {
      'components': [
        {
          'name': 'makerAddress',
          'type': 'address'
        },
        {
          'name': 'takerAddress',
          'type': 'address'
        },
        {
          'name': 'feeRecipientAddress',
          'type': 'address'
        },
        {
          'name': 'senderAddress',
          'type': 'address'
        },
        {
          'name': 'makerAssetAmount',
          'type': 'uint256'
        },
        {
          'name': 'takerAssetAmount',
          'type': 'uint256'
        },
        {
          'name': 'makerFee',
          'type': 'uint256'
        },
        {
          'name': 'takerFee',
          'type': 'uint256'
        },
        {
          'name': 'expirationTimeSeconds',
          'type': 'uint256'
        },
        {
          'name': 'salt',
          'type': 'uint256'
        },
        {
          'name': 'makerAssetData',
          'type': 'bytes'
        },
        {
          'name': 'takerAssetData',
          'type': 'bytes'
        },
        {
          'name': 'makerFeeAssetData',
          'type': 'bytes'
        },
        {
          'name': 'takerFeeAssetData',
          'type': 'bytes'
        }
      ],
      'name': 'order',
      'type': 'tuple'
    },
    {
      'name': 'name4',
      'type': 'bytes'
    },
    {
      'name': 'name5',
      'type': 'address[]'
    }
  ],
  'name': 'functionName',
  'outputs': [

  ],
  'payable': False,
  'stateMutability': 'nonpayable',
  'type': 'function'
}

Best Answer

A contract on a blockchain does not store method signatures, only hashes of method signatures.

This information is encoded in the EVM bytecode as "jump destinations" based on the method signature.

For everything else, you need ABI files, precompiled or compile yourself.

EtherScan collects contract source code and recompiles it when you "verify" the contract.

Related Topic