Solidity
Solidity keccak 行為
我有一個奇怪的問題。我正在嘗試在 Rust 中 keccak256 打包編碼參數
$$ which should mimic Soldity’s behavior to be checked on chain later $$. 我暫時失敗了。為了解決這個問題,我一直在編寫一個具有以下功能的小型測試合約:
function doKeccak(bytes memory _data) public pure returns (bytes32) { return keccak256(_data); } function packed( address _from, address _to, uint256 _value, bytes memory _data, uint256 _nonce, uint256 _gasPrice, uint256 _gasLimit ) public pure returns (bytes memory) { return abi.encodePacked( bytes1(0x19), bytes1(0), _from, _to, _value, _data, _nonce, _gasPrice, _gasLimit ); } function doKeccakPacked( address _from, address _to, uint256 _value, bytes memory _data, uint256 _nonce, uint256 _gasPrice, uint256 _gasLimit ) public pure returns (bytes32) { return keccak256( abi.encodePacked( bytes1(0x19), bytes1(0), _from, _to, _value, _data, _nonce, _gasPrice, _gasLimit ) ); }
現在,如果我打電話給 rust 程序
$$ pseudo-code $$
contract.doKeccakPacked(args..)
我得到不同的contract.doKeccak(contract.packed(args))
結果…… 任何的想法 ?編輯 例如,這裡是一個原始的 Rust 參數數組,它會導致不同的結果:
[ Address( 0xdfa1468d07fc86840a6eb53e0e65cebde81d1af9, ), Address( 0x7f114fc87edc5f1311d4e77d1a3018a3dc34f47e, ), Uint( 0, ), Bytes( [ 201, 13, 180, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 17, 79, 200, 126, 220, 95, 19, 17, 212, 231, 125, 26, 48, 24, 163, 220, 52, 244, 126, ], ), Uint( 94481061581245121, ), Uint( 0, ), Uint( 250000, ), ]
編輯 2
這是生鏽程式碼:
fn hash_sign( &self, wallet: Address, data: ethabi::Bytes, nonce: U256, ) -> Result<Bytes, String> { let options = Options::default(); // this is the contract whose test functions are above let erc_1077_hash_abi = ethabi::Contract::load(constants::abis::ERC1077_HASH).unwrap(); let erc_1077_hash_address = Address::from_str(&"83649266Ba0a8CAd860403a6532F12c6074BBDAC").unwrap(); let function = erc_1077_hash_abi.function("doKeccakPacked").unwrap(); let params: [ethabi::Token; 7] = [ ethabi::Token::Address(self.address), ethabi::Token::Address(wallet), ethabi::Token::Uint(self.value()), ethabi::Token::Bytes(data.clone()), ethabi::Token::Uint(nonce), ethabi::Token::Uint(self.gas_price()), ethabi::Token::Uint(self.gas_limit()), ]; let encoded = function.encode_input(¶ms).unwrap(); let result_1 = self.web3.eth().call( CallRequest { from: None, to: erc_1077_hash_address, gas: options.gas, gas_price: options.gas_price, value: options.value, data: Some(Bytes(encoded)), }, None.into(), ); let result_1 = match result_1.wait() { Ok(s) => Ok(s), Err(_e) => Err(format!("error")), }; let function = erc_1077_hash_abi.function("packed").unwrap(); let encoded = function.encode_input(¶ms).unwrap(); let packed = self.web3.eth().call( CallRequest { from: None, to: erc_1077_hash_address, gas: options.gas, gas_price: options.gas_price, value: options.value, data: Some(Bytes(encoded.clone())), }, None.into(), ); let packed = packed.wait().unwrap(); let packed = packed.0; let function = erc_1077_hash_abi.function("doKeccak").unwrap(); let params: [ethabi::Token; 1] = [ ethabi::Token::Bytes(packed), ]; let encoded = function.encode_input(¶ms).unwrap(); let result_2 = self.web3.eth().call( CallRequest { from: None, to: erc_1077_hash_address, gas: options.gas, gas_price: options.gas_price, value: options.value, data: Some(Bytes(encoded)), }, None.into(), ); let result_2 = match result_2.wait() { Ok(s) => Ok(s), Err(_e) => Err(format!("error")), }; result_1 }
這裡 result_1 和 result_2 是不同的……
其實我想通了。這不是
keccak
問題,而是與web3
rust crate 解碼從鏈返回的字節數據的方式有關的問題。它強制執行一些奇怪的填充 - 將其轉換為FixedBytes
類型 - 從而弄亂整個工作流程。謝謝大家。