3

Suppose a contract has been deployed and I don't have its source code or ABI. From web3, I would like to know if the contract has a method with a given signature. (An example application would be a blockchain service that responds to requests by invoking a specific callback method on the calling contract, like Oraclize.)

I can get close with the following:

methodSignature = web3.sha3('methodName(bytes32,bytes)');
calltx = {
  to: TARGET_ADDR,
  data: methodSignature.substring(0,10)
};
let result = web3.eth.call(calltx)

and then if result is not '0x' then the method exists because it returned some value. But '0x' doesn't mean the method doesn't exist, depending on the method itself. How do I tell the difference?

Related: What happens if you call a non-existent function of another contract that has no fallback function in Solidity?

3

I'm using this method:

public async hasMethod(contractAddress, signature) {
    const w3 = this.$connection.web3; // this is my web3 instance
    const code = await w3.eth.getCode(contractAddress);
    const hash = w3.eth.abi.encodeFunctionSignature(signature);
    return code.indexOf(hash.slice(2, hash.length)) > 0;
  }

And than:

const adress = '0xB8c77482e45F1F44dE1745F52C74426C631bDD52';
const signature = 'transferFrom(address,address,uint256)';
this.hasMethod(address, signature).then((has) => console.log(has));
2

There is no perfect way to do this, but you can scan the code for occurrences of the signature hash. To make this a bit more precise you can make sure that the opcode of PUSH4 precedes it.

Here is some python code for this (I guess JS is almost identical):

def hasMethod(contract_addr, signature):
    code = w3.eth.getCode(contract_addr)
    fn_hash = w3.sha3(signature.encode("utf-8"))
    fn_hash = "63" + fn_hash[2:10] # 0x63 is PUSH4
    return fn_hash in code

contract_addr = "0xB8c77482e45F1F44dE1745F52C74426C631bDD52"
signature = "transferFrom(address,address,uint256)"
print(hasMethod(contract_addr, signature))
0

This is not part of WEB3.js 1.0, this is a basic javascript function, that could only check if supplied ABI does have this property (method), but it will not be able to check if the smart contract instantiated with this ABI really does have this method

EVM does not support validation of method existence. Best you can do is to call the method and if the method is programmed in a way that non-zero result will always be returned if method exists, then you can validate it.

There is no way around it otherwise.

-1

With web3 1.0.0 you can check for the existance of the signature inside the methods property of your contract instance.

contract.methods.hasOwnProperty('SIGNATURE')
  • He needs the ABI for that though which he doesn't have access to. – mafrasi2 Apr 7 '18 at 23:17

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.