-
Notifications
You must be signed in to change notification settings - Fork 1
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 base and advanced Checker and Excubia contracts
- Loading branch information
Showing
18 changed files
with
409 additions
and
156 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 was deleted.
Oops, something went wrong.
73 changes: 73 additions & 0 deletions
73
packages/contracts/contracts/src/core/checker/AdvancedChecker.sol
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.27; | ||
|
||
import {IAdvancedChecker, Check} from "./IAdvancedChecker.sol"; | ||
|
||
struct CheckStatus { | ||
bool pre; | ||
uint8 main; | ||
bool post; | ||
} | ||
|
||
/// @title AdvancedChecker. | ||
/// @notice Abstract base contract which can be extended to implement a specific `AdvancedChecker`. | ||
/// @dev The `AdvancedChecker` contract builds upon the `BaseChecker` by introducing additional validation phases. | ||
/// It allows for pre-condition (`PRE`), main (`MAIN`), and post-condition (`POST`) checks, with the option to skip | ||
/// pre and post checks based on constructor parameters. The `_check` method orchestrates the validation process | ||
/// based on the specified check type. | ||
abstract contract AdvancedChecker is IAdvancedChecker { | ||
/// @notice Flag to determine if pre-condition checks should be skipped. | ||
bool public skipPre; | ||
|
||
/// @notice Flag to determine if post-condition checks should be skipped. | ||
bool public skipPost; | ||
|
||
/// @notice Flag to determine if main checks can be executed multiple times. | ||
bool public allowMultipleMain; | ||
|
||
/// @param _skipPre Indicates whether to skip pre-condition checks. | ||
/// @param _skipPost Indicates whether to skip post-condition checks. | ||
/// @param _allowMultipleMain Indicates whether the main check can be executed multiple times. | ||
constructor(bool _skipPre, bool _skipPost, bool _allowMultipleMain) { | ||
skipPre = _skipPre; | ||
skipPost = _skipPost; | ||
allowMultipleMain = _allowMultipleMain; | ||
} | ||
|
||
/// @notice Public method to check the validity of the provided data for a given address and check type. | ||
/// @param passerby The address to be checked. | ||
/// @param data The data associated with the check. | ||
/// @param checkType The type of check to perform (PRE, MAIN, POST). | ||
function check(address passerby, bytes memory data, Check checkType) external view override { | ||
_check(passerby, data, checkType); | ||
} | ||
|
||
/// @notice Internal method to orchestrate the validation process based on the specified check type. | ||
/// @param passerby The address to be checked. | ||
/// @param data The data associated with the check. | ||
/// @param checkType The type of check to perform (PRE, MAIN, POST). | ||
function _check(address passerby, bytes memory data, Check checkType) internal view { | ||
if (!skipPre && checkType == Check.PRE) { | ||
_checkPre(passerby, data); | ||
} else if (!skipPost && checkType == Check.POST) { | ||
_checkPost(passerby, data); | ||
} else if (checkType == Check.MAIN) { | ||
_checkMain(passerby, data); | ||
} | ||
} | ||
|
||
/// @notice Internal method for performing pre-condition checks. | ||
/// @param passerby The address to be checked. | ||
/// @param data The data associated with the check. | ||
function _checkPre(address passerby, bytes memory data) internal view virtual {} | ||
|
||
/// @notice Internal method for performing main checks. | ||
/// @param passerby The address to be checked. | ||
/// @param data The data associated with the check. | ||
function _checkMain(address passerby, bytes memory data) internal view virtual; | ||
|
||
/// @notice Internal method for performing post-condition checks. | ||
/// @param passerby The address to be checked. | ||
/// @param data The data associated with the check. | ||
function _checkPost(address passerby, bytes memory data) internal view virtual {} | ||
} |
23 changes: 23 additions & 0 deletions
23
packages/contracts/contracts/src/core/checker/BaseChecker.sol
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,23 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.27; | ||
|
||
import {IBaseChecker} from "./IBaseChecker.sol"; | ||
|
||
/// @title BaseChecker. | ||
/// @notice Abstract base contract which can be extended to implement a specific `BaseChecker`. | ||
/// @dev The `BaseChecker` contract provides a foundational structure for implementing specific checker logic. | ||
/// It defines a method `check` that invokes a protected `_check` method, which must be implemented by derived | ||
/// contracts. | ||
abstract contract BaseChecker is IBaseChecker { | ||
/// @notice Checks the validity of the provided data for a given address. | ||
/// @param passerby The address to be checked. | ||
/// @param data The data associated with the check. | ||
function check(address passerby, bytes memory data) external view override { | ||
_check(passerby, data); | ||
} | ||
|
||
/// @notice Internal method to perform the actual check logic. | ||
/// @param passerby The address to be checked. | ||
/// @param data The data associated with the check. | ||
function _check(address passerby, bytes memory data) internal view virtual; | ||
} |
24 changes: 24 additions & 0 deletions
24
packages/contracts/contracts/src/core/checker/IAdvancedChecker.sol
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,24 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.27; | ||
|
||
/// @notice This enum defines the types of checks that can be performed in the AdvancedChecker system. | ||
/// @dev The `Check` enum represents the different phases of validation in the AdvancedChecker system. | ||
/// - `PRE`: Represents the pre-condition check that must be satisfied before the `MAIN` check can occur. | ||
/// - `MAIN`: The primary check that is executed, which can be validated multiple times. | ||
/// - `POST`: Represents the post-condition check that can be validated after the `MAIN` check has been completed. | ||
enum Check { | ||
PRE, | ||
MAIN, | ||
POST | ||
} | ||
|
||
/// @title IAdvancedChecker. | ||
/// @notice AdvancedChecker contract interface. | ||
interface IAdvancedChecker { | ||
/// @dev Defines the custom `gate` protection logic. | ||
/// @param passerby The address of the entity attempting to pass the `gate`. | ||
/// @param data Additional data that may be required for the check. | ||
/// @param checkType The type of check to be enforced (e.g., PRE, MAIN, POST). | ||
function check(address passerby, bytes calldata data, Check checkType) external view; // Function to check if the | ||
// passerby can pass the gate with a specific check type. | ||
} |
11 changes: 11 additions & 0 deletions
11
packages/contracts/contracts/src/core/checker/IBaseChecker.sol
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,11 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.27; | ||
|
||
/// @title IBaseChecker | ||
/// @notice BaseChecker contract interface that defines the basic check functionality. | ||
interface IBaseChecker { | ||
/// @dev Defines the custom `gate` protection logic. | ||
/// @param passerby The address of the entity attempting to pass the `gate`. | ||
/// @param data Additional data that may be required for the check. | ||
function check(address passerby, bytes calldata data) external view; | ||
} |
54 changes: 54 additions & 0 deletions
54
packages/contracts/contracts/src/core/gatekeeper/AdvancedExcubia.sol
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,54 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.27; | ||
|
||
import {Excubia} from "./Excubia.sol"; | ||
import {IAdvancedExcubia, Check} from "./IAdvancedExcubia.sol"; | ||
import {AdvancedChecker, CheckStatus} from "../checker/AdvancedChecker.sol"; | ||
|
||
/// @title AdvancedExcubia | ||
/// @notice Abstract base contract which can be extended to implement a specific `AdvancedExcubia`. | ||
abstract contract AdvancedExcubia is IAdvancedExcubia, Excubia { | ||
/// @dev Reference to the AdvancedChecker contract for validation. | ||
AdvancedChecker public immutable ADVANCED_CHECKER; | ||
|
||
/// @dev Tracks the check status of each address. | ||
mapping(address => CheckStatus) public isPassed; | ||
|
||
/// @notice Constructor to initialize the AdvancedChecker contract. | ||
/// @param _advancedChecker The address of the AdvancedChecker contract. | ||
constructor(AdvancedChecker _advancedChecker) { | ||
ADVANCED_CHECKER = _advancedChecker; | ||
} | ||
|
||
/// @notice Passes the gate check for a given address. | ||
/// @dev Calls the internal `_pass` function to enforce the gate logic. | ||
/// @param passerby The address attempting to pass the gate. | ||
/// @param data Additional data required for the check. | ||
/// @param checkType The type of check being performed (PRE, MAIN, POST). | ||
function pass(address passerby, bytes calldata data, Check checkType) external override onlyGate { | ||
_pass(passerby, data, checkType); | ||
} | ||
|
||
/// @notice Internal function to enforce the gate passing logic. | ||
/// @param passerby The address attempting to pass the gate. | ||
/// @param data Additional data required for the check. | ||
/// @param checkType The type of check being performed (PRE, MAIN, POST). | ||
function _pass(address passerby, bytes calldata data, Check checkType) internal { | ||
ADVANCED_CHECKER.check(passerby, data, checkType); | ||
|
||
if (checkType == Check.PRE) { | ||
if (ADVANCED_CHECKER.skipPre()) revert PreCheckSkipped(); | ||
else if (isPassed[passerby].pre) revert AlreadyPassed(); | ||
else isPassed[passerby].pre = true; | ||
} else if (checkType == Check.POST) { | ||
if (ADVANCED_CHECKER.skipPost()) revert PostCheckSkipped(); | ||
else if (isPassed[passerby].post) revert AlreadyPassed(); | ||
else isPassed[passerby].post = true; | ||
} else if (checkType == Check.MAIN) { | ||
if (!ADVANCED_CHECKER.allowMultipleMain() && isPassed[passerby].main > 0) revert MainCheckAlreadyEnforced(); | ||
else isPassed[passerby].main += 1; | ||
} | ||
|
||
emit GatePassed(passerby, gate, data, checkType); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
packages/contracts/contracts/src/core/gatekeeper/BaseExcubia.sol
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,43 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.27; | ||
|
||
import {IBaseExcubia} from "./IBaseExcubia.sol"; | ||
import {Excubia} from "./Excubia.sol"; | ||
import {BaseChecker} from "../checker/BaseChecker.sol"; | ||
|
||
/// @title BaseExcubia | ||
/// @notice Abstract base contract which can be extended to implement a specific `BaseExcubia`. | ||
abstract contract BaseExcubia is Excubia, IBaseExcubia { | ||
/// @dev Reference to the BaseChecker contract for validation. | ||
BaseChecker public immutable BASE_CHECKER; | ||
|
||
/// @dev Tracks whether an address has passed the gate check. | ||
mapping(address => bool) public isPassed; | ||
|
||
/// @notice Constructor to initialize the BaseChecker contract. | ||
/// @param _baseChecker The address of the BaseChecker contract. | ||
constructor(BaseChecker _baseChecker) { | ||
BASE_CHECKER = _baseChecker; | ||
} | ||
|
||
/// @notice Passes the gate check for a given address. | ||
/// @dev Calls the internal `_pass` function to enforce the gate logic. | ||
/// @param passerby The address attempting to pass the gate. | ||
/// @param data Additional data required for the check. | ||
function pass(address passerby, bytes calldata data) external override onlyGate { | ||
_pass(passerby, data); | ||
} | ||
|
||
/// @notice Internal function to enforce the gate passing logic. | ||
/// @param passerby The address attempting to pass the gate. | ||
/// @param data Additional data required for the check. | ||
function _pass(address passerby, bytes calldata data) internal { | ||
BASE_CHECKER.check(passerby, data); | ||
|
||
if (isPassed[passerby]) revert AlreadyPassed(); | ||
|
||
isPassed[passerby] = true; | ||
|
||
emit GatePassed(passerby, gate, data); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
packages/contracts/contracts/src/core/gatekeeper/Excubia.sol
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,33 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.27; | ||
|
||
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; | ||
import {IExcubia} from "./IExcubia.sol"; | ||
|
||
/// @title Excubia abstract contract. | ||
/// @dev This contract implements the IExcubia interface and manages the gate address. | ||
abstract contract Excubia is IExcubia, Ownable(msg.sender) { | ||
/// @notice The Excubia-protected contract address. | ||
/// @dev The gate can be any contract address that requires a prior check to enable logic. | ||
/// For example, the gate is a Semaphore group that requires the passerby | ||
/// to meet certain criteria before joining. | ||
address public gate; | ||
|
||
/// @notice Modifier that restricts access to the gate address. | ||
modifier onlyGate() { | ||
if (msg.sender != gate) revert GateOnly(); | ||
_; | ||
} | ||
|
||
/// @notice Sets the gate address. | ||
/// @dev Only the owner can set the destination `gate` address. | ||
/// @param _gate The address of the contract to be set as the gate. | ||
function setGate(address _gate) public virtual onlyOwner { | ||
if (_gate == address(0)) revert ZeroAddress(); | ||
if (gate != address(0)) revert GateAlreadySet(); | ||
|
||
gate = _gate; | ||
|
||
emit GateSet(_gate); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
packages/contracts/contracts/src/core/gatekeeper/IAdvancedExcubia.sol
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,33 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.27; | ||
|
||
import {IExcubia} from "./IExcubia.sol"; | ||
import {Check} from "../checker/IAdvancedChecker.sol"; | ||
|
||
/// @title IAdvancedExcubia | ||
/// @notice AdvancedExcubia contract interface that extends the IExcubia interface. | ||
interface IAdvancedExcubia is IExcubia { | ||
/// @notice Error thrown when the PRE check is skipped. | ||
error PreCheckSkipped(); | ||
|
||
/// @notice Error thrown when the MAIN check cannot be executed more than once. | ||
error MainCheckAlreadyEnforced(); | ||
|
||
/// @notice Error thrown when the POST check is skipped. | ||
error PostCheckSkipped(); | ||
|
||
/// @notice Event emitted when someone passes the `gate` check. | ||
/// @param passerby The address of those who have successfully passed the check. | ||
/// @param gate The address of the excubia-protected contract address. | ||
/// @param data Additional data related to the gate check. | ||
/// @param checkType The type of check that was performed (e.g., PRE, MAIN, POST). | ||
event GatePassed(address indexed passerby, address indexed gate, bytes data, Check checkType); | ||
|
||
/// @notice Enforces the custom gate passing logic. | ||
/// @dev Must call the right `check` method based on the `checkType` to handle the logic of checking | ||
/// passerby for specific gate. | ||
/// @param passerby The address of the entity attempting to pass the gate. | ||
/// @param data Additional data required for the check (e.g., encoded token identifier). | ||
/// @param checkType The type of the check to be enforced for the passerby with the given data. | ||
function pass(address passerby, bytes calldata data, Check checkType) external; | ||
} |
Oops, something went wrong.