5

I am running hardhat. How do I ensure the contract below is always deployed to a specific address on my localhost dev chain, say: 0x5FbDB2315678afecb367f032d93F642f64180aa3:

  const Factory = await hre.ethers.getContractFactory("FactoryContract");
  const factory = await Factory.deploy(owner.address);

  await factory.deployed();

The reason I want to do this is I want to run subsequent scripts which interact with this contract and I don't want to have to lookup the factory contract address every time I restart my dev chain.

5
  • 1. the address is deterministic, if you either use create2, or know how many transactions have occured since the deployment. 2. What do you mean you don't want to have to look up the factory contract? All you have to do is save the artifact after deploying and then calling it using the get function
    – johnny 5
    Commented Jan 19, 2023 at 15:43
  • It is not deterministic in my experience using the above code snippet - I get a different address each time I restart the block chain and deploy for the first time. Commented Jan 19, 2023 at 17:08
  • Create2 should make it deterministic on local (assuming no transactions are made to the account in between testing)
    – johnny 5
    Commented Jan 19, 2023 at 17:27
  • Thanks, but how do I use Create2 in this script? Can't find documentation. Unless you are referring to me manually deploying first my own deployer contract which implements create2...? Commented Jan 20, 2023 at 17:10
  • Why do you even need create2, this still doesn't make sense to me, why arent you just storing the contract in the artifacts, and then call (await get("FactoryContract")).address
    – johnny 5
    Commented Jan 20, 2023 at 17:20

4 Answers 4

2
+50

Another option is the hardhat_setCode RPC method. You can set any runtime bytecode to any address. https://hardhat.org/hardhat-network/docs/reference#hardhat_setCode

await network.provider.send("hardhat_setCode", [
  "0x0d2026b3EE6eC71FC6746ADb6311F6d3Ba1C000B",
  "0xa1a2a3...",
]);

This will result in account 0x0d20...000B becoming a smart contract with bytecode a1a2a3.... If that address was already a smart contract, then its code will be replaced by the specified one.

But the caveat is - this sets/replaces the runtime bytecode, the constructor won't be executed, so you have to initialize the storage variables separately.

1

You could use deterministicDeployment from hardhat-deploy https://github.com/wighawag/hardhat-deploy#4-deterministicdeployment-ability-to-specify-a-deployment-factory

1

Deployment of contract with same address is not possible without using Factory method using smart contract. You can deploy the contract at same contract address using salt. This is called deployment of a deterministic smart contract.

Note: Before you redeploy your contract you need to destroy the contract.

Eg.

//SPDX-License-Identifier: None

pragma solidity ^ 0.8.7;


contract Factory {
    address public owner;
    uint _salt = 1234;

    address public autoCode;
    bool public paid;

    receive() payable external {
        autoCode = address(0);
        unchecked {
            deploy();
        }
        paid = true;
    }

    constructor() {
        owner = msg.sender;
    }

    function deploy() public {
        paid = false;
        if(address(this).balance > 0)
            payable(owner).transfer(address(this).balance);
        autoCode = address(new AutoCode{salt: bytes32(_salt)}());
        require(autoCode == getAddress());
    }

    function getBytecode() public pure returns (bytes memory) {
        bytes memory bytecode = type(AutoCode).creationCode;
        return abi.encodePacked(bytecode);
    }
    
    function getAddress() public view returns (address){
        bytes32 hash = keccak256(
            abi.encodePacked(bytes1(0xff), 
            address(this),
            bytes32(_salt), 
            keccak256(getBytecode())));
        return address(uint160(uint256(hash)));
    }
}

contract AutoCode {

    address public owner;

    receive() payable external {
        destroy();
    }

    constructor() {
        owner = msg.sender;
    }

    function destroy() public {
        selfdestruct(payable(owner));
    }

}
0

Did you try deploy(overrides) function with select(to address field, overrides object)? you can do it like that

const Factory = await hre.ethers.getContractFactory("FactoryContract");

// Set the desired address as the `to` field in the overrides object
const overrides = {
  to: "0x5FbDB2315678afecb367f032d93F642f64180aa3"
};

// Use the deploy function with the overrides object
const factory = await Factory.deploy(owner.address, overrides);

await factory.deployed();
2
  • Thanks Omar. However it seems you can't override the "to" field. I am getting the error: "reason: 'cannot override to', code: 'UNSUPPORTED_OPERATION'" Commented Jan 6, 2023 at 17:14
  • I apologize for this mistake, I'll do some searches about this error and I will send you my solution very soon here, sorry again! Commented Jan 6, 2023 at 17:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.