Web3.py

從合約中獲取方法簽名而不是手動建構

  • May 6, 2020

有沒有辦法從合約對象(使用 Web3.py)獲取方法簽名,而不是手動建構它?我在那裡沒有看到實現這一點的功能。似乎應該內置一些東西。

我一直使用 Web3.sha3 手動計算方法簽名,如下所示,但這需要我手動輸入函式參數。

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

contract對像已經知道 ABI JSON,所以它不應該能夠為我生成它嗎?

如果我能做到這一點,那就太好了:

function.method_signature

因為我已經可以這樣做了:

function.abi

請注意,我並不是要建立一個交易來廣播到網路。給定合約對象 ABI,我正在嘗試從合約中生成大量函式雜湊。這些契約會隨著時間而改變,所以我不想硬編碼任何東西。

編輯:我自己寫這個來完成這項工作。它支持正常類型和元組。儘管如此,仍然更喜歡使用內置的東西。

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 簡單範例:

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

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

ABI 元組範例:

{
 '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'
}

區塊鏈上的合約不儲存方法簽名,只儲存方法簽名的雜湊值。

此資訊在 EVM 字節碼中編碼為基於方法簽名的“跳轉目的地”。

對於其他一切,您需要預編譯或自己編譯的 ABI 文件。

EtherScan 收集合約原始碼並在您“驗證”合約時重新編譯它。

給定合約的 ABI,您可以生成該合約中每個函式的簽名:

signatures = {}
for func in [obj for obj in abi if obj['type'] == 'function']:
   name = func['name']
   types = [input['type'] for input in func['inputs']]
   signatures[name] = '{}({})'.format(name,','.join(types))

然後Web3.sha3用這些簽名中的每一個呼叫。

這應該允許您以程式方式處理契約更改。


如果它使您更容易,那麼您還可以創建一個數組而不是字典:

signatures = ['{}({})'.format(func['name'],','.join([input['type'] for input in func['inputs']])) for func in [obj for obj in abi if obj['type'] == 'function']]

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