Solidity 的 keccak256 雜湊與 WEB3 keccak 雜湊不匹配
TL;DR:我在契約中有一個計算 keccak256 雜湊的方法,我試圖在 Web3 中複製它,但雜湊不匹配。我的問題與此問題中的問題非常相似,但那裡的答案對我沒有幫助。這可能是編碼問題,但我不確定如何解決。
我試圖像這樣散列三個參數:
pragma solidity >=0.7.0 <0.9.0; contract Test { function makeHash(uint intValue, string calldata strValue) public view returns (bytes32) { bytes32 myHash = keccak256(abi.encode(intValue, strValue, msg.sender)); return myHash; } }
呼叫
makeHash(1, 'test1')
此地址0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
返回0x94822408407fb535100a4152f8709ed58507e1b3dfd32798d25051065f680d64
在 Web3 中,我嘗試連接字元串中的值(我現在意識到這是錯誤的,但也不確定如何在 web3 中執行此操作):
web3.utils.keccak256("1test10x5B38Da6a701c568545dCfcB03FcB875f56beddC4")
返回0xcd347147b43e04263a58ca2b6d0f0aa8a3e0b00bd02c0e9bbee008aad68b1bf0
從這個答案我也嘗試了這種方法:
web3.utils.soliditySha3( { type: 'uint', value: 1 }, { type: 'string', value: 'test1' }, { type: 'address', value: '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4' } )
它返回
0x0aca86dcfc0a652e35268737960c05e51eb03dbfc4c175fd3ca094a2e99e180c
由於所有方法都返回了不同的雜湊值,我決定測試只對合約和 web3 中的字元串進行雜湊處理,但即便如此,它們也會生成不同的雜湊值。
bytes32 myHash = keccak256(abi.encode(strValue));
使用合約中的 aboce 行,呼叫
makeHash('test1')
返回0xf5e2ed7011d2249ef10becf6f745e4b900ab43c0dc529b97d308f25bb36416d0
但是在 web3 中,所有這些方法都返回相同的雜湊值:
web3.utils.keccak256("test1") web3.utils.sha3Raw('test1') web3.utils.sha3('test1') web3.utils.soliditySha3('test1') web3.utils.soliditySha3Raw('test1') // Tried encoding web3.utils.sha3('test1', {encoding: 'String'}) web3.utils.sha3('test1', {encoding: 'hex'}) web3.utils.sha3('test1', {encoding: 'string'}) // Tried converting to hex web3.utils.soliditySha3Raw(web3.utils.asciiToHex('test1')) web3.utils.keccak256(web3.utils.asciiToHex('test1')) // Tried from this answer https://ethereum.stackexchange.com/a/74082/68459 web3.utils.soliditySha3({ type: 'string', value: 'test1' })
他們都回來了
0x6d255fc3390ee6b41191da315958b7d6a1e5b17904cc7683558f98acc57977b4
此外,決定嘗試
abi.encode
通過使用在 web3 中進行複制,web3.eth.abi.encodeParameter(String, 'test1')
但它總是返回錯誤:if (type.match(paramTypeBytesArray) || type.match(paramTypeNumberArray)) { ^ Uncaught TypeError: type.match is not a function at ABICoder.formatParam (..\truffle\build\webpack:\node_modules\web3-eth-abi\src\index.js:255:1) at ..\truffle\build\webpack:\node_modules\web3-eth-abi\src\index.js:117:1 at Array.map (<anonymous>) at ABICoder.encodeParameters (..\truffle\build\webpack:\node_modules\web3-eth-abi\src\index.js:105:1) at ABICoder.encodeParameter (..\truffle\build\webpack:\node_modules\web3-eth-abi\src\index.js:88:1) at evalmachine.<anonymous>:0:14 at sigintHandlersWrap (vm.js:274:15) at Script.runInContext (vm.js:128:14) at runScript (..\truffle\build\webpack:\packages\core\lib\console.js:270:1) at Console.interpret (..\truffle\build\webpack:\packages\core\lib\console.js:285:1) at bound (domain.js:426:14) at REPLServer.runBound [as eval] (domain.js:439:12) at REPLServer.onLine (repl.js:760:10) at REPLServer.emit (events.js:315:20) at REPLServer.EventEmitter.emit (domain.js:482:12) at REPLServer.Interface._onLine (readline.js:329:10) at REPLServer.Interface._line (readline.js:658:8) at REPLServer.Interface._ttyWrite (readline.js:999:14) at REPLServer.self._ttyWrite (repl.js:851:9) at ReadStream.onkeypress (readline.js:205:10) at ReadStream.emit (events.js:315:20) at ReadStream.EventEmitter.emit (domain.js:482:12)
該
abi.encode
函式使用 Solidity 的 ABI規範對合約呼叫的參數進行編碼。對於 uintXXX、bool、address 等固定大小的類型,這很簡單,只需將它們填充到 32 個字節即可;對於動態類型,它很複雜。相當於這個 Solidity 程式碼:
bytes32 myHash = keccak256(abi.encode('test1'));
在 JavaScript 中將是:
const encoded = web3.eth.abi.encodeParameters(['string'],['test1']) const hash = web3.utils.sha3(encoded, {encoding: 'hex'}) console.log(hash)
如果你好奇,’test1’ ABI 編碼是:
0x 0000000000000000000000000000000000000000000000000000000000000020 // offset 0000000000000000000000000000000000000000000000000000000000000005 // length 7465737431000000000000000000000000000000000000000000000000000000 // data
makeHash
在您的情況下, JavaScript 中的等價物是:const encoded = web3.eth.abi.encodeParameters(['uint256', 'string', 'address'],[1234, 'country roads', 0x44444..]) const hash = web3.utils.sha3(encoded, {encoding: 'hex'})