Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example of diamonds for DID resolution #22

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,17 @@ dist

# TernJS port file
.tern-port




# MacOS Stuff
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
9 changes: 9 additions & 0 deletions diamonds/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

```shell
# Install deps (please no yarn)
npm install
# Build the contract and generate the Typescript types
npm run build
# Run the tests
npm run test
```
148 changes: 148 additions & 0 deletions diamonds/contracts/DID.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
//SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.13;

import "./libraries/AppStorage.sol";
import {DEFAULT_ADMIN_ROLE} from "./shared/Roles.sol";
import "@solidstate/contracts/access/access_control/AccessControlInternal.sol";

/// @title DIDRegistry
/// @notice Entry point of all calls of the DIDRegistry system and module manager
contract DIDRegistry is AccessControlInternal {
event ModuleAdded(address indexed moduleAddr, bytes4[] selectors);
event ModuleRemoved(address indexed moduleAddr, bytes4[] selectors);
event ModuleUpdated(
address indexed oldImplementation,
address indexed newImplementation,
bytes4[] oldSelectors,
bytes4[] newSelectors
);

constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}

/// @notice pass a call to a module
/* solhint-disable no-complex-fallback, payable-fallback, no-inline-assembly */
fallback() external {
address implementation = AppStorage.getStorage().implementations[
msg.sig
];
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(
gas(),
implementation,
0,
calldatasize(),
0,
0
)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}

/* solhint-enable no-complex-fallback, payable-fallback, no-inline-assembly */

/// @notice Updates module
/// @dev oldImplementation should be registered
/// @param oldImplementation address of the module to remove
/// @param newImplementation address of the module to register
/// @param oldSelectors old function signatures list
/// @param newSelectors new function signatures list
function updateModule(
address oldImplementation,
address newImplementation,
bytes4[] calldata oldSelectors,
bytes4[] calldata newSelectors
) external onlyRole(DEFAULT_ADMIN_ROLE) {
_removeModule(oldImplementation, oldSelectors);
_addModule(newImplementation, newSelectors);
emit ModuleUpdated(
oldImplementation,
newImplementation,
oldSelectors,
newSelectors
);
}

/// @notice Adds a new module
/// @dev function selector should not have been registered
/// @param implementation address of the implementation
/// @param selectors selectors of the implementation contract
function addModule(
address implementation,
bytes4[] calldata selectors
) external onlyRole(DEFAULT_ADMIN_ROLE) {
_addModule(implementation, selectors);
emit ModuleAdded(implementation, selectors);
}

/// @notice Removes a module and supported functions
/// @dev function selector should not exist
/// @param implementation implementation address
/// @param selectors function selectors
function removeModule(
address implementation,
bytes4[] calldata selectors
) external onlyRole(DEFAULT_ADMIN_ROLE) {
_removeModule(implementation, selectors);
emit ModuleRemoved(implementation, selectors);
}

/// @notice Adds a new module
/// @dev function selector should not have been registered
/// @param implementation address of the implementation
/// @param selectors selectors of the implementation contract
function _addModule(
address implementation,
bytes4[] calldata selectors
) private {
AppStorage.Storage storage s = AppStorage.getStorage();
require(
s.selectorsHash[implementation] == 0x0,
"Implementation already exists"
);

for (uint256 i = 0; i < selectors.length; i++) {
require(
s.implementations[selectors[i]] == address(0),
"Selector already registered"
);
s.implementations[selectors[i]] = implementation;
}
bytes32 hash = keccak256(abi.encode(selectors));
s.selectorsHash[implementation] = hash;
}

/// @notice Removes a module and supported functions
/// @dev function selector should not exist
/// @param implementation implementation address
/// @param selectors function selectors
function _removeModule(
address implementation,
bytes4[] calldata selectors
) private {
AppStorage.Storage storage s = AppStorage.getStorage();
bytes32 hash = keccak256(abi.encode(selectors));
require(
s.selectorsHash[implementation] == hash,
"Invalid selector list"
);

for (uint256 i = 0; i < selectors.length; i++) {
require(
s.implementations[selectors[i]] == implementation,
"Selector registered in another module"
);
s.implementations[selectors[i]] = address(0);
}
s.selectorsHash[implementation] = 0x0;
}
}
27 changes: 27 additions & 0 deletions diamonds/contracts/Eip712/Eip712Checker.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.13;

import "./Eip712CheckerStorage.sol";

import {DEFAULT_ADMIN_ROLE} from "../shared/Roles.sol";

import "@solidstate/contracts/access/access_control/AccessControlInternal.sol";

/// @title Eip712Checker
/// @notice Contract used for verifying signatures
/// @dev Based on the EIP-712 https://eips.ethereum.org/EIPS/eip-712
contract Eip712Checker is AccessControlInternal {
/// @notice Sets name and version
/// @param name Domain name
/// @param version Domain version
function initialize(
string calldata name,
string calldata version
) external onlyRole(DEFAULT_ADMIN_ROLE) {
Eip712CheckerStorage.Storage storage s = Eip712CheckerStorage
.getStorage();

s.name = keccak256(abi.encodePacked(name));
s.version = keccak256(abi.encodePacked(version));
}
}
73 changes: 73 additions & 0 deletions diamonds/contracts/Eip712/Eip712CheckerInternal.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.13;

import "./Eip712CheckerStorage.sol";

import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

/// @title Eip712CheckerInternal
/// @notice Contract with internal functions to assist in verifying signatures
/// @dev Based on the EIP-712 https://eips.ethereum.org/EIPS/eip-712
library Eip712CheckerInternal {
bytes32 private constant EIP712_DOMAIN_TYPEHASH =
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);

/// @dev Returns the EIP-712 domain separator
function _eip712Domain() internal view returns (bytes32) {
Eip712CheckerStorage.Storage storage s = Eip712CheckerStorage
.getStorage();

return
keccak256(
abi.encode(
EIP712_DOMAIN_TYPEHASH,
s.name,
s.version,
block.chainid,
address(this)
)
);
}

/// @dev Recovers message signer and verifies if metches signatory
/// @param signatory The signer to be verified
/// @param message Hashed data payload
/// @param signature Signed data payload
function _verifySignature(
address signatory,
bytes32 message,
bytes calldata signature
) internal view returns (bool success) {
require(signatory != address(0), "ECDSA: zero signatory address");

bytes32 msgHash = keccak256(
abi.encodePacked("\x19\x01", _eip712Domain(), message)
);

return signatory == ECDSA.recover(msgHash, signature);
}

/// @dev Recovers message signer and verifies if metches signatory
/// @param signatory The signer to be verified
/// @param message Hashed data payload
/// @param v Signature "v" value
/// @param r Signature "r" value
/// @param s Signature "s" value
function _verifySignature(
address signatory,
bytes32 message,
uint8 v,
bytes32 r,
bytes32 s
) internal view returns (bool success) {
require(signatory != address(0), "ECDSA: zero signatory address");

bytes32 msgHash = keccak256(
abi.encodePacked("\x19\x01", _eip712Domain(), message)
);

return signatory == ECDSA.recover(msgHash, v, r, s);
}
}
23 changes: 23 additions & 0 deletions diamonds/contracts/Eip712/Eip712CheckerStorage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.13;

/// @title Eip712CheckerStorage
/// @notice Storage of the Eip712Checker contract
library Eip712CheckerStorage {
bytes32 internal constant EIP712_CHECKER_STORAGE_SLOT =
keccak256("DIDRegistry.eip712Checker.storage");

struct Storage {
bytes32 name;
bytes32 version;
}

/* solhint-disable no-inline-assembly */
function getStorage() internal pure returns (Storage storage s) {
bytes32 slot = EIP712_CHECKER_STORAGE_SLOT;
assembly {
s.slot := slot
}
}
/* solhint-enable no-inline-assembly */
}
44 changes: 44 additions & 0 deletions diamonds/contracts/implementations/Documents.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.13;

import "../libraries/DocumentStorage.sol";

/// @title Documents
/// @notice Contract to store data related to the documents
contract Documents {
/// @notice Gets the info of a document
/// @param idProxyAddress The address of the proxy associated with the document
/// @param documentId The documentId
function getDocumentInfo(
address idProxyAddress,
int256 documentId
) external view returns (string memory info) {
info = DocumentStorage
.getStorage()
.documents[idProxyAddress][documentId].info;
}

/// @notice Gets the owner of a document
/// @param idProxyAddress The address of the proxy associated with the document
/// @param documentId The documentId
function getDocumentOwner(
address idProxyAddress,
int256 documentId
) external view returns (address owner) {
owner = DocumentStorage
.getStorage()
.documents[idProxyAddress][documentId].owner;
}

/// @notice Gets the version of a document
/// @param idProxyAddress The address of the proxy associated with the document
/// @param documentId The documentId
function getDocumentVersion(
address idProxyAddress,
int256 documentId
) external view returns (int256 version) {
version = DocumentStorage
.getStorage()
.documents[idProxyAddress][documentId].version;
}
}
Loading