@@ -29,6 +29,124 @@ Compose uses clear naming patterns to distinguish Solidity file types:
2929- Files ending in **`Diamond.sol`** (e.g., `ExampleDiamond.sol`) implement diamond contracts.
3030- Files ending in **`Mod`** (e.g., `ERC20Mod.sol`) are **Solidity modules** — intended to be imported and used within facets or diamond contracts.
3131
32- **Exception:**
33- `DiamondMod.sol` is a **module**, not a diamond contract. It provides core diamond functionality that diamond contracts import.
32+ ### Example Solidity Module
33+
34+ Here is an example of a Solidity module that implements contract ownership functionality:
35+
36+ ```solidity
37+ // SPDX-License-Identifier: MIT
38+ pragma solidity >=0.8.30;
39+
40+ /*
41+ * @title ERC-173 Contract Ownership
42+ * @notice Provides internal functions and storage for owner management.
43+ */
44+
45+ /**
46+ * @dev This emits when ownership of a contract changes.
47+ */
48+ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
49+
50+ /*
51+ * @notice Thrown when a non-owner attempts an action restricted to owner.
52+ */
53+ error OwnerUnauthorizedAccount();
54+
55+ bytes32 constant STORAGE_POSITION = keccak256("compose.owner");
56+
57+ /**
58+ * @custom:storage-location erc8042:compose.owner
59+ */
60+ struct OwnerStorage {
61+ address owner;
62+ }
63+
64+ /**
65+ * @notice Returns a pointer to the ERC-173 storage struct.
66+ * @dev Uses inline assembly to access the storage slot defined by STORAGE_POSITION.
67+ * @return s The OwnerStorage struct in storage.
68+ */
69+ function getStorage() pure returns (OwnerStorage storage s) {
70+ bytes32 position = STORAGE_POSITION;
71+ assembly {
72+ s.slot := position
73+ }
74+ }
75+
76+ function setContractOwner(address _initialOwner) {
77+ OwnerStorage storage s = getStorage();
78+ s.owner = _initialOwner;
79+ emit OwnershipTransferred(address(0), _initialOwner);
80+ }
81+
82+
83+ /**
84+ * @notice Reverts if the caller is not the owner.
85+ */
86+ function requireOwner() view {
87+ if (getStorage().owner != msg.sender) {
88+ revert OwnerUnauthorizedAccount();
89+ }
90+ }
91+ ```
92+
93+ Here is an example of a diamond contract that uses Solidity modules to implement ERC-2535 Diamonds:
94+
95+ ```solidity
96+ // SPDX-License-Identifier: MIT
97+ pragma solidity >=0.8.30;
98+
99+ import "../DiamondMod.sol" as DiamondMod;
100+ import "../../access/Owner/OwnerMod.sol" as OwnerMod;
101+ import "../../token/ERC721/ERC721/ERC721Mod.sol" as ERC721Mod;
102+ import "../../interfaceDetection/ERC165/ERC165Mod.sol" as ERC165Mod;
103+ import {IERC721} from "../../interfaces/IERC721.sol";
104+ import {IERC721Metadata} from "../../interfaces/IERC721Metadata.sol";
105+
106+ contract ExampleDiamond {
107+ /**
108+ * @notice Struct to hold facet address and its function selectors.
109+ * struct FacetCut {
110+ * address facetAddress;
111+ * FacetCutAction action; // Add=0, Replace=1, Remove=2
112+ * bytes4[] functionSelectors;
113+ * }
114+ */
115+ /**
116+ * @notice Initializes the diamond contract with facets, owner and other data.
117+ * @dev Adds all provided facets to the diamond's function selector mapping and sets the contract owner.
118+ * Each facet in the array will have its function selectors registered to enable delegatecall routing.
119+ * @param _facets Array of facet addresses and their corresponding function selectors to add to the diamond.
120+ * @param _diamondOwner Address that will be set as the owner of the diamond contract.
121+ */
122+ constructor(DiamondMod.FacetCut[] memory _facets, address _diamondOwner) {
123+ DiamondMod.addFacets(_facets);
124+
125+ /*************************************
126+ * Initialize storage variables
127+ ************************************/
128+
129+ /**
130+ * Setting the contract owner
131+ */
132+ OwnerMod.setContractOwner(_diamondOwner);
133+ /**
134+ * Setting ERC721 token details
135+ */
136+ ERC721Mod.setMetadata({_name: "ExampleDiamondNFT", _symbol: "EDN", _baseURI: "https://example.com/metadata/"});
137+ /**
138+ * Registering ERC165 interfaces
139+ */
140+ ERC165Mod.registerInterface(type(IERC721).interfaceId);
141+ ERC165Mod.registerInterface(type(IERC721Metadata).interfaceId);
142+ }
143+
144+ fallback() external payable {
145+ DiamondMod.diamondFallback();
146+ }
147+
148+ receive() external payable {}
149+ }
150+ ```
151+
34152
0 commit comments