diff --git a/contracts/access/access_control/AccessControlInternal.sol b/contracts/access/access_control/AccessControlInternal.sol index ff147f25..82267a1f 100644 --- a/contracts/access/access_control/AccessControlInternal.sol +++ b/contracts/access/access_control/AccessControlInternal.sol @@ -33,7 +33,11 @@ abstract contract AccessControlInternal is IAccessControlInternal { address account ) internal view virtual returns (bool) { return - AccessControlStorage.layout().roles[role].members.contains(account); + AccessControlStorage + .layout(AccessControlStorage.DEFAULT_STORAGE_SLOT) + .roles[role] + .members + .contains(account); } /** @@ -72,7 +76,11 @@ abstract contract AccessControlInternal is IAccessControlInternal { function _getRoleAdmin( bytes32 role ) internal view virtual returns (bytes32) { - return AccessControlStorage.layout().roles[role].adminRole; + return + AccessControlStorage + .layout(AccessControlStorage.DEFAULT_STORAGE_SLOT) + .roles[role] + .adminRole; } /** @@ -82,7 +90,10 @@ abstract contract AccessControlInternal is IAccessControlInternal { */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = _getRoleAdmin(role); - AccessControlStorage.layout().roles[role].adminRole = adminRole; + AccessControlStorage + .layout(AccessControlStorage.DEFAULT_STORAGE_SLOT) + .roles[role] + .adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } @@ -92,7 +103,11 @@ abstract contract AccessControlInternal is IAccessControlInternal { * @param account recipient of role assignment */ function _grantRole(bytes32 role, address account) internal virtual { - AccessControlStorage.layout().roles[role].members.add(account); + AccessControlStorage + .layout(AccessControlStorage.DEFAULT_STORAGE_SLOT) + .roles[role] + .members + .add(account); emit RoleGranted(role, account, msg.sender); } @@ -102,7 +117,11 @@ abstract contract AccessControlInternal is IAccessControlInternal { * @parm account */ function _revokeRole(bytes32 role, address account) internal virtual { - AccessControlStorage.layout().roles[role].members.remove(account); + AccessControlStorage + .layout(AccessControlStorage.DEFAULT_STORAGE_SLOT) + .roles[role] + .members + .remove(account); emit RoleRevoked(role, account, msg.sender); } @@ -123,7 +142,12 @@ abstract contract AccessControlInternal is IAccessControlInternal { bytes32 role, uint256 index ) internal view virtual returns (address) { - return AccessControlStorage.layout().roles[role].members.at(index); + return + AccessControlStorage + .layout(AccessControlStorage.DEFAULT_STORAGE_SLOT) + .roles[role] + .members + .at(index); } /** @@ -133,6 +157,11 @@ abstract contract AccessControlInternal is IAccessControlInternal { function _getRoleMemberCount( bytes32 role ) internal view virtual returns (uint256) { - return AccessControlStorage.layout().roles[role].members.length(); + return + AccessControlStorage + .layout(AccessControlStorage.DEFAULT_STORAGE_SLOT) + .roles[role] + .members + .length(); } } diff --git a/contracts/access/access_control/AccessControlStorage.sol b/contracts/access/access_control/AccessControlStorage.sol index b1d5dd06..2f75b911 100644 --- a/contracts/access/access_control/AccessControlStorage.sol +++ b/contracts/access/access_control/AccessControlStorage.sol @@ -16,11 +16,22 @@ library AccessControlStorage { bytes32 internal constant DEFAULT_ADMIN_ROLE = 0x00; - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.AccessControl'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes('solidstate.contracts.storage.AccessControl') + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/access/ownable/OwnableInternal.sol b/contracts/access/ownable/OwnableInternal.sol index b702e0d1..dec7b1c6 100644 --- a/contracts/access/ownable/OwnableInternal.sol +++ b/contracts/access/ownable/OwnableInternal.sol @@ -22,7 +22,7 @@ abstract contract OwnableInternal is IOwnableInternal { } function _owner() internal view virtual returns (address) { - return OwnableStorage.layout().owner; + return OwnableStorage.layout(OwnableStorage.DEFAULT_STORAGE_SLOT).owner; } function _transitiveOwner() internal view virtual returns (address owner) { @@ -42,7 +42,9 @@ abstract contract OwnableInternal is IOwnableInternal { } function _setOwner(address account) internal virtual { - OwnableStorage.Layout storage l = OwnableStorage.layout(); + OwnableStorage.Layout storage l = OwnableStorage.layout( + OwnableStorage.DEFAULT_STORAGE_SLOT + ); emit OwnershipTransferred(l.owner, account); l.owner = account; } diff --git a/contracts/access/ownable/OwnableStorage.sol b/contracts/access/ownable/OwnableStorage.sol index 7d999dc1..224a306f 100644 --- a/contracts/access/ownable/OwnableStorage.sol +++ b/contracts/access/ownable/OwnableStorage.sol @@ -7,11 +7,20 @@ library OwnableStorage { address owner; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.Ownable'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.Ownable')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/access/ownable/SafeOwnableInternal.sol b/contracts/access/ownable/SafeOwnableInternal.sol index ca10b580..60b1d04a 100644 --- a/contracts/access/ownable/SafeOwnableInternal.sol +++ b/contracts/access/ownable/SafeOwnableInternal.sol @@ -17,7 +17,10 @@ abstract contract SafeOwnableInternal is ISafeOwnableInternal, OwnableInternal { * @notice get the nominated owner who has permission to call acceptOwnership */ function _nomineeOwner() internal view virtual returns (address) { - return SafeOwnableStorage.layout().nomineeOwner; + return + SafeOwnableStorage + .layout(SafeOwnableStorage.DEFAULT_STORAGE_SLOT) + .nomineeOwner; } /** @@ -25,7 +28,9 @@ abstract contract SafeOwnableInternal is ISafeOwnableInternal, OwnableInternal { */ function _acceptOwnership() internal virtual { _setOwner(msg.sender); - delete SafeOwnableStorage.layout().nomineeOwner; + delete SafeOwnableStorage + .layout(SafeOwnableStorage.DEFAULT_STORAGE_SLOT) + .nomineeOwner; } /** @@ -39,6 +44,8 @@ abstract contract SafeOwnableInternal is ISafeOwnableInternal, OwnableInternal { * @notice set nominee owner */ function _setNomineeOwner(address account) internal virtual { - SafeOwnableStorage.layout().nomineeOwner = account; + SafeOwnableStorage + .layout(SafeOwnableStorage.DEFAULT_STORAGE_SLOT) + .nomineeOwner = account; } } diff --git a/contracts/access/ownable/SafeOwnableStorage.sol b/contracts/access/ownable/SafeOwnableStorage.sol index 4664d57e..5847342b 100644 --- a/contracts/access/ownable/SafeOwnableStorage.sol +++ b/contracts/access/ownable/SafeOwnableStorage.sol @@ -7,11 +7,20 @@ library SafeOwnableStorage { address nomineeOwner; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.SafeOwnable'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.SafeOwnable')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/introspection/ERC165/base/ERC165BaseInternal.sol b/contracts/introspection/ERC165/base/ERC165BaseInternal.sol index 8ce45441..df2e8a90 100644 --- a/contracts/introspection/ERC165/base/ERC165BaseInternal.sol +++ b/contracts/introspection/ERC165/base/ERC165BaseInternal.sol @@ -17,7 +17,10 @@ abstract contract ERC165BaseInternal is IERC165BaseInternal { function _supportsInterface( bytes4 interfaceId ) internal view virtual returns (bool) { - return ERC165BaseStorage.layout().supportedInterfaces[interfaceId]; + return + ERC165BaseStorage + .layout(ERC165BaseStorage.DEFAULT_STORAGE_SLOT) + .supportedInterfaces[interfaceId]; } /** @@ -30,6 +33,8 @@ abstract contract ERC165BaseInternal is IERC165BaseInternal { bool status ) internal virtual { if (interfaceId == 0xffffffff) revert ERC165Base__InvalidInterfaceId(); - ERC165BaseStorage.layout().supportedInterfaces[interfaceId] = status; + ERC165BaseStorage + .layout(ERC165BaseStorage.DEFAULT_STORAGE_SLOT) + .supportedInterfaces[interfaceId] = status; } } diff --git a/contracts/introspection/ERC165/base/ERC165BaseStorage.sol b/contracts/introspection/ERC165/base/ERC165BaseStorage.sol index ee683530..7e335e7d 100644 --- a/contracts/introspection/ERC165/base/ERC165BaseStorage.sol +++ b/contracts/introspection/ERC165/base/ERC165BaseStorage.sol @@ -7,11 +7,20 @@ library ERC165BaseStorage { mapping(bytes4 => bool) supportedInterfaces; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC165Base'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.ERC165Base')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/multisig/ECDSAMultisigWalletInternal.sol b/contracts/multisig/ECDSAMultisigWalletInternal.sol index ad5ece8f..b6fbf45d 100644 --- a/contracts/multisig/ECDSAMultisigWalletInternal.sol +++ b/contracts/multisig/ECDSAMultisigWalletInternal.sol @@ -19,16 +19,21 @@ abstract contract ECDSAMultisigWalletInternal is IECDSAMultisigWalletInternal { address account, uint256 nonce ) internal view returns (bool) { - return ECDSAMultisigWalletStorage.layout().nonces[account][nonce]; + return + ECDSAMultisigWalletStorage + .layout(ECDSAMultisigWalletStorage.DEFAULT_STORAGE_SLOT) + .nonces[account][nonce]; } function _setInvalidNonce(address account, uint256 nonce) internal { - ECDSAMultisigWalletStorage.layout().nonces[account][nonce] = true; + ECDSAMultisigWalletStorage + .layout(ECDSAMultisigWalletStorage.DEFAULT_STORAGE_SLOT) + .nonces[account][nonce] = true; } function _setQuorum(uint256 quorum) internal { ECDSAMultisigWalletStorage.Layout storage l = ECDSAMultisigWalletStorage - .layout(); + .layout(ECDSAMultisigWalletStorage.DEFAULT_STORAGE_SLOT); if (quorum > l.signers.length()) revert ECDSAMultisigWallet__InsufficientSigners(); @@ -36,12 +41,16 @@ abstract contract ECDSAMultisigWalletInternal is IECDSAMultisigWalletInternal { } function _isSigner(address account) internal view returns (bool) { - return ECDSAMultisigWalletStorage.layout().signers.contains(account); + return + ECDSAMultisigWalletStorage + .layout(ECDSAMultisigWalletStorage.DEFAULT_STORAGE_SLOT) + .signers + .contains(account); } function _addSigner(address account) internal { ECDSAMultisigWalletStorage.Layout storage l = ECDSAMultisigWalletStorage - .layout(); + .layout(ECDSAMultisigWalletStorage.DEFAULT_STORAGE_SLOT); if (l.signers.length() >= 256) revert ECDSAMultisigWallet__SignerLimitReached(); @@ -51,7 +60,7 @@ abstract contract ECDSAMultisigWalletInternal is IECDSAMultisigWalletInternal { function _removeSigner(address account) internal { ECDSAMultisigWalletStorage.Layout storage l = ECDSAMultisigWalletStorage - .layout(); + .layout(ECDSAMultisigWalletStorage.DEFAULT_STORAGE_SLOT); if (l.quorum > l.signers.length() - 1) revert ECDSAMultisigWallet__InsufficientSigners(); @@ -125,7 +134,7 @@ abstract contract ECDSAMultisigWalletInternal is IECDSAMultisigWalletInternal { Signature[] memory signatures ) internal virtual { ECDSAMultisigWalletStorage.Layout storage l = ECDSAMultisigWalletStorage - .layout(); + .layout(ECDSAMultisigWalletStorage.DEFAULT_STORAGE_SLOT); if (l.quorum > signatures.length) revert ECDSAMultisigWallet__QuorumNotReached(); diff --git a/contracts/multisig/ECDSAMultisigWalletStorage.sol b/contracts/multisig/ECDSAMultisigWalletStorage.sol index afec826e..406bf90c 100644 --- a/contracts/multisig/ECDSAMultisigWalletStorage.sol +++ b/contracts/multisig/ECDSAMultisigWalletStorage.sol @@ -11,11 +11,24 @@ library ECDSAMultisigWalletStorage { mapping(address => mapping(uint256 => bool)) nonces; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ECDSAMultisigWallet'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes( + 'solidstate.contracts.storage.ECDSAMultisigWallet' + ) + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/proxy/diamond/base/DiamondBase.sol b/contracts/proxy/diamond/base/DiamondBase.sol index 5d9ea6ae..f400f6fb 100644 --- a/contracts/proxy/diamond/base/DiamondBase.sol +++ b/contracts/proxy/diamond/base/DiamondBase.sol @@ -24,7 +24,7 @@ abstract contract DiamondBase is IDiamondBase, Proxy { { // inline storage layout retrieval uses less gas DiamondBaseStorage.Layout storage l; - bytes32 slot = DiamondBaseStorage.STORAGE_SLOT; + bytes32 slot = DiamondBaseStorage.DEFAULT_STORAGE_SLOT; assembly { l.slot := slot } diff --git a/contracts/proxy/diamond/base/DiamondBaseStorage.sol b/contracts/proxy/diamond/base/DiamondBaseStorage.sol index 5496f514..734196a1 100644 --- a/contracts/proxy/diamond/base/DiamondBaseStorage.sol +++ b/contracts/proxy/diamond/base/DiamondBaseStorage.sol @@ -16,11 +16,20 @@ library DiamondBaseStorage { address fallbackAddress; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.DiamondBase'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.DiamondBase')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/proxy/diamond/fallback/DiamondFallback.sol b/contracts/proxy/diamond/fallback/DiamondFallback.sol index d92a0209..7f507f64 100644 --- a/contracts/proxy/diamond/fallback/DiamondFallback.sol +++ b/contracts/proxy/diamond/fallback/DiamondFallback.sol @@ -61,7 +61,9 @@ abstract contract DiamondFallback is virtual returns (address fallbackAddress) { - fallbackAddress = DiamondBaseStorage.layout().fallbackAddress; + fallbackAddress = DiamondBaseStorage + .layout(DiamondBaseStorage.DEFAULT_STORAGE_SLOT) + .fallbackAddress; } /** @@ -69,6 +71,8 @@ abstract contract DiamondFallback is * @param fallbackAddress address of fallback implementation */ function _setFallbackAddress(address fallbackAddress) internal virtual { - DiamondBaseStorage.layout().fallbackAddress = fallbackAddress; + DiamondBaseStorage + .layout(DiamondBaseStorage.DEFAULT_STORAGE_SLOT) + .fallbackAddress = fallbackAddress; } } diff --git a/contracts/proxy/diamond/readable/DiamondReadableInternal.sol b/contracts/proxy/diamond/readable/DiamondReadableInternal.sol index 5d61c94d..96bfa942 100644 --- a/contracts/proxy/diamond/readable/DiamondReadableInternal.sol +++ b/contracts/proxy/diamond/readable/DiamondReadableInternal.sol @@ -15,7 +15,9 @@ abstract contract DiamondReadableInternal is IDiamondReadableInternal { * @return diamondFacets array of structured facet data */ function _facets() internal view returns (Facet[] memory diamondFacets) { - DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout(); + DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout( + DiamondBaseStorage.DEFAULT_STORAGE_SLOT + ); diamondFacets = new Facet[](l.selectorCount); @@ -94,7 +96,9 @@ abstract contract DiamondReadableInternal is IDiamondReadableInternal { function _facetFunctionSelectors( address facet ) internal view returns (bytes4[] memory selectors) { - DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout(); + DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout( + DiamondBaseStorage.DEFAULT_STORAGE_SLOT + ); selectors = new bytes4[](l.selectorCount); @@ -140,7 +144,9 @@ abstract contract DiamondReadableInternal is IDiamondReadableInternal { view returns (address[] memory addresses) { - DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout(); + DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout( + DiamondBaseStorage.DEFAULT_STORAGE_SLOT + ); addresses = new address[](l.selectorCount); uint256 numFacets; @@ -195,6 +201,12 @@ abstract contract DiamondReadableInternal is IDiamondReadableInternal { function _facetAddress( bytes4 selector ) internal view returns (address facet) { - facet = address(bytes20(DiamondBaseStorage.layout().facets[selector])); + facet = address( + bytes20( + DiamondBaseStorage + .layout(DiamondBaseStorage.DEFAULT_STORAGE_SLOT) + .facets[selector] + ) + ); } } diff --git a/contracts/proxy/diamond/writable/DiamondWritableInternal.sol b/contracts/proxy/diamond/writable/DiamondWritableInternal.sol index 82d972dd..fa6f7552 100644 --- a/contracts/proxy/diamond/writable/DiamondWritableInternal.sol +++ b/contracts/proxy/diamond/writable/DiamondWritableInternal.sol @@ -25,7 +25,9 @@ abstract contract DiamondWritableInternal is IDiamondWritableInternal { address target, bytes memory data ) internal virtual { - DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout(); + DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout( + DiamondBaseStorage.DEFAULT_STORAGE_SLOT + ); unchecked { uint256 originalSelectorCount = l.selectorCount; diff --git a/contracts/proxy/upgradeable/UpgradeableProxy.sol b/contracts/proxy/upgradeable/UpgradeableProxy.sol index db6c11b2..fc48428c 100644 --- a/contracts/proxy/upgradeable/UpgradeableProxy.sol +++ b/contracts/proxy/upgradeable/UpgradeableProxy.sol @@ -16,7 +16,7 @@ abstract contract UpgradeableProxy is IUpgradeableProxy, Proxy { function _getImplementation() internal view override returns (address) { // inline storage layout retrieval uses less gas UpgradeableProxyStorage.Layout storage l; - bytes32 slot = UpgradeableProxyStorage.STORAGE_SLOT; + bytes32 slot = UpgradeableProxyStorage.DEFAULT_STORAGE_SLOT; assembly { l.slot := slot } @@ -29,6 +29,8 @@ abstract contract UpgradeableProxy is IUpgradeableProxy, Proxy { * @param implementation implementation address */ function _setImplementation(address implementation) internal { - UpgradeableProxyStorage.layout().implementation = implementation; + UpgradeableProxyStorage + .layout(UpgradeableProxyStorage.DEFAULT_STORAGE_SLOT) + .implementation = implementation; } } diff --git a/contracts/proxy/upgradeable/UpgradeableProxyStorage.sol b/contracts/proxy/upgradeable/UpgradeableProxyStorage.sol index 2719509e..fc628cca 100644 --- a/contracts/proxy/upgradeable/UpgradeableProxyStorage.sol +++ b/contracts/proxy/upgradeable/UpgradeableProxyStorage.sol @@ -7,11 +7,22 @@ library UpgradeableProxyStorage { address implementation; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.UpgradeableProxy'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes('solidstate.contracts.storage.UpgradeableProxy') + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/security/initializable/InitializableInternal.sol b/contracts/security/initializable/InitializableInternal.sol index 804efe15..6057ea72 100644 --- a/contracts/security/initializable/InitializableInternal.sol +++ b/contracts/security/initializable/InitializableInternal.sol @@ -21,7 +21,9 @@ abstract contract InitializableInternal is IInitializableInternal { } function _setInitializedVersion(uint8 version) internal virtual { - InitializableStorage.Layout storage l = InitializableStorage.layout(); + InitializableStorage.Layout storage l = InitializableStorage.layout( + InitializableStorage.DEFAULT_STORAGE_SLOT + ); if (l.initialized >= version) revert Initializable__AlreadyInitialized(); @@ -36,6 +38,8 @@ abstract contract InitializableInternal is IInitializableInternal { virtual returns (uint8 version) { - version = InitializableStorage.layout().initialized; + version = InitializableStorage + .layout(InitializableStorage.DEFAULT_STORAGE_SLOT) + .initialized; } } diff --git a/contracts/security/initializable/InitializableStorage.sol b/contracts/security/initializable/InitializableStorage.sol index feae6b33..4ebd0947 100644 --- a/contracts/security/initializable/InitializableStorage.sol +++ b/contracts/security/initializable/InitializableStorage.sol @@ -7,11 +7,22 @@ library InitializableStorage { uint8 initialized; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.Initializable'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes('solidstate.contracts.storage.Initializable') + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/security/partially_pausable/PartiallyPausableInternal.sol b/contracts/security/partially_pausable/PartiallyPausableInternal.sol index 4be92983..4bd76b3d 100644 --- a/contracts/security/partially_pausable/PartiallyPausableInternal.sol +++ b/contracts/security/partially_pausable/PartiallyPausableInternal.sol @@ -27,7 +27,9 @@ abstract contract PartiallyPausableInternal is IPartiallyPausableInternal { function _partiallyPaused( bytes32 key ) internal view virtual returns (bool status) { - status = PartiallyPausableStorage.layout().partiallyPaused[key]; + status = PartiallyPausableStorage + .layout(PartiallyPausableStorage.DEFAULT_STORAGE_SLOT) + .partiallyPaused[key]; } /** @@ -37,7 +39,9 @@ abstract contract PartiallyPausableInternal is IPartiallyPausableInternal { function _partiallyPause( bytes32 key ) internal virtual whenNotPartiallyPaused(key) { - PartiallyPausableStorage.layout().partiallyPaused[key] = true; + PartiallyPausableStorage + .layout(PartiallyPausableStorage.DEFAULT_STORAGE_SLOT) + .partiallyPaused[key] = true; emit PartiallyPaused(msg.sender, key); } @@ -48,7 +52,9 @@ abstract contract PartiallyPausableInternal is IPartiallyPausableInternal { function _partiallyUnpause( bytes32 key ) internal virtual whenPartiallyPaused(key) { - delete PartiallyPausableStorage.layout().partiallyPaused[key]; + delete PartiallyPausableStorage + .layout(PartiallyPausableStorage.DEFAULT_STORAGE_SLOT) + .partiallyPaused[key]; emit PartiallyUnpaused(msg.sender, key); } } diff --git a/contracts/security/partially_pausable/PartiallyPausableStorage.sol b/contracts/security/partially_pausable/PartiallyPausableStorage.sol index 6423659e..2d2f2e4a 100644 --- a/contracts/security/partially_pausable/PartiallyPausableStorage.sol +++ b/contracts/security/partially_pausable/PartiallyPausableStorage.sol @@ -7,11 +7,22 @@ library PartiallyPausableStorage { mapping(bytes32 => bool) partiallyPaused; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.PartiallyPausable'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes('solidstate.contracts.storage.PartiallyPausable') + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/security/pausable/PausableInternal.sol b/contracts/security/pausable/PausableInternal.sol index 468c9ded..3b075f7f 100644 --- a/contracts/security/pausable/PausableInternal.sol +++ b/contracts/security/pausable/PausableInternal.sol @@ -24,14 +24,18 @@ abstract contract PausableInternal is IPausableInternal { * @return status whether contract is paused */ function _paused() internal view virtual returns (bool status) { - status = PausableStorage.layout().paused; + status = PausableStorage + .layout(PausableStorage.DEFAULT_STORAGE_SLOT) + .paused; } /** * @notice Triggers paused state, when contract is unpaused. */ function _pause() internal virtual whenNotPaused { - PausableStorage.layout().paused = true; + PausableStorage + .layout(PausableStorage.DEFAULT_STORAGE_SLOT) + .paused = true; emit Paused(msg.sender); } @@ -39,7 +43,9 @@ abstract contract PausableInternal is IPausableInternal { * @notice Triggers unpaused state, when contract is paused. */ function _unpause() internal virtual whenPaused { - delete PausableStorage.layout().paused; + delete PausableStorage + .layout(PausableStorage.DEFAULT_STORAGE_SLOT) + .paused; emit Unpaused(msg.sender); } } diff --git a/contracts/security/pausable/PausableStorage.sol b/contracts/security/pausable/PausableStorage.sol index 39bdf795..ea4b0dc8 100644 --- a/contracts/security/pausable/PausableStorage.sol +++ b/contracts/security/pausable/PausableStorage.sol @@ -7,11 +7,20 @@ library PausableStorage { bool paused; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.Pausable'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.Pausable')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/security/reentrancy_guard/ReentrancyGuard.sol b/contracts/security/reentrancy_guard/ReentrancyGuard.sol index d3f51980..5debefcb 100644 --- a/contracts/security/reentrancy_guard/ReentrancyGuard.sol +++ b/contracts/security/reentrancy_guard/ReentrancyGuard.sol @@ -24,20 +24,26 @@ abstract contract ReentrancyGuard is IReentrancyGuard { */ function _isReentrancyGuardLocked() internal view virtual returns (bool) { return - ReentrancyGuardStorage.layout().status == REENTRANCY_STATUS_LOCKED; + ReentrancyGuardStorage + .layout(ReentrancyGuardStorage.DEFAULT_STORAGE_SLOT) + .status == REENTRANCY_STATUS_LOCKED; } /** * @notice lock functions that use the nonReentrant modifier */ function _lockReentrancyGuard() internal virtual { - ReentrancyGuardStorage.layout().status = REENTRANCY_STATUS_LOCKED; + ReentrancyGuardStorage + .layout(ReentrancyGuardStorage.DEFAULT_STORAGE_SLOT) + .status = REENTRANCY_STATUS_LOCKED; } /** * @notice unlock functions that use the nonReentrant modifier */ function _unlockReentrancyGuard() internal virtual { - ReentrancyGuardStorage.layout().status = REENTRANCY_STATUS_UNLOCKED; + ReentrancyGuardStorage + .layout(ReentrancyGuardStorage.DEFAULT_STORAGE_SLOT) + .status = REENTRANCY_STATUS_UNLOCKED; } } diff --git a/contracts/security/reentrancy_guard/ReentrancyGuardStorage.sol b/contracts/security/reentrancy_guard/ReentrancyGuardStorage.sol index 87929c21..02061833 100644 --- a/contracts/security/reentrancy_guard/ReentrancyGuardStorage.sol +++ b/contracts/security/reentrancy_guard/ReentrancyGuardStorage.sol @@ -7,11 +7,22 @@ library ReentrancyGuardStorage { uint256 status; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ReentrancyGuard'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes('solidstate.contracts.storage.ReentrancyGuard') + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/signature/base/ERC1271Base.sol b/contracts/signature/ERC1271/base/ERC1271Base.sol similarity index 90% rename from contracts/signature/base/ERC1271Base.sol rename to contracts/signature/ERC1271/base/ERC1271Base.sol index 15826e8b..c6a34d4a 100644 --- a/contracts/signature/base/ERC1271Base.sol +++ b/contracts/signature/ERC1271/base/ERC1271Base.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; -import { IERC1271 } from '../../interfaces/IERC1271.sol'; +import { IERC1271 } from '../../../interfaces/IERC1271.sol'; import { IERC1271Base } from './IERC1271Base.sol'; import { ERC1271BaseInternal } from './ERC1271BaseInternal.sol'; diff --git a/contracts/signature/base/ERC1271BaseInternal.sol b/contracts/signature/ERC1271/base/ERC1271BaseInternal.sol similarity index 91% rename from contracts/signature/base/ERC1271BaseInternal.sol rename to contracts/signature/ERC1271/base/ERC1271BaseInternal.sol index 537d1111..0cad9ffb 100644 --- a/contracts/signature/base/ERC1271BaseInternal.sol +++ b/contracts/signature/ERC1271/base/ERC1271BaseInternal.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; -import { IERC1271 } from '../../interfaces/IERC1271.sol'; +import { IERC1271 } from '../../../interfaces/IERC1271.sol'; /** * @title ERC1271Base internal functions diff --git a/contracts/signature/base/IERC1271Base.sol b/contracts/signature/ERC1271/base/IERC1271Base.sol similarity index 61% rename from contracts/signature/base/IERC1271Base.sol rename to contracts/signature/ERC1271/base/IERC1271Base.sol index b319155a..c39b41e4 100644 --- a/contracts/signature/base/IERC1271Base.sol +++ b/contracts/signature/ERC1271/base/IERC1271Base.sol @@ -2,6 +2,6 @@ pragma solidity ^0.8.20; -import { IERC1271 } from '../../interfaces/IERC1271.sol'; +import { IERC1271 } from '../../../interfaces/IERC1271.sol'; interface IERC1271Base is IERC1271 {} diff --git a/contracts/signature/ownable/ERC1271Ownable.sol b/contracts/signature/ERC1271/ownable/ERC1271Ownable.sol similarity index 100% rename from contracts/signature/ownable/ERC1271Ownable.sol rename to contracts/signature/ERC1271/ownable/ERC1271Ownable.sol diff --git a/contracts/signature/ownable/ERC1271OwnableInternal.sol b/contracts/signature/ERC1271/ownable/ERC1271OwnableInternal.sol similarity index 84% rename from contracts/signature/ownable/ERC1271OwnableInternal.sol rename to contracts/signature/ERC1271/ownable/ERC1271OwnableInternal.sol index 69769902..46d453e3 100644 --- a/contracts/signature/ownable/ERC1271OwnableInternal.sol +++ b/contracts/signature/ERC1271/ownable/ERC1271OwnableInternal.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.20; -import { OwnableInternal } from '../../access/ownable/OwnableInternal.sol'; -import { ECDSA } from '../../cryptography/ECDSA.sol'; +import { OwnableInternal } from '../../../access/ownable/OwnableInternal.sol'; +import { ECDSA } from '../../../cryptography/ECDSA.sol'; import { ERC1271BaseInternal } from '../base/ERC1271BaseInternal.sol'; /** diff --git a/contracts/signature/ownable/ERC1271OwnableMock.sol b/contracts/signature/ERC1271/ownable/ERC1271OwnableMock.sol similarity index 100% rename from contracts/signature/ownable/ERC1271OwnableMock.sol rename to contracts/signature/ERC1271/ownable/ERC1271OwnableMock.sol diff --git a/contracts/signature/ownable/IERC1271Ownable.sol b/contracts/signature/ERC1271/ownable/IERC1271Ownable.sol similarity index 100% rename from contracts/signature/ownable/IERC1271Ownable.sol rename to contracts/signature/ERC1271/ownable/IERC1271Ownable.sol diff --git a/contracts/signature/stored/ERC1271Stored.sol b/contracts/signature/ERC1271/stored/ERC1271Stored.sol similarity index 100% rename from contracts/signature/stored/ERC1271Stored.sol rename to contracts/signature/ERC1271/stored/ERC1271Stored.sol diff --git a/contracts/signature/stored/ERC1271StoredInternal.sol b/contracts/signature/ERC1271/stored/ERC1271StoredInternal.sol similarity index 70% rename from contracts/signature/stored/ERC1271StoredInternal.sol rename to contracts/signature/ERC1271/stored/ERC1271StoredInternal.sol index 3b393095..54de6f5f 100644 --- a/contracts/signature/stored/ERC1271StoredInternal.sol +++ b/contracts/signature/ERC1271/stored/ERC1271StoredInternal.sol @@ -14,12 +14,16 @@ abstract contract ERC1271StoredInternal is ERC1271BaseInternal { bytes memory ) internal view virtual override returns (bytes4 magicValue) { return - ERC1271StoredStorage.layout().hashes[hash] + ERC1271StoredStorage + .layout(ERC1271StoredStorage.DEFAULT_STORAGE_SLOT) + .hashes[hash] ? MAGIC_VALUE : bytes4(0); } function _setValidSignature(bytes32 hash, bool status) internal { - ERC1271StoredStorage.layout().hashes[hash] = status; + ERC1271StoredStorage + .layout(ERC1271StoredStorage.DEFAULT_STORAGE_SLOT) + .hashes[hash] = status; } } diff --git a/contracts/signature/stored/ERC1271StoredMock.sol b/contracts/signature/ERC1271/stored/ERC1271StoredMock.sol similarity index 81% rename from contracts/signature/stored/ERC1271StoredMock.sol rename to contracts/signature/ERC1271/stored/ERC1271StoredMock.sol index 3fc90f9d..5784580e 100644 --- a/contracts/signature/stored/ERC1271StoredMock.sol +++ b/contracts/signature/ERC1271/stored/ERC1271StoredMock.sol @@ -7,7 +7,9 @@ import { ERC1271Stored } from './ERC1271Stored.sol'; contract ERC1271StoredMock is ERC1271Stored { constructor(bytes32 hash) { - ERC1271StoredStorage.layout().hashes[hash] = true; + ERC1271StoredStorage + .layout(ERC1271StoredStorage.DEFAULT_STORAGE_SLOT) + .hashes[hash] = true; } function __isValidSignature( diff --git a/contracts/signature/ERC1271/stored/ERC1271StoredStorage.sol b/contracts/signature/ERC1271/stored/ERC1271StoredStorage.sol new file mode 100644 index 00000000..9c2b4a3e --- /dev/null +++ b/contracts/signature/ERC1271/stored/ERC1271StoredStorage.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +library ERC1271StoredStorage { + struct Layout { + mapping(bytes32 => bool) hashes; + } + + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes('solidstate.contracts.storage.ERC1271Stored') + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); + + function layout() internal pure returns (Layout storage l) { + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { + assembly { + l.slot := slot + } + } +} diff --git a/contracts/signature/stored/IERC1271Stored.sol b/contracts/signature/ERC1271/stored/IERC1271Stored.sol similarity index 100% rename from contracts/signature/stored/IERC1271Stored.sol rename to contracts/signature/ERC1271/stored/IERC1271Stored.sol diff --git a/contracts/signature/ERC7201/ERC7201.sol b/contracts/signature/ERC7201/ERC7201.sol new file mode 100644 index 00000000..ed195a24 --- /dev/null +++ b/contracts/signature/ERC7201/ERC7201.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +/** + * @title EIP-7201 namespaced storage layout library + * @dev see https://eips.ethereum.org/EIPS/eip-7201 + */ +library ERC7201 { + /** + * @notice calculate the EIP-7201 storage slot for a given string id + * @dev id parameter should not contain whitespace + * @param id namespace id + */ + function calculateStorageSlot( + string memory id + ) internal pure returns (bytes32 slot) { + slot = + keccak256(abi.encode(uint256(keccak256(bytes(id))) - 1)) & + ~bytes32(uint256(0xff)); + } +} diff --git a/contracts/signature/ERC7201/ERC7201Mock.sol b/contracts/signature/ERC7201/ERC7201Mock.sol new file mode 100644 index 00000000..667df2a9 --- /dev/null +++ b/contracts/signature/ERC7201/ERC7201Mock.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import { ERC7201 } from './ERC7201.sol'; + +contract ERC7201Mock { + function calculateStorageSlot( + string calldata id + ) external pure returns (bytes32 slot) { + slot = ERC7201.calculateStorageSlot(id); + } +} diff --git a/contracts/signature/stored/ERC1271StoredStorage.sol b/contracts/signature/stored/ERC1271StoredStorage.sol deleted file mode 100644 index 7ce41d18..00000000 --- a/contracts/signature/stored/ERC1271StoredStorage.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.20; - -library ERC1271StoredStorage { - struct Layout { - mapping(bytes32 => bool) hashes; - } - - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC1271Stored'); - - function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; - assembly { - l.slot := slot - } - } -} diff --git a/contracts/token/ERC1155/base/ERC1155Base.sol b/contracts/token/ERC1155/base/ERC1155Base.sol index bc6069e9..44be7c50 100644 --- a/contracts/token/ERC1155/base/ERC1155Base.sol +++ b/contracts/token/ERC1155/base/ERC1155Base.sol @@ -34,7 +34,9 @@ abstract contract ERC1155Base is IERC1155Base, ERC1155BaseInternal { revert ERC1155Base__ArrayLengthMismatch(); mapping(uint256 => mapping(address => uint256)) - storage balances = ERC1155BaseStorage.layout().balances; + storage balances = ERC1155BaseStorage + .layout(ERC1155BaseStorage.DEFAULT_STORAGE_SLOT) + .balances; uint256[] memory batchBalances = new uint256[](accounts.length); @@ -56,7 +58,10 @@ abstract contract ERC1155Base is IERC1155Base, ERC1155BaseInternal { address account, address operator ) public view virtual returns (bool) { - return ERC1155BaseStorage.layout().operatorApprovals[account][operator]; + return + ERC1155BaseStorage + .layout(ERC1155BaseStorage.DEFAULT_STORAGE_SLOT) + .operatorApprovals[account][operator]; } /** @@ -64,9 +69,9 @@ abstract contract ERC1155Base is IERC1155Base, ERC1155BaseInternal { */ function setApprovalForAll(address operator, bool status) public virtual { if (msg.sender == operator) revert ERC1155Base__SelfApproval(); - ERC1155BaseStorage.layout().operatorApprovals[msg.sender][ - operator - ] = status; + ERC1155BaseStorage + .layout(ERC1155BaseStorage.DEFAULT_STORAGE_SLOT) + .operatorApprovals[msg.sender][operator] = status; emit ApprovalForAll(msg.sender, operator, status); } diff --git a/contracts/token/ERC1155/base/ERC1155BaseInternal.sol b/contracts/token/ERC1155/base/ERC1155BaseInternal.sol index 8dbba8ff..caadd04b 100644 --- a/contracts/token/ERC1155/base/ERC1155BaseInternal.sol +++ b/contracts/token/ERC1155/base/ERC1155BaseInternal.sol @@ -26,7 +26,10 @@ abstract contract ERC1155BaseInternal is IERC1155BaseInternal { ) internal view virtual returns (uint256) { if (account == address(0)) revert ERC1155Base__BalanceQueryZeroAddress(); - return ERC1155BaseStorage.layout().balances[id][account]; + return + ERC1155BaseStorage + .layout(ERC1155BaseStorage.DEFAULT_STORAGE_SLOT) + .balances[id][account]; } /** @@ -54,7 +57,9 @@ abstract contract ERC1155BaseInternal is IERC1155BaseInternal { data ); - ERC1155BaseStorage.layout().balances[id][account] += amount; + ERC1155BaseStorage + .layout(ERC1155BaseStorage.DEFAULT_STORAGE_SLOT) + .balances[id][account] += amount; emit TransferSingle(msg.sender, address(0), account, id, amount); } @@ -112,7 +117,9 @@ abstract contract ERC1155BaseInternal is IERC1155BaseInternal { ); mapping(uint256 => mapping(address => uint256)) - storage balances = ERC1155BaseStorage.layout().balances; + storage balances = ERC1155BaseStorage + .layout(ERC1155BaseStorage.DEFAULT_STORAGE_SLOT) + .balances; for (uint256 i; i < ids.length; ) { balances[ids[i]][account] += amounts[i]; @@ -172,7 +179,7 @@ abstract contract ERC1155BaseInternal is IERC1155BaseInternal { ); mapping(address => uint256) storage balances = ERC1155BaseStorage - .layout() + .layout(ERC1155BaseStorage.DEFAULT_STORAGE_SLOT) .balances[id]; unchecked { @@ -202,7 +209,9 @@ abstract contract ERC1155BaseInternal is IERC1155BaseInternal { _beforeTokenTransfer(msg.sender, account, address(0), ids, amounts, ''); mapping(uint256 => mapping(address => uint256)) - storage balances = ERC1155BaseStorage.layout().balances; + storage balances = ERC1155BaseStorage + .layout(ERC1155BaseStorage.DEFAULT_STORAGE_SLOT) + .balances; unchecked { for (uint256 i; i < ids.length; i++) { @@ -247,7 +256,9 @@ abstract contract ERC1155BaseInternal is IERC1155BaseInternal { ); mapping(uint256 => mapping(address => uint256)) - storage balances = ERC1155BaseStorage.layout().balances; + storage balances = ERC1155BaseStorage + .layout(ERC1155BaseStorage.DEFAULT_STORAGE_SLOT) + .balances; unchecked { uint256 senderBalance = balances[id][sender]; @@ -316,7 +327,9 @@ abstract contract ERC1155BaseInternal is IERC1155BaseInternal { _beforeTokenTransfer(operator, sender, recipient, ids, amounts, data); mapping(uint256 => mapping(address => uint256)) - storage balances = ERC1155BaseStorage.layout().balances; + storage balances = ERC1155BaseStorage + .layout(ERC1155BaseStorage.DEFAULT_STORAGE_SLOT) + .balances; for (uint256 i; i < ids.length; ) { uint256 token = ids[i]; diff --git a/contracts/token/ERC1155/base/ERC1155BaseStorage.sol b/contracts/token/ERC1155/base/ERC1155BaseStorage.sol index de355743..3ca70126 100644 --- a/contracts/token/ERC1155/base/ERC1155BaseStorage.sol +++ b/contracts/token/ERC1155/base/ERC1155BaseStorage.sol @@ -8,11 +8,20 @@ library ERC1155BaseStorage { mapping(address => mapping(address => bool)) operatorApprovals; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC1155Base'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.ERC1155Base')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/ERC1155/enumerable/ERC1155EnumerableInternal.sol b/contracts/token/ERC1155/enumerable/ERC1155EnumerableInternal.sol index 2a9fee73..e5d5fc3f 100644 --- a/contracts/token/ERC1155/enumerable/ERC1155EnumerableInternal.sol +++ b/contracts/token/ERC1155/enumerable/ERC1155EnumerableInternal.sol @@ -19,7 +19,10 @@ abstract contract ERC1155EnumerableInternal is ERC1155BaseInternal { * @return token supply */ function _totalSupply(uint256 id) internal view virtual returns (uint256) { - return ERC1155EnumerableStorage.layout().totalSupply[id]; + return + ERC1155EnumerableStorage + .layout(ERC1155EnumerableStorage.DEFAULT_STORAGE_SLOT) + .totalSupply[id]; } /** @@ -28,7 +31,11 @@ abstract contract ERC1155EnumerableInternal is ERC1155BaseInternal { * @return quantity of holders */ function _totalHolders(uint256 id) internal view virtual returns (uint256) { - return ERC1155EnumerableStorage.layout().accountsByToken[id].length(); + return + ERC1155EnumerableStorage + .layout(ERC1155EnumerableStorage.DEFAULT_STORAGE_SLOT) + .accountsByToken[id] + .length(); } /** @@ -40,7 +47,7 @@ abstract contract ERC1155EnumerableInternal is ERC1155BaseInternal { uint256 id ) internal view virtual returns (address[] memory) { EnumerableSet.AddressSet storage accounts = ERC1155EnumerableStorage - .layout() + .layout(ERC1155EnumerableStorage.DEFAULT_STORAGE_SLOT) .accountsByToken[id]; address[] memory addresses = new address[](accounts.length()); @@ -63,7 +70,7 @@ abstract contract ERC1155EnumerableInternal is ERC1155BaseInternal { address account ) internal view virtual returns (uint256[] memory) { EnumerableSet.UintSet storage tokens = ERC1155EnumerableStorage - .layout() + .layout(ERC1155EnumerableStorage.DEFAULT_STORAGE_SLOT) .tokensByAccount[account]; uint256[] memory ids = new uint256[](tokens.length()); @@ -93,7 +100,7 @@ abstract contract ERC1155EnumerableInternal is ERC1155BaseInternal { if (from != to) { ERC1155EnumerableStorage.Layout storage l = ERC1155EnumerableStorage - .layout(); + .layout(ERC1155EnumerableStorage.DEFAULT_STORAGE_SLOT); mapping(uint256 => EnumerableSet.AddressSet) storage tokenAccounts = l.accountsByToken; EnumerableSet.UintSet storage fromTokens = l.tokensByAccount[from]; diff --git a/contracts/token/ERC1155/enumerable/ERC1155EnumerableStorage.sol b/contracts/token/ERC1155/enumerable/ERC1155EnumerableStorage.sol index 957c9d74..5b6a96cd 100644 --- a/contracts/token/ERC1155/enumerable/ERC1155EnumerableStorage.sol +++ b/contracts/token/ERC1155/enumerable/ERC1155EnumerableStorage.sol @@ -11,11 +11,22 @@ library ERC1155EnumerableStorage { mapping(address => EnumerableSet.UintSet) tokensByAccount; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC1155Enumerable'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes('solidstate.contracts.storage.ERC1155Enumerable') + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/ERC1155/metadata/ERC1155Metadata.sol b/contracts/token/ERC1155/metadata/ERC1155Metadata.sol index b267b8d7..6a251280 100644 --- a/contracts/token/ERC1155/metadata/ERC1155Metadata.sol +++ b/contracts/token/ERC1155/metadata/ERC1155Metadata.sol @@ -17,8 +17,9 @@ abstract contract ERC1155Metadata is IERC1155Metadata, ERC1155MetadataInternal { * @notice inheritdoc IERC1155Metadata */ function uri(uint256 tokenId) public view virtual returns (string memory) { - ERC1155MetadataStorage.Layout storage l = ERC1155MetadataStorage - .layout(); + ERC1155MetadataStorage.Layout storage l = ERC1155MetadataStorage.layout( + ERC1155MetadataStorage.DEFAULT_STORAGE_SLOT + ); string memory tokenIdURI = l.tokenURIs[tokenId]; string memory baseURI = l.baseURI; diff --git a/contracts/token/ERC1155/metadata/ERC1155MetadataInternal.sol b/contracts/token/ERC1155/metadata/ERC1155MetadataInternal.sol index e34aad11..cccdc896 100644 --- a/contracts/token/ERC1155/metadata/ERC1155MetadataInternal.sol +++ b/contracts/token/ERC1155/metadata/ERC1155MetadataInternal.sol @@ -15,7 +15,9 @@ abstract contract ERC1155MetadataInternal is IERC1155MetadataInternal { * @param baseURI base URI */ function _setBaseURI(string memory baseURI) internal { - ERC1155MetadataStorage.layout().baseURI = baseURI; + ERC1155MetadataStorage + .layout(ERC1155MetadataStorage.DEFAULT_STORAGE_SLOT) + .baseURI = baseURI; } /** @@ -24,7 +26,9 @@ abstract contract ERC1155MetadataInternal is IERC1155MetadataInternal { * @param tokenURI per-token URI */ function _setTokenURI(uint256 tokenId, string memory tokenURI) internal { - ERC1155MetadataStorage.layout().tokenURIs[tokenId] = tokenURI; + ERC1155MetadataStorage + .layout(ERC1155MetadataStorage.DEFAULT_STORAGE_SLOT) + .tokenURIs[tokenId] = tokenURI; emit URI(tokenURI, tokenId); } } diff --git a/contracts/token/ERC1155/metadata/ERC1155MetadataMock.sol b/contracts/token/ERC1155/metadata/ERC1155MetadataMock.sol index 03c91522..c82712ed 100644 --- a/contracts/token/ERC1155/metadata/ERC1155MetadataMock.sol +++ b/contracts/token/ERC1155/metadata/ERC1155MetadataMock.sol @@ -7,6 +7,8 @@ import { ERC165Base } from '../../../introspection/ERC165/base/ERC165Base.sol'; contract ERC1155MetadataMock is ERC1155Metadata, ERC165Base { constructor(string memory baseURI) { - ERC1155MetadataStorage.layout().baseURI = baseURI; + ERC1155MetadataStorage + .layout(ERC1155MetadataStorage.DEFAULT_STORAGE_SLOT) + .baseURI = baseURI; } } diff --git a/contracts/token/ERC1155/metadata/ERC1155MetadataStorage.sol b/contracts/token/ERC1155/metadata/ERC1155MetadataStorage.sol index fd453dc9..ea0c0d19 100644 --- a/contracts/token/ERC1155/metadata/ERC1155MetadataStorage.sol +++ b/contracts/token/ERC1155/metadata/ERC1155MetadataStorage.sol @@ -6,8 +6,16 @@ pragma solidity ^0.8.20; * @title ERC1155 metadata extensions */ library ERC1155MetadataStorage { - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC1155Metadata'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes('solidstate.contracts.storage.ERC1155Metadata') + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); struct Layout { string baseURI; @@ -15,7 +23,10 @@ library ERC1155MetadataStorage { } function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/ERC1404/base/ERC1404BaseInternal.sol b/contracts/token/ERC1404/base/ERC1404BaseInternal.sol index 6c6d516c..740f93a8 100644 --- a/contracts/token/ERC1404/base/ERC1404BaseInternal.sol +++ b/contracts/token/ERC1404/base/ERC1404BaseInternal.sol @@ -22,7 +22,7 @@ abstract contract ERC1404BaseInternal is revert ERC1404Base__ArrayLengthMismatch(); mapping(uint8 => string) storage restrictions = ERC1404BaseStorage - .layout() + .layout(ERC1404BaseStorage.DEFAULT_STORAGE_SLOT) .restrictions; unchecked { @@ -41,7 +41,10 @@ abstract contract ERC1404BaseInternal is function _messageForTransferRestriction( uint8 restrictionCode ) internal view virtual returns (string memory) { - return ERC1404BaseStorage.layout().restrictions[restrictionCode]; + return + ERC1404BaseStorage + .layout(ERC1404BaseStorage.DEFAULT_STORAGE_SLOT) + .restrictions[restrictionCode]; } /** diff --git a/contracts/token/ERC1404/base/ERC1404BaseStorage.sol b/contracts/token/ERC1404/base/ERC1404BaseStorage.sol index 7f7c8f4b..ced5d93d 100644 --- a/contracts/token/ERC1404/base/ERC1404BaseStorage.sol +++ b/contracts/token/ERC1404/base/ERC1404BaseStorage.sol @@ -7,11 +7,20 @@ library ERC1404BaseStorage { mapping(uint8 => string) restrictions; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC1404Base'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.ERC1404Base')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/ERC20/base/ERC20BaseInternal.sol b/contracts/token/ERC20/base/ERC20BaseInternal.sol index 6de697ae..3f09dd0f 100644 --- a/contracts/token/ERC20/base/ERC20BaseInternal.sol +++ b/contracts/token/ERC20/base/ERC20BaseInternal.sol @@ -14,7 +14,10 @@ abstract contract ERC20BaseInternal is IERC20BaseInternal { * @return token supply */ function _totalSupply() internal view virtual returns (uint256) { - return ERC20BaseStorage.layout().totalSupply; + return + ERC20BaseStorage + .layout(ERC20BaseStorage.DEFAULT_STORAGE_SLOT) + .totalSupply; } /** @@ -25,7 +28,10 @@ abstract contract ERC20BaseInternal is IERC20BaseInternal { function _balanceOf( address account ) internal view virtual returns (uint256) { - return ERC20BaseStorage.layout().balances[account]; + return + ERC20BaseStorage + .layout(ERC20BaseStorage.DEFAULT_STORAGE_SLOT) + .balances[account]; } /** @@ -38,7 +44,10 @@ abstract contract ERC20BaseInternal is IERC20BaseInternal { address holder, address spender ) internal view virtual returns (uint256) { - return ERC20BaseStorage.layout().allowances[holder][spender]; + return + ERC20BaseStorage + .layout(ERC20BaseStorage.DEFAULT_STORAGE_SLOT) + .allowances[holder][spender]; } /** @@ -56,7 +65,9 @@ abstract contract ERC20BaseInternal is IERC20BaseInternal { if (holder == address(0)) revert ERC20Base__ApproveFromZeroAddress(); if (spender == address(0)) revert ERC20Base__ApproveToZeroAddress(); - ERC20BaseStorage.layout().allowances[holder][spender] = amount; + ERC20BaseStorage + .layout(ERC20BaseStorage.DEFAULT_STORAGE_SLOT) + .allowances[holder][spender] = amount; emit Approval(holder, spender, amount); @@ -93,7 +104,9 @@ abstract contract ERC20BaseInternal is IERC20BaseInternal { _beforeTokenTransfer(address(0), account, amount); - ERC20BaseStorage.Layout storage l = ERC20BaseStorage.layout(); + ERC20BaseStorage.Layout storage l = ERC20BaseStorage.layout( + ERC20BaseStorage.DEFAULT_STORAGE_SLOT + ); l.totalSupply += amount; l.balances[account] += amount; @@ -110,7 +123,9 @@ abstract contract ERC20BaseInternal is IERC20BaseInternal { _beforeTokenTransfer(account, address(0), amount); - ERC20BaseStorage.Layout storage l = ERC20BaseStorage.layout(); + ERC20BaseStorage.Layout storage l = ERC20BaseStorage.layout( + ERC20BaseStorage.DEFAULT_STORAGE_SLOT + ); uint256 balance = l.balances[account]; if (amount > balance) revert ERC20Base__BurnExceedsBalance(); unchecked { @@ -138,7 +153,9 @@ abstract contract ERC20BaseInternal is IERC20BaseInternal { _beforeTokenTransfer(holder, recipient, amount); - ERC20BaseStorage.Layout storage l = ERC20BaseStorage.layout(); + ERC20BaseStorage.Layout storage l = ERC20BaseStorage.layout( + ERC20BaseStorage.DEFAULT_STORAGE_SLOT + ); uint256 holderBalance = l.balances[holder]; if (amount > holderBalance) revert ERC20Base__TransferExceedsBalance(); unchecked { diff --git a/contracts/token/ERC20/base/ERC20BaseStorage.sol b/contracts/token/ERC20/base/ERC20BaseStorage.sol index 89b7e8d4..ded3d6d0 100644 --- a/contracts/token/ERC20/base/ERC20BaseStorage.sol +++ b/contracts/token/ERC20/base/ERC20BaseStorage.sol @@ -9,11 +9,20 @@ library ERC20BaseStorage { uint256 totalSupply; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC20Base'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.ERC20Base')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalInternal.sol b/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalInternal.sol index cf8ba444..8f61276f 100644 --- a/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalInternal.sol +++ b/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalInternal.sol @@ -49,6 +49,9 @@ abstract contract ERC20ImplicitApprovalInternal is ERC20BaseInternal { function _isImplicitlyApproved( address account ) internal view virtual returns (bool) { - return ERC20ImplicitApprovalStorage.layout().implicitApprovals[account]; + return + ERC20ImplicitApprovalStorage + .layout(ERC20ImplicitApprovalStorage.DEFAULT_STORAGE_SLOT) + .implicitApprovals[account]; } } diff --git a/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalMock.sol b/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalMock.sol index 68a464f1..d0174237 100644 --- a/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalMock.sol +++ b/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalMock.sol @@ -8,7 +8,9 @@ import { ERC20ImplicitApprovalStorage } from './ERC20ImplicitApprovalStorage.sol contract ERC20ImplicitApprovalMock is ERC20ImplicitApproval { constructor(address[] memory approvedAccounts) { ERC20ImplicitApprovalStorage.Layout - storage l = ERC20ImplicitApprovalStorage.layout(); + storage l = ERC20ImplicitApprovalStorage.layout( + ERC20ImplicitApprovalStorage.DEFAULT_STORAGE_SLOT + ); for (uint256 i; i < approvedAccounts.length; i++) { l.implicitApprovals[approvedAccounts[i]] = true; diff --git a/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalStorage.sol b/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalStorage.sol index 82ac22e9..8e2f9f7b 100644 --- a/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalStorage.sol +++ b/contracts/token/ERC20/implicit_approval/ERC20ImplicitApprovalStorage.sol @@ -7,11 +7,24 @@ library ERC20ImplicitApprovalStorage { mapping(address => bool) implicitApprovals; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC20ImplicitApproval'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes( + 'solidstate.contracts.storage.ERC20ImplicitApproval' + ) + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/ERC20/metadata/ERC20MetadataInternal.sol b/contracts/token/ERC20/metadata/ERC20MetadataInternal.sol index a749fb08..cff232ce 100644 --- a/contracts/token/ERC20/metadata/ERC20MetadataInternal.sol +++ b/contracts/token/ERC20/metadata/ERC20MetadataInternal.sol @@ -14,7 +14,10 @@ abstract contract ERC20MetadataInternal is IERC20MetadataInternal { * @return token name */ function _name() internal view virtual returns (string memory) { - return ERC20MetadataStorage.layout().name; + return + ERC20MetadataStorage + .layout(ERC20MetadataStorage.DEFAULT_STORAGE_SLOT) + .name; } /** @@ -22,7 +25,10 @@ abstract contract ERC20MetadataInternal is IERC20MetadataInternal { * @return token symbol */ function _symbol() internal view virtual returns (string memory) { - return ERC20MetadataStorage.layout().symbol; + return + ERC20MetadataStorage + .layout(ERC20MetadataStorage.DEFAULT_STORAGE_SLOT) + .symbol; } /** @@ -30,18 +36,27 @@ abstract contract ERC20MetadataInternal is IERC20MetadataInternal { * @return token decimals */ function _decimals() internal view virtual returns (uint8) { - return ERC20MetadataStorage.layout().decimals; + return + ERC20MetadataStorage + .layout(ERC20MetadataStorage.DEFAULT_STORAGE_SLOT) + .decimals; } function _setName(string memory name) internal virtual { - ERC20MetadataStorage.layout().name = name; + ERC20MetadataStorage + .layout(ERC20MetadataStorage.DEFAULT_STORAGE_SLOT) + .name = name; } function _setSymbol(string memory symbol) internal virtual { - ERC20MetadataStorage.layout().symbol = symbol; + ERC20MetadataStorage + .layout(ERC20MetadataStorage.DEFAULT_STORAGE_SLOT) + .symbol = symbol; } function _setDecimals(uint8 decimals) internal virtual { - ERC20MetadataStorage.layout().decimals = decimals; + ERC20MetadataStorage + .layout(ERC20MetadataStorage.DEFAULT_STORAGE_SLOT) + .decimals = decimals; } } diff --git a/contracts/token/ERC20/metadata/ERC20MetadataStorage.sol b/contracts/token/ERC20/metadata/ERC20MetadataStorage.sol index ba1ce09f..83d9e2e0 100644 --- a/contracts/token/ERC20/metadata/ERC20MetadataStorage.sol +++ b/contracts/token/ERC20/metadata/ERC20MetadataStorage.sol @@ -9,11 +9,22 @@ library ERC20MetadataStorage { uint8 decimals; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC20Metadata'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes('solidstate.contracts.storage.ERC20Metadata') + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/ERC20/permit/ERC20PermitInternal.sol b/contracts/token/ERC20/permit/ERC20PermitInternal.sol index f7ac96d5..3ca0bebb 100644 --- a/contracts/token/ERC20/permit/ERC20PermitInternal.sol +++ b/contracts/token/ERC20/permit/ERC20PermitInternal.sol @@ -34,9 +34,9 @@ abstract contract ERC20PermitInternal is view returns (bytes32 domainSeparator) { - domainSeparator = ERC20PermitStorage.layout().domainSeparators[ - block.chainid - ]; + domainSeparator = ERC20PermitStorage + .layout(ERC20PermitStorage.DEFAULT_STORAGE_SLOT) + .domainSeparators[block.chainid]; if (domainSeparator == 0x00) { domainSeparator = EIP712.calculateDomainSeparator( @@ -51,7 +51,10 @@ abstract contract ERC20PermitInternal is * @return current nonce */ function _nonces(address owner) internal view returns (uint256) { - return ERC20PermitStorage.layout().nonces[owner]; + return + ERC20PermitStorage + .layout(ERC20PermitStorage.DEFAULT_STORAGE_SLOT) + .nonces[owner]; } /** @@ -83,7 +86,9 @@ abstract contract ERC20PermitInternal is ) internal virtual { if (deadline < block.timestamp) revert ERC20Permit__ExpiredDeadline(); - ERC20PermitStorage.Layout storage l = ERC20PermitStorage.layout(); + ERC20PermitStorage.Layout storage l = ERC20PermitStorage.layout( + ERC20PermitStorage.DEFAULT_STORAGE_SLOT + ); // execute EIP-712 hashStruct procedure using assembly, equavalent to: // @@ -173,6 +178,8 @@ abstract contract ERC20PermitInternal is function _setName(string memory name) internal virtual override { // TODO: cache invalidation can fail if chainid is reverted to a previous value super._setName(name); - delete ERC20PermitStorage.layout().domainSeparators[block.chainid]; + delete ERC20PermitStorage + .layout(ERC20PermitStorage.DEFAULT_STORAGE_SLOT) + .domainSeparators[block.chainid]; } } diff --git a/contracts/token/ERC20/permit/ERC20PermitMock.sol b/contracts/token/ERC20/permit/ERC20PermitMock.sol index 66dc0b97..67bf57e9 100644 --- a/contracts/token/ERC20/permit/ERC20PermitMock.sol +++ b/contracts/token/ERC20/permit/ERC20PermitMock.sol @@ -8,7 +8,9 @@ import { ERC20Permit } from './ERC20Permit.sol'; contract ERC20PermitMock is ERC20Permit, ERC20Base { constructor(string memory tokenName) { - ERC20MetadataStorage.layout().name = tokenName; + ERC20MetadataStorage + .layout(ERC20MetadataStorage.DEFAULT_STORAGE_SLOT) + .name = tokenName; } /** diff --git a/contracts/token/ERC20/permit/ERC20PermitStorage.sol b/contracts/token/ERC20/permit/ERC20PermitStorage.sol index 383d3c3e..ef415b16 100644 --- a/contracts/token/ERC20/permit/ERC20PermitStorage.sol +++ b/contracts/token/ERC20/permit/ERC20PermitStorage.sol @@ -11,11 +11,20 @@ library ERC20PermitStorage { mapping(uint256 => bytes32) domainSeparators; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC20Permit'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.ERC20Permit')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/ERC20/snapshot/ERC20Snapshot.sol b/contracts/token/ERC20/snapshot/ERC20Snapshot.sol index 9e9d2b1e..6809ee68 100644 --- a/contracts/token/ERC20/snapshot/ERC20Snapshot.sol +++ b/contracts/token/ERC20/snapshot/ERC20Snapshot.sol @@ -24,7 +24,9 @@ abstract contract ERC20Snapshot is ERC20SnapshotInternal { ) public view returns (uint256) { (bool snapshotted, uint256 value) = _valueAt( snapshotId, - ERC20SnapshotStorage.layout().accountBalanceSnapshots[account] + ERC20SnapshotStorage + .layout(ERC20SnapshotStorage.DEFAULT_STORAGE_SLOT) + .accountBalanceSnapshots[account] ); return snapshotted ? value : _balanceOf(account); } @@ -37,7 +39,9 @@ abstract contract ERC20Snapshot is ERC20SnapshotInternal { function totalSupplyAt(uint256 snapshotId) public view returns (uint256) { (bool snapshotted, uint256 value) = _valueAt( snapshotId, - ERC20SnapshotStorage.layout().totalSupplySnapshots + ERC20SnapshotStorage + .layout(ERC20SnapshotStorage.DEFAULT_STORAGE_SLOT) + .totalSupplySnapshots ); return snapshotted ? value : _totalSupply(); } @@ -47,7 +51,9 @@ abstract contract ERC20Snapshot is ERC20SnapshotInternal { ERC20SnapshotStorage.Snapshots storage snapshots ) private view returns (bool, uint256) { if (snapshotId == 0) revert ERC20Snapshot__SnapshotIdIsZero(); - ERC20SnapshotStorage.Layout storage l = ERC20SnapshotStorage.layout(); + ERC20SnapshotStorage.Layout storage l = ERC20SnapshotStorage.layout( + ERC20SnapshotStorage.DEFAULT_STORAGE_SLOT + ); if (snapshotId > l.snapshotId) revert ERC20Snapshot__SnapshotIdDoesNotExists(); diff --git a/contracts/token/ERC20/snapshot/ERC20SnapshotInternal.sol b/contracts/token/ERC20/snapshot/ERC20SnapshotInternal.sol index f4bdb93c..0cf35700 100644 --- a/contracts/token/ERC20/snapshot/ERC20SnapshotInternal.sol +++ b/contracts/token/ERC20/snapshot/ERC20SnapshotInternal.sol @@ -12,7 +12,9 @@ abstract contract ERC20SnapshotInternal is ERC20BaseInternal { event Snapshot(uint256 id); function _snapshot() internal virtual returns (uint256) { - ERC20SnapshotStorage.Layout storage l = ERC20SnapshotStorage.layout(); + ERC20SnapshotStorage.Layout storage l = ERC20SnapshotStorage.layout( + ERC20SnapshotStorage.DEFAULT_STORAGE_SLOT + ); l.snapshotId++; @@ -23,14 +25,18 @@ abstract contract ERC20SnapshotInternal is ERC20BaseInternal { function _updateAccountSnapshot(address account) private { _updateSnapshot( - ERC20SnapshotStorage.layout().accountBalanceSnapshots[account], + ERC20SnapshotStorage + .layout(ERC20SnapshotStorage.DEFAULT_STORAGE_SLOT) + .accountBalanceSnapshots[account], _balanceOf(account) ); } function _updateTotalSupplySnapshot() private { _updateSnapshot( - ERC20SnapshotStorage.layout().totalSupplySnapshots, + ERC20SnapshotStorage + .layout(ERC20SnapshotStorage.DEFAULT_STORAGE_SLOT) + .totalSupplySnapshots, _totalSupply() ); } @@ -39,7 +45,9 @@ abstract contract ERC20SnapshotInternal is ERC20BaseInternal { ERC20SnapshotStorage.Snapshots storage snapshots, uint256 value ) private { - uint256 current = ERC20SnapshotStorage.layout().snapshotId; + uint256 current = ERC20SnapshotStorage + .layout(ERC20SnapshotStorage.DEFAULT_STORAGE_SLOT) + .snapshotId; if (_lastSnapshotId(snapshots.ids) < current) { snapshots.ids.push(current); diff --git a/contracts/token/ERC20/snapshot/ERC20SnapshotStorage.sol b/contracts/token/ERC20/snapshot/ERC20SnapshotStorage.sol index 9c766d0b..267e5eb7 100644 --- a/contracts/token/ERC20/snapshot/ERC20SnapshotStorage.sol +++ b/contracts/token/ERC20/snapshot/ERC20SnapshotStorage.sol @@ -14,11 +14,22 @@ library ERC20SnapshotStorage { uint256 snapshotId; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC20Snapshot'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes('solidstate.contracts.storage.ERC20Snapshot') + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/ERC4626/SolidStateERC4626Mock.sol b/contracts/token/ERC4626/SolidStateERC4626Mock.sol index 677a8f5e..a587ec8a 100644 --- a/contracts/token/ERC4626/SolidStateERC4626Mock.sol +++ b/contracts/token/ERC4626/SolidStateERC4626Mock.sol @@ -24,9 +24,13 @@ contract SolidStateERC4626Mock is SolidStateERC4626 { string memory symbol, uint8 decimals ) { - ERC4626BaseStorage.layout().asset = asset; + ERC4626BaseStorage + .layout(ERC4626BaseStorage.DEFAULT_STORAGE_SLOT) + .asset = asset; - ERC20MetadataStorage.Layout storage l = ERC20MetadataStorage.layout(); + ERC20MetadataStorage.Layout storage l = ERC20MetadataStorage.layout( + ERC20MetadataStorage.DEFAULT_STORAGE_SLOT + ); l.name = name; l.symbol = symbol; l.decimals = decimals; diff --git a/contracts/token/ERC4626/base/ERC4626BaseInternal.sol b/contracts/token/ERC4626/base/ERC4626BaseInternal.sol index 2b7e729c..8b809d82 100644 --- a/contracts/token/ERC4626/base/ERC4626BaseInternal.sol +++ b/contracts/token/ERC4626/base/ERC4626BaseInternal.sol @@ -24,7 +24,10 @@ abstract contract ERC4626BaseInternal is * @return base token address */ function _asset() internal view virtual returns (address) { - return ERC4626BaseStorage.layout().asset; + return + ERC4626BaseStorage + .layout(ERC4626BaseStorage.DEFAULT_STORAGE_SLOT) + .asset; } /** diff --git a/contracts/token/ERC4626/base/ERC4626BaseMock.sol b/contracts/token/ERC4626/base/ERC4626BaseMock.sol index 5132eab9..583e21a7 100644 --- a/contracts/token/ERC4626/base/ERC4626BaseMock.sol +++ b/contracts/token/ERC4626/base/ERC4626BaseMock.sol @@ -24,9 +24,13 @@ contract ERC4626BaseMock is ERC4626Base { string memory symbol, uint8 decimals ) { - ERC4626BaseStorage.layout().asset = asset; + ERC4626BaseStorage + .layout(ERC4626BaseStorage.DEFAULT_STORAGE_SLOT) + .asset = asset; - ERC20MetadataStorage.Layout storage l = ERC20MetadataStorage.layout(); + ERC20MetadataStorage.Layout storage l = ERC20MetadataStorage.layout( + ERC20MetadataStorage.DEFAULT_STORAGE_SLOT + ); l.name = name; l.symbol = symbol; l.decimals = decimals; diff --git a/contracts/token/ERC4626/base/ERC4626BaseStorage.sol b/contracts/token/ERC4626/base/ERC4626BaseStorage.sol index a236dfd2..b2c101f1 100644 --- a/contracts/token/ERC4626/base/ERC4626BaseStorage.sol +++ b/contracts/token/ERC4626/base/ERC4626BaseStorage.sol @@ -7,11 +7,20 @@ library ERC4626BaseStorage { address asset; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC4626Base'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.ERC4626Base')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/ERC721/SolidStateERC721Mock.sol b/contracts/token/ERC721/SolidStateERC721Mock.sol index 7a5a3ce1..84533f31 100644 --- a/contracts/token/ERC721/SolidStateERC721Mock.sol +++ b/contracts/token/ERC721/SolidStateERC721Mock.sol @@ -13,7 +13,9 @@ contract SolidStateERC721Mock is SolidStateERC721 { string memory symbol, string memory baseURI ) { - ERC721MetadataStorage.Layout storage l = ERC721MetadataStorage.layout(); + ERC721MetadataStorage.Layout storage l = ERC721MetadataStorage.layout( + ERC721MetadataStorage.DEFAULT_STORAGE_SLOT + ); l.name = name; l.symbol = symbol; l.baseURI = baseURI; diff --git a/contracts/token/ERC721/base/ERC721BaseInternal.sol b/contracts/token/ERC721/base/ERC721BaseInternal.sol index 5ead5f4e..60cfde1d 100644 --- a/contracts/token/ERC721/base/ERC721BaseInternal.sol +++ b/contracts/token/ERC721/base/ERC721BaseInternal.sol @@ -21,17 +21,28 @@ abstract contract ERC721BaseInternal is IERC721BaseInternal { address account ) internal view virtual returns (uint256) { if (account == address(0)) revert ERC721Base__BalanceQueryZeroAddress(); - return ERC721BaseStorage.layout().holderTokens[account].length(); + return + ERC721BaseStorage + .layout(ERC721BaseStorage.DEFAULT_STORAGE_SLOT) + .holderTokens[account] + .length(); } function _ownerOf(uint256 tokenId) internal view virtual returns (address) { - address owner = ERC721BaseStorage.layout().tokenOwners.get(tokenId); + address owner = ERC721BaseStorage + .layout(ERC721BaseStorage.DEFAULT_STORAGE_SLOT) + .tokenOwners + .get(tokenId); if (owner == address(0)) revert ERC721Base__InvalidOwner(); return owner; } function _exists(uint256 tokenId) internal view virtual returns (bool) { - return ERC721BaseStorage.layout().tokenOwners.contains(tokenId); + return + ERC721BaseStorage + .layout(ERC721BaseStorage.DEFAULT_STORAGE_SLOT) + .tokenOwners + .contains(tokenId); } function _getApproved( @@ -39,14 +50,20 @@ abstract contract ERC721BaseInternal is IERC721BaseInternal { ) internal view virtual returns (address) { if (!_exists(tokenId)) revert ERC721Base__NonExistentToken(); - return ERC721BaseStorage.layout().tokenApprovals[tokenId]; + return + ERC721BaseStorage + .layout(ERC721BaseStorage.DEFAULT_STORAGE_SLOT) + .tokenApprovals[tokenId]; } function _isApprovedForAll( address account, address operator ) internal view virtual returns (bool) { - return ERC721BaseStorage.layout().operatorApprovals[account][operator]; + return + ERC721BaseStorage + .layout(ERC721BaseStorage.DEFAULT_STORAGE_SLOT) + .operatorApprovals[account][operator]; } function _isApprovedOrOwner( @@ -68,7 +85,9 @@ abstract contract ERC721BaseInternal is IERC721BaseInternal { _beforeTokenTransfer(address(0), to, tokenId); - ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout(); + ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout( + ERC721BaseStorage.DEFAULT_STORAGE_SLOT + ); l.holderTokens[to].add(tokenId); l.tokenOwners.set(tokenId, to); @@ -95,7 +114,9 @@ abstract contract ERC721BaseInternal is IERC721BaseInternal { _beforeTokenTransfer(owner, address(0), tokenId); - ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout(); + ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout( + ERC721BaseStorage.DEFAULT_STORAGE_SLOT + ); l.holderTokens[owner].remove(tokenId); l.tokenOwners.remove(tokenId); @@ -118,7 +139,9 @@ abstract contract ERC721BaseInternal is IERC721BaseInternal { _beforeTokenTransfer(from, to, tokenId); - ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout(); + ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout( + ERC721BaseStorage.DEFAULT_STORAGE_SLOT + ); l.holderTokens[from].remove(tokenId); l.holderTokens[to].add(tokenId); @@ -180,7 +203,9 @@ abstract contract ERC721BaseInternal is IERC721BaseInternal { if (msg.sender != owner && !_isApprovedForAll(owner, msg.sender)) revert ERC721Base__NotOwnerOrApproved(); - ERC721BaseStorage.layout().tokenApprovals[tokenId] = operator; + ERC721BaseStorage + .layout(ERC721BaseStorage.DEFAULT_STORAGE_SLOT) + .tokenApprovals[tokenId] = operator; emit Approval(owner, operator, tokenId); } @@ -189,9 +214,9 @@ abstract contract ERC721BaseInternal is IERC721BaseInternal { bool status ) internal virtual { if (operator == msg.sender) revert ERC721Base__SelfApproval(); - ERC721BaseStorage.layout().operatorApprovals[msg.sender][ - operator - ] = status; + ERC721BaseStorage + .layout(ERC721BaseStorage.DEFAULT_STORAGE_SLOT) + .operatorApprovals[msg.sender][operator] = status; emit ApprovalForAll(msg.sender, operator, status); } diff --git a/contracts/token/ERC721/base/ERC721BaseStorage.sol b/contracts/token/ERC721/base/ERC721BaseStorage.sol index 75a07deb..6d560872 100644 --- a/contracts/token/ERC721/base/ERC721BaseStorage.sol +++ b/contracts/token/ERC721/base/ERC721BaseStorage.sol @@ -9,8 +9,14 @@ library ERC721BaseStorage { using EnumerableSet for EnumerableSet.UintSet; using EnumerableMap for EnumerableMap.UintToAddressMap; - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC721Base'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.ERC721Base')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); struct Layout { EnumerableMap.UintToAddressMap tokenOwners; @@ -20,7 +26,10 @@ library ERC721BaseStorage { } function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/ERC721/enumerable/ERC721EnumerableInternal.sol b/contracts/token/ERC721/enumerable/ERC721EnumerableInternal.sol index 7d7a7ac6..5179618c 100644 --- a/contracts/token/ERC721/enumerable/ERC721EnumerableInternal.sol +++ b/contracts/token/ERC721/enumerable/ERC721EnumerableInternal.sol @@ -14,7 +14,11 @@ abstract contract ERC721EnumerableInternal { * @notice TODO */ function _totalSupply() internal view returns (uint256) { - return ERC721BaseStorage.layout().tokenOwners.length(); + return + ERC721BaseStorage + .layout(ERC721BaseStorage.DEFAULT_STORAGE_SLOT) + .tokenOwners + .length(); } /** @@ -24,7 +28,11 @@ abstract contract ERC721EnumerableInternal { address owner, uint256 index ) internal view returns (uint256) { - return ERC721BaseStorage.layout().holderTokens[owner].at(index); + return + ERC721BaseStorage + .layout(ERC721BaseStorage.DEFAULT_STORAGE_SLOT) + .holderTokens[owner] + .at(index); } /** @@ -33,6 +41,9 @@ abstract contract ERC721EnumerableInternal { function _tokenByIndex( uint256 index ) internal view returns (uint256 tokenId) { - (tokenId, ) = ERC721BaseStorage.layout().tokenOwners.at(index); + (tokenId, ) = ERC721BaseStorage + .layout(ERC721BaseStorage.DEFAULT_STORAGE_SLOT) + .tokenOwners + .at(index); } } diff --git a/contracts/token/ERC721/metadata/ERC721MetadataInternal.sol b/contracts/token/ERC721/metadata/ERC721MetadataInternal.sol index b640dd6c..0ae9c965 100644 --- a/contracts/token/ERC721/metadata/ERC721MetadataInternal.sol +++ b/contracts/token/ERC721/metadata/ERC721MetadataInternal.sol @@ -22,7 +22,10 @@ abstract contract ERC721MetadataInternal is * @return token name */ function _name() internal view virtual returns (string memory) { - return ERC721MetadataStorage.layout().name; + return + ERC721MetadataStorage + .layout(ERC721MetadataStorage.DEFAULT_STORAGE_SLOT) + .name; } /** @@ -30,7 +33,10 @@ abstract contract ERC721MetadataInternal is * @return token symbol */ function _symbol() internal view virtual returns (string memory) { - return ERC721MetadataStorage.layout().symbol; + return + ERC721MetadataStorage + .layout(ERC721MetadataStorage.DEFAULT_STORAGE_SLOT) + .symbol; } /** @@ -42,7 +48,9 @@ abstract contract ERC721MetadataInternal is ) internal view virtual returns (string memory) { if (!_exists(tokenId)) revert ERC721Metadata__NonExistentToken(); - ERC721MetadataStorage.Layout storage l = ERC721MetadataStorage.layout(); + ERC721MetadataStorage.Layout storage l = ERC721MetadataStorage.layout( + ERC721MetadataStorage.DEFAULT_STORAGE_SLOT + ); string memory tokenIdURI = l.tokenURIs[tokenId]; string memory baseURI = l.baseURI; @@ -68,7 +76,9 @@ abstract contract ERC721MetadataInternal is super._beforeTokenTransfer(from, to, tokenId); if (to == address(0)) { - delete ERC721MetadataStorage.layout().tokenURIs[tokenId]; + delete ERC721MetadataStorage + .layout(ERC721MetadataStorage.DEFAULT_STORAGE_SLOT) + .tokenURIs[tokenId]; } } } diff --git a/contracts/token/ERC721/metadata/ERC721MetadataMock.sol b/contracts/token/ERC721/metadata/ERC721MetadataMock.sol index 2ed885ee..674f0e4e 100644 --- a/contracts/token/ERC721/metadata/ERC721MetadataMock.sol +++ b/contracts/token/ERC721/metadata/ERC721MetadataMock.sol @@ -12,7 +12,9 @@ contract ERC721MetadataMock is ERC721Metadata, ERC165Base { string memory symbol, string memory baseURI ) { - ERC721MetadataStorage.Layout storage l = ERC721MetadataStorage.layout(); + ERC721MetadataStorage.Layout storage l = ERC721MetadataStorage.layout( + ERC721MetadataStorage.DEFAULT_STORAGE_SLOT + ); l.name = name; l.symbol = symbol; l.baseURI = baseURI; diff --git a/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol b/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol index 9ee340d2..8f5d685e 100644 --- a/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol +++ b/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol @@ -3,8 +3,16 @@ pragma solidity ^0.8.20; library ERC721MetadataStorage { - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC721Metadata'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256( + bytes('solidstate.contracts.storage.ERC721Metadata') + ) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); struct Layout { string name; @@ -14,7 +22,10 @@ library ERC721MetadataStorage { } function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/contracts/token/common/ERC2981/ERC2981Internal.sol b/contracts/token/common/ERC2981/ERC2981Internal.sol index 38ad7bc1..b7c39bf8 100644 --- a/contracts/token/common/ERC2981/ERC2981Internal.sol +++ b/contracts/token/common/ERC2981/ERC2981Internal.sol @@ -37,7 +37,9 @@ abstract contract ERC2981Internal is IERC2981Internal { function _getRoyaltyBPS( uint256 tokenId ) internal view virtual returns (uint16 royaltyBPS) { - ERC2981Storage.Layout storage l = ERC2981Storage.layout(); + ERC2981Storage.Layout storage l = ERC2981Storage.layout( + ERC2981Storage.DEFAULT_STORAGE_SLOT + ); royaltyBPS = l.royaltiesBPS[tokenId]; if (royaltyBPS == 0) { @@ -54,7 +56,9 @@ abstract contract ERC2981Internal is IERC2981Internal { function _getRoyaltyReceiver( uint256 tokenId ) internal view virtual returns (address royaltyReceiver) { - ERC2981Storage.Layout storage l = ERC2981Storage.layout(); + ERC2981Storage.Layout storage l = ERC2981Storage.layout( + ERC2981Storage.DEFAULT_STORAGE_SLOT + ); royaltyReceiver = l.royaltyReceivers[tokenId]; if (royaltyReceiver == address(0)) { diff --git a/contracts/token/common/ERC2981/ERC2981Mock.sol b/contracts/token/common/ERC2981/ERC2981Mock.sol index 690f6b40..6925c3dc 100644 --- a/contracts/token/common/ERC2981/ERC2981Mock.sol +++ b/contracts/token/common/ERC2981/ERC2981Mock.sol @@ -13,7 +13,9 @@ contract ERC2981Mock is ERC2981, ERC165Base { uint16[] memory royaltiesBPS, address defaultRoyaltyReceiver ) { - ERC2981Storage.Layout storage l = ERC2981Storage.layout(); + ERC2981Storage.Layout storage l = ERC2981Storage.layout( + ERC2981Storage.DEFAULT_STORAGE_SLOT + ); l.defaultRoyaltyBPS = defaultRoyaltyBPS; l.defaultRoyaltyReceiver = defaultRoyaltyReceiver; @@ -26,6 +28,8 @@ contract ERC2981Mock is ERC2981, ERC165Base { } function setRoyalty(uint16 defaultRoyaltyBPS) external { - ERC2981Storage.layout().defaultRoyaltyBPS = defaultRoyaltyBPS; + ERC2981Storage + .layout(ERC2981Storage.DEFAULT_STORAGE_SLOT) + .defaultRoyaltyBPS = defaultRoyaltyBPS; } } diff --git a/contracts/token/common/ERC2981/ERC2981Storage.sol b/contracts/token/common/ERC2981/ERC2981Storage.sol index 74b4c65a..9a13fb8a 100644 --- a/contracts/token/common/ERC2981/ERC2981Storage.sol +++ b/contracts/token/common/ERC2981/ERC2981Storage.sol @@ -12,11 +12,20 @@ library ERC2981Storage { address defaultRoyaltyReceiver; } - bytes32 internal constant STORAGE_SLOT = - keccak256('solidstate.contracts.storage.ERC2981'); + bytes32 internal constant DEFAULT_STORAGE_SLOT = + keccak256( + abi.encode( + uint256( + keccak256(bytes('solidstate.contracts.storage.ERC2981')) + ) - 1 + ) + ) & ~bytes32(uint256(0xff)); function layout() internal pure returns (Layout storage l) { - bytes32 slot = STORAGE_SLOT; + l = layout(DEFAULT_STORAGE_SLOT); + } + + function layout(bytes32 slot) internal pure returns (Layout storage l) { assembly { l.slot := slot } diff --git a/spec/signature/base/ERC1271Base.behavior.ts b/spec/signature/ERC1271/base/ERC1271Base.behavior.ts similarity index 100% rename from spec/signature/base/ERC1271Base.behavior.ts rename to spec/signature/ERC1271/base/ERC1271Base.behavior.ts diff --git a/spec/signature/base/index.ts b/spec/signature/ERC1271/base/index.ts similarity index 100% rename from spec/signature/base/index.ts rename to spec/signature/ERC1271/base/index.ts diff --git a/spec/signature/ERC1271/index.ts b/spec/signature/ERC1271/index.ts new file mode 100644 index 00000000..3913577d --- /dev/null +++ b/spec/signature/ERC1271/index.ts @@ -0,0 +1,3 @@ +export * from './base'; +export * from './ownable'; +export * from './stored'; diff --git a/spec/signature/ownable/ERC1271Ownable.behavior.ts b/spec/signature/ERC1271/ownable/ERC1271Ownable.behavior.ts similarity index 100% rename from spec/signature/ownable/ERC1271Ownable.behavior.ts rename to spec/signature/ERC1271/ownable/ERC1271Ownable.behavior.ts diff --git a/spec/signature/ownable/index.ts b/spec/signature/ERC1271/ownable/index.ts similarity index 100% rename from spec/signature/ownable/index.ts rename to spec/signature/ERC1271/ownable/index.ts diff --git a/spec/signature/stored/ERC1271Stored.behavior.ts b/spec/signature/ERC1271/stored/ERC1271Stored.behavior.ts similarity index 100% rename from spec/signature/stored/ERC1271Stored.behavior.ts rename to spec/signature/ERC1271/stored/ERC1271Stored.behavior.ts diff --git a/spec/signature/stored/index.ts b/spec/signature/ERC1271/stored/index.ts similarity index 100% rename from spec/signature/stored/index.ts rename to spec/signature/ERC1271/stored/index.ts diff --git a/spec/signature/index.ts b/spec/signature/index.ts index 3913577d..47a0dace 100644 --- a/spec/signature/index.ts +++ b/spec/signature/index.ts @@ -1,3 +1 @@ -export * from './base'; -export * from './ownable'; -export * from './stored'; +export * from './ERC1271'; diff --git a/test/signature/ownable/ERC1271Ownable.ts b/test/signature/ERC1271/ownable/ERC1271Ownable.ts similarity index 100% rename from test/signature/ownable/ERC1271Ownable.ts rename to test/signature/ERC1271/ownable/ERC1271Ownable.ts diff --git a/test/signature/stored/ERC1271Stored.ts b/test/signature/ERC1271/stored/ERC1271Stored.ts similarity index 100% rename from test/signature/stored/ERC1271Stored.ts rename to test/signature/ERC1271/stored/ERC1271Stored.ts diff --git a/test/signature/ERC7201/ERC7201.ts b/test/signature/ERC7201/ERC7201.ts new file mode 100644 index 00000000..466fd347 --- /dev/null +++ b/test/signature/ERC7201/ERC7201.ts @@ -0,0 +1,23 @@ +import { hashData, signData } from '@solidstate/library'; +import { ERC7201Mock, ERC7201Mock__factory } from '@solidstate/typechain-types'; +import { expect } from 'chai'; +import { ethers } from 'hardhat'; + +describe('ERC7201', () => { + let instance: ERC7201Mock; + + beforeEach(async () => { + const [deployer] = await ethers.getSigners(); + instance = await new ERC7201Mock__factory(deployer).deploy(); + }); + + describe('__internal', () => { + describe('#calculateStorageSlot(string)', () => { + it('calculates storage slot using "erc7201" formula', async () => { + expect(await instance.calculateStorageSlot('example.main')).to.equal( + '0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab500', + ); + }); + }); + }); +});