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

Core Excubiae smart contract framework #3

Merged
merged 6 commits into from
Oct 4, 2024
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"scripts": {
"build": "yarn build:docs && yarn build:website && yarn build:packages",
"build:packages": "yarn workspaces foreach -Apt --no-private run build",
"build:docs": "yarn workspace excubiae-docs build",
"build:docs": "yarn workspace excubiae-docs build && yarn workspace excubiae-contracts docs:forge",
"build:website": "yarn workspace excubiae-website build",
"compile:contracts": "yarn workspace excubiae-contracts compile",
"test": "yarn test:contracts",
Expand Down
1 change: 1 addition & 0 deletions packages/contracts/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ node_modules
# solidity-coverage files
/coverage
/coverage.json
lcov.info

# Hardhat Ignition
ignition/deployments/chain-*
1 change: 1 addition & 0 deletions packages/contracts/.solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"func-visibility": ["error", { "ignoreConstructors": true }],
"max-line-length": ["error", 120],
"not-rely-on-time": "off",
"func-name-mixedcase": "off",
"reason-string": ["warn", { "maxLength": 80 }]
}
}
29 changes: 0 additions & 29 deletions packages/contracts/contracts/src/Lock.sol

This file was deleted.

69 changes: 69 additions & 0 deletions packages/contracts/contracts/src/core/Excubia.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IExcubia} from "./IExcubia.sol";

/// @title Excubia.
/// @notice Abstract base contract which can be extended to implement a specific `Excubia`.
/// @dev Inherit from this contract and implement the `_pass` & `_check` methods to define
/// your custom gatekeeping logic.
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;

/// @dev Modifier to restrict function calls to only from the `gate` address.
modifier onlyGate() {
if (msg.sender != gate) revert GateOnly();
_;
}

/// @inheritdoc IExcubia
function trait() external pure virtual returns (string memory) {
return _trait();
}

/// @inheritdoc IExcubia
function setGate(address _gate) public virtual onlyOwner {
if (_gate == address(0)) revert ZeroAddress();
if (gate != address(0)) revert GateAlreadySet();

gate = _gate;

emit GateSet(_gate);
}

/// @inheritdoc IExcubia
function pass(address passerby, bytes calldata data) external onlyGate {
_pass(passerby, data);
}

/// @inheritdoc IExcubia
function check(address passerby, bytes calldata data) external view {
_check(passerby, data);
}

/// @notice Internal function to define the trait of the Excubia contract.
/// @dev maintain consistency across `_pass` & `_check` definitions.
/// @return The specific trait of the Excubia contract (e.g., SemaphoreExcubia has trait Semaphore).
function _trait() internal pure virtual returns (string memory) {}

/// @notice Internal function to enforce the custom `gate` passing logic.
/// @dev Calls the `_check` internal logic and emits the relative event if successful.
/// @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).
function _pass(address passerby, bytes calldata data) internal virtual {
_check(passerby, data);

emit GatePassed(passerby, gate);
}

/// @notice Internal function to define the custom `gate` protection logic.
/// @dev Custom logic to determine if the passerby can pass the `gate`.
/// @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) internal view virtual {}
}
50 changes: 50 additions & 0 deletions packages/contracts/contracts/src/core/IExcubia.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;

/// @title IExcubia.
/// @notice Excubia contract interface.
interface IExcubia {
/// @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.
event GatePassed(address indexed passerby, address indexed gate);

/// @notice Event emitted when the `gate` address is set.
/// @param gate The address of the contract set as the `gate`.
event GateSet(address indexed gate);

/// @notice Error thrown when an address equal to zero is given.
error ZeroAddress();

/// @notice Error thrown when the `gate` address is not set.
error GateNotSet();

/// @notice Error thrown when the callee is not the `gate` contract.
error GateOnly();

/// @notice Error thrown when the `gate` address has been already set.
error GateAlreadySet();

/// @notice Error thrown when the passerby has already passed the `gate`.
error AlreadyPassed();

/// @notice Gets the trait of the Excubia contract.
/// @return The specific trait of the Excubia contract (e.g., SemaphoreExcubia has trait Semaphore).
function trait() external pure returns (string memory);

/// @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) external;

/// @notice Enforces the custom `gate` passing logic.
/// @dev Must call the `check` 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).
function pass(address passerby, bytes calldata data) external;

/// @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;
}
44 changes: 44 additions & 0 deletions packages/contracts/contracts/src/extensions/FreeForAllExcubia.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;

import {Excubia} from "../core/Excubia.sol";

/// @title FreeForAll Excubia Contract.
/// @notice This contract extends the `Excubia` contract to allow free access through the `gate`.
/// This contract does not perform any checks and allows any `passerby` to pass the `gate`.
/// @dev The contract overrides the `_check` function to always return true.
contract FreeForAllExcubia is Excubia {
/// @notice Constructor for the FreeForAllExcubia contract.
constructor() {}

/// @notice Mapping to track already passed passersby.
mapping(address => bool) public passedPassersby;

/// @notice The trait of the `Excubia` contract.
function _trait() internal pure override returns (string memory) {
super._trait();

return "FreeForAll";
}

/// @notice Internal function to handle the `gate` passing logic.
/// @dev This function calls the parent `_pass` function and then tracks the `passerby`.
/// @param passerby The address of the entity passing the `gate`.
/// @param data Additional data required for the pass (not used in this implementation).
function _pass(address passerby, bytes calldata data) internal override {
// Avoiding passing the `gate` twice with the same address.
if (passedPassersby[passerby]) revert AlreadyPassed();

passedPassersby[passerby] = true;

super._pass(passerby, data);
}

/// @notice Internal function to handle the `gate` protection logic.
/// @dev This function always returns true, signaling that any `passerby` is able to pass the `gate`.
/// @param passerby The address of the entity attempting to pass the `gate`.
/// @param data Additional data required for the check (e.g., encoded attestation ID).
function _check(address passerby, bytes calldata data) internal view override {
super._check(passerby, data);
}
}
Loading