Hardhat

hardhat-deploy 確定性部署

  • March 8, 2022

我正在嘗試部署契約,將其刪除,然後使用CREATE2hardhat-deploy確定性功能再次部署它。

但是,我似乎無法讓我的契約具有相同的地址。這是我的兩份契約:

盒子:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

contract Box{
   function version() public pure returns (uint256) {
       return 1;
   }
   function destroy() public {
       selfdestruct(payable(msg.sender));
   }
}

盒子V2:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

contract BoxV2{
   function version() public pure returns (uint256) {
       return 2;
   }
}

這是我的部署和“升級”(確定性地銷毀和重新部署)腳本:

module.exports = async ({ getNamedAccounts, deployments }) => {
   const { deploy } = deployments
   const { deployer } = await getNamedAccounts()

   const box = await deploy("Box", {
       from: deployer,
       args: [],
       deterministicDeployment: "0x1234",
   })

   const boxContract = await ethers.getContract("Box")
   await boxContract.destroy()
   
   const boxV2 = await deploy("BoxV2", {
       from: deployer,
       args: [],
       deterministicDeployment: "0x1234",
   })
   console.log(`Box address ${box.address}`)
   console.log(`BoxV2 address ${boxV2.address}`)
}

但是,我得到不同的地址:

Box address 0x5c5457177d92B27981809C6B5a3C960E69a2Cb23
BoxV2 address 0xBCf2C4fE08453C6898E7C18eFE4AF24521196622

為了使用 Create2 並獲得相同的地址,您必須傳遞相同的變數:

create2(someValueToPreventCollisionWithCreate, msg.sender, salt, contractBytecode)

因此,如果您contractBytecode在 create2 中的不同,您將不會獲得相同的地址。要製作變形合約,您必須部署一個代理合約,該合約將指向您的不同程式碼。像這樣的東西:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

// See import "@openzeppelin/contracts/proxy/Proxy.sol"; for full example
import "@openzeppelin/contracts/proxy/Proxy.sol";

contract MetamorphicProxy is Proxy {
   // Don't do this!!
   // You'll get storage clashes!
   // address public s_implementation;

   // This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1
   bytes32 private constant _IMPLEMENTATION_SLOT =
       0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

   function setImplementation(address newImplementation) public {
       assembly {
           sstore(_IMPLEMENTATION_SLOT, newImplementation)
       }
   }

   function _implementation() internal view override returns (address implementationAddress) {
       assembly {
           implementationAddress := sload(_IMPLEMENTATION_SLOT)
       }
   }

   function destroy() public {
       selfdestruct(payable(msg.sender));
   }
}

然後,銷毀代理合約並使用不同的實現地址重新部署它以擦除儲存並重新部署。

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