Solidity

使用工廠模式複製合約時使用 Create2 計算確定性地址

  • June 13, 2021

另一位作者有一個存在相同問題的未回答問題,我正在創建一個更詳細的問題,希望兩者都可以關閉。

我有一份基於這篇文章的想法的可靠契約。基本上它是允許部署貨運代理契約的工廠契約。為了最大限度地降低 gas 成本,在創建轉發器後,您可以創建它的複製。

我希望計算將使用 create2 生成的地址,該地址適用於該createForwarder函式:

貨代工廠.sol

   function createForwarder(address forwardAddress, uint256 salt)
       public
       onlyOwner
       returns (Forwarder forwarder)
   {
       bytes memory bytecode =
           abi.encodePacked(
               type(Forwarder).creationCode,
               uint256(uint160(address(forwardAddress)))
           );

       assembly {
           forwarder := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
       }

       emit Deployed(address(forwarder), salt);
   }

計算地址.js

let bytecode = `${forwarderBytecode}${encodeParam(
 "address",
 forwardAddress
).slice(2)}`;

function buildCreate2Address(creatorAddress, saltHex, byteCode) {
 return `0x${web3.utils
   .sha3(
     `0x${["ff", creatorAddress, saltHex, web3.utils.sha3(byteCode)]
       .map((x) => x.replace(/0x/, ""))
       .join("")}`
   )
   .slice(-40)}`.toLowerCase();
}

效果很好。但是在生成新的複製地址時,之前的buildCreate2Address函式不再起作用,因為 create2 函式中的第二個和第三個參數不同。

貨代工廠.sol

   function generateCloneAddress(address target, uint256 salt)
       private
       returns (address cloneAddress)
   {
       bytes20 targetBytes = bytes20(target);
       assembly {
           let clone := mload(0x40)
           mstore(
               clone,
               0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
           )
           mstore(add(clone, 0x14), targetBytes)
           mstore(
               add(clone, 0x28),
               0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
           )
           cloneAddress := create2(0, clone, 0x37, salt)
       }
   }

我不太確定它的字節碼是否正在改變,或者它是否buildCreate2Address需要更新。

事實證明,複製是使用標準EIP 1167創建的,因此它具有與原始轉發器不同的創建字節碼。因此,要計算複製的確定性地址,您可以修改buildCreate2Address函式的字節碼參數,也可以在合約中實現以下函式:

   function predictCloneAddress(address forwarderAddress_, uint256 salt_)
       public
       view
       returns (address)
   {
       address predictedAddress =
           Clones.predictDeterministicAddress(
               forwarderAddress_,
               bytes32(salt_)
           );

       return predictedAddress;
   }

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