Web3js

如果已部署的契約上存在方法,如何從 web3 中檢測?

  • March 11, 2022

假設已經部署了一個合約,但我沒有它的原始碼或 ABI。從 web3 開始,我想知道合約是否有帶有給定簽名的方法。(一個範例應用程序是一個區塊鏈服務,它通過呼叫呼叫合約的特定回調方法來響應請求,例如 Oraclize。)

我可以接近以下內容:

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

然後如果結果不是“0x”,則該方法存在,因為它返回了一些值。但是'0x’並不意味著該方法不存在,這取決於方法本身。我如何區分?

相關:如果你呼叫另一個在 Solidity 中沒有備份功能的合約的不存在的功能會發生什麼?

我正在使用這種方法:

public async hasMethod(contractAddress, signature) {
   const w3 = this.$connection.web3; // this is my web3 instance
   const code = await w3.eth.getCode(contractAddress);
   const functionSignature = w3.eth.abi.encodeFunctionSignature(signature);
   // remove "0x" prefixed in 0x<4bytes-selector>
   return code.indexOf(functionSignature.slice(2, hash.length)) > 0;
 }

然後:

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

沒有完美的方法可以做到這一點,但您可以掃描程式碼以查找簽名雜湊的出現。為了使這一點更精確,您可以確保 PUSH4 的操作碼在它之前。

這是一些python程式碼(我猜JS幾乎相同):

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))

引用自:https://ethereum.stackexchange.com/questions/11856