Skip to content

Commit c56120e

Browse files
committed
deploy script: more additions/fixes
1 parent d58de7e commit c56120e

File tree

14 files changed

+560
-215
lines changed

14 files changed

+560
-215
lines changed

script/Deploy.sol

Lines changed: 0 additions & 94 deletions
This file was deleted.

script/DeployMain.s.sol

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.20;
3+
4+
import {Script} from "forge-std/Script.sol";
5+
import {console2} from "forge-std/console2.sol";
6+
import {IDiamondCut} from "../src/facets/Diamond/IDiamondCut.sol"; // Adjust to your imports
7+
import {DiamondCutFacet} from "../src/facets/Diamond/DiamondCutFacet.sol"; // Example; not used directly
8+
9+
contract DeployDiamond is Script {
10+
// Configurable list: Add new facet names here (e.g., "MarketplaceFacet")
11+
string[] public facetNames = [
12+
"DiamondCutFacet",
13+
"DiamondLoupeFacet",
14+
"OwnershipFacet",
15+
"ERC20Facet"
16+
// Add "MarketplaceFacet" here for auto-inclusion
17+
];
18+
19+
function setUp() public {} // Optional setup
20+
21+
function run() public {
22+
vm.startBroadcast();
23+
24+
// Step 1: Dynamically deploy facets and build FacetCut[]
25+
IDiamondCut.FacetCut[] memory facetCuts = _buildFacetCuts();
26+
27+
// Step 2: Your existing Registry registration (pseudo-code; adapt as needed)
28+
// Registry registry = new Registry();
29+
// registry.registerFacets(facetCuts);
30+
31+
// Step 3: Deploy Diamond (adapt to your DiamondDeploy logic)
32+
// address diamond = address(new DiamondDeploy(facetCuts));
33+
// ... (e.g., cut the diamond, transfer ownership)
34+
35+
// Optional: Persist selectors to JSON for reuse
36+
_persistSelectors(facetCuts);
37+
38+
vm.stopBroadcast();
39+
}
40+
41+
/// @dev Builds FacetCut[] by dynamically fetching selectors and deploying facets.
42+
function _buildFacetCuts() internal returns (IDiamondCut.FacetCut[] memory cuts) {
43+
uint256 numFacets = facetNames.length;
44+
cuts = new IDiamondCut.FacetCut[](numFacets);
45+
46+
for (uint256 i = 0; i < numFacets; ++i) {
47+
string memory name = facetNames[i];
48+
string memory contractId = string.concat("src/facets/", name, ".sol:", name);
49+
50+
// Fetch methodIdentifiers JSON
51+
string[] memory inspectCmd = new string[](5);
52+
inspectCmd[0] = "forge";
53+
inspectCmd[1] = "inspect";
54+
inspectCmd[2] = contractId;
55+
inspectCmd[3] = "methodIdentifiers";
56+
inspectCmd[4] = "--json";
57+
58+
bytes memory outputBytes = vm.ffi(inspectCmd);
59+
string memory json = string(outputBytes);
60+
61+
// Parse all selector hex strings (e.g., ["0xa9059cbb", ...])
62+
bytes memory selBytes = vm.parseJson(json, ".methodIdentifiers.[]");
63+
string[] memory selStrings = abi.decode(selBytes, (string[]));
64+
65+
// Convert to bytes4[]
66+
bytes4[] memory selectors = new bytes4[](selStrings.length);
67+
for (uint256 j = 0; j < selStrings.length; ++j) {
68+
selectors[j] = bytes4(vm.parseBytes32(selStrings[j]));
69+
}
70+
71+
// Fetch bytecode JSON for deployment
72+
string[] memory bytecodeCmd = new string[](5);
73+
bytecodeCmd[0] = "forge";
74+
bytecodeCmd[1] = "inspect";
75+
bytecodeCmd[2] = contractId;
76+
bytecodeCmd[3] = "bytecode";
77+
bytecodeCmd[4] = "--json";
78+
79+
bytes memory bytecodeOutputBytes = vm.ffi(bytecodeCmd);
80+
string memory bytecodeJson = string(bytecodeOutputBytes);
81+
82+
// Parse bytecode hex string (e.g., "0x6080604052...")
83+
string memory bytecodeStr = abi.decode(vm.parseJson(bytecodeJson, ".bytecode"), (string));
84+
bytes memory bytecode = vm.parseBytes(bytecodeStr); // Handles full hex
85+
86+
// Deploy facet
87+
address facetAddr = _deployCode(bytecode);
88+
89+
// Build cut (Add action; adjust if Replace/Remove needed)
90+
cuts[i] = IDiamondCut.FacetCut({
91+
facetAddress: facetAddr,
92+
action: IDiamondCut.FacetCutAction.Add,
93+
functionSelectors: selectors
94+
});
95+
96+
console2.log("Deployed %s at %s with %d selectors", name, facetAddr, selectors.length);
97+
}
98+
}
99+
100+
/// @dev Deploys raw creation bytecode (assumes no constructor args).
101+
function _deployCode(bytes memory code) internal returns (address addr) {
102+
assembly {
103+
addr := create(0, add(code, 0x20), mload(code))
104+
if iszero(extcodesize(addr)) {
105+
revert(0, 0)
106+
}
107+
}
108+
}
109+
110+
/// @dev Optional: Persist all selectors to JSON (e.g., for tests or reuse).
111+
function _persistSelectors(IDiamondCut.FacetCut[] memory cuts) internal {
112+
string memory root = vm.projectRoot();
113+
string memory filePath = string.concat(root, "/facet-selectors.json");
114+
115+
// Manual JSON build (simple; use forge-std/StdJson.sol for complex structs)
116+
string memory jsonContent = '{"facets": [';
117+
for (uint256 i = 0; i < cuts.length; ++i) {
118+
string memory name = facetNames[i]; // Map back via index
119+
jsonContent = string.concat(jsonContent, '{"name":"', name, '","selectors":[');
120+
for (uint256 j = 0; j < cuts[i].functionSelectors.length; ++j) {
121+
// Convert bytes4 back to hex string for JSON
122+
bytes memory selHex = new bytes(10); // "0x" + 8 hex chars
123+
selHex[0] = bytes1(hex"30"); // '0'
124+
selHex[1] = bytes1(hex"78"); // 'x'
125+
// ... (assembly or loop to append hex; simplified here)
126+
// Full impl: Use toHexString from forge-std/Test.sol
127+
jsonContent = string.concat(jsonContent, '"0x', _toHexString(cuts[i].functionSelectors[j]), '"');
128+
if (j < cuts[i].functionSelectors.length - 1) jsonContent = string.concat(jsonContent, ",");
129+
}
130+
jsonContent = string.concat(jsonContent, ']}}');
131+
if (i < cuts.length - 1) jsonContent = string.concat(jsonContent, ",");
132+
}
133+
jsonContent = string.concat(jsonContent, ']}');
134+
135+
vm.writeFile(filePath, jsonContent);
136+
console2.log("Persisted selectors to %s", filePath);
137+
}
138+
139+
// Helper: bytes4 to hex string (adapt from forge-std/Test.sol)
140+
function _toHexString(bytes4 value) internal pure returns (string memory) {
141+
bytes memory str = new bytes(10);
142+
str[0] = "0";
143+
str[1] = "x";
144+
for (uint256 i = 0; i < 4; ++i) {
145+
uint8 _byte = uint8(uint32(value) >> (8 * (3 - i)));
146+
str[2 + i * 2] = _toHexDigit(_byte >> 4);
147+
str[3 + i * 2] = _toHexDigit(_byte & 0x0f);
148+
}
149+
return string(str);
150+
}
151+
152+
function _toHexDigit(uint8 digit) internal pure returns (bytes1) {
153+
if (digit < 10) return bytes1(char(uint8(48 + digit)));
154+
return bytes1(char(uint8(97 + digit - 10)));
155+
}
156+
157+
function char(uint8 b) internal pure returns (bytes1) {
158+
return bytes1(b);
159+
}
160+
}

src/Diamond.sol

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ contract Diamond is iOwnership {
3333
ds.slot := position
3434
}
3535
// get facet from function selector
36-
console.logBytes4(msg.sig);
3736
address facet = ds.selectorToFacetAndPosition[msg.sig].facetAddress;
3837
require(facet != address(0), "Diamond: Function does not exist");
3938
// Execute external function from facet using delegatecall and return any value.

src/IERC165.sol

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
interface IERC165 {
5+
/// @notice Query if a contract implements an interface
6+
/// @param interfaceId The interface identifier, as specified in ERC-165
7+
/// @dev Interface identification is specified in ERC-165. This function
8+
/// uses less than 30,000 gas.
9+
/// @return `true` if the contract implements `interfaceID` and
10+
/// `interfaceID` is not 0xffffffff, `false` otherwise
11+
function supportsInterface(bytes4 interfaceId) external view returns (bool);
12+
}

src/deploy/diamondDeploy.sol

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ pragma solidity ^0.8.9;
33

44
import "../facets/Diamond/IDiamondCut.sol";
55
import "./IDiamondDeploy.sol";
6-
import "hardhat/console.sol";
76

87
contract DiamondDeploy {
98
address public registryAddress;
@@ -17,14 +16,11 @@ contract DiamondDeploy {
1716
}
1817

1918
function deploy(address owner, uint256 _salt, bytes calldata _bytecode, IDiamondCut.FacetCut[] memory _facetCuts) external returns (address diamond_) {
20-
console.log(3);
2119
require(msg.sender == registryAddress,"Must be initiated from the MassDX registry.");
22-
console.log(4);
2320
// Initialize a variable to hold the deployed address
2421
address deployedAddress;
2522

2623
require(keccak256(_bytecode) == bytecodeHash, "Bytecode must match that of the Diamond associated with this contract.");
27-
console.log(5);
2824
// ABI encode the constructor parameters
2925
bytes memory encodedParams = abi.encode(owner, msg.sender, _facetCuts);
3026

@@ -34,7 +30,6 @@ contract DiamondDeploy {
3430
// Use CREATE2 opcode to deploy the contract with static bytecode
3531
// Generate a unique salt based on msg.sender
3632
bytes32 salt = keccak256(abi.encodePacked(msg.sender, _salt, encodedParams));
37-
console.log(55);
3833
// The following assembly block deploys the contract using CREATE2 opcode
3934
assembly {
4035
deployedAddress := create2(
@@ -48,15 +43,8 @@ contract DiamondDeploy {
4843
revert(0, 0)
4944
}
5045
}
51-
console.log(6);
5246
return deployedAddress;
5347
}
5448

5549

5650
}
57-
58-
/**
59-
* We store hash of bytecode.
60-
* Client deploys bytecode.
61-
* Checks hash, deploys.
62-
*/

0 commit comments

Comments
 (0)