-
Notifications
You must be signed in to change notification settings - Fork 410
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update ERC-7208: pushing example implementation
Merged by EIP-Bot.
- Loading branch information
Showing
15 changed files
with
1,693 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "@openzeppelin/contracts/access/AccessControl.sol"; | ||
import "./interfaces/IDataIndex.sol"; | ||
import "./interfaces/IDataObject.sol"; | ||
import "./interfaces/IIDManager.sol"; | ||
import "./interfaces/IDataPointRegistry.sol"; | ||
|
||
/** | ||
* @title Data Index contract | ||
* @notice Minimalistic implementation of a Data Index contract | ||
*/ | ||
contract DataIndex is IDataIndex, IIDManager, AccessControl { | ||
/// @dev Error thrown when the sender is not an admin of the DataPoint | ||
error InvalidDataPointAdmin(DataPoint dp, address sender); | ||
|
||
/// @dev Error thrown when the DataManager is not approved to interact with the DataPoint | ||
error DataManagerNotApproved(DataPoint dp, address dm); | ||
|
||
/// @dev Error thrown when the dataIndex identifier is incorrect | ||
error IncorrectIdentifier(bytes32 diid); | ||
|
||
/** | ||
* @notice Event emitted when DataManager is approved for DataPoint | ||
* @param dp Identifier of the DataPoint | ||
* @param dm Address of DataManager | ||
* @param approved if DataManager is approved | ||
*/ | ||
event DataPointDMApprovalChanged(DataPoint dp, address dm, bool approved); | ||
|
||
/// @dev Mapping of DataPoint to DataManagers allowed to write to this DP (in any DataObject) | ||
mapping(DataPoint => mapping(address dm => bool allowed)) dmApprovals; | ||
|
||
/** | ||
* @notice Restricts access to the function, allowing only DataPoint admins | ||
* @param dp DataPoint to check ownership of | ||
*/ | ||
modifier onlyDPOwner(DataPoint dp) { | ||
(uint32 chainId, address registry, ) = DataPoints.decode(dp); | ||
ChainidTools.requireCurrentChain(chainId); | ||
bool isAdmin = IDataPointRegistry(registry).isAdmin(dp, msg.sender); | ||
if (!isAdmin) revert InvalidDataPointAdmin(dp, msg.sender); | ||
_; | ||
} | ||
|
||
/** | ||
* @notice Allows access only to DataManagers which was previously approved | ||
* @param dp DataPoint to check DataManager approval for | ||
*/ | ||
modifier onlyApprovedDM(DataPoint dp) { | ||
bool approved = dmApprovals[dp][msg.sender]; | ||
if (!approved) revert DataManagerNotApproved(dp, msg.sender); | ||
_; | ||
} | ||
|
||
/// @dev Sets the default admin role | ||
constructor() { | ||
_grantRole(DEFAULT_ADMIN_ROLE, _msgSender()); | ||
} | ||
|
||
///@inheritdoc IDataIndex | ||
function isApprovedDataManager(DataPoint dp, address dm) external view returns (bool) { | ||
return dmApprovals[dp][dm]; | ||
} | ||
|
||
///@inheritdoc IDataIndex | ||
function allowDataManager(DataPoint dp, address dm, bool approved) external onlyDPOwner(dp) { | ||
dmApprovals[dp][dm] = approved; | ||
emit DataPointDMApprovalChanged(dp, dm, approved); | ||
} | ||
|
||
///@inheritdoc IDataIndex | ||
function read(address dobj, DataPoint dp, bytes4 operation, bytes calldata data) external view returns (bytes memory) { | ||
return IDataObject(dobj).read(dp, operation, data); | ||
} | ||
|
||
///@inheritdoc IDataIndex | ||
function write(address dobj, DataPoint dp, bytes4 operation, bytes calldata data) external onlyApprovedDM(dp) returns (bytes memory) { | ||
return IDataObject(dobj).write(dp, operation, data); | ||
} | ||
|
||
///@inheritdoc IIDManager | ||
function diid(address account, DataPoint) external pure returns (bytes32) { | ||
return bytes32(uint256(uint160(account))); | ||
} | ||
|
||
///@inheritdoc IIDManager | ||
function ownerOf(bytes32 _diid) external view returns (uint32, address) { | ||
if (_diid & 0xFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000 != 0) revert IncorrectIdentifier(_diid); // Require first 12 bytes empty, leaving only 20 bytes of address non-empty | ||
address account = address(uint160(uint256(_diid))); | ||
if (account == address(0)) revert IncorrectIdentifier(_diid); | ||
return (ChainidTools.chainid(), account); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {DataPoints, DataPoint} from "./utils/DataPoints.sol"; | ||
import {IDataPointRegistry} from "./interfaces/IDataPointRegistry.sol"; | ||
|
||
/** | ||
* @title DataPointRegistry contract | ||
* @notice Contract for managing the creation, transfer and access control of DataPoints | ||
*/ | ||
contract DataPointRegistry is IDataPointRegistry { | ||
/** | ||
* @notice DataPoint access data | ||
* @param owner Owner of the DataPoint | ||
* @param isAdmin Mapping of isAdmin status for each account | ||
*/ | ||
struct DPAccessData { | ||
address owner; | ||
mapping(address => bool) isAdmin; | ||
} | ||
|
||
/// @dev Counter for DataPoint allocation | ||
uint256 private counter; | ||
|
||
/// @dev Access data for each DataPoint | ||
mapping(DataPoint => DPAccessData) private accessData; | ||
|
||
/// @inheritdoc IDataPointRegistry | ||
function isAdmin(DataPoint dp, address account) public view returns (bool) { | ||
return accessData[dp].isAdmin[account]; | ||
} | ||
|
||
/// @inheritdoc IDataPointRegistry | ||
function allocate(address owner) external payable returns (DataPoint) { | ||
if (msg.value > 0) revert NativeCoinDepositIsNotAccepted(); | ||
uint256 newCounter = ++counter; | ||
if (newCounter > type(uint32).max) revert CounterOverflow(); | ||
DataPoint dp = DataPoints.encode(address(this), uint32(newCounter)); | ||
DPAccessData storage dpd = accessData[dp]; | ||
dpd.owner = owner; | ||
dpd.isAdmin[owner] = true; | ||
emit DataPointAllocated(dp, owner); | ||
return dp; | ||
} | ||
|
||
/// @inheritdoc IDataPointRegistry | ||
function transferOwnership(DataPoint dp, address newOwner) external { | ||
DPAccessData storage dpd = accessData[dp]; | ||
address currentOwner = dpd.owner; | ||
if (msg.sender != currentOwner) revert InvalidDataPointOwner(dp, msg.sender); | ||
dpd.owner = newOwner; | ||
emit DataPointOwnershipTransferred(dp, currentOwner, newOwner); | ||
} | ||
|
||
/// @inheritdoc IDataPointRegistry | ||
function grantAdminRole(DataPoint dp, address account) external returns (bool) { | ||
DPAccessData storage dpd = accessData[dp]; | ||
if (msg.sender != dpd.owner) revert InvalidDataPointOwner(dp, msg.sender); | ||
if (!isAdmin(dp, account)) { | ||
dpd.isAdmin[account] = true; | ||
emit DataPointAdminGranted(dp, account); | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
/// @inheritdoc IDataPointRegistry | ||
function revokeAdminRole(DataPoint dp, address account) external returns (bool) { | ||
DPAccessData storage dpd = accessData[dp]; | ||
if (msg.sender != dpd.owner) revert InvalidDataPointOwner(dp, msg.sender); | ||
if (isAdmin(dp, account)) { | ||
dpd.isAdmin[account] = false; | ||
emit DataPointAdminRevoked(dp, account); | ||
return true; | ||
} | ||
return false; | ||
} | ||
} |
Oops, something went wrong.