Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement ERC7201 #236

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
43 changes: 36 additions & 7 deletions contracts/access/access_control/AccessControlInternal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -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);
}

Expand All @@ -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);
}

Expand All @@ -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);
}

Expand All @@ -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);
}

/**
Expand All @@ -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();
}
}
17 changes: 14 additions & 3 deletions contracts/access/access_control/AccessControlStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
6 changes: 4 additions & 2 deletions contracts/access/ownable/OwnableInternal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
}
Expand Down
15 changes: 12 additions & 3 deletions contracts/access/ownable/OwnableStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
13 changes: 10 additions & 3 deletions contracts/access/ownable/SafeOwnableInternal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,20 @@ 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;
}

/**
* @notice accept transfer of contract ownership
*/
function _acceptOwnership() internal virtual {
_setOwner(msg.sender);
delete SafeOwnableStorage.layout().nomineeOwner;
delete SafeOwnableStorage
.layout(SafeOwnableStorage.DEFAULT_STORAGE_SLOT)
.nomineeOwner;
}

/**
Expand All @@ -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;
}
}
15 changes: 12 additions & 3 deletions contracts/access/ownable/SafeOwnableStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
9 changes: 7 additions & 2 deletions contracts/introspection/ERC165/base/ERC165BaseInternal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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];
}

/**
Expand All @@ -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;
}
}
15 changes: 12 additions & 3 deletions contracts/introspection/ERC165/base/ERC165BaseStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
23 changes: 16 additions & 7 deletions contracts/multisig/ECDSAMultisigWalletInternal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,38 @@ 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();
l.quorum = quorum;
}

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();
Expand All @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
19 changes: 16 additions & 3 deletions contracts/multisig/ECDSAMultisigWalletStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/proxy/diamond/base/DiamondBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
15 changes: 12 additions & 3 deletions contracts/proxy/diamond/base/DiamondBaseStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Loading