0

This is a simple storage contract:

contract SimpleStorage {
    uint public data;

    function set(uint x) public {
        data = x;
    }
}

The ABI is:

[
    {
        "constant": false,
        "inputs": [
            {
                "name": "x",
                "type": "uint256"
            }
        ],
        "name": "set",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [],
        "name": "data",
        "outputs": [
            {
                "name": "",
                "type": "uint256"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    }
]

The function signatures is:

{
    "73d4a13a": "data()",
    "60fe47b1": "set(uint256)"
}

I know how to compute the function signatures. My question is if I have only a contract ABI and I want to get function signature from the ABI, what is a good way to implement it? What library can I use?

  • What do you actually want to do? Please describe your use case. If you want to call a Solidity function from JavaScript or query a value then you should look at web3.js. It's rare that you need to work with low level function signatures directly. – Validity Labs - Sebastian Feb 12 '18 at 7:44
  • A function selector is the first 4 bytes of the function signature (e.g. "set(uint256)"). The function signature is the name of the function, followed by the parameter types, comma separated, enclosed in parentheses. That's pretty straightforward to derive from the ABI JSON. But if you're using a library, like web3.js, web3.py, the library can just do this for you. – user19510 Feb 12 '18 at 8:20
  • As I said, I know how to compute the function signatures, and I know how to use web3. What I want to do is to get the function signatures "directly form ABI through a program". – Anderson Feb 13 '18 at 3:55
1

I already has some working code samples for a dummy smart contract. No doubt you can adapt them fairly easily to your case.

Here is my dummy smart contract:

pragma solidity ^0.4.18;

contract AdditionContract {
  uint public state = 0;

  function add(uint value1, uint value2) public {
    state = value1 + value2;
  }

  function getState() public constant returns (uint) {
      return state;
  }
}

and some python code to parse the abi and compute your function selectors (compile your smart contract with truffle to create the abi, or with solcjs)

### parse your abi from truffle
import json

truffleFile = json.load(open('/path/to/your/truffle/workspace' + '/build/contracts/AdditionContract.json'))
abi = truffleFile['abi']

functionSelector = []
for fields in abi:
    if(fields['type'] == 'function'):
        functionName = fields['name']
        print(functionName)
        functionInputs = []
        for inputs in fields['inputs']:
            functionInputs.append(inputs['type'])
            print(inputs)
        functionSelector.append([functionName, functionInputs])

print(functionSelector)

### prepare the data field of the transaction
# function selector and argument encoding
# https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding

import web3 # Release 4.0.0-beta.9
w3 = web3.Web3()

value1, value2 = 10, 32 # your input value here
function = 'add(uint256,uint256)'
methodId = w3.sha3(text=function)[0:4].hex()
param1 = (value1).to_bytes(32, byteorder='big').hex()
param2 = (value2).to_bytes(32, byteorder='big').hex()
data = '0x' + methodId + param1 + param2

print(data)

### example of transaction dict
transaction_dict = {'from':myAddress,
                    'to':myContractAddress,
                    'chainId':CHAINID,
                    'gasPrice':myGasPrice,
                    'nonce':myNonce,
                    'data':data}

terminal prints :

getState
add
{'name': 'value1', 'type': 'uint256'}
{'name': 'value2', 'type': 'uint256'}
state
[['getState', []], ['add', ['uint256', 'uint256']], ['state', []]]

0x771602f7000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000020

if you want rock solid parsing I suggest that you give a look at the web3py source code (or web3js).

UPDATE

I don't know how much you know about python so I give you the way to build "add(uint256,uint256)" from the code above. But please also spend some time trying as this is fairly straightforward...

for functions in functionSelector:
    functionName = functions[0]
    functionType = functions[1]
    s = functionName + '('
    for i in range(len(functionType)):
        s += functionType[i]
        if(i+1 < len(functionType)):
            s += ','
    s += ')'
    print(s)

prints:

getState()
add(uint256,uint256)
state()
  • Thank you! Is is possible to get "add(uint256,uint256)" from ABI? – Anderson Feb 13 '18 at 3:49
  • I've edited my post to answer your question – salanfe Feb 13 '18 at 8:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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