Skip to content

Commit

Permalink
Merge pull request #11 from OriumNetwork/ON-486-update-interface
Browse files Browse the repository at this point in the history
Update interface to use structs and remove tokenId level approvals
  • Loading branch information
karacurt authored Oct 5, 2023
2 parents 7369cc0 + 94c8256 commit 589b0f1
Show file tree
Hide file tree
Showing 5 changed files with 320 additions and 454 deletions.
104 changes: 29 additions & 75 deletions contracts/ERC7432/ERC7432.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ contract ERC7432 is IERC7432 {
// grantor => tokenAddress => tokenId => role => grantee
mapping(address => mapping(address => mapping(uint256 => mapping(bytes32 => address)))) public latestGrantees;

// grantor => tokenAddress => tokenId => operator => isApproved
mapping(address => mapping(address => mapping(uint256 => mapping(address => bool)))) public tokenIdApprovals;

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

Expand All @@ -23,56 +20,34 @@ contract ERC7432 is IERC7432 {
_;
}

modifier onlyApproved(address _tokenAddress, uint256 _tokenId, address _account) {
modifier onlyAccountOrApproved(address _tokenAddress, address _account) {
require(
_isRoleApproved(_tokenAddress, _tokenId, _account, msg.sender),
msg.sender == _account || isRoleApprovedForAll(_tokenAddress, _account, msg.sender),
"ERC7432: sender must be approved"
);
_;
}

function grantRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantee,
uint64 _expirationDate,
bool _revocable,
bytes calldata _data
) external {
_grantRole(_role, _tokenAddress, _tokenId, msg.sender, _grantee, _expirationDate, _revocable, _data);
function grantRevocableRoleFrom(RoleAssignment calldata _roleAssignment) override onlyAccountOrApproved(_roleAssignment.tokenAddress, _roleAssignment.grantor) external {
_grantRole(_roleAssignment, true);
}

function grantRoleFrom(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee,
uint64 _expirationDate,
bool _revocable,
bytes calldata _data
) external override onlyApproved(_tokenAddress, _tokenId, _grantor) {
_grantRole(_role, _tokenAddress, _tokenId, _grantor, _grantee, _expirationDate, _revocable, _data);
function grantRoleFrom(RoleAssignment calldata _roleAssignment) external override onlyAccountOrApproved(_roleAssignment.tokenAddress, _roleAssignment.grantor) {
_grantRole(_roleAssignment, false);
}

function _grantRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee,
uint64 _expirationDate,
bool _revocable,
bytes calldata _data
) internal validExpirationDate(_expirationDate) {
roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role] = RoleData(_expirationDate, _revocable, _data);
latestGrantees[_grantor][_tokenAddress][_tokenId][_role] = _grantee;
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, msg.sender);
function _grantRole(
RoleAssignment memory _roleAssignment,
bool _revocable
) internal validExpirationDate(_roleAssignment.expirationDate) {
roleAssignments[_roleAssignment.grantor][_roleAssignment.grantee][_roleAssignment.tokenAddress][
_roleAssignment.tokenId
][_roleAssignment.role] = RoleData(_roleAssignment.expirationDate, _revocable, _roleAssignment.data);
latestGrantees[_roleAssignment.grantor][_roleAssignment.tokenAddress][_roleAssignment.tokenId][
_roleAssignment.role
] = _roleAssignment.grantee;
emit RoleGranted(_roleAssignment.role, _roleAssignment.tokenAddress, _roleAssignment.tokenId, _roleAssignment.grantor, _roleAssignment.grantee, _roleAssignment.expirationDate, _revocable, _roleAssignment.data);
}

function revokeRoleFrom(
Expand All @@ -82,14 +57,14 @@ contract ERC7432 is IERC7432 {
address _revoker,
address _grantee
) external override {
address _caller = _getApprovedCaller(_tokenAddress, _tokenId, _revoker, _grantee);
address _caller = msg.sender == _revoker || msg.sender == _grantee ? msg.sender : _getApprovedCaller(_tokenAddress, _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)){
function _getApprovedCaller(address _tokenAddress, address _revoker, address _grantee) internal view returns (address) {
if(isRoleApprovedForAll(_tokenAddress, _grantee, msg.sender)){
return _grantee;
} else if(_isRoleApproved(_tokenAddress, _tokenId, _revoker, msg.sender)){
} else if(isRoleApprovedForAll(_tokenAddress, _revoker, msg.sender)){
return _revoker;
} else {
revert("ERC7432: sender must be approved");
Expand Down Expand Up @@ -137,9 +112,8 @@ contract ERC7432 is IERC7432 {
uint256 _tokenId,
address _grantor,
address _grantee
) external view returns (bytes memory data_) {
RoleData memory _roleData = roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role];
return (_roleData.data);
) external view returns (RoleData memory) {
return roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role];
}

function roleExpirationDate(
Expand All @@ -149,8 +123,7 @@ contract ERC7432 is IERC7432 {
address _grantor,
address _grantee
) external view returns (uint64 expirationDate_) {
RoleData memory _roleData = roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role];
return (_roleData.expirationDate);
return roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role].expirationDate;
}

function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {
Expand All @@ -166,16 +139,6 @@ contract ERC7432 is IERC7432 {
emit RoleApprovalForAll(_tokenAddress, _operator, _isApproved);
}

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);
}

function isRoleApprovedForAll(
address _tokenAddress,
address _grantor,
Expand All @@ -184,21 +147,12 @@ contract ERC7432 is IERC7432 {
return tokenApprovals[_grantor][_tokenAddress][_operator];
}

function getApprovedRole(
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _operator
) public view override returns (bool) {
return tokenIdApprovals[_grantor][_tokenAddress][_tokenId][_operator];
}

function _isRoleApproved(
function lastGrantee(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _operator
) internal view returns (bool) {
return isRoleApprovedForAll(_tokenAddress, _grantor, _operator) || getApprovedRole(_tokenAddress, _tokenId, _grantor, _operator);
address _grantor
) public view override returns (address) {
return latestGrantees[_grantor][_tokenAddress][_tokenId][_role];
}
}
106 changes: 25 additions & 81 deletions contracts/ERC7432/interfaces/IERC7432.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,24 @@ 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 0x25be10b2.
/// Note: the ERC-165 identifier for this interface is 0x17ef8677.
interface IERC7432 is IERC165 {
struct RoleData {
uint64 expirationDate;
bool revocable;
bytes data;
}

struct RoleAssignment {
bytes32 role;
address tokenAddress;
uint256 tokenId;
address grantor;
address grantee;
uint64 expirationDate;
bytes data;
}

/** Events **/

/// @notice Emitted when a role is granted.
Expand Down Expand Up @@ -60,69 +70,15 @@ interface IERC7432 is IERC165 {
bool _isApproved
);

/// @notice Emitted when a user is approved to manage the roles of an NFT on behalf of another user.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _operator The user approved to grant and revoke roles.
/// @param _isApproved The approval status.
event RoleApproval(
address indexed _tokenAddress,
uint256 indexed _tokenId,
address _operator,
bool _isApproved
);

/** External Functions **/

/// @notice Grants a role to a user.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @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;

/// @notice Revokes a role from a user.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _grantee The user that receives the role revocation.
function revokeRole(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantee
) external;
/// @notice Grants a role on behalf of a user.
/// @param _roleAssignment The role assignment data.
function grantRoleFrom(RoleAssignment calldata _roleAssignment) external;

/// @notice Grants a role on behalf of a user.
/// @param _role The role identifier.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @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,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee,
uint64 _expirationDate,
bool _revocable,
bytes calldata _data
) external;
/// @param _roleAssignment The role assignment data.
function grantRevocableRoleFrom(RoleAssignment calldata _roleAssignment) external;

/// @notice Revokes a role on behalf of a user.
/// @param _role The role identifier.
Expand All @@ -148,18 +104,6 @@ interface IERC7432 is IERC165 {
bool _approved
) external;

/// @notice Approves operator to grant and revoke roles of an NFT on behalf of another user.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _operator The user approved to grant and revoke roles.
/// @param _approved The approval status.
function approveRole(
address _tokenAddress,
uint256 _tokenId,
address _operator,
bool _approved
) external;

/** View Functions **/

/// @notice Checks if a user has a role.
Expand Down Expand Up @@ -202,7 +146,7 @@ interface IERC7432 is IERC165 {
uint256 _tokenId,
address _grantor,
address _grantee
) external view returns (bytes memory data_);
) external view returns (RoleData memory data_);

/// @notice Returns the expiration date of a role assignment.
/// @param _role The role identifier.
Expand All @@ -228,15 +172,15 @@ interface IERC7432 is IERC165 {
address _operator
) external view returns (bool);

/// @notice Checks if the grantor approved the operator for a specific NFT.
/// @notice Returns the last grantee of a role.
/// @param _role The role.
/// @param _tokenAddress The token address.
/// @param _tokenId The token identifier.
/// @param _grantor The user that approved the operator.
/// @param _operator The user approved to grant and revoke roles.
function getApprovedRole(
/// @param _tokenId The token ID.
/// @param _grantor The user that granted the role.
function lastGrantee(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _operator
) external view returns (bool);
address _grantor
) external view returns (address);
}
Loading

0 comments on commit 589b0f1

Please # to comment.