-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from privacy-scaling-explorations/proposal/gate…
…keepers Initial proposal for `excubiae` framework
- Loading branch information
Showing
19 changed files
with
772 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
COINMARKETCAP_API_KEY= | ||
REPORT_GAS=false |
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,6 @@ | ||
{ | ||
"semi": false, | ||
"arrowParens": "always", | ||
"trailingComma": "none", | ||
"plugins": ["prettier-plugin-solidity"] | ||
} |
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,4 @@ | ||
module.exports = { | ||
istanbulFolder: "../../coverage/excubiae", | ||
skipFiles: ["test"] | ||
} |
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,20 @@ | ||
{ | ||
"extends": "solhint:recommended", | ||
"plugins": ["prettier"], | ||
"rules": { | ||
"compiler-version": ["error", ">=0.8.0"], | ||
"const-name-snakecase": "off", | ||
"no-empty-blocks": "off", | ||
"constructor-syntax": "error", | ||
"func-visibility": ["error", { "ignoreConstructors": true }], | ||
"max-line-length": ["error", 120], | ||
"not-rely-on-time": "off", | ||
"prettier/prettier": [ | ||
"error", | ||
{ | ||
"endOfLine": "auto" | ||
} | ||
], | ||
"reason-string": ["warn", { "maxLength": 80 }] | ||
} | ||
} |
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,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2024 Ethereum Foundation | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
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 @@ | ||
contracts/README.md |
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,44 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.0 <0.9.0; | ||
|
||
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 `_check` method to define | ||
/// the 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`. | ||
/// 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 setGate(address _gate) public virtual onlyOwner { | ||
if (_gate == address(0)) revert ZeroAddress(); | ||
if (gate != address(0)) revert GateAlreadySet(); | ||
|
||
gate = _gate; | ||
} | ||
|
||
/// @inheritdoc IExcubia | ||
function pass(address passerby, bytes calldata data) public virtual onlyGate { | ||
if (!_check(passerby, data)) revert AccessDenied(); | ||
|
||
emit GatePassed(passerby, gate); | ||
} | ||
|
||
/// @dev Abstract internal function to be implemented with custom logic to check 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. | ||
/// @return True if the passerby passes the check, false otherwise. | ||
function _check(address passerby, bytes calldata data) internal virtual returns (bool); | ||
} |
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,37 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.0 <0.9.0; | ||
|
||
/// @title IExcubia. | ||
/// @notice Excubia contract interface. | ||
interface IExcubia { | ||
/// @notice Event emitted when someone passes the `_check` method. | ||
/// @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 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 access is denied by the excubia. | ||
error AccessDenied(); | ||
|
||
/// @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 Initiates the excubia's check and triggers the associated action if the check is passed. | ||
/// @dev Calls `_check` to handle the logic of checking for passing 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 token identifier). | ||
function pass(address passerby, bytes calldata data) external; | ||
} |
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,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2024 Ethereum Foundation | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
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,80 @@ | ||
<p align="center"> | ||
<h1 align="center"> | ||
Excubiae | ||
</h1> | ||
<p align="center">A flexible and modular framework for general-purpose on-chain gatekeepers.</p> | ||
</p> | ||
|
||
<p align="center"> | ||
<a href="https://github.com/privacy-scaling-explorations/excubiae"> | ||
<img src="https://img.shields.io/badge/project-excubiae-blue.svg?style=flat-square"> | ||
</a> | ||
<a href="https://github.com/privacy-scaling-explorations/excubiae/blob/main/LICENSE"> | ||
<img alt="NPM license" src="https://img.shields.io/npm/l/excubiae?style=flat-square"> | ||
</a> | ||
<a href="https://www.npmjs.com/package/excubiae"> | ||
<img alt="NPM version" src="https://img.shields.io/npm/v/excubiae?style=flat-square" /> | ||
</a> | ||
<a href="https://npmjs.org/package/excubiae"> | ||
<img alt="Downloads" src="https://img.shields.io/npm/dm/excubiae.svg?style=flat-square" /> | ||
</a> | ||
<a href="https://prettier.io/"> | ||
<img alt="Code style prettier" src="https://img.shields.io/badge/code%20style-prettier-f8bc45?style=flat-square&logo=prettier" /> | ||
</a> | ||
</p> | ||
|
||
<div align="center"> | ||
<h4> | ||
<a href="https://appliedzkp.org/discord"> | ||
🗣️ Chat & Support | ||
</a> | ||
</h4> | ||
</div> | ||
|
||
> [!NOTE] | ||
> This library is experimental and untested yet - use at your own discretion... | ||
Excubiae is a generalized framework for on-chain gatekeepers that allows developers to define custom access control mechanisms using different on-chain credentials. By abstracting the gatekeeper logic, excubiae provides a reusable and composable solution for securing decentralised applications. This package provides a pre-defined set of specific excubia (_extensions_) for credentials based on different protocols. | ||
|
||
## 🛠 Install | ||
|
||
### npm or yarn | ||
|
||
Install the ` @zk-kit/excubiae` package with npm: | ||
|
||
```bash | ||
npm i @zk-kit/excubiae --save | ||
``` | ||
|
||
or yarn: | ||
|
||
```bash | ||
yarn add @zk-kit/excubiae | ||
``` | ||
|
||
## 📜 Usage | ||
|
||
To build your own Excubia: | ||
|
||
1. Inherit from the [Excubia](./Excubia.sol) abstract contract that conforms to the [IExcubia](./IExcubia.sol) interface. | ||
2. Implement the `_check()` method to define your own gatekeeping logic and to prevent unwanted access (sybils, double checks). | ||
|
||
```solidity | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.0 <0.9.0; | ||
import { Excubia } from "excubiae/contracts/Excubia.sol"; | ||
contract MyExcubia is Excubia { | ||
// ... | ||
function _check(address passerby, bytes calldata data) internal override returns (bool) { | ||
// Implement custom access control logic here. | ||
// Implement your logic to prevent unwanted access here. | ||
return true; | ||
} | ||
} | ||
``` | ||
|
||
Please see the [extensions](./extensions/) folder for more complex reference implementations and the [test contracts](./test) folder for guidance on using the libraries. |
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.0 <0.9.0; | ||
|
||
import {Excubia} from "../Excubia.sol"; | ||
import {IEAS} from "@ethereum-attestation-service/eas-contracts/contracts/IEAS.sol"; | ||
import {Attestation} from "@ethereum-attestation-service/eas-contracts/contracts/Common.sol"; | ||
|
||
/// @title EAS Excubia Contract. | ||
/// @notice This contract extends the Excubia contract to integrate with the Ethereum Attestation Service (EAS). | ||
/// This contract checks an EAS attestation to permit access through the gate. | ||
/// @dev The contract uses a specific attestation schema & attester to admit the recipient of the attestation. | ||
contract EASExcubia is Excubia { | ||
/// @notice The Ethereum Attestation Service contract interface. | ||
IEAS public immutable EAS; | ||
/// @notice The specific schema ID that attestations must match to pass the gate. | ||
bytes32 public immutable SCHEMA; | ||
/// @notice The trusted attester address whose attestations are considered | ||
/// the only ones valid to pass the gate. | ||
address public immutable ATTESTER; | ||
|
||
/// @notice Mapping to track which attestations have been registered by the contract to | ||
/// avoid double checks with the same attestation. | ||
mapping(bytes32 => bool) public registeredAttestations; | ||
|
||
/// @notice Error thrown when the attestation has been already used to pass the gate. | ||
error AlreadyRegistered(); | ||
|
||
/// @notice Error thrown when the attestation does not match the designed schema. | ||
error UnexpectedSchema(); | ||
|
||
/// @notice Error thrown when the attestation does not match the designed trusted attester. | ||
error UnexpectedAttester(); | ||
|
||
/// @notice Error thrown when the attestation does not match the passerby as recipient. | ||
error UnexpectedRecipient(); | ||
|
||
/// @notice Error thrown when the attestation has been revoked. | ||
error RevokedAttestation(); | ||
|
||
/// @notice Constructor to initialize with target EAS contract with specific attester and schema. | ||
/// @param _eas The address of the EAS contract. | ||
/// @param _attester The address of the trusted attester. | ||
/// @param _schema The schema ID that attestations must match. | ||
constructor(address _eas, address _attester, bytes32 _schema) { | ||
if (_eas == address(0) || _attester == address(0)) revert ZeroAddress(); | ||
|
||
EAS = IEAS(_eas); | ||
ATTESTER = _attester; | ||
SCHEMA = _schema; | ||
} | ||
|
||
/// @notice Overrides the `_check` function to validate against specific criteria. | ||
/// @param passerby The address of the entity attempting to pass the gate. | ||
/// @param data Encoded attestation ID. | ||
/// @return True if the attestation meets all criteria, revert otherwise. | ||
function _check(address passerby, bytes calldata data) internal override returns (bool) { | ||
bytes32 attestationId = abi.decode(data, (bytes32)); | ||
|
||
// Avoiding double check of the same attestation. | ||
if (registeredAttestations[attestationId]) revert AlreadyRegistered(); | ||
|
||
registeredAttestations[attestationId] = true; | ||
|
||
Attestation memory attestation = EAS.getAttestation(attestationId); | ||
|
||
if (attestation.schema != SCHEMA) revert UnexpectedSchema(); | ||
if (attestation.attester != ATTESTER) revert UnexpectedAttester(); | ||
if (attestation.recipient != passerby) revert UnexpectedRecipient(); | ||
if (attestation.revocationTime != 0) revert RevokedAttestation(); | ||
|
||
return true; | ||
} | ||
} |
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,31 @@ | ||
{ | ||
"name": "@zk-kit/excubiae", | ||
"version": "0.0.1", | ||
"description": "A general purpose on-chain gatekeeping smart contract framework.", | ||
"license": "MIT", | ||
"files": [ | ||
"*.sol", | ||
"!test/*", | ||
"README.md", | ||
"LICENSE" | ||
], | ||
"keywords": [ | ||
"blockchain", | ||
"ethereum", | ||
"hardhat", | ||
"smart-contracts", | ||
"solidity", | ||
"libraries", | ||
"gatekeepers", | ||
"credentials" | ||
], | ||
"repository": "git@github.com:privacy-scaling-explorations/zk-kit.solidity.git", | ||
"homepage": "https://github.com/privacy-scaling-explorations/zk-kit.solidity/tree/main/packages/gatekeepers", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"dependencies": { | ||
"@ethereum-attestation-service/eas-contracts": "^1.7.1", | ||
"@openzeppelin/contracts": "^5.0.2" | ||
} | ||
} |
Oops, something went wrong.