Skip to content

Commit

Permalink
Merge pull request #10 from OriumNetwork/feature--ON-476
Browse files Browse the repository at this point in the history
ON-476: Revocable flag
  • Loading branch information
karacurt authored Sep 21, 2023
2 parents bab0a03 + 4c0e1da commit 7369cc0
Show file tree
Hide file tree
Showing 7 changed files with 354 additions and 214 deletions.
57 changes: 40 additions & 17 deletions contracts/ERC7432/ERC7432.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pragma solidity 0.8.9;
import { IERC7432 } from "./interfaces/IERC7432.sol";

contract ERC7432 is IERC7432 {

// grantor => grantee => tokenAddress => tokenId => role => struct(expirationDate, data)
mapping(address => mapping(address => mapping(address => mapping(uint256 => mapping(bytes32 => RoleData)))))
public roleAssignments;
Expand All @@ -24,10 +23,9 @@ contract ERC7432 is IERC7432 {
_;
}

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),
"ERC7432: sender must be approved"
);
_;
Expand All @@ -39,9 +37,10 @@ contract ERC7432 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 @@ -51,9 +50,10 @@ contract ERC7432 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 @@ -63,15 +63,16 @@ contract ERC7432 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 @@ -80,17 +81,31 @@ contract ERC7432 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("ERC7432: 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, "ERC7432: 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 @@ -113,8 +128,7 @@ contract ERC7432 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 All @@ -128,13 +142,13 @@ contract ERC7432 is IERC7432 {
return (_roleData.data);
}

function roleExpirationDate(
function roleExpirationDate(
bytes32 _role,
address _tokenAddress,
uint256 _tokenId,
address _grantor,
address _grantee
) external view returns (uint64 expirationDate_){
) external view returns (uint64 expirationDate_) {
RoleData memory _roleData = roleAssignments[_grantor][_grantee][_tokenAddress][_tokenId][_role];
return (_roleData.expirationDate);
}
Expand All @@ -159,7 +173,7 @@ contract ERC7432 is IERC7432 {
bool _approved
) external override {
tokenIdApprovals[msg.sender][_tokenAddress][_tokenId][_operator] = _approved;
emit RoleApproval( _tokenAddress, _tokenId, _operator, _approved);
emit RoleApproval(_tokenAddress, _tokenId, _operator, _approved);
}

function isRoleApprovedForAll(
Expand All @@ -178,4 +192,13 @@ contract ERC7432 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);
}
}
13 changes: 9 additions & 4 deletions contracts/ERC7432/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);

}
}
10 changes: 9 additions & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'solidity-coverage'
import 'hardhat-spdx-license-identifier'
import '@nomicfoundation/hardhat-toolbox'
import 'hardhat-gas-reporter'

module.exports = {
solidity: {
Expand All @@ -10,11 +11,18 @@ module.exports = {
runs: 200,
},
},
gasReporter: {
enabled: true,
excludeContracts: ['contracts/mocks'],
gasPrice: 100,
token: 'MATIC',
currency: 'USD',
},
mocha: {
timeout: 840000,
},
spdxLicenseIdentifier: {
overwrite: false,
runOnCompile: true,
},
}
}
Loading

0 comments on commit 7369cc0

Please # to comment.