Skip to content

Commit ee3147e

Browse files
committed
Merge branch 'deploy'
2 parents 9a2bd17 + 42d1e1f commit ee3147e

File tree

19 files changed

+314
-105
lines changed

19 files changed

+314
-105
lines changed

.vscode/settings.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
// Solidity extension settings for import resolution
3+
"solidity.remappings": [
4+
"forge-std/=lib/forge-std/src/"
5+
],
6+
"solidity.packageDefaultDependenciesDirectory": "lib",
7+
"solidity.compileUsingRemoteVersion": "v0.8.30",
8+
9+
// Enable GitHub Copilot
10+
"github.copilot.enable": true,
11+
"github.copilot.inlineSuggest.enable": true,
12+
"editor.inlineSuggest.enabled": true,
13+
14+
// File associations
15+
"files.associations": {
16+
"*.sol": "solidity"
17+
},
18+
19+
// Editor suggestions
20+
"editor.quickSuggestions": {
21+
"other": true,
22+
"comments": false,
23+
"strings": true
24+
},
25+
"editor.suggestOnTriggerCharacters": true,
26+
"editor.suggestSelection": "first"
27+
}

src/access/Owner/LibOwner.sol

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ library LibOwner {
2929
}
3030
}
3131

32+
function setContractOwner(address _initialOwner) internal {
33+
OwnerStorage storage s = getStorage();
34+
s.owner = _initialOwner;
35+
emit OwnershipTransferred(address(0), _initialOwner);
36+
}
37+
3238
/// @notice Get the address of the owner
3339
/// @return The address of the owner.
3440
function owner() internal view returns (address) {
@@ -54,13 +60,4 @@ library LibOwner {
5460
s.owner = _newOwner;
5561
emit OwnershipTransferred(previousOwner, _newOwner);
5662
}
57-
58-
/// @notice Renounce ownership of the contract
59-
/// @dev Sets the owner to address(0), disabling all functions restricted to the owner.
60-
function renounceOwnership() internal {
61-
OwnerStorage storage s = getStorage();
62-
address previousOwner = s.owner;
63-
s.owner = address(0);
64-
emit OwnershipTransferred(previousOwner, address(0));
65-
}
6663
}

src/diamond/ComposeDiamond.sol

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >=0.8.30;
3+
4+
contract ComposeDiamond {
5+
bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("compose.diamond");
6+
7+
/// @notice Data stored for each function selector.
8+
/// @dev Facet address of function selector.
9+
/// Position of selector in the 'bytes4[] selectors' array.
10+
struct FacetAndPosition {
11+
address facet;
12+
uint32 position;
13+
}
14+
15+
/// @custom:storage-location erc8042:compose.diamond
16+
struct DiamondStorage {
17+
mapping(bytes4 functionSelector => FacetAndPosition) facetAndPosition;
18+
}
19+
20+
function getStorage() internal pure returns (DiamondStorage storage s) {
21+
bytes32 position = DIAMOND_STORAGE_POSITION;
22+
assembly {
23+
s.slot := position
24+
}
25+
}
26+
27+
error FunctionNotFound(bytes4 _selector);
28+
29+
// Find facet for function that is called and execute the
30+
// function if a facet is found and return any value.
31+
fallback() external payable {
32+
DiamondStorage storage s = getStorage();
33+
// get facet from function selector
34+
address facet = s.facetAndPosition[msg.sig].facet;
35+
if (facet == address(0)) {
36+
revert FunctionNotFound(msg.sig);
37+
}
38+
// Execute external function from facet using delegatecall and return any value.
39+
assembly {
40+
// copy function selector and any arguments
41+
calldatacopy(0, 0, calldatasize())
42+
// execute function call using the facet
43+
let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
44+
// get any return value
45+
returndatacopy(0, 0, returndatasize())
46+
// return any return value or error back to the caller
47+
switch result
48+
case 0 {
49+
revert(0, returndatasize())
50+
}
51+
default {
52+
return(0, returndatasize())
53+
}
54+
}
55+
}
56+
57+
receive() external payable {}
58+
}

src/diamond/DiamondCutFacet.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ contract DiamondCutFacet {
4141
/// Position of selector in the 'bytes4[] selectors' array
4242
struct FacetAndPosition {
4343
address facet;
44-
uint16 position;
44+
uint32 position;
4545
}
4646

4747
/// @custom:storage-location erc8042:compose.diamond

src/diamond/DiamondLoupeFacet.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ contract DiamondLoupeFacet {
1111
/// Position of selector in the 'bytes4[] selectors' array.
1212
struct FacetAndPosition {
1313
address facet;
14-
uint16 position;
14+
uint32 position;
1515
}
1616

1717
/// @custom:storage-location erc8042:compose.diamond
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity >=0.8.30;
33

4-
library LibDiamond {
4+
library LibDiamondCut {
55
error NoSelectorsProvidedForFacet(address _facet);
66
error NoBytecodeAtAddress(address _contractAddress, string _message);
77
error RemoveFacetAddressMustBeZeroAddress(address _facet);
@@ -21,7 +21,7 @@ library LibDiamond {
2121
/// Position of selector in the 'bytes4[] selectors' array
2222
struct FacetAndPosition {
2323
address facet;
24-
uint16 position;
24+
uint32 position;
2525
}
2626

2727
/// @custom:storage-location erc8042:compose.diamond
@@ -44,7 +44,7 @@ library LibDiamond {
4444
revert NoBytecodeAtAddress(_facet, "LibDiamond: Add facet has no code");
4545
}
4646
// The position to store the next selector in the selectors array
47-
uint16 selectorPosition = uint16(s.selectors.length);
47+
uint32 selectorPosition = uint32(s.selectors.length);
4848
for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
4949
bytes4 selector = _functionSelectors[selectorIndex];
5050
address oldFacet = s.facetAndPosition[selector].facet;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >=0.8.30;
3+
4+
import {ComposeDiamond} from "../ComposeDiamond.sol";
5+
import {LibDiamondDeploy, Facet} from "./LibDiamondDeploy.sol";
6+
import {LibOwner} from "../../access/Owner/LibOwner.sol";
7+
import {LibERC721} from "../../token/ERC721/ERC721/LibERC721.sol";
8+
import {LibERC165} from "../../interfaceDetection/ERC165/LibERC165.sol";
9+
import {IERC721} from "../../interfaces/IERC721.sol";
10+
import {IERC721Metadata} from "../../interfaces/IERC721Metadata.sol";
11+
12+
contract ExampleDiamond is ComposeDiamond {
13+
/// @notice Struct to hold facet address and its function selectors.
14+
// struct Facet {
15+
// address facet;
16+
// bytes4[] functionSelectors;
17+
// }
18+
19+
/// @notice Initializes the diamond contract with facets, owner and other data.
20+
/// @dev Adds all provided facets to the diamond's function selector mapping and sets the contract owner.
21+
/// Each facet in the array will have its function selectors registered to enable delegatecall routing.
22+
/// @param _facets Array of facet addresses and their corresponding function selectors to add to the diamond.
23+
/// @param _diamondOwner Address that will be set as the owner of the diamond contract.
24+
constructor(Facet[] memory _facets, address _diamondOwner) {
25+
LibDiamondDeploy.addFunctions(_facets);
26+
27+
// Initialize storage variables
28+
//////////////////////////////////////////////////////
29+
30+
// Setting the contract owner
31+
LibOwner.setContractOwner(_diamondOwner);
32+
// Setting ERC721 token details
33+
LibERC721.setMetadata("ExampleDiamondNFT", "EDN", "https://example.com/metadata/");
34+
// Registering ERC165 interfaces
35+
LibERC165.registerInterface(type(IERC721).interfaceId);
36+
LibERC165.registerInterface(type(IERC721Metadata).interfaceId);
37+
}
38+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >=0.8.30;
3+
4+
/// @notice Struct to hold facet address and its function selectors.
5+
struct Facet {
6+
address facet;
7+
bytes4[] functionSelectors;
8+
}
9+
10+
library LibDiamondDeploy {
11+
bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("compose.diamond");
12+
13+
/// @notice Data stored for each function selector.
14+
/// @dev Facet address of function selector.
15+
/// Position of selector in the 'bytes4[] selectors' array.
16+
struct FacetAndPosition {
17+
address facet;
18+
uint32 position;
19+
}
20+
21+
/// @custom:storage-location erc8042:compose.diamond
22+
struct DiamondStorage {
23+
mapping(bytes4 functionSelector => FacetAndPosition) facetAndPosition;
24+
// Array of all function selectors that can be called in the diamond.
25+
bytes4[] selectors;
26+
}
27+
28+
function getStorage() internal pure returns (DiamondStorage storage s) {
29+
bytes32 position = DIAMOND_STORAGE_POSITION;
30+
assembly {
31+
s.slot := position
32+
}
33+
}
34+
35+
error NoBytecodeAtAddress(address _contractAddress, string _message);
36+
error CannotAddFunctionToDiamondThatAlreadyExists(bytes4 _selector);
37+
38+
function addFunctions(Facet[] memory _facets) internal {
39+
DiamondStorage storage s = getStorage();
40+
uint32 selectorPosition = uint32(s.selectors.length);
41+
for (uint256 i; i < _facets.length; i++) {
42+
address facet = _facets[i].facet;
43+
if (facet.code.length == 0) {
44+
revert NoBytecodeAtAddress(facet, "LibDiamondDeploy: Add facet has no code");
45+
}
46+
bytes4[] memory functionSelectors = _facets[i].functionSelectors;
47+
for (uint256 selectorIndex; selectorIndex < functionSelectors.length; selectorIndex++) {
48+
bytes4 selector = functionSelectors[selectorIndex];
49+
address oldFacet = s.facetAndPosition[selector].facet;
50+
if (oldFacet != address(0)) {
51+
revert CannotAddFunctionToDiamondThatAlreadyExists(selector);
52+
}
53+
s.facetAndPosition[selector] = FacetAndPosition(facet, selectorPosition);
54+
s.selectors.push(selector);
55+
selectorPosition++;
56+
}
57+
}
58+
}
59+
}

src/interfaces/IERC721.sol

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pragma solidity >=0.8.30;
44
/// @title ERC-721 Token Standard Interface
55
/// @notice Interface for ERC-721 token contracts with custom errors
66
/// @dev This interface includes all custom errors used by ERC-721 implementations
7+
/// Note: the ERC-165 identifier for this interface is 0x80ac58cd.
78
interface IERC721 {
89
/// @notice Error indicating the queried owner address is invalid (zero address).
910
error ERC721InvalidOwner(address _owner);
@@ -38,14 +39,6 @@ interface IERC721 {
3839
/// @notice Emitted when an operator is enabled or disabled for an owner.
3940
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
4041

41-
/// @notice Returns the token collection name.
42-
/// @return The name of the token collection.
43-
function name() external view returns (string memory);
44-
45-
/// @notice Returns the token collection symbol.
46-
/// @return The symbol of the token collection.
47-
function symbol() external view returns (string memory);
48-
4942
/// @notice Returns the number of tokens owned by a given address.
5043
/// @param _owner The address to query the balance of.
5144
/// @return The balance (number of tokens) owned by `_owner`.
@@ -95,9 +88,4 @@ interface IERC721 {
9588
/// @param _tokenId The token ID to transfer.
9689
/// @param _data Additional data with no specified format.
9790
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata _data) external;
98-
99-
/// @notice Provide the metadata URI for a given token ID.
100-
/// @param _tokenId tokenID of the NFT to query the metadata from
101-
/// @return the URI providing the detailed metadata of the specified tokenID
102-
function tokenURI(uint256 _tokenId) external view returns (string memory);
10391
}

src/interfaces/IERC721Metadata.sol

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >=0.8.30;
3+
4+
/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
5+
/// @dev See https://eips.ethereum.org/EIPS/eip-721
6+
/// Note: the ERC-165 identifier for this interface is 0x5b5e139f.
7+
interface IERC721Metadata {
8+
/* is ERC721 */
9+
/// @notice A descriptive name for a collection of NFTs in this contract
10+
function name() external view returns (string memory _name);
11+
12+
/// @notice An abbreviated name for NFTs in this contract
13+
function symbol() external view returns (string memory _symbol);
14+
15+
/// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
16+
/// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
17+
/// 3986. The URI may point to a JSON file that conforms to the "ERC721
18+
/// Metadata JSON Schema".
19+
function tokenURI(uint256 _tokenId) external view returns (string memory);
20+
}

0 commit comments

Comments
 (0)