Web3.py
從合約中獲取方法簽名而不是手動建構
有沒有辦法從合約對象(使用 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']]