Solidity
為什麼 create2 預測地址不等於實際地址?
由於某種原因,當創建的合約接受它的建構子參數時,預測/預先計算的地址不等於實際地址
address
,但是當建構子參數為uint
. 我已經在下面的腳本中展示了這兩個範例。// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Factory { // example 1: function createTest1(uint number1, uint number2) public { bytes32 salt = keccak256(abi.encodePacked(number1, number2)); // source: https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2 address predictedAddress = address(uint160(uint(keccak256(abi.encodePacked( bytes1(0xff), address(this), salt, keccak256(abi.encodePacked( type(Test1).creationCode, number1, number2 )) ))))); Test1 test1 = new Test1{salt: salt}(number1, number2); require(address(test1) == predictedAddress); // Does NOT revert } // example 2: function createTest2(address address1, address address2) public { bytes32 salt = keccak256(abi.encodePacked(address1, address2)); address predictedAddress = address(uint160(uint(keccak256(abi.encodePacked( bytes1(0xff), address(this), salt, keccak256(abi.encodePacked( type(Test2).creationCode, address1, address2 )) ))))); Test2 test2 = new Test2{salt: salt}(address1, address2); require(address(test2) == predictedAddress); // Does revert } } contract Test1 { uint public number1; uint public number2; constructor(uint _number1, uint _number2) { number1 = _number1; number2 = _number2; } } contract Test2 { address public address1; address public address2; constructor(address _address1, address _address2) { address1 = _address1; address2 = _address2; } }
由於某種原因,當創建的合約接受其建構子參數的地址時,預測/預先計算的地址不等於實際地址,但是當建構子參數為 uint 時很好
那是因為您沒有
abi.encode
在參數上使用,而是abi.encodePacked
. 將元素填充到abi.encode
32 字節時,如果您的參數已經是 32 字節長(如 uint),則沒有區別。在缺少填充的情況下address
會導致不同的輸出。因此,更通用和正確的版本是:
address predictedAddress = address(uint160(uint(keccak256(abi.encodePacked( bytes1(0xff), address(this), salt, keccak256(abi.encodePacked( type(Test2).creationCode, abi.encode(address1, address2) // <-- abi.encode the parameters )) )))));
我設法讓它工作,我所要做的就是將地址轉換為 uint
是的,因為您隱含地呼叫
abi.encode
了參數,因為它的abi.encode(address_variable)
輸出完全相同,因為uint(uint160(address1))
它只是一種特殊情況,不適用於長度超過 32 字節的類型,而 usingabi.encode
將始終有效,因為它始終會產生確切的部署字節碼 + abi。編碼參數。