Skip to content

Commit b9040ad

Browse files
author
Ryan
committed
Updated scripts
1 parent 5da6242 commit b9040ad

8 files changed

Lines changed: 316 additions & 70 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ docs/
1212

1313
# Dotenv file
1414
.env
15+
16+
.DS_Store

.prettierrc.json

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
{
2+
"printWidth": 120,
3+
"tabWidth": 4,
4+
"useTabs": true,
5+
"singleQuote": false,
6+
"trailingComma": "all",
27
"overrides": [
38
{
49
"files": "*.sol",
510
"options": {
6-
"printWidth": 120,
7-
"tabWidth": 4,
8-
"useTabs": true,
9-
"singleQuote": false,
1011
"bracketSpacing": false
1112
}
1213
},
1314
{
14-
"files": ["*.json"],
15-
"options": {
16-
"tabWidth": 4,
17-
"useTabs": true,
18-
"singleQuote": false
19-
}
15+
"files": ["*.ts", "*.js", "*.json"],
16+
"options": {}
2017
}
2118
]
2219
}

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,21 @@
44

55
## Features
66

7-
- **CREATE**: Traditional contract deployment
8-
- **CREATE2**: Deterministic contract deployment
9-
- **CREATE3**: Chain-agnostic deterministic deployment
10-
- **EIP-1167 Clone**: Minimal proxy pattern deployment
11-
- **EIP-1167 CloneDeterministic**: Deterministic minimal proxy deployment
12-
- **Address Prediction**: Compute contract addresses before deployment
13-
- **Dual Approach**: Use as a library in your contracts or interact with the deployed factory
7+
- **CREATE**: Traditional contract deployment
8+
- **CREATE2**: Deterministic contract deployment
9+
- **CREATE3**: Chain-agnostic deterministic deployment
10+
- **EIP-1167 Clone**: Minimal proxy pattern deployment
11+
- **EIP-1167 CloneDeterministic**: Deterministic minimal proxy deployment
12+
- **Address Prediction**: Compute contract addresses before deployment
13+
- **Dual Approach**: Use as a library in your contracts or interact with the deployed factory
1414

1515
## Directory
1616

1717
```text
1818
createx/
1919
├── deployments/...
2020
├── script/
21-
│ ├── Create.s.sol
21+
│ ├── CreateX.s.sol
2222
│ └── Deploy.s.sol
2323
├── src/
2424
│ ├── CreateX.sol
@@ -322,19 +322,19 @@ function deployCreateX(
322322

323323
The factory includes built-in access control through salt validation:
324324

325-
- For salted deployments (CREATE2, CREATE3, CloneDeterministic), the first 20 bytes of the salt must match either:
326-
- The caller's address (for user-specific deployments)
327-
- Zero address (for open deployments)
325+
- For salted deployments (CREATE2, CREATE3, CloneDeterministic), the first 20 bytes of the salt must match either:
326+
- The caller's address (for user-specific deployments)
327+
- Zero address (for open deployments)
328328

329329
---
330330

331331
## Acknowledgements
332332

333333
The following repositories served as key references during the development of this project:
334334

335-
- [Solady](https://github.com/Vectorized/solady)
336-
- [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts)
335+
- [Solady](https://github.com/Vectorized/solady)
336+
- [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts)
337337

338338
## Author
339339

340-
- [fomoweth](https://github.com/fomoweth)
340+
- [fomoweth](https://github.com/fomoweth)

foundry.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ ffi = true
99
optimizer = true
1010
optimizer_runs = 44444444
1111
via_ir = true
12+
1213
fs_permissions = [
1314
{ access = "read-write", path = "./deployments"},
1415
{ access = "read", path = "./out"},
1516
{ access = "read", path = "./script" },
1617
{ access = "read", path = "./test"}
1718
]
19+
1820
gas_reports = ["CreateXFactory"]
1921

2022
[fuzz]

script/BaseScript.sol

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.30;
3+
4+
import {Script, console2 as console, stdJson} from "forge-std/Script.sol";
5+
import {ICreateXFactory} from "src/ICreateXFactory.sol";
6+
import {VmSafe} from "forge-std/Vm.sol";
7+
8+
abstract contract BaseScript is Script {
9+
using stdJson for string;
10+
11+
string private constant DEFAULT_MNEMONIC = "test test test test test test test test test test test junk";
12+
13+
string private constant DEFAULT_CHAINS = "ethereum, optimism, polygon, base, arbitrum";
14+
15+
address internal broadcaster;
16+
17+
modifier broadcast() {
18+
vm.startBroadcast(broadcaster);
19+
_;
20+
vm.stopBroadcast();
21+
}
22+
23+
modifier fork(string memory chainAlias) {
24+
vm.createSelectFork(chainAlias);
25+
_;
26+
}
27+
28+
function setUp() public virtual {
29+
broadcaster = vm.rememberKey(configurePrivateKey());
30+
}
31+
32+
function configurePrivateKey() internal view virtual returns (uint256 privateKey) {
33+
privateKey = vm.envOr({
34+
name: "PRIVATE_KEY",
35+
defaultValue: vm.deriveKey({
36+
mnemonic: vm.envOr({name: "MNEMONIC", defaultValue: DEFAULT_MNEMONIC}),
37+
index: uint8(vm.envOr({name: "EOA_INDEX", defaultValue: uint256(0)}))
38+
})
39+
});
40+
}
41+
42+
function generateJson(string memory path, string memory name, address instance, bytes32 salt) internal virtual {
43+
string memory json = "json";
44+
json.serialize("address", instance);
45+
json.serialize("blockNumber", vm.getBlockNumber());
46+
json.serialize("timestamp", vm.getBlockTimestamp());
47+
json.serialize("salt", salt);
48+
json = json.serialize("name", name);
49+
json.write(path);
50+
}
51+
52+
function promptChains() internal virtual returns (string[] memory chainAliases) {
53+
string memory input = prompt("Chains separated by ','", defaultChains());
54+
return vm.split(vm.replace(input, " ", ""), ",");
55+
}
56+
57+
function prompt(string memory promptText) internal returns (string memory input) {
58+
return prompt(promptText, new string(0));
59+
}
60+
61+
function prompt(string memory promptText, string memory defaultValue) internal returns (string memory input) {
62+
input = vm.prompt(string.concat(promptText, " (default: `", defaultValue, "`)"));
63+
if (bytes(input).length == 0) input = defaultValue;
64+
}
65+
66+
function promptAddress(string memory promptText, address defaultValue) internal returns (address) {
67+
return vm.parseAddress(prompt(promptText, vm.toString(defaultValue)));
68+
}
69+
70+
function promptAddress(string memory promptText) internal returns (address) {
71+
return promptAddress(promptText, address(0));
72+
}
73+
74+
function promptBool(string memory promptText, bool defaultValue) internal returns (bool) {
75+
return vm.parseBool(prompt(promptText, vm.toString(defaultValue)));
76+
}
77+
78+
function promptBool(string memory promptText) internal returns (bool) {
79+
return promptBool(promptText, false);
80+
}
81+
82+
function promptUint256(string memory promptText, uint256 defaultValue) internal returns (uint256) {
83+
return vm.parseUint(prompt(promptText, vm.toString(defaultValue)));
84+
}
85+
86+
function promptUint256(string memory promptText) internal returns (uint256) {
87+
return promptUint256(promptText, uint256(0));
88+
}
89+
90+
function promptInt256(string memory promptText, int256 defaultValue) internal returns (int256) {
91+
return vm.parseInt(prompt(promptText, vm.toString(defaultValue)));
92+
}
93+
94+
function promptInt256(string memory promptText) internal returns (int256) {
95+
return promptInt256(promptText, int256(0));
96+
}
97+
98+
function promptBytes32(string memory promptText, bytes32 defaultValue) internal returns (bytes32) {
99+
return vm.parseBytes32(prompt(promptText, vm.toString(defaultValue)));
100+
}
101+
102+
function promptBytes32(string memory promptText) internal returns (bytes32) {
103+
return promptBytes32(promptText, bytes32(0));
104+
}
105+
106+
function promptBytes(string memory promptText, bytes memory defaultValue) internal returns (bytes memory) {
107+
return vm.parseBytes(prompt(promptText, vm.toString(defaultValue)));
108+
}
109+
110+
function promptBytes(string memory promptText) internal returns (bytes memory) {
111+
return promptBytes(promptText, new bytes(0));
112+
}
113+
114+
function defaultChains() internal view virtual returns (string memory chains) {
115+
return DEFAULT_CHAINS;
116+
}
117+
118+
function defaultSalt() internal view virtual returns (bytes32) {
119+
return bytes32(0);
120+
}
121+
}

script/CreateX.s.sol

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.30;
3+
4+
import {ICreateXFactory} from "src/ICreateXFactory.sol";
5+
import {CreateX as CreateXLib} from "src/CreateX.sol";
6+
import {BaseScript} from "./BaseScript.sol";
7+
import {ERC1967_PROXY_BYTECODE, TRANSPARENT_PROXY_BYTECODE} from "./Precompiles.sol";
8+
9+
contract CreateX is BaseScript {
10+
ICreateXFactory internal constant CREATEX_FACTORY = ICreateXFactory(0xfC5D1D7b066730fC403C994365205a96fE1d8Bcf);
11+
12+
function deployContract() internal virtual broadcast returns (address) {
13+
uint256 creationType = promptCreationType();
14+
bytes memory initCode;
15+
bytes32 salt;
16+
uint256 value;
17+
18+
if (creationType < uint8(ICreateXFactory.CreationType.Clone)) {
19+
bytes memory creationCode = vm.getCode(prompt("Artifact path"));
20+
bytes memory arguments = promptBytes("Constructor arguments");
21+
initCode = bytes.concat(creationCode, arguments);
22+
} else {
23+
address implementation = vm.promptAddress("Implementation");
24+
initCode = abi.encodePacked(implementation);
25+
}
26+
27+
if (
28+
creationType != uint8(ICreateXFactory.CreationType.CREATE) &&
29+
creationType != uint8(ICreateXFactory.CreationType.Clone)
30+
) {
31+
salt = promptBytes32("Salt", defaultSalt());
32+
}
33+
34+
value = promptUint256("msg.value");
35+
36+
return deployCreateX(creationType, initCode, salt, value);
37+
}
38+
39+
function deployCreateX(uint256 creationType, bytes memory initCode, bytes32 salt) internal returns (address) {
40+
return deployCreateX(creationType, initCode, salt, 0);
41+
}
42+
43+
function deployCreateX(
44+
uint256 creationType,
45+
bytes memory initCode,
46+
bytes32 salt,
47+
uint256 value
48+
) internal returns (address) {
49+
return CREATEX_FACTORY.createX{value: value}(asCreationType(creationType), initCode, salt);
50+
}
51+
52+
function deployCreate(bytes memory initCode) internal returns (address) {
53+
return deployCreate(initCode, 0);
54+
}
55+
56+
function deployCreate(bytes memory initCode, uint256 value) internal returns (address) {
57+
return CREATEX_FACTORY.create{value: value}(initCode);
58+
}
59+
60+
function deployCreate2(bytes memory initCode, bytes32 salt) internal returns (address) {
61+
return deployCreate2(initCode, salt, 0);
62+
}
63+
64+
function deployCreate2(bytes memory initCode, bytes32 salt, uint256 value) internal returns (address) {
65+
return CREATEX_FACTORY.create2{value: value}(initCode, salt);
66+
}
67+
68+
function deployCreate3(bytes memory initCode, bytes32 salt) internal returns (address) {
69+
return deployCreate3(initCode, salt, 0);
70+
}
71+
72+
function deployCreate3(bytes memory initCode, bytes32 salt, uint256 value) internal returns (address) {
73+
return CREATEX_FACTORY.create3{value: value}(initCode, salt);
74+
}
75+
76+
function deployClone(address implementation) internal returns (address) {
77+
return deployClone(implementation, 0);
78+
}
79+
80+
function deployClone(address implementation, uint256 value) internal returns (address) {
81+
return CREATEX_FACTORY.clone{value: value}(implementation);
82+
}
83+
84+
function deployCloneDeterministic(address implementation, bytes32 salt) internal returns (address) {
85+
return deployCloneDeterministic(implementation, salt, 0);
86+
}
87+
88+
function deployCloneDeterministic(address implementation, bytes32 salt, uint256 value) internal returns (address) {
89+
return CREATEX_FACTORY.cloneDeterministic{value: value}(implementation, salt);
90+
}
91+
92+
function deployERC1967Proxy(
93+
address implementation,
94+
bytes memory data,
95+
uint256 value
96+
) internal returns (address proxy) {
97+
bytes memory arguments = abi.encode(implementation, data);
98+
bytes memory initCode = bytes.concat(ERC1967_PROXY_BYTECODE, arguments);
99+
return deployCreate(initCode, value);
100+
}
101+
102+
function deployERC1967Proxy(
103+
address implementation,
104+
bytes memory data,
105+
bytes32 salt,
106+
uint256 value
107+
) internal returns (address proxy) {
108+
bytes memory arguments = abi.encode(implementation, data);
109+
bytes memory initCode = bytes.concat(ERC1967_PROXY_BYTECODE, arguments);
110+
return deployCreate2(initCode, salt, value);
111+
}
112+
113+
function deployTransparentProxy(
114+
address owner,
115+
address implementation,
116+
bytes memory data,
117+
uint256 value
118+
) internal returns (address proxy, address proxyAdmin) {
119+
bytes memory arguments = abi.encode(owner, implementation, data);
120+
bytes memory initCode = bytes.concat(TRANSPARENT_PROXY_BYTECODE, arguments);
121+
proxyAdmin = CreateXLib.computeCreateAddress(proxy = deployCreate(initCode, value), 1);
122+
}
123+
124+
function deployTransparentProxy(
125+
address owner,
126+
address implementation,
127+
bytes memory data,
128+
bytes32 salt,
129+
uint256 value
130+
) internal returns (address proxy, address proxyAdmin) {
131+
bytes memory arguments = abi.encode(owner, implementation, data);
132+
bytes memory initCode = bytes.concat(TRANSPARENT_PROXY_BYTECODE, arguments);
133+
proxyAdmin = CreateXLib.computeCreateAddress(proxy = deployCreate2(initCode, salt, value), 1);
134+
}
135+
136+
function promptCreationType() internal returns (uint256) {
137+
string memory promptText = "CreationType (0: CREATE, 1: CREATE2, 2: CREATE3, 3: Clone, 4: CloneDeterministic)";
138+
return vm.promptUint(promptText);
139+
}
140+
141+
function asCreationType(uint256 creationType) internal pure returns (ICreateXFactory.CreationType) {
142+
if (creationType > uint8(type(ICreateXFactory.CreationType).max)) revert ICreateXFactory.InvalidCreationType();
143+
return ICreateXFactory.CreationType(creationType);
144+
}
145+
}

0 commit comments

Comments
 (0)