From 027ffca1ebe738aaccb04f91e035fa11e08ec28f Mon Sep 17 00:00:00 2001 From: hotaplayer <15000810224@139.com> Date: Fri, 9 Jun 2023 18:01:21 +0800 Subject: [PATCH] create2 --- basic/77-create2/.gitignore | 11 +++ basic/77-create2/README.md | 56 ++++++++++++++ .../77-create2/contracts/ContractFactory.sol | 22 ++++++ basic/77-create2/contracts/Target.sol | 9 +++ basic/77-create2/hardhat.config.js | 6 ++ basic/77-create2/package.json | 32 ++++++++ basic/77-create2/scripts/deploy.js | 33 +++++++++ basic/77-create2/test/create2.js | 73 +++++++++++++++++++ 8 files changed, 242 insertions(+) create mode 100644 basic/77-create2/.gitignore create mode 100644 basic/77-create2/README.md create mode 100644 basic/77-create2/contracts/ContractFactory.sol create mode 100644 basic/77-create2/contracts/Target.sol create mode 100644 basic/77-create2/hardhat.config.js create mode 100644 basic/77-create2/package.json create mode 100644 basic/77-create2/scripts/deploy.js create mode 100644 basic/77-create2/test/create2.js diff --git a/basic/77-create2/.gitignore b/basic/77-create2/.gitignore new file mode 100644 index 000000000..00dad7734 --- /dev/null +++ b/basic/77-create2/.gitignore @@ -0,0 +1,11 @@ +node_modules +.env +coverage +coverage.json +typechain +typechain-types + +# Hardhat files +cache +artifacts + diff --git a/basic/77-create2/README.md b/basic/77-create2/README.md new file mode 100644 index 000000000..57a66cc05 --- /dev/null +++ b/basic/77-create2/README.md @@ -0,0 +1,56 @@ +# What is CREATE2 + +The Opcode CREATE2 is imported in EIP-1014,which allows the user to determinesticly deploy and address given the tripple: the deployer, the init code, and the salt, while with the traditional CREATE the address of the contract to deploy is decided by the hash of the pair: the deployer, the nonce of the deployer. + + +What's more ,with the help of CREATE2, we can even pre-calculate the address before the contract is deployed. + +# Why we need CREATE2 + +CREATE2 allows user to determinesticly deploy the contract. This is useful when we want to controll the address of the contract, especially in multi-chain scenarios. For example, if we want to have the contrac to then same address on different blockchains, we cannot use CREATE because the same deployer may have different nonces on different chains. + +# How the address is calculated? + +The address is determined by the following rule: + +``` +addr = keccak256(0xff, deployer, salt, initCodeHash) +``` + +where: +- deployer: the address of the deployer. Also, it is a CA rather than EOA since the Ethereum transaction does not support it. Usually the deployer is a factory contract like the one defined in EIP-2470. +- salt: this is a byte32 value. +- initCodeHash: the keccak256 hash of the initCode which is the creationCode(compiled from source solidity) plus the constructor args. + +# How to deploy + +## Solidity + +Basicly you can deploy it via **new**: + +``` +address actual = address(new Target{salt: salt}()); + +``` + +You can also deploy it via OZ: + +``` +import "@openzeppelin/contracts/utils/Create2.sol"; +... + + bytes32 salt = xxx; + bytes memory initCode = xxx; + address actual = Create2.deploy(0, salt,initCode); + require(actual != address(0), "deploy failed"); + +``` +## Ethers + +You can deploy it through EIP-2470. + +# QA + +## What if we deploy the contract to the address that has existing balance? + +The deployment will be successful, and the contract will hold the previous balance. diff --git a/basic/77-create2/contracts/ContractFactory.sol b/basic/77-create2/contracts/ContractFactory.sol new file mode 100644 index 000000000..679c9ead7 --- /dev/null +++ b/basic/77-create2/contracts/ContractFactory.sol @@ -0,0 +1,22 @@ +pragma solidity ^0.8.17; + +import "@openzeppelin/contracts/utils/Create2.sol"; + + +contract ContractFactory { + + event Deployed(address addr); + + function deploy(bytes calldata initCode, bytes32 salt) external { + address deployed = Create2.deploy(0, salt,initCode); + require(deployed != address(0), "deploy failed"); + emit Deployed(deployed); + } + + function computeAddress(bytes calldata initCode, bytes32 salt) external view returns(address) { + bytes32 initCodeHash = keccak256(initCode); + address addr = Create2.computeAddress(salt, initCodeHash); + return addr; + } + +} \ No newline at end of file diff --git a/basic/77-create2/contracts/Target.sol b/basic/77-create2/contracts/Target.sol new file mode 100644 index 000000000..b3419be84 --- /dev/null +++ b/basic/77-create2/contracts/Target.sol @@ -0,0 +1,9 @@ +pragma solidity ^0.8.17; + +contract Target { + uint256 private state; + + constructor(uint256 _state) { + state = _state; + } +} diff --git a/basic/77-create2/hardhat.config.js b/basic/77-create2/hardhat.config.js new file mode 100644 index 000000000..d5dd5f4e8 --- /dev/null +++ b/basic/77-create2/hardhat.config.js @@ -0,0 +1,6 @@ +require("@nomicfoundation/hardhat-toolbox"); + +/** @type import('hardhat/config').HardhatUserConfig */ +module.exports = { + solidity: "0.8.18", +}; diff --git a/basic/77-create2/package.json b/basic/77-create2/package.json new file mode 100644 index 000000000..4123055cf --- /dev/null +++ b/basic/77-create2/package.json @@ -0,0 +1,32 @@ +{ + "name": "77-create2", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-verify": "^1.0.0", + "@openzeppelin/contracts": "^4.9.1", + "@typechain/ethers-v6": "^0.4.0", + "@types/mocha": ">=9.1.0", + "hardhat": "^2.15.0", + "ts-node": ">=8.0.0", + "typescript": ">=4.5.0" + }, + "devDependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/providers": "^5.7.2", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.1", + "@nomicfoundation/hardhat-network-helpers": "^1.0.8", + "@nomicfoundation/hardhat-toolbox": "^3.0.0", + "@nomiclabs/hardhat-ethers": "^2.2.3", + "@nomiclabs/hardhat-etherscan": "^3.1.7", + "@typechain/ethers-v5": "^11.0.0", + "@typechain/hardhat": "^8.0.0", + "chai": "^4.3.7", + "ethers": "^6.4.0", + "hardhat-gas-reporter": "^1.0.9", + "solidity-coverage": "^0.8.2", + "typechain": "^8.2.0" + } +} diff --git a/basic/77-create2/scripts/deploy.js b/basic/77-create2/scripts/deploy.js new file mode 100644 index 000000000..39c08d67b --- /dev/null +++ b/basic/77-create2/scripts/deploy.js @@ -0,0 +1,33 @@ +// We require the Hardhat Runtime Environment explicitly here. This is optional +// but useful for running the script in a standalone fashion through `node