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

chore(contracts): Stop supporting deprecated Portal functions #810

Merged
Merged
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
20 changes: 20 additions & 0 deletions contracts/src/DefaultPortalV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { AbstractPortalV2 } from "./abstracts/AbstractPortalV2.sol";

/**
* @title Default Portal V2
* @author Consensys
* @notice This contract aims to provide a default portal compatible with the V2 version of Abstract Portal
* @dev This Portal does not add any logic to the AbstractPortalV2
*/
contract DefaultPortalV2 is AbstractPortalV2 {
/**
* @notice Contract constructor
* @param modules list of modules to use for the portal (can be empty). The modules should be based on AbstractModuleV2
* @param router the Router's address
* @dev This sets the addresses for the AttestationRegistry, ModuleRegistry and PortalRegistry
*/
constructor(address[] memory modules, address router) AbstractPortalV2(modules, router) {}
}
5 changes: 1 addition & 4 deletions contracts/src/ModuleRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,7 @@ contract ModuleRegistry is OwnableUpgradeable {
// Check if moduleAddress is a smart contract address
if (!isContractAddress(moduleAddress)) revert ModuleAddressInvalid();
// Check if module has implemented AbstractModule or AbstractModuleV2
if (
!ERC165CheckerUpgradeable.supportsInterface(moduleAddress, type(AbstractModule).interfaceId) &&
!ERC165CheckerUpgradeable.supportsInterface(moduleAddress, type(AbstractModuleV2).interfaceId)
) {
if (!ERC165CheckerUpgradeable.supportsInterface(moduleAddress, type(AbstractModuleV2).interfaceId)) {
revert ModuleInvalid();
}
// Module address is used to identify uniqueness of the module
Expand Down
16 changes: 8 additions & 8 deletions contracts/src/PortalRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ pragma solidity 0.8.21;
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
// solhint-disable-next-line max-line-length
import { ERC165CheckerUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165CheckerUpgradeable.sol";
import { AbstractPortal } from "./abstracts/AbstractPortal.sol";
import { DefaultPortal } from "./DefaultPortal.sol";
import { AbstractPortalV2 } from "./abstracts/AbstractPortalV2.sol";
import { DefaultPortalV2 } from "./DefaultPortalV2.sol";
import { Portal } from "./types/Structs.sol";
import { IRouter } from "./interfaces/IRouter.sol";
import { IPortal } from "./interfaces/IPortal.sol";
import { uncheckedInc256 } from "./Common.sol";

/**
* @title Portal Registry
Expand Down Expand Up @@ -161,11 +161,11 @@ contract PortalRegistry is OwnableUpgradeable {
// Check if the owner's name is not empty
if (bytes(ownerName).length == 0) revert PortalOwnerNameMissing();

// Check if portal has implemented AbstractPortal
if (!ERC165CheckerUpgradeable.supportsInterface(id, type(IPortal).interfaceId)) revert PortalInvalid();
// Check if portal has implemented AbstractPortalV2
if (!ERC165CheckerUpgradeable.supportsInterface(id, type(AbstractPortalV2).interfaceId)) revert PortalInvalid();

// Get the array of modules implemented by the portal
address[] memory modules = AbstractPortal(id).getModules();
address[] memory modules = AbstractPortalV2(id).getModules();

// Add portal to mapping
Portal memory newPortal = Portal(id, msg.sender, modules, isRevocable, name, description, ownerName);
Expand All @@ -189,7 +189,7 @@ contract PortalRegistry is OwnableUpgradeable {
}

/**
* @notice Deploys and registers a clone of default portal
* @notice Deploys and registers a clone of default portal V2
* @param modules the modules addresses
* @param name the portal name
* @param description the portal description
Expand All @@ -202,7 +202,7 @@ contract PortalRegistry is OwnableUpgradeable {
bool isRevocable,
string calldata ownerName
) external onlyAllowlisted(msg.sender) {
DefaultPortal defaultPortal = new DefaultPortal(modules, address(router));
DefaultPortalV2 defaultPortal = new DefaultPortalV2(modules, address(router));
register(address(defaultPortal), name, description, isRevocable, ownerName);
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/src/abstracts/AbstractModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol
/**
* @title Abstract Module
* @author Consensys
* @notice Defines the minimal Module interface
* @notice Deprecated. Use the AbstractModuleV2 contract instead.
*/
abstract contract AbstractModule is IERC165 {
/// @notice Error thrown when someone else than the portal's owner is trying to revoke
Expand Down
4 changes: 1 addition & 3 deletions contracts/src/abstracts/AbstractPortal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ import { IPortal } from "../interfaces/IPortal.sol";
/**
* @title Abstract Portal
* @author Consensys
* @notice This contract is an abstracts contract with basic Portal logic
* to be inherited. We strongly encourage all Portals to implement
* this contract.
* @notice Deprecated. Use the AbstractPortalV2 contract instead.
*/
abstract contract AbstractPortal is IPortal {
IRouter public router;
Expand Down
278 changes: 278 additions & 0 deletions contracts/src/abstracts/AbstractPortalV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { AttestationRegistry } from "../AttestationRegistry.sol";
import { ModuleRegistry } from "../ModuleRegistry.sol";
import { PortalRegistry } from "../PortalRegistry.sol";
import { OperationType } from "../types/Enums.sol";
import { AttestationPayload } from "../types/Structs.sol";
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import { IRouter } from "../interfaces/IRouter.sol";
import { IPortal } from "../interfaces/IPortal.sol";

/**
* @title Abstract Portal V2
* @author Consensys
* @notice This contract is an abstracts contract with basic Portal logic
* to be inherited. We strongly encourage all Portals to implement
* this contract.
*/
abstract contract AbstractPortalV2 is IPortal {
IRouter public router;
address[] public modules;
ModuleRegistry public moduleRegistry;
AttestationRegistry public attestationRegistry;
PortalRegistry public portalRegistry;

/// @notice Error thrown when someone else than the portal's owner is trying to revoke
error OnlyPortalOwner();

/// @notice Error thrown when withdrawing funds fails
error WithdrawFail();

/**
* @notice Contract constructor
* @param _modules list of modules to use for the portal (can be empty)
* @param _router Router's address
* @dev This sets the addresses for the AttestationRegistry, ModuleRegistry and PortalRegistry
*/
constructor(address[] memory _modules, address _router) {
modules = _modules;
router = IRouter(_router);
attestationRegistry = AttestationRegistry(router.getAttestationRegistry());
moduleRegistry = ModuleRegistry(router.getModuleRegistry());
portalRegistry = PortalRegistry(router.getPortalRegistry());
}

/**
* @notice Withdraw funds from the Portal
* @param to the address to send the funds to
* @param amount the amount to withdraw
* @dev Only the Portal owner can withdraw funds
*/
function withdraw(address payable to, uint256 amount) external virtual {
if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner();
(bool s, ) = to.call{ value: amount }("");
if (!s) revert WithdrawFail();
}

/**
* @notice Attest the schema with given attestationPayload and validationPayload
* @param attestationPayload the payload to attest
* @param validationPayloads the payloads to validate via the modules to issue the attestations
* @dev Runs all modules for the portal and registers the attestation using AttestationRegistry
*/
function attest(AttestationPayload memory attestationPayload, bytes[] memory validationPayloads) public payable {
moduleRegistry.runModulesV2(
modules,
attestationPayload,
validationPayloads,
msg.value,
msg.sender,
getAttester(),
OperationType.Attest
);

_onAttest(attestationPayload, validationPayloads, msg.value);

attestationRegistry.attest(attestationPayload, getAttester());
}

/**
* @notice Bulk attest the schema with payloads to attest and validation payloads
* @param attestationPayloads the payloads to attest
* @param validationPayloads the payloads to validate via the modules to issue the attestations
* @dev DISCLAIMER: This method may have unexpected behavior if one of the Module checks is done on the attestation ID
* as this ID won't be incremented before the end of the transaction.
* If you need to check the attestation ID, please use the `attestV2` method.
*/
function bulkAttest(AttestationPayload[] memory attestationPayloads, bytes[][] memory validationPayloads) public {
moduleRegistry.bulkRunModulesV2(
modules,
attestationPayloads,
validationPayloads,
msg.sender,
getAttester(),
OperationType.BulkAttest
);

_onBulkAttest(attestationPayloads, validationPayloads);

attestationRegistry.bulkAttest(attestationPayloads, getAttester());
}

/**
* @notice Replaces the attestation for the given identifier and replaces it with a new attestation
* @param attestationId the ID of the attestation to replace
* @param attestationPayload the attestation payload to create the new attestation and register it
* @param validationPayloads the payloads to validate via the modules to issue the attestation
* @dev Runs all modules for the portal and registers the attestation using AttestationRegistry
*/
function replace(
bytes32 attestationId,
AttestationPayload memory attestationPayload,
bytes[] memory validationPayloads
) public payable {
moduleRegistry.runModulesV2(
modules,
attestationPayload,
validationPayloads,
msg.value,
msg.sender,
getAttester(),
OperationType.Replace
);

_onReplace(attestationId, attestationPayload, getAttester(), msg.value);

attestationRegistry.replace(attestationId, attestationPayload, getAttester());
}

/**
* @notice Bulk replaces the attestation for the given identifiers and replaces them with new attestations
* @param attestationIds the list of IDs of the attestations to replace
* @param attestationsPayloads the list of attestation payloads to create the new attestations and register them
* @param validationPayloads the payloads to validate via the modules to issue the attestations
* @dev DISCLAIMER: This method may have unexpected behavior if one of the Module checks is done on the attestation ID
* as this ID won't be incremented before the end of the transaction.
* If you need to check the attestation ID, please use the `replaceV2` method.
*/
function bulkReplace(
bytes32[] memory attestationIds,
AttestationPayload[] memory attestationsPayloads,
bytes[][] memory validationPayloads
) public {
moduleRegistry.bulkRunModulesV2(
modules,
attestationsPayloads,
validationPayloads,
msg.sender,
getAttester(),
OperationType.BulkReplace
);

_onBulkReplace(attestationIds, attestationsPayloads, validationPayloads);

attestationRegistry.bulkReplace(attestationIds, attestationsPayloads, getAttester());
}

/**
* @notice Revokes an attestation for the given identifier
* @param attestationId the ID of the attestation to revoke
* @dev By default, revocation is only possible by the portal owner
* We strongly encourage implementing such a rule in your Portal if you intend on overriding this method
*/
function revoke(bytes32 attestationId) public {
_onRevoke(attestationId);

attestationRegistry.revoke(attestationId);
}

/**
* @notice Bulk revokes a list of attestations for the given identifiers
* @param attestationIds the IDs of the attestations to revoke
*/
function bulkRevoke(bytes32[] memory attestationIds) public {
_onBulkRevoke(attestationIds);

attestationRegistry.bulkRevoke(attestationIds);
}

/**
* @notice Get all the modules addresses used by the Portal
* @return The list of modules addresses linked to the Portal
*/
function getModules() external view returns (address[] memory) {
return modules;
}

/**
* @notice Verifies that a specific interface is implemented by the Portal, following ERC-165 specification
* @param interfaceID the interface identifier checked in this call
* @return The list of modules addresses linked to the Portal
*/
function supportsInterface(bytes4 interfaceID) public pure virtual override returns (bool) {
return
interfaceID == type(AbstractPortalV2).interfaceId ||
interfaceID == type(IPortal).interfaceId ||
interfaceID == type(IERC165).interfaceId;
}

/**
* @notice Defines the address of the entity issuing attestations to the subject
* @dev We strongly encourage a reflection when overriding this rule: who should be set as the attester?
*/
function getAttester() public view virtual returns (address) {
return msg.sender;
}

/**
* @notice Optional method run before a payload is attested
* @param attestationPayload the attestation payload to attest
* @param validationPayloads the payloads to validate via the modules
* @param value the value sent with the attestation
*/
function _onAttest(
AttestationPayload memory attestationPayload,
bytes[] memory validationPayloads,
uint256 value
) internal virtual {}

/**
* @notice Optional method run when an attestation is replaced
* @dev IMPORTANT NOTE: By default, replacement is only possible by the portal owner
* @param attestationId the ID of the attestation being replaced
* @param attestationPayload the attestation payload to create attestation and register it
* @param attester the address of the attester
* @param value the value sent with the attestation
*/
function _onReplace(
bytes32 attestationId,
AttestationPayload memory attestationPayload,
address attester,
uint256 value
) internal virtual {
if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner();
}

/**
* @notice Optional method run when attesting a batch of payloads
* @param attestationsPayloads the payloads to attest
* @param validationPayloads the payloads to validate in order to issue the attestations
*/
function _onBulkAttest(
AttestationPayload[] memory attestationsPayloads,
bytes[][] memory validationPayloads
) internal virtual {}

/**
* @notice Optional method run when replacing a batch of payloads
* @dev IMPORTANT NOTE: By default, bulk replacement is only possible by the portal owner
* @param attestationIds the IDs of the attestations being replaced
* @param attestationsPayloads the payloads to replace
* @param validationPayloads the payloads to validate in order to replace the attestations
*/
function _onBulkReplace(
bytes32[] memory attestationIds,
AttestationPayload[] memory attestationsPayloads,
bytes[][] memory validationPayloads
) internal virtual {
if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner();
}

/**
* @notice Optional method run when an attestation is revoked or replaced
* @dev IMPORTANT NOTE: By default, revocation is only possible by the portal owner
*/
function _onRevoke(bytes32 /*attestationId*/) internal virtual {
if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner();
}

/**
* @notice Optional method run when a batch of attestations are revoked or replaced
* @dev IMPORTANT NOTE: By default, revocation is only possible by the portal owner
*/
function _onBulkRevoke(bytes32[] memory /*attestationIds*/) internal virtual {
if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner();
}
}
Loading
Loading