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

ON-483: [Part 1] Update ERC7432 interface, revocable roles #7

Merged
merged 2 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 50 additions & 22 deletions contracts/RolesRegistry/RolesRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,17 @@ contract RolesRegistry is IERC7432 {
// grantor => tokenAddress => tokenId => operator => isApproved
mapping(address => mapping(address => mapping(uint256 => mapping(address => bool)))) public tokenIdApprovals;

// grantor => tokenAddress => operator => isApproved
// grantor => tokenAddress => operator => isApproved
mapping(address => mapping(address => mapping(address => bool))) public tokenApprovals;

modifier validExpirationDate(uint64 _expirationDate) {
require(_expirationDate > block.timestamp, "RolesRegistry: expiration date must be in the future");
_;
}

modifier onlyApproved(
address _tokenAddress,
uint256 _tokenId,
address _grantor
) {
modifier onlyApproved(address _tokenAddress, uint256 _tokenId, address _account) {
require(
isRoleApprovedForAll(_tokenAddress, _grantor, msg.sender) ||
getApprovedRole(_tokenAddress, _tokenId, _grantor, msg.sender),
_isRoleApproved(_tokenAddress, _tokenId, _account, msg.sender),
"RolesRegistry: sender must be approved"
);
_;
Expand All @@ -42,9 +37,10 @@ contract RolesRegistry is IERC7432 {
uint256 _tokenId,
address _grantee,
uint64 _expirationDate,
bool _revocable,
bytes calldata _data
) external {
_grantRole(_role, _tokenAddress, _tokenId, msg.sender, _grantee, _expirationDate, _data);
_grantRole(_role, _tokenAddress, _tokenId, msg.sender, _grantee, _expirationDate, _revocable, _data);
}

function grantRoleFrom(
Expand All @@ -54,9 +50,10 @@ contract RolesRegistry is IERC7432 {
address _grantor,
address _grantee,
uint64 _expirationDate,
bool _revocable,
bytes calldata _data
) external override onlyApproved(_tokenAddress, _tokenId, _grantor) {
_grantRole(_role, _tokenAddress, _tokenId, _grantor, _grantee, _expirationDate, _data);
_grantRole(_role, _tokenAddress, _tokenId, _grantor, _grantee, _expirationDate, _revocable, _data);
}

function _grantRole(
Expand All @@ -66,15 +63,16 @@ contract RolesRegistry is IERC7432 {
address _grantor,
address _grantee,
uint64 _expirationDate,
bool _revocable,
bytes calldata _data
) internal validExpirationDate(_expirationDate) {
roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role] = RoleData(_expirationDate, _data);
roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role] = RoleData(_expirationDate, _revocable, _data);
latestGrantees[_grantor][_tokenAddress][_tokenId][_role] = _grantee;
emit RoleGranted(_role, _tokenAddress, _tokenId, _grantor, _grantee, _expirationDate, _data);
emit RoleGranted(_role, _tokenAddress, _tokenId, _grantor, _grantee, _expirationDate, _revocable, _data);
}

function revokeRole(bytes32 _role, address _tokenAddress, uint256 _tokenId, address _grantee) external {
_revokeRole(_role, _tokenAddress, _tokenId, msg.sender, _grantee);
_revokeRole(_role, _tokenAddress, _tokenId, msg.sender, _grantee, msg.sender);
}

function revokeRoleFrom(
Expand All @@ -83,17 +81,31 @@ contract RolesRegistry is IERC7432 {
uint256 _tokenId,
address _revoker,
address _grantee
) external override onlyApproved(_tokenAddress, _tokenId, _revoker) {
_revokeRole(_role, _tokenAddress, _tokenId, _revoker, _grantee);
) external override {
address _caller = _getApprovedCaller(_tokenAddress, _tokenId, _revoker, _grantee);
_revokeRole(_role, _tokenAddress, _tokenId, _revoker, _grantee, _caller);
}

function _getApprovedCaller(address _tokenAddress, uint256 _tokenId, address _revoker, address _grantee) internal view returns (address) {
if(_isRoleApproved(_tokenAddress, _tokenId, _grantee, msg.sender)){
return _grantee;
} else if(_isRoleApproved(_tokenAddress, _tokenId, _revoker, msg.sender)){
return _revoker;
} else {
revert("RolesRegistry: sender must be approved");
}
}

function _revokeRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _revoker,
address _grantee
address _grantee,
address _caller
) internal {
bool _isRevocable = roleAssignments[_revoker][_grantee][_tokenAddress][_tokenId][_role].revocable;
require(_isRevocable || _caller == _grantee, "RolesRegistry: Role is not revocable or caller is not the grantee");
delete roleAssignments[_revoker][_grantee][_tokenAddress][_tokenId][_role];
delete latestGrantees[_revoker][_tokenAddress][_tokenId][_role];
emit RoleRevoked(_role, _tokenAddress, _tokenId, _revoker, _grantee);
Expand All @@ -116,9 +128,7 @@ contract RolesRegistry is IERC7432 {
address _grantor,
address _grantee
) external view returns (bool) {
return
latestGrantees[_grantor][_tokenAddress][_tokenId][_role] == _grantee &&
roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role].expirationDate > block.timestamp;
return latestGrantees[_grantor][_tokenAddress][_tokenId][_role] == _grantee && roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role].expirationDate > block.timestamp;
}

function roleData(
Expand Down Expand Up @@ -147,12 +157,21 @@ contract RolesRegistry is IERC7432 {
return interfaceId == type(IERC7432).interfaceId;
}

function setRoleApprovalForAll(address _tokenAddress, address _operator, bool _isApproved) external override {
function setRoleApprovalForAll(
address _tokenAddress,
address _operator,
bool _isApproved
) external override {
tokenApprovals[msg.sender][_tokenAddress][_operator] = _isApproved;
emit RoleApprovalForAll(_tokenAddress, _operator, _isApproved);
}

function approveRole(address _tokenAddress, uint256 _tokenId, address _operator, bool _approved) external override {
function approveRole(
address _tokenAddress,
uint256 _tokenId,
address _operator,
bool _approved
) external override {
tokenIdApprovals[msg.sender][_tokenAddress][_tokenId][_operator] = _approved;
emit RoleApproval(_tokenAddress, _tokenId, _operator, _approved);
}
Expand All @@ -173,4 +192,13 @@ contract RolesRegistry is IERC7432 {
) public view override returns (bool) {
return tokenIdApprovals[_grantor][_tokenAddress][_tokenId][_operator];
}
}

function _isRoleApproved(
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _operator
) internal view returns (bool) {
return isRoleApprovedForAll(_tokenAddress, _grantor, _operator) || getApprovedRole(_tokenAddress, _tokenId, _grantor, _operator);
}
}
11 changes: 8 additions & 3 deletions contracts/RolesRegistry/interfaces/IERC7432.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ pragma solidity 0.8.9;

import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";


/// @title ERC-7432 Non-Fungible Token Roles
/// @dev See https://eips.ethereum.org/EIPS/eip-7432
/// Note: the ERC-165 identifier for this interface is 0xd7e151ef.
/// Note: the ERC-165 identifier for this interface is 0x25be10b2.
interface IERC7432 is IERC165 {
struct RoleData {
uint64 expirationDate;
bool revocable;
bytes data;
}

Expand All @@ -23,6 +23,7 @@ interface IERC7432 is IERC165 {
/// @param _grantor The user assigning the role.
/// @param _grantee The user receiving the role.
/// @param _expirationDate The expiration date of the role.
/// @param _revocable Whether the role is revocable or not.
/// @param _data Any additional data about the role.
event RoleGranted(
bytes32 indexed _role,
Expand All @@ -31,6 +32,7 @@ interface IERC7432 is IERC165 {
address _grantor,
address _grantee,
uint64 _expirationDate,
bool _revocable,
bytes _data
);

Expand Down Expand Up @@ -78,13 +80,15 @@ interface IERC7432 is IERC165 {
/// @param _tokenId The token identifier.
/// @param _grantee The user receiving the role.
/// @param _expirationDate The expiration date of the role.
/// @param _revocable Whether the role is revocable or not.
/// @param _data Any additional data about the role.
function grantRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantee,
uint64 _expirationDate,
bool _revocable,
bytes calldata _data
) external;

Expand All @@ -107,6 +111,7 @@ interface IERC7432 is IERC165 {
/// @param _grantor The user assigning the role.
/// @param _grantee The user that receives the role.
/// @param _expirationDate The expiration date of the role.
/// @param _revocable Whether the role is revocable or not.
/// @param _data Any additional data about the role.
function grantRoleFrom(
bytes32 _role,
Expand All @@ -115,6 +120,7 @@ interface IERC7432 is IERC165 {
address _grantor,
address _grantee,
uint64 _expirationDate,
bool _revocable,
bytes calldata _data
) external;

Expand Down Expand Up @@ -233,5 +239,4 @@ interface IERC7432 is IERC165 {
address _grantor,
address _operator
) external view returns (bool);

}
Loading