Skip to content

Commit

Permalink
feat: As a Dev, I want the EASPortal to be based on the AbstractPortal (
Browse files Browse the repository at this point in the history
  • Loading branch information
0xEillo authored Aug 29, 2023
1 parent 065e7f5 commit 116b4b5
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 86 deletions.
25 changes: 17 additions & 8 deletions src/interface/AbstractPortal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable {
address[] public modules;
ModuleRegistry public moduleRegistry;
AttestationRegistry public attestationRegistry;

error ModulePayloadMismatch();

/**
Expand All @@ -32,7 +33,10 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable {
* @notice attest the schema with given attestationPayload and validationPayload
* @dev Runs all modules for the portal and registers the attestation using AttestationRegistry
*/
function attest(AttestationPayload memory attestationPayload, bytes[] memory validationPayload) external payable {
function attest(
AttestationPayload memory attestationPayload,
bytes[] memory validationPayload
) public payable virtual {
if (modules.length != 0) _runModules(validationPayload);

_beforeAttest(attestationPayload, msg.value);
Expand All @@ -42,11 +46,6 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable {
_afterAttest(attestation);
}

function revoke(bytes32 attestationId, bytes32 replacedBy) external {
_onRevoke(attestationId, replacedBy);
attestationRegistry.revoke(attestationId, replacedBy);
}

/**
* @notice Bulk attest the schema with payloads to attest and validation payloads
* @param attestationsPayloads the payloads to attest
Expand All @@ -55,20 +54,30 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable {
function bulkAttest(
AttestationPayload[] memory attestationsPayloads,
bytes[][] memory validationPayloads
) external payable {
) public payable {
_onBulkAttest(attestationsPayloads, validationPayloads);
// Run all modules for all payloads
moduleRegistry.bulkRunModules(modules, validationPayloads);
// Register attestations using the attestation registry
attestationRegistry.bulkAttest(attestationsPayloads);
}

/**
* @notice Revokes the attestation for the given identifier and can replace it by a new one
* @param attestationId the attestation ID to revoke
* @param replacedBy the replacing attestation ID (leave to just revoke)
*/
function revoke(bytes32 attestationId, bytes32 replacedBy) external virtual {
_onRevoke(attestationId, replacedBy);
attestationRegistry.revoke(attestationId, replacedBy);
}

/**
* @notice Bulk revokes attestations for given identifiers and can replace them by new ones
* @param attestationIds the attestations IDs to revoke
* @param replacedBy the replacing attestations IDs (leave an ID empty to just revoke)
*/
function bulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) external {
function bulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) external virtual {
_onBulkRevoke(attestationIds, replacedBy);
attestationRegistry.bulkRevoke(attestationIds, replacedBy);
}
Expand Down
104 changes: 58 additions & 46 deletions src/portal/EASPortal.sol
Original file line number Diff line number Diff line change
@@ -1,69 +1,81 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { Initializable } from "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol";
// solhint-disable-next-line max-line-length
import { IERC165Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165Upgradeable.sol";
import { AttestationRegistry } from "../AttestationRegistry.sol";
import { ModuleRegistry } from "../ModuleRegistry.sol";
import { SchemaRegistry } from "../SchemaRegistry.sol";
import { AbstractPortal } from "../interface/AbstractPortal.sol";
import { Attestation, AttestationPayload, Portal } from "../types/Structs.sol";

struct AttestationRequestData {
address recipient;
uint64 expirationTime;
bool revocable;
bytes32 refUID;
bytes data;
uint256 value;
}

struct AttestationRequest {
bytes32 schema;
AttestationRequestData data;
}

abstract contract EASAbstractPortal {
function attest(AttestationRequest memory attestationRequest) external payable virtual;
}

/**
* @title EAS Portal
* @author Consensys
* @notice This contract aims to integrate with dapps that are already integrated with EAS
* @notice This contract aims to provide a default portal
*/
contract EASPortal is Initializable, EASAbstractPortal, IERC165Upgradeable {
AttestationRegistry public attestationRegistry;

/**
* @notice Contract initialization
*/
function initialize(address _attestationRegistry) public initializer {
// Store registries addresses
attestationRegistry = AttestationRegistry(_attestationRegistry);
contract EASPortal is AbstractPortal {
struct AttestationRequestData {
address recipient;
uint64 expirationTime;
bool revocable;
bytes32 refUID;
bytes data;
uint256 value;
}

struct AttestationRequest {
bytes32 schema;
AttestationRequestData data;
}

/**
* @notice attest the schema with given attestationPayload and validationPayload
* @dev Runs all modules for the portal and stores the attestation in AttestationRegistry
*/
function attest(AttestationRequest memory attestationRequest) external payable override {
AttestationRequestData memory attestationRequestData = attestationRequest.data;
function _beforeAttest(AttestationPayload memory attestation, uint256 value) internal override {}

function _afterAttest(Attestation memory attestation) internal override {}

function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal override {}

function _onBulkAttest(
AttestationPayload[] memory attestationsPayloads,
bytes[][] memory validationPayloads
) internal override {}

function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal override {}

function attest(AttestationRequest memory attestationRequest) external payable {
bytes[] memory validationPayload = new bytes[](0);

AttestationPayload memory attestationPayload = AttestationPayload(
attestationRequest.schema,
abi.encodePacked(attestationRequestData.recipient),
uint256(attestationRequestData.expirationTime),
attestationRequestData.data
abi.encodePacked(attestationRequest.data.recipient),
uint256(attestationRequest.data.expirationTime),
attestationRequest.data.data
);

attestationRegistry.attest(attestationPayload);
super.attest(attestationPayload, validationPayload);
}

function bulkAttest(AttestationRequest[] memory attestationsRequests) external payable {
AttestationPayload[] memory attestationsPayloads = new AttestationPayload[](attestationsRequests.length);
bytes[][] memory validationPayloads = new bytes[][](attestationsRequests.length);

for (uint i = 0; i < attestationsRequests.length; i++) {
attestationsPayloads[i] = AttestationPayload(
attestationsRequests[i].schema,
abi.encodePacked(attestationsRequests[i].data.recipient),
uint256(attestationsRequests[i].data.expirationTime),
attestationsRequests[i].data.data
);

validationPayloads[i] = new bytes[](0);
}

super.bulkAttest(attestationsPayloads, validationPayloads);
}

function revoke(bytes32 /*attestationId*/, bytes32 /*replacedBy*/) external pure override {
revert("No revoking");
}

/**
* @notice Implements supports interface method declaring it is an EASAbstractPortal
*/
function supportsInterface(bytes4 interfaceID) public pure override returns (bool) {
return interfaceID == type(EASAbstractPortal).interfaceId || interfaceID == type(IERC165Upgradeable).interfaceId;
function bulkRevoke(bytes32[] memory /*attestationIds*/, bytes32[] memory /*replacedBy*/) external pure override {
revert("No bulk revoking");
}
}
6 changes: 4 additions & 2 deletions test/PortalRegistry.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ contract PortalRegistryTest is Test {
string public expectedName = "Name";
string public expectedDescription = "Description";
string public expectedOwnerName = "Owner Name";
ValidPortal public validPortal = new ValidPortal();
ValidPortal public validPortal;
InvalidPortal public invalidPortal = new InvalidPortal();

event Initialized(uint8 version);
Expand All @@ -44,6 +44,8 @@ contract PortalRegistryTest is Test {
router.updateAttestationRegistry(attestationRegistryAddress);
vm.prank(address(0));
portalRegistry.setIssuer(user);

validPortal = new ValidPortal();
}

function test_alreadyInitialized() public {
Expand Down Expand Up @@ -194,7 +196,7 @@ contract PortalRegistryTest is Test {
contract ValidPortal is AbstractPortal {
function test() public {}

function _beforeAttest(AttestationPayload memory attestation, uint256 value) internal override {}
function _beforeAttest(AttestationPayload memory attestationPayload, uint256 value) internal override {}

function _afterAttest(Attestation memory attestation) internal override {}

Expand Down
22 changes: 11 additions & 11 deletions test/mocks/AttestationRegistryMock.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { Attestation, AttestationPayload } from "../../src/types/Structs.sol";
import { Attestation, AttestationPayload, Attestation } from "../../src/types/Structs.sol";

contract AttestationRegistryMock {
bytes32 public _attestationId;
Expand All @@ -15,22 +15,22 @@ contract AttestationRegistryMock {
function test() public {}

function attest(AttestationPayload calldata attestationPayload) public returns (Attestation memory) {
require(bytes32(attestationPayload.schemaId) != 0, "Invalid attestation payload");
emit AttestationRegistered();
require(bytes32(attestationPayload.schemaId) != 0 && tx.origin != address(0), "Invalid attestation payload");

Check warning on line 18 in test/mocks/AttestationRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Avoid to use tx.origin

Check warning on line 18 in test/mocks/AttestationRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Avoid to use tx.origin

Check warning on line 18 in test/mocks/AttestationRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Avoid to use tx.origin
Attestation memory attestation = Attestation(
bytes32(uint(1)),
bytes32(keccak256(abi.encode((1)))),
attestationPayload.schemaId,
tx.origin,

Check warning on line 22 in test/mocks/AttestationRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Avoid to use tx.origin

Check warning on line 22 in test/mocks/AttestationRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Avoid to use tx.origin

Check warning on line 22 in test/mocks/AttestationRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Avoid to use tx.origin
address(1),
msg.sender,
attestationPayload.subject,
block.timestamp,
attestationPayload.expirationDate,
false,
0,
bytes32(0),
1,
version,
attestationPayload.attestationData
);
emit AttestationRegistered();
return attestation;
}

Expand All @@ -46,16 +46,16 @@ contract AttestationRegistryMock {
emit AttestationRevoked(attestationId, replacedBy);
}

function bulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) public {
require(attestationIds.length > 0, "Invalid attestation");
emit BulkAttestationsRevoked(attestationIds, replacedBy);
}

function getAttestationId() public view returns (bytes32) {
return _attestationId;
}

function getVersionNumber() public view returns (uint16) {
return version;
}

function bulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) public {
require(attestationIds.length > 0, "Invalid attestation");
emit BulkAttestationsRevoked(attestationIds, replacedBy);
}
}
8 changes: 3 additions & 5 deletions test/mocks/ModuleRegistryMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ contract ModuleRegistryMock {

function test() public {}

function runModules(address[] memory modulesAddresses, bytes[] memory validationPayload) public {
require(modulesAddresses.length > 0 && validationPayload.length >= 0, "Invalid input");
emit ModulesRunForAttestation();
}
function runModules(address[] memory modulesAddresses, bytes[] memory validationPayload) public {}

function bulkRunModules(address[] memory modulesAddresses, bytes[][] memory validationPayloads) public {
require(modulesAddresses.length > 0 && validationPayloads.length >= 0, "Invalid input");
require(modulesAddresses.length >= 0, "Invalid input for modulesAddresses");

Check warning on line 15 in test/mocks/ModuleRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Error message for require is too long

Check warning on line 15 in test/mocks/ModuleRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Error message for require is too long

Check warning on line 15 in test/mocks/ModuleRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Error message for require is too long
require(validationPayloads.length >= 0, "Invalid input for validationPayloads");

Check warning on line 16 in test/mocks/ModuleRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Error message for require is too long

Check warning on line 16 in test/mocks/ModuleRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Error message for require is too long

Check warning on line 16 in test/mocks/ModuleRegistryMock.sol

View workflow job for this annotation

GitHub Actions / lint

Error message for require is too long
emit ModulesBulkRunForAttestation();
}
}
8 changes: 7 additions & 1 deletion test/portal/DefaultPortal.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,17 @@ contract DefaultPortalTest is Test {
event BulkAttestationsRevoked(bytes32[] attestationId, bytes32[] replacedBy);

function setUp() public {
defaultPortal = new DefaultPortal();
modules.push(address(correctModule));
defaultPortal = new DefaultPortal();
defaultPortal.initialize(modules, address(moduleRegistryMock), address(attestationRegistryMock));
}

function test_setup() public {
assertEq(address(defaultPortal.modules(0)), address(modules[0]));
assertEq(address(defaultPortal.moduleRegistry()), address(moduleRegistryMock));
assertEq(address(defaultPortal.attestationRegistry()), address(attestationRegistryMock));
}

function test_initialize() public {
DefaultPortal defaultPortalTest = new DefaultPortal();
vm.expectEmit();
Expand Down
Loading

0 comments on commit 116b4b5

Please sign in to comment.