diff --git a/src/access/AccessControl/AccessControlFacet.sol b/src/access/AccessControl/AccessControlFacet.sol index 1a0779b1..dd31dd64 100644 --- a/src/access/AccessControl/AccessControlFacet.sol +++ b/src/access/AccessControl/AccessControlFacet.sol @@ -56,6 +56,7 @@ contract AccessControlFacet { /** * @notice storage struct for the AccessControl. + * @custom:storage-location erc8042:compose.accesscontrol */ struct AccessControlStorage { mapping(address account => mapping(bytes32 role => bool hasRole)) hasRole; diff --git a/src/access/AccessControlPausable/AccessControlPausableMod.sol b/src/access/AccessControlPausable/AccessControlPausableMod.sol index 36d6adba..2b8e0f31 100644 --- a/src/access/AccessControlPausable/AccessControlPausableMod.sol +++ b/src/access/AccessControlPausable/AccessControlPausableMod.sol @@ -42,7 +42,7 @@ bytes32 constant ACCESS_CONTROL_STORAGE_POSITION = keccak256("compose.accesscont */ bytes32 constant PAUSABLE_STORAGE_POSITION = keccak256("compose.accesscontrol.pausable"); -/* +/** * @notice Storage struct for AccessControl (reused struct definition). * @dev Must match the struct definition in AccessControlFacet. * @custom:storage-location erc8042:compose.accesscontrol @@ -52,7 +52,7 @@ struct AccessControlStorage { mapping(bytes32 role => bytes32 adminRole) adminRole; } -/* +/** * @notice Storage struct for AccessControlPausable. * @custom:storage-location erc8042:compose.accesscontrol.pausable */ diff --git a/src/access/AccessControlTemporal/AccessControlTemporalMod.sol b/src/access/AccessControlTemporal/AccessControlTemporalMod.sol index b58e7c17..5e2a6871 100644 --- a/src/access/AccessControlTemporal/AccessControlTemporalMod.sol +++ b/src/access/AccessControlTemporal/AccessControlTemporalMod.sol @@ -48,7 +48,7 @@ bytes32 constant ACCESS_CONTROL_STORAGE_POSITION = keccak256("compose.accesscont */ bytes32 constant TEMPORAL_STORAGE_POSITION = keccak256("compose.accesscontrol.temporal"); -/* +/** * @notice Storage struct for AccessControl (reused struct definition). * @dev Must match the struct definition in AccessControlFacet. * @custom:storage-location erc8042:compose.accesscontrol @@ -58,7 +58,7 @@ struct AccessControlStorage { mapping(bytes32 role => bytes32 adminRole) adminRole; } -/* +/** * @notice Storage struct for AccessControlTemporal. * @custom:storage-location erc8042:compose.accesscontrol.temporal */ diff --git a/src/access/Owner/OwnerFacet.sol b/src/access/Owner/OwnerFacet.sol index e809bf25..7249942e 100644 --- a/src/access/Owner/OwnerFacet.sol +++ b/src/access/Owner/OwnerFacet.sol @@ -19,10 +19,10 @@ contract OwnerFacet { */ error OwnerUnauthorizedAccount(); - bytes32 constant STORAGE_POSITION = keccak256("compose.owner"); + bytes32 constant STORAGE_POSITION = keccak256("erc173.owner"); /** - * @custom:storage-location erc8042:compose.owner + * @custom:storage-location erc8042:erc173.owner */ struct OwnerStorage { address owner; diff --git a/src/access/Owner/OwnerMod.sol b/src/access/Owner/OwnerMod.sol index a5eb3bd6..ffefc4e3 100644 --- a/src/access/Owner/OwnerMod.sol +++ b/src/access/Owner/OwnerMod.sol @@ -24,10 +24,10 @@ error OwnerUnauthorizedAccount(); */ error OwnerAlreadyRenounced(); -bytes32 constant STORAGE_POSITION = keccak256("compose.owner"); +bytes32 constant STORAGE_POSITION = keccak256("erc173.owner"); /** - * @custom:storage-location erc8042:compose.owner + * @custom:storage-location erc8042:erc173.owner */ struct OwnerStorage { address owner; diff --git a/src/access/OwnerTwoSteps/OwnerTwoStepsFacet.sol b/src/access/OwnerTwoSteps/OwnerTwoStepsFacet.sol index c71259a4..d106537e 100644 --- a/src/access/OwnerTwoSteps/OwnerTwoStepsFacet.sol +++ b/src/access/OwnerTwoSteps/OwnerTwoStepsFacet.sol @@ -24,10 +24,10 @@ contract OwnerTwoStepsFacet { */ error OwnerUnauthorizedAccount(); - bytes32 constant OWNER_STORAGE_POSITION = keccak256("compose.owner"); + bytes32 constant OWNER_STORAGE_POSITION = keccak256("erc173.owner"); /** - * @custom:storage-location erc8042:compose.owner + * @custom:storage-location erc8042:erc173.owner */ struct OwnerStorage { address owner; @@ -45,10 +45,10 @@ contract OwnerTwoStepsFacet { } } - bytes32 constant PENDING_OWNER_STORAGE_POSITION = keccak256("compose.owner.pending"); + bytes32 constant PENDING_OWNER_STORAGE_POSITION = keccak256("erc173.owner.pending"); /** - * @custom:storage-location erc8042:compose.owner.pending + * @custom:storage-location erc8042:erc173.owner.pending */ struct PendingOwnerStorage { address pendingOwner; diff --git a/src/access/OwnerTwoSteps/OwnerTwoStepsMod.sol b/src/access/OwnerTwoSteps/OwnerTwoStepsMod.sol index fb9027c8..391f92d7 100644 --- a/src/access/OwnerTwoSteps/OwnerTwoStepsMod.sol +++ b/src/access/OwnerTwoSteps/OwnerTwoStepsMod.sol @@ -28,10 +28,10 @@ error OwnerUnauthorizedAccount(); */ error OwnerAlreadyRenounced(); -bytes32 constant OWNER_STORAGE_POSITION = keccak256("compose.owner"); +bytes32 constant OWNER_STORAGE_POSITION = keccak256("erc173.owner"); /** - * @custom:storage-location erc8042:compose.owner + * @custom:storage-location erc8042:erc173.owner */ struct OwnerStorage { address owner; @@ -49,10 +49,10 @@ function getOwnerStorage() pure returns (OwnerStorage storage s) { } } -bytes32 constant PENDING_OWNER_STORAGE_POSITION = keccak256("compose.owner.pending"); +bytes32 constant PENDING_OWNER_STORAGE_POSITION = keccak256("erc173.owner.pending"); /** - * @custom:storage-location erc8042:compose.owner.pending + * @custom:storage-location erc8042:erc173.owner.pending */ struct PendingOwnerStorage { address pendingOwner; diff --git a/src/diamond/DiamondMod.sol b/src/diamond/DiamondMod.sol index b3658889..4cb090fb 100644 --- a/src/diamond/DiamondMod.sol +++ b/src/diamond/DiamondMod.sol @@ -128,7 +128,7 @@ function importSelectors(address _facet) view returns (bytes memory selectors) { } } - // Validate ABI offset == 0x20 for a single dynamic return + /* Validate ABI offset == 0x20 for a single dynamic return */ uint256 offset; assembly ("memory-safe") { offset := mload(add(data, 0x20)) diff --git a/src/diamond/DiamondUpgradeFacet.sol b/src/diamond/DiamondUpgradeFacet.sol index 20c585ce..260bc82c 100644 --- a/src/diamond/DiamondUpgradeFacet.sol +++ b/src/diamond/DiamondUpgradeFacet.sol @@ -121,7 +121,7 @@ contract DiamondUpgradeFacet { } /** - * @custom:storage-location erc8042:erc8109.diamond + * @custom:storage-location erc8042:erc8153.diamond */ struct DiamondStorage { mapping(bytes4 functionSelector => FacetNode) facetNodes; @@ -228,7 +228,7 @@ contract DiamondUpgradeFacet { } } - // Validate ABI offset == 0x20 for a single dynamic return + /* Validate ABI offset == 0x20 for a single dynamic return */ uint256 offset; assembly ("memory-safe") { offset := mload(add(data, 0x20)) diff --git a/src/diamond/DiamondUpgradeMod.sol b/src/diamond/DiamondUpgradeMod.sol index a4695371..a1892d93 100644 --- a/src/diamond/DiamondUpgradeMod.sol +++ b/src/diamond/DiamondUpgradeMod.sol @@ -201,7 +201,7 @@ function importSelectors(address _facet) view returns (bytes memory selectors) { } } - // Validate ABI offset == 0x20 for a single dynamic return + /* Validate ABI offset == 0x20 for a single dynamic return */ uint256 offset; assembly ("memory-safe") { offset := mload(add(data, 0x20)) diff --git a/src/interfaceDetection/ERC165/ERC165Facet.sol b/src/interfaceDetection/ERC165/ERC165Facet.sol index 2ac74c90..64eb061a 100644 --- a/src/interfaceDetection/ERC165/ERC165Facet.sol +++ b/src/interfaceDetection/ERC165/ERC165Facet.sol @@ -33,11 +33,11 @@ contract ERC165Facet { * @notice Storage slot identifier for ERC-165 interface detection * @dev Defined using keccak256 hash following ERC-8042 standard */ - bytes32 constant STORAGE_POSITION = keccak256("compose.erc165"); + bytes32 constant STORAGE_POSITION = keccak256("erc165"); /** * @notice ERC-165 storage layout using the ERC-8042 standard - * @custom:storage-location erc8042:compose.erc165 + * @custom:storage-location erc8042:erc165 */ struct ERC165Storage { /** diff --git a/src/interfaceDetection/ERC165/ERC165Mod.sol b/src/interfaceDetection/ERC165/ERC165Mod.sol index 99a593c2..37f86375 100644 --- a/src/interfaceDetection/ERC165/ERC165Mod.sol +++ b/src/interfaceDetection/ERC165/ERC165Mod.sol @@ -14,11 +14,11 @@ pragma solidity >=0.8.30; /* * Storage slot identifier, defined using keccak256 hash of the library diamond storage identifier. */ -bytes32 constant STORAGE_POSITION = keccak256("compose.erc165"); +bytes32 constant STORAGE_POSITION = keccak256("erc165"); /* * @notice ERC-165 storage layout using the ERC-8042 standard. - * @custom:storage-location erc8042:compose.erc165 + * @custom:storage-location erc8042:erc165 */ struct ERC165Storage { /* diff --git a/src/token/ERC1155/ERC1155DataFacet.sol b/src/token/ERC1155/ERC1155DataFacet.sol index 42a3d643..2a61230f 100644 --- a/src/token/ERC1155/ERC1155DataFacet.sol +++ b/src/token/ERC1155/ERC1155DataFacet.sol @@ -24,7 +24,7 @@ contract ERC1155DataFacet { /** * @dev ERC-8042 compliant storage struct for ERC-1155 token data. - * @custom:storage-location erc8042:compose.erc1155 + * @custom:storage-location erc8042:erc1155 */ struct ERC1155Storage { mapping(uint256 id => mapping(address account => uint256 balance)) balanceOf; diff --git a/src/token/ERC1155/ERC1155Facet.sol b/src/token/ERC1155/ERC1155Facet.sol index c238a5e5..fb551c81 100644 --- a/src/token/ERC1155/ERC1155Facet.sol +++ b/src/token/ERC1155/ERC1155Facet.sol @@ -60,7 +60,7 @@ interface IERC1155Receiver { * * For developers creating custom facets that need to interact with ERC-1155 storage (e.g., custom minting logic), * use the LibERC1155 library which provides helper functions to access this facet's storage. - * This facet does NOT depend on LibERC1155 - both access the same storage at keccak256("compose.erc1155"). + * This facet does NOT depend on LibERC1155 - both access the same storage at keccak256("erc1155"). */ contract ERC1155Facet { /** @@ -156,7 +156,7 @@ contract ERC1155Facet { /** * @dev ERC-8042 compliant storage struct for ERC-1155 token data. - * @custom:storage-location erc8042:compose.erc1155 + * @custom:storage-location erc8042:erc1155 */ struct ERC1155Storage { mapping(uint256 id => mapping(address account => uint256 balance)) balanceOf; diff --git a/src/token/ERC1155/ERC1155Mod.sol b/src/token/ERC1155/ERC1155Mod.sol index 474adfdf..82452b33 100644 --- a/src/token/ERC1155/ERC1155Mod.sol +++ b/src/token/ERC1155/ERC1155Mod.sol @@ -129,11 +129,11 @@ event URI(string _value, uint256 indexed _id); /** * @dev Storage position determined by the keccak256 hash of the diamond storage identifier. */ -bytes32 constant STORAGE_POSITION = keccak256("compose.erc1155"); +bytes32 constant STORAGE_POSITION = keccak256("erc1155"); /** * @dev ERC-8042 compliant storage struct for ERC-1155 token data. - * @custom:storage-location erc8042:compose.erc1155 + * @custom:storage-location erc8042:erc1155 */ struct ERC1155Storage { mapping(uint256 id => mapping(address account => uint256 balance)) balanceOf; diff --git a/src/token/ERC20/Bridgeable/ERC20BridgeableFacet.sol b/src/token/ERC20/Bridgeable/ERC20BridgeableFacet.sol index e1b2d3d5..d8f87f8b 100644 --- a/src/token/ERC20/Bridgeable/ERC20BridgeableFacet.sol +++ b/src/token/ERC20/Bridgeable/ERC20BridgeableFacet.sol @@ -116,6 +116,7 @@ contract ERC20BridgeableFacet { /** * @notice storage struct for the AccessControl. + * @custom:storage-location erc8042:compose.accesscontrol */ struct AccessControlStorage { mapping(address account => mapping(bytes32 role => bool hasRole)) hasRole; diff --git a/src/token/ERC20/Bridgeable/ERC20BridgeableMod.sol b/src/token/ERC20/Bridgeable/ERC20BridgeableMod.sol index 1f2989cb..2ebf36ba 100644 --- a/src/token/ERC20/Bridgeable/ERC20BridgeableMod.sol +++ b/src/token/ERC20/Bridgeable/ERC20BridgeableMod.sol @@ -114,8 +114,9 @@ function getERC20Storage() pure returns (ERC20Storage storage s) { */ bytes32 constant ACCESS_STORAGE_POSITION = keccak256("compose.accesscontrol"); -/* +/** * @notice storage struct for the AccessControl. + * @custom:storage-location erc8042:compose.accesscontrol */ struct AccessControlStorage { mapping(address account => mapping(bytes32 role => bool hasRole)) hasRole; diff --git a/src/token/ERC20/Burn/ERC20BurnMod.sol b/src/token/ERC20/Burn/ERC20BurnMod.sol index 4c421308..5298589e 100644 --- a/src/token/ERC20/Burn/ERC20BurnMod.sol +++ b/src/token/ERC20/Burn/ERC20BurnMod.sol @@ -38,7 +38,7 @@ event Transfer(address indexed _from, address indexed _to, uint256 _value); */ bytes32 constant STORAGE_POSITION = keccak256("erc20"); -/* +/** * @notice ERC-20 storage layout using the ERC-8042 standard. * @custom:storage-location erc8042:erc20 */ diff --git a/src/token/ERC20/Data/ERC20DataFacet.sol b/src/token/ERC20/Data/ERC20DataFacet.sol index dd1e5660..b6c8713e 100644 --- a/src/token/ERC20/Data/ERC20DataFacet.sol +++ b/src/token/ERC20/Data/ERC20DataFacet.sol @@ -13,7 +13,7 @@ contract ERC20DataFacet { /** * @dev ERC-8042 compliant storage struct for ERC20 token data. - * @custom:storage-location erc8042:erc20.transfer + * @custom:storage-location erc8042:erc20 */ struct ERC20Storage { mapping(address owner => uint256 balance) balanceOf; diff --git a/src/token/ERC6909/ERC6909/ERC6909Facet.sol b/src/token/ERC6909/ERC6909/ERC6909Facet.sol index 4be87a18..ebac7e47 100644 --- a/src/token/ERC6909/ERC6909/ERC6909Facet.sol +++ b/src/token/ERC6909/ERC6909/ERC6909Facet.sol @@ -55,10 +55,10 @@ contract ERC6909Facet { /** * @dev Storage position determined by the keccak256 hash of the diamond storage identifier. */ - bytes32 constant STORAGE_POSITION = keccak256("compose.erc6909"); + bytes32 constant STORAGE_POSITION = keccak256("erc6909"); /** - * @custom:storage-location erc8042:compose.erc6909 + * @custom:storage-location erc8042:erc6909 */ struct ERC6909Storage { mapping(address owner => mapping(uint256 id => uint256 amount)) balanceOf; diff --git a/src/token/ERC6909/ERC6909/ERC6909Mod.sol b/src/token/ERC6909/ERC6909/ERC6909Mod.sol index ed4c84ff..d7c9621c 100644 --- a/src/token/ERC6909/ERC6909/ERC6909Mod.sol +++ b/src/token/ERC6909/ERC6909/ERC6909Mod.sol @@ -87,10 +87,10 @@ event Approval(address indexed _owner, address indexed _spender, uint256 indexed /** * @dev Storage position determined by the keccak256 hash of the diamond storage identifier. */ -bytes32 constant STORAGE_POSITION = keccak256("compose.erc6909"); +bytes32 constant STORAGE_POSITION = keccak256("erc6909"); /** - * @custom:storage-location erc8042:compose.erc6909 + * @custom:storage-location erc8042:erc6909 */ struct ERC6909Storage { mapping(address owner => mapping(uint256 id => uint256 amount)) balanceOf; diff --git a/src/token/ERC721/Burn/ERC721BurnFacet.sol b/src/token/ERC721/Burn/ERC721BurnFacet.sol index 20e84548..2a9d8d54 100644 --- a/src/token/ERC721/Burn/ERC721BurnFacet.sol +++ b/src/token/ERC721/Burn/ERC721BurnFacet.sol @@ -29,7 +29,7 @@ contract ERC721BurnFacet { bytes32 constant STORAGE_POSITION = keccak256("erc721"); /** - * @custom:storage-location erc8042:compose.erc721 + * @custom:storage-location erc8042:erc721 */ struct ERC721Storage { mapping(uint256 tokenId => address owner) ownerOf; diff --git a/src/token/ERC721/Burn/ERC721BurnMod.sol b/src/token/ERC721/Burn/ERC721BurnMod.sol index 7d0f7d58..b99c1d12 100644 --- a/src/token/ERC721/Burn/ERC721BurnMod.sol +++ b/src/token/ERC721/Burn/ERC721BurnMod.sol @@ -24,10 +24,10 @@ event Transfer(address indexed _from, address indexed _to, uint256 indexed _toke */ bytes32 constant STORAGE_POSITION = keccak256("erc721"); -/* - * @custom:storage-location erc8042:erc721 +/** * @notice Storage layout for ERC-721 token management. * @dev Defines ownership, balances, approvals, and operator mappings per ERC-721 standard. + * @custom:storage-location erc8042:erc721 */ struct ERC721Storage { mapping(uint256 tokenId => address owner) ownerOf; diff --git a/src/token/ERC721/Metadata/ERC721MetadataFacet.sol b/src/token/ERC721/Metadata/ERC721MetadataFacet.sol index c44161b4..cb0efe70 100644 --- a/src/token/ERC721/Metadata/ERC721MetadataFacet.sol +++ b/src/token/ERC721/Metadata/ERC721MetadataFacet.sol @@ -20,7 +20,7 @@ contract ERC721MetadataFacet { bytes32 constant STORAGE_POSITION = keccak256("erc721.metadata"); /** - * @custom:storage-location erc8042:erc721 + * @custom:storage-location erc8042:erc721.metadata */ struct ERC721MetadataStorage { string name; diff --git a/src/token/ERC721/Metadata/ERC721MetadataMod.sol b/src/token/ERC721/Metadata/ERC721MetadataMod.sol index af7094a3..c5be1f98 100644 --- a/src/token/ERC721/Metadata/ERC721MetadataMod.sol +++ b/src/token/ERC721/Metadata/ERC721MetadataMod.sol @@ -14,7 +14,7 @@ error ERC721InvalidOwner(address _owner); bytes32 constant STORAGE_POSITION = keccak256("erc721.metadata"); /** - * @custom:storage-location erc8042:erc721 + * @custom:storage-location erc8042:erc721.metadata */ struct ERC721MetadataStorage { string name; diff --git a/src/token/ERC721/Transfer/ERC721TransferMod.sol b/src/token/ERC721/Transfer/ERC721TransferMod.sol index a3f4648a..bd964cd2 100644 --- a/src/token/ERC721/Transfer/ERC721TransferMod.sol +++ b/src/token/ERC721/Transfer/ERC721TransferMod.sol @@ -42,10 +42,10 @@ event Transfer(address indexed _from, address indexed _to, uint256 indexed _toke */ bytes32 constant STORAGE_POSITION = keccak256("erc721"); -/* - * @custom:storage-location erc8042:erc721 +/** * @notice Storage layout for ERC-721 token management. * @dev Defines ownership, balances, approvals, and operator mappings per ERC-721 standard. + * @custom:storage-location erc8042:erc721 */ struct ERC721Storage { mapping(uint256 tokenId => address owner) ownerOf; diff --git a/src/token/Royalty/RoyaltyFacet.sol b/src/token/Royalty/RoyaltyFacet.sol index 6d1e8cbe..33cf00a5 100644 --- a/src/token/Royalty/RoyaltyFacet.sol +++ b/src/token/Royalty/RoyaltyFacet.sol @@ -16,7 +16,7 @@ contract RoyaltyFacet { /** * @notice Storage slot identifier for royalty storage. */ - bytes32 constant STORAGE_POSITION = keccak256("compose.erc2981"); + bytes32 constant STORAGE_POSITION = keccak256("erc2981"); /** * @dev The denominator with which to interpret royalty fees as a percentage of sale price. @@ -36,7 +36,7 @@ contract RoyaltyFacet { } /** - * @custom:storage-location erc8042:compose.erc2981 + * @custom:storage-location erc8042:erc2981 */ struct RoyaltyStorage { RoyaltyInfo defaultRoyaltyInfo; diff --git a/src/token/Royalty/RoyaltyMod.sol b/src/token/Royalty/RoyaltyMod.sol index 03026b9b..ecb64dcd 100644 --- a/src/token/Royalty/RoyaltyMod.sol +++ b/src/token/Royalty/RoyaltyMod.sol @@ -40,7 +40,7 @@ error ERC2981InvalidTokenRoyalty(uint256 _tokenId, uint256 _numerator, uint256 _ */ error ERC2981InvalidTokenRoyaltyReceiver(uint256 _tokenId, address _receiver); -bytes32 constant STORAGE_POSITION = keccak256("compose.erc2981"); +bytes32 constant STORAGE_POSITION = keccak256("erc2981"); /** * @dev The denominator with which to interpret royalty fees as a percentage of sale price. @@ -62,7 +62,7 @@ struct RoyaltyInfo { } /** - * @custom:storage-location erc8042:compose.erc2981 + * @custom:storage-location erc8042:erc2981 */ struct RoyaltyStorage { RoyaltyInfo defaultRoyaltyInfo; diff --git a/website/docs/contribution/code-style-guide.mdx b/website/docs/contribution/code-style-guide.mdx index a484a4c8..1ca41b69 100644 --- a/website/docs/contribution/code-style-guide.mdx +++ b/website/docs/contribution/code-style-guide.mdx @@ -32,6 +32,13 @@ Follow the [Solidity feature ban](/docs/design/banned-solidity-features). delete balances[_owner]; ``` +### Storage Position Conventions + +Diamond storage slots (and the matching `@custom:storage-location erc8042:...` annotations on structs) follow: + +- **ERC standards:** Use the `erc` prefix and the standard number or name (e.g. `erc20`, `erc721`, `erc1155`, `erc165`, `erc2981`, `erc6909`, `erc173.owner`, `erc8153.diamond`). Sub-features use a dot (e.g. `erc20.metadata`, `erc721.enumerable`). +- **Custom / Compose features:** Use the `compose.` prefix (e.g. `compose.accesscontrol`, `compose.accesscontrol.pausable`, `compose.accesscontrol.temporal`). + ### Avoid Assembly - Avoid using assembly if you can. If you can't and you access memory, do it [safely](https://docs.soliditylang.org/en/latest/assembly.html#memory-safety), and use `assembly ("memory-safe")`. `"memory safe"` tells the Solidity compiler that memory is being used safely so it should not disable optimizations.