Skip to content

Commit

Permalink
chore(contracts): Stop supporting deprecated Portal functions (#810)
Browse files Browse the repository at this point in the history
  • Loading branch information
satyajeetkolhapure authored Nov 26, 2024
1 parent b95345a commit eac2e44
Show file tree
Hide file tree
Showing 23 changed files with 712 additions and 417 deletions.
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

0 comments on commit eac2e44

Please sign in to comment.