Skip to content

Commit

Permalink
ON-533: draft impl
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Lima committed Mar 19, 2024
1 parent 050bc9f commit b645f21
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 19 deletions.
68 changes: 50 additions & 18 deletions contracts/RolesRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

pragma solidity 0.8.9;

import { IERC7432 } from './interfaces/IERC7432.sol';
import { IRolesRegistryCustodial } from './interfaces/IRolesRegistryCustodial.sol';
import { IERC721 } from '@openzeppelin/contracts/token/ERC721/IERC721.sol';
import { ERC165Checker } from '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';

contract RolesRegistry is IERC7432 {
contract RolesRegistryCustodial is IRolesRegistryCustodial {
// grantee => tokenAddress => tokenId => role => struct(expirationDate, data)
mapping(address => mapping(address => mapping(uint256 => mapping(bytes32 => RoleData)))) public roleAssignments;

Expand All @@ -16,6 +16,9 @@ contract RolesRegistry is IERC7432 {
// grantor => tokenAddress => operator => isApproved
mapping(address => mapping(address => mapping(address => bool))) public tokenApprovals;

// tokenAddress => tokenId => owner
mapping(address => mapping(uint256 => address)) public tokenOwners;

modifier validExpirationDate(uint64 _expirationDate) {
require(_expirationDate > block.timestamp, 'RolesRegistry: expiration date must be in the future');
_;
Expand Down Expand Up @@ -44,24 +47,14 @@ contract RolesRegistry is IERC7432 {
_;
}

function grantRoleFrom(
function grantRole(
RoleAssignment calldata _roleAssignment
)
external
override
onlyOwnerOrApproved(_roleAssignment.tokenAddress, _roleAssignment.tokenId, _roleAssignment.grantor)
{
_grantRole(_roleAssignment, false);
}

function grantRevocableRoleFrom(
RoleAssignment calldata _roleAssignment
)
external
override
onlyOwnerOrApproved(_roleAssignment.tokenAddress, _roleAssignment.tokenId, _roleAssignment.grantor)
{
_grantRole(_roleAssignment, true);
_grantRole(_roleAssignment, _roleAssignment.revocable);
}

function _grantRole(
Expand Down Expand Up @@ -97,9 +90,24 @@ contract RolesRegistry is IERC7432 {
_revocable,
_roleAssignment.data
);

// Just an example of transfer logic when granting roles
// that would be a separated helper function
address _tokenOwner = tokenOwners[_roleAssignment.tokenAddress][_roleAssignment.tokenId];
if (_tokenOwner != address(0)) {
require(_tokenOwner == _roleAssignment.grantor, 'RolesRegistry: grantor must be token owner');
} else {
IERC721(_roleAssignment.tokenAddress).transferFrom(
_roleAssignment.grantor,
address(this),
_roleAssignment.tokenId
);
tokenOwners[_roleAssignment.tokenAddress][_roleAssignment.tokenId] = _roleAssignment.grantor;
emit Deposit(_roleAssignment.grantor, _roleAssignment.tokenAddress, _roleAssignment.tokenId);
}
}

function revokeRoleFrom(
function revokeRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
Expand Down Expand Up @@ -143,6 +151,16 @@ contract RolesRegistry is IERC7432 {
emit RoleRevoked(_role, _tokenAddress, _tokenId, _revoker, _grantee);
}

function withdraw(
address _tokenAddress,
uint256 _tokenId
) external onlyOwnerOrApproved(_tokenAddress, _tokenId, msg.sender) {
address _tokenOwner = tokenOwners[_tokenAddress][_tokenId];
IERC721(_tokenAddress).transferFrom(address(this), _tokenOwner, _tokenId);
delete tokenOwners[_tokenAddress][_tokenId];
emit Withdraw(_tokenOwner, _tokenAddress, _tokenId);
}

function hasNonUniqueRole(
bytes32 _role,
address _tokenAddress,
Expand Down Expand Up @@ -171,8 +189,8 @@ contract RolesRegistry is IERC7432 {
uint256 _tokenId,
address _grantor, // not used, but needed for compatibility with ERC7432
address _grantee
) external view returns (RoleData memory) {
return roleAssignments[_grantee][_tokenAddress][_tokenId][_role];
) external view returns (bytes memory) {
return roleAssignments[_grantee][_tokenAddress][_tokenId][_role].data;
}

function roleExpirationDate(
Expand All @@ -186,7 +204,7 @@ contract RolesRegistry is IERC7432 {
}

function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {
return interfaceId == type(IERC7432).interfaceId;
return interfaceId == type(IRolesRegistryCustodial).interfaceId;
}

function setRoleApprovalForAll(address _tokenAddress, address _operator, bool _isApproved) external override {
Expand All @@ -202,6 +220,20 @@ contract RolesRegistry is IERC7432 {
return tokenApprovals[_grantor][_tokenAddress][_operator];
}

function isRoleRevocable(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee
) public view override returns (bool) {
return roleAssignments[_grantee][_tokenAddress][_tokenId][_role].revocable;
}

function ownerOf(address _tokenAddress, uint256 _tokenId) external view override returns (address) {
return tokenOwners[_tokenAddress][_tokenId];
}

function lastGrantee(
bytes32 _role,
address _tokenAddress,
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IRolesRegistryCustodial.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity 0.8.9;

import { IERC7432 } from './IERC7432.sol';

interface IRolesRegistryCustodial {
interface IRolesRegistryCustodial is IERC7432 {

/// @notice Emitted when tokens are deposited.
/// @param _owner The owner of the NFTs.
Expand Down

0 comments on commit b645f21

Please sign in to comment.