-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Introduce Modules V2 with more flexibility
- Loading branch information
Showing
7 changed files
with
439 additions
and
4 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.21; | ||
|
||
import { AttestationPayload } from "../types/Structs.sol"; | ||
import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; | ||
|
||
/** | ||
* @title Abstract Module V2 | ||
* @author Consensys | ||
* @notice Defines the minimal Module V2 interface | ||
*/ | ||
abstract contract AbstractModuleV2 is IERC165 { | ||
/// @notice Error thrown when someone else than the portal's owner is trying to revoke | ||
error OnlyPortalOwner(); | ||
|
||
/** | ||
* @notice Executes the module's custom logic | ||
* @param attestationPayload The incoming attestation data | ||
* @param validationPayload Additional data required for verification | ||
* @param initialCaller The address of the initial caller (transaction sender) | ||
* @param value The value (ETH) optionally passed in the attesting transaction | ||
* @param attester The address defined by the Portal as the attester for this payload | ||
* @param portal The issuing Portal's address | ||
*/ | ||
function run( | ||
AttestationPayload memory attestationPayload, | ||
bytes memory validationPayload, | ||
address initialCaller, | ||
uint256 value, | ||
address attester, | ||
address portal | ||
) public virtual; | ||
|
||
/** | ||
* @notice Checks if the contract implements the Module interface. | ||
* @param interfaceID The ID of the interface to check. | ||
* @return A boolean indicating interface support. | ||
*/ | ||
function supportsInterface(bytes4 interfaceID) public pure virtual override returns (bool) { | ||
return interfaceID == type(AbstractModuleV2).interfaceId || interfaceID == type(IERC165).interfaceId; | ||
} | ||
} |
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,73 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.21; | ||
|
||
import { AbstractModuleV2 } from "../abstracts/AbstractModuleV2.sol"; | ||
import { AttestationPayload } from "../types/Structs.sol"; | ||
import { PortalRegistry } from "../PortalRegistry.sol"; | ||
|
||
/** | ||
* @title Fee Module V2 | ||
* @author Consensys | ||
* @notice This module can be used by portal creators to enforce a fee on attestations. | ||
* @dev This Module checks the fee is sent, but doesn't collect the fee | ||
*/ | ||
contract FeeModuleV2 is AbstractModuleV2 { | ||
PortalRegistry public portalRegistry; | ||
|
||
mapping(address portal => mapping(bytes32 schemaId => uint256 attestationFee)) public attestationFees; | ||
|
||
/// @notice Error thrown when an array length mismatch occurs | ||
error ArrayLengthMismatch(); | ||
/// @notice Error thrown when an invalid attestation fee is provided | ||
error InvalidAttestationFee(); | ||
|
||
modifier onlyPortalOwner(address portal) { | ||
if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); | ||
_; | ||
} | ||
|
||
event FeesSet(address portal, bytes32[] schemaIds, uint256[] attestationFees); | ||
|
||
/** | ||
* @notice Contract constructor sets the Portal Registry | ||
*/ | ||
constructor(address _portalRegistry) { | ||
portalRegistry = PortalRegistry(_portalRegistry); | ||
} | ||
|
||
/** | ||
* @notice Set the fee required to attest for a given Portal and one or multiple Schemas | ||
* @param portal The Portal targeted by the fees | ||
* @param schemaIds The Schema IDs to set the fees for | ||
* @param fees The fees required to attest with the Schemas on the Portal | ||
* @dev The length of `schemaIds` and `attestationFees` must be the same | ||
* Only the Portal owner can call this function to set the fees on his Portal | ||
*/ | ||
function setFees(address portal, bytes32[] memory schemaIds, uint256[] memory fees) public onlyPortalOwner(portal) { | ||
if (schemaIds.length != fees.length) revert ArrayLengthMismatch(); | ||
|
||
for (uint256 i = 0; i < schemaIds.length; i++) { | ||
attestationFees[portal][schemaIds[i]] = fees[i]; | ||
} | ||
|
||
emit FeesSet(portal, schemaIds, fees); | ||
} | ||
|
||
/** | ||
* @inheritdoc AbstractModuleV2 | ||
* @param value The value sent for the attestation (= the fee) | ||
* @param portal The Portal issuing the attestation | ||
* @notice If the provided fee is not enough, an error is thrown | ||
*/ | ||
function run( | ||
AttestationPayload memory attestationPayload, | ||
bytes memory /*validationPayload*/, | ||
address /*initialCaller*/, | ||
uint256 value, | ||
address /*attester*/, | ||
address portal | ||
) public view override { | ||
uint256 attestationFee = attestationFees[portal][attestationPayload.schemaId]; | ||
if (value < attestationFee) revert InvalidAttestationFee(); | ||
} | ||
} |
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,42 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.21; | ||
|
||
import { AbstractModuleV2 } from "../abstracts/AbstractModuleV2.sol"; | ||
import { AttestationPayload } from "../types/Structs.sol"; | ||
import { PortalRegistry } from "../PortalRegistry.sol"; | ||
|
||
/** | ||
* @title Issuers Module V2 | ||
* @author Consensys | ||
* @notice This Modules checks if the subject of an Attestation is registered as an Issuer | ||
*/ | ||
contract IssuersModuleV2 is AbstractModuleV2 { | ||
PortalRegistry public portalRegistry; | ||
|
||
/// @notice Error thrown when the subject of an Attestation is not an Issuer | ||
error UnauthorizedSubject(); | ||
|
||
constructor(address _portalRegistry) { | ||
portalRegistry = PortalRegistry(_portalRegistry); | ||
} | ||
|
||
/** | ||
* @inheritdoc AbstractModuleV2 | ||
* @notice If the Attestation subject is not an Issuer, an error is thrown | ||
*/ | ||
function run( | ||
AttestationPayload memory attestationPayload, | ||
bytes memory /*validationPayload*/, | ||
address /*initialCaller*/, | ||
uint256 /*value*/, | ||
address /*attester*/, | ||
address /*portal*/ | ||
) public view override { | ||
address subject = address(0); | ||
|
||
if (attestationPayload.subject.length == 32) subject = abi.decode(attestationPayload.subject, (address)); | ||
if (attestationPayload.subject.length == 20) subject = address(uint160(bytes20(attestationPayload.subject))); | ||
|
||
if (!portalRegistry.isIssuer(subject)) revert UnauthorizedSubject(); | ||
} | ||
} |
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,68 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.21; | ||
|
||
import { AbstractModuleV2 } from "../abstracts/AbstractModuleV2.sol"; | ||
import { AttestationPayload } from "../types/Structs.sol"; | ||
import { PortalRegistry } from "../PortalRegistry.sol"; | ||
|
||
/** | ||
* @title Sender Module V2 | ||
* @author Consensys | ||
* @notice This Module checks if the transaction sender is authorized for a specific Portal | ||
*/ | ||
contract SenderModuleV2 is AbstractModuleV2 { | ||
PortalRegistry public portalRegistry; | ||
|
||
mapping(address portal => mapping(address sender => bool authorized)) public authorizedSenders; | ||
|
||
/// @notice Error thrown when an array length mismatch occurs | ||
error ArrayLengthMismatch(); | ||
/// @notice Error thrown when the transaction sender is not authorized | ||
error UnauthorizedSender(); | ||
|
||
modifier onlyPortalOwner(address portal) { | ||
if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); | ||
_; | ||
} | ||
|
||
/** | ||
* @notice Contract constructor sets the portal registry | ||
*/ | ||
constructor(address _portalRegistry) { | ||
portalRegistry = PortalRegistry(_portalRegistry); | ||
} | ||
|
||
/** | ||
* @notice Set the authorized status of senders | ||
* @param senders The senders to be set | ||
* @param authorizedStatus The authorized status of senders | ||
*/ | ||
function setAuthorizedSenders( | ||
address portal, | ||
address[] memory senders, | ||
bool[] memory authorizedStatus | ||
) public onlyPortalOwner(portal) { | ||
if (senders.length != authorizedStatus.length) revert ArrayLengthMismatch(); | ||
|
||
for (uint256 i = 0; i < senders.length; i++) { | ||
authorizedSenders[portal][senders[i]] = authorizedStatus[i]; | ||
} | ||
} | ||
|
||
/** | ||
* @inheritdoc AbstractModuleV2 | ||
* @param initialCaller The initial transaction sender | ||
* @param portal The Portal issuing the attestation | ||
* @notice If the transaction sender is not the expected address, an error is thrown | ||
*/ | ||
function run( | ||
AttestationPayload memory /*attestationPayload*/, | ||
bytes memory /*validationPayload*/, | ||
address initialCaller, | ||
uint256 /*value*/, | ||
address /*attester*/, | ||
address portal | ||
) public view override { | ||
if (!authorizedSenders[portal][initialCaller]) revert UnauthorizedSender(); | ||
} | ||
} |
Oops, something went wrong.