-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(contracts): add eas registry contract
- [x] Add BaseRegistry contract - [x] Add EASRegistry contract - [x] Add tests
- Loading branch information
Showing
12 changed files
with
512 additions
and
104 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
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
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 |
---|---|---|
|
@@ -5,4 +5,5 @@ deployed-contracts.json | |
cache | ||
artifacts | ||
typechain-types | ||
coverage.json | ||
|
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,35 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
/// @title IEAS | ||
/// @notice An interface to the EAS contract. | ||
interface IEAS { | ||
/// @notice A struct representing a single attestation. | ||
struct Attestation { | ||
// A unique identifier of the attestation. | ||
bytes32 uid; | ||
// The unique identifier of the schema. | ||
bytes32 schema; | ||
// The time when the attestation was created (Unix timestamp). | ||
uint64 time; | ||
// The time when the attestation expires (Unix timestamp). | ||
uint64 expirationTime; | ||
// The time when the attestation was revoked (Unix timestamp). | ||
uint64 revocationTime; | ||
// The UID of the related attestation. | ||
bytes32 refUID; | ||
// The recipient of the attestation. | ||
address recipient; | ||
// The attester/sender of the attestation. | ||
address attester; | ||
// Whether the attestation is revocable. | ||
bool revocable; | ||
// Custom attestation data. | ||
bytes data; | ||
} | ||
|
||
/// Get an attestation by its unique identifier. | ||
/// @param uid The unique identifier of the attestation. | ||
/// @return attestation The attestation. | ||
function getAttestation(bytes32 uid) external view returns (Attestation memory); | ||
} |
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
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,56 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import { IEAS } from "../interfaces/IEAS.sol"; | ||
|
||
/// @title MockEAS | ||
/// @notice A mock contract to test the EASGatekeeper | ||
contract MockEAS is IEAS { | ||
address public immutable attester; | ||
bytes32 public immutable schema; | ||
address public immutable recipient; | ||
|
||
/// @param _attester The address of the attester | ||
/// @param _schema The schema of the attestation | ||
/// @param _recipient The recipient of the attestation | ||
constructor(address _attester, bytes32 _schema, address _recipient) { | ||
attester = _attester; | ||
schema = _schema; | ||
recipient = _recipient; | ||
} | ||
|
||
/// @inheritdoc IEAS | ||
function getAttestation(bytes32 attestationId) external view override returns (Attestation memory) { | ||
// revoked | ||
if (attestationId == 0x0000000000000000000000000000000000000000000000000000000000000001) { | ||
return | ||
Attestation({ | ||
uid: "0x000000000000000000000000000001", | ||
schema: schema, | ||
time: 0, | ||
expirationTime: 0, | ||
revocationTime: 1, | ||
refUID: "0x000000000000000000000000000001", | ||
recipient: recipient, | ||
attester: attester, | ||
revocable: true, | ||
data: "" | ||
}); | ||
// valid | ||
} else { | ||
return | ||
Attestation({ | ||
uid: "0x000000000000000000000000000001", | ||
schema: schema, | ||
time: 0, | ||
expirationTime: 0, | ||
revocationTime: 0, | ||
refUID: "0x000000000000000000000000000001", | ||
recipient: recipient, | ||
attester: attester, | ||
revocable: false, | ||
data: "" | ||
}); | ||
} | ||
} | ||
} |
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,80 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import { IRecipientRegistry } from "../interfaces/IRecipientRegistry.sol"; | ||
|
||
/// @title BaseRegistry | ||
/// @notice Base contract for a registry | ||
abstract contract BaseRegistry is IRecipientRegistry { | ||
/// @notice The storage of recipients | ||
mapping(uint256 => Recipient) internal recipients; | ||
|
||
/// @inheritdoc IRecipientRegistry | ||
uint256 public immutable maxRecipients; | ||
|
||
/// @inheritdoc IRecipientRegistry | ||
uint256 public recipientCount; | ||
|
||
/// @notice The registry metadata url | ||
bytes32 public immutable metadataUrl; | ||
|
||
/// @notice Create a new instance of the registry contract | ||
/// @param _maxRecipients The maximum number of recipients that can be registered | ||
/// @param _metadataUrl The metadata url | ||
constructor(uint256 _maxRecipients, bytes32 _metadataUrl) payable { | ||
maxRecipients = _maxRecipients; | ||
metadataUrl = _metadataUrl; | ||
} | ||
|
||
/// @inheritdoc IRecipientRegistry | ||
function getRegistryMetadataUrl() public view virtual override returns (bytes32) { | ||
return metadataUrl; | ||
} | ||
|
||
/// @inheritdoc IRecipientRegistry | ||
function addRecipient(Recipient calldata recipient) public virtual override returns (uint256) { | ||
uint256 index = recipientCount; | ||
|
||
if (index >= maxRecipients) { | ||
revert MaxRecipientsReached(); | ||
} | ||
|
||
recipients[index] = recipient; | ||
recipientCount++; | ||
|
||
emit RecipientAdded(index, recipient.id, recipient.metadataUrl, recipient.recipient); | ||
|
||
return index; | ||
} | ||
|
||
/// @inheritdoc IRecipientRegistry | ||
function removeRecipient(uint256 index) public virtual override { | ||
if (index >= recipientCount) { | ||
revert InvalidIndex(); | ||
} | ||
|
||
Recipient memory recipient = recipients[index]; | ||
|
||
delete recipients[index]; | ||
|
||
emit RecipientRemoved(index, recipient.id, recipient.recipient); | ||
} | ||
|
||
/// @inheritdoc IRecipientRegistry | ||
function changeRecipient(uint256 index, Recipient calldata recipient) public virtual override { | ||
if (index >= recipientCount) { | ||
revert InvalidIndex(); | ||
} | ||
|
||
recipients[index].id = recipient.id; | ||
recipients[index].recipient = recipient.recipient; | ||
recipients[index].metadataUrl = metadataUrl; | ||
|
||
emit RecipientChanged(index, recipient.id, recipient.metadataUrl, recipient.recipient); | ||
} | ||
|
||
/// @inheritdoc IRecipientRegistry | ||
function getRecipient(uint256 index) public view virtual override returns (Recipient memory) { | ||
return recipients[index]; | ||
} | ||
} |
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,62 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; | ||
|
||
import { IEAS } from "../interfaces/IEAS.sol"; | ||
import { BaseRegistry } from "./BaseRegistry.sol"; | ||
|
||
contract EASRegistry is Ownable, BaseRegistry { | ||
/// @notice The EAS contract | ||
IEAS public immutable eas; | ||
|
||
/// @notice Custom errors | ||
error NotYourAttestation(); | ||
|
||
/// @notice Create a new instance of the registry contract | ||
/// @param _maxRecipients The maximum number of projects that can be registered | ||
/// @param _metadataUrl The metadata url | ||
/// @param _eas The EAS address | ||
constructor( | ||
uint256 _maxRecipients, | ||
bytes32 _metadataUrl, | ||
address _eas | ||
) payable Ownable(msg.sender) BaseRegistry(_maxRecipients, _metadataUrl) { | ||
eas = IEAS(_eas); | ||
} | ||
|
||
/// @notice Add multiple recipients to the registry | ||
/// @param recipients The recipients | ||
function addRecipients(Recipient[] calldata recipients) external onlyOwner { | ||
uint256 length = recipients.length; | ||
|
||
for (uint256 i = 0; i < length; ) { | ||
addRecipient(recipients[i]); | ||
|
||
unchecked { | ||
i++; | ||
} | ||
} | ||
} | ||
|
||
/// @inheritdoc BaseRegistry | ||
function addRecipient(Recipient calldata recipient) public override onlyOwner returns (uint256) { | ||
return super.addRecipient(recipient); | ||
} | ||
|
||
/// @notice Edit the address of a project | ||
/// @param index The index of the project to edit | ||
/// @param recipient The new recipient | ||
function changeRecipient(uint256 index, Recipient calldata recipient) public override { | ||
IEAS.Attestation memory attestation = eas.getAttestation(recipients[index].id); | ||
|
||
if (attestation.recipient != msg.sender) revert NotYourAttestation(); | ||
|
||
super.changeRecipient(index, recipient); | ||
} | ||
|
||
/// @inheritdoc BaseRegistry | ||
function removeRecipient(uint256 index) public override onlyOwner { | ||
super.removeRecipient(index); | ||
} | ||
} |
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
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
Oops, something went wrong.