4

A contract has many functions and how to automatically generate the full selector list, including inherited functions, for the whole contract?

Preferred solution shouldn’t require more than a web browser.

5 Answers 5

6

Maybe you can use the online Ethereum IDE (Remix):

  • Paste the whole code of the address you posted.
  • Select the same compiler version: v0.4.25+commit.59dbf8f1.
  • Select the contract by name: SaiProxyCreateAndExecute.

enter image description here

Press on Compilation Details and check the functionHashes section. You will get something like the following:

{
    "581f3c50": "createAndOpen(address,address)",
    "eefe3818": "createOpenAndLock(address,address)",
    "d3140a65": "createOpenLockAndDraw(address,address,uint256)",
    "0344a36f": "draw(address,bytes32,uint256)",
    "f9ef04be": "free(address,bytes32,uint256)",
    "da93dfcf": "give(address,bytes32,address)",
    "bc25a810": "lock(address,bytes32)",
    "1edf0c1e": "lockAndDraw(address,bytes32,uint256)",
    "516e9aec": "lockAndDraw(address,uint256)",
    "b95460f8": "open(address)",
    "bc244c11": "shut(address,bytes32)",
    "792037e3": "shut(address,bytes32,address)",
    "a3dc65a7": "wipe(address,bytes32,uint256)",
    "8a9fc475": "wipe(address,bytes32,uint256,address)",
    "faed77ab": "wipeAndFree(address,bytes32,uint256,uint256)",
    "1b968160": "wipeAndFree(address,bytes32,uint256,uint256,address)"
}
3
  • Comments are not for extended discussion; this conversation has been moved to chat.
    – eth
    Jul 30, 2019 at 18:27
  • Except solidity is unable to generate the list of function selectors for the theᴅᴀᴏ, and thus I don’t know the function name of 82661dc4. Aug 15, 2019 at 12:48
  • This is still the best solution today, but it's a PITA for contracts verified via multi-part (i.e. source code not flattened). You'd have to create N files on Remix, where N = total number of contract files. Aug 6, 2021 at 10:12
4

For every function, you want to calculate keccak256(signature) (try https://emn178.github.io/online-tools/keccak_256.html)

signature is a concatenation of function's name and parameters' types in parentheses, omitting all spaces and parameter names.

For example function

transfer(address to, uint256 amount)

has signature

transfer(address,uint256)

keccak256(signature) result is

a9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b

Function selector is first 4 bytes (according to https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector) which is

a9059cbb

As ABI can be interpreted in JavaScript as simple array of JSON objects, it would be simple to iterate through this array and compose signature for every function and calculate selectors

2
  • 1
    Yes, I already know. But by doing function by function I failed to find what 8a9fc475 match for this contract : etherscan.io/address/…. So my point is to process the whole contract source code or it’s ᴀʙɪ in the way you described. Jul 29, 2019 at 9:48
  • 1
    You may have to also process code that's included or imported into the .sol you're looking at, for example, base contracts and/or libraries (if there are any -- I didn't look). Jul 29, 2019 at 14:50
1

It's kind of ridiculous that it's not part of the artifacts. Here's a quick js script that will extract them out of the artifacts/build-info json data:

#!/usr/bin/env node

// Reads JSON from stdin and writes equivalent
// nicely-formatted JSON to stdout.

var stdin = process.stdin,
    stdout = process.stdout,
    inputChunks = [];

stdin.resume();
stdin.setEncoding('utf8');

stdin.on('data', function (chunk) {
    inputChunks.push(chunk);
});

// Search for  path of item with name and value
function path(c, name, currentPath, t){
    var currentPath = currentPath || "root";

    for(var i in c){
      if(i == name){
        t = currentPath;
        console.log(t + "." + name + ' -> ' + JSON.stringify(c[name], null, '    '));
      }
      else if(typeof c[i] == "object"){
        path(c[i], name, currentPath + "." + i);
      }
    }
};


stdin.on('end', function () {
    var inputJSON = inputChunks.join("");
    var parsedData = JSON.parse(inputJSON);

    path(parsedData,"methodIdentifiers", '');
});

It works on stdin so , just run like this: cat artifacts/build-info/2e388aff5c540fc7cba05810417a6a1d.json | ./extractSelectors.js

0

There you go (using web3.js v1.0.0-beta.34):

const Web3    = require("web3");
const request = require("request");
request("http://api.etherscan.io/api?module=contract&action=getabi&address=0x526af336d614ade5cc252a407062b8861af998f5&format=raw", function(error, response, body) {
    const web3 = new Web3();
    for (const func of JSON.parse(body))
        console.log(func.name, web3.eth.abi.encodeFunctionSignature(func));
});
3
  • Comments are not for extended discussion; this conversation has been moved to chat.
    – eth
    Jul 30, 2019 at 18:20
  • In latest version of web3 (the one available with MetaMask). web3.eth.abi.encodeFunctionSignaturedoesn’t exist. web3.eth.abi isn’t there at all. Aug 15, 2019 at 8:21
  • 1
    @user2284570: First of all, you need to avoid this kind of tone, which leaves the impression of very little appreciation towards the help you're getting here! Second, there's hardly such thing as "latest version" for web3.js at the moment. The latest beta version is 55, and is known to be unstable. The last stable beta versions are 34 to 37 (which are more or less the same). Based on 37, an official release v1.2 has recently been published. On top of all that, I have specifically stated the version for which this answer is relevant, so your down-voting of my answer is totally not in place!!! Aug 15, 2019 at 17:20
0

This can get tricky for functions that have complex argument definitions. slither has a feature that can help here, though:

slither --print function-id .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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