Skip to content

Commit

Permalink
ON-483: Update ERC7432 interface, revocable roles
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Lima committed Sep 25, 2023
1 parent 4224334 commit 500ba41
Show file tree
Hide file tree
Showing 4 changed files with 311 additions and 49 deletions.
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 => operator => tokenAddress => 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

0 comments on commit 500ba41

Please sign in to comment.