Skip to content

Commit 2da8355

Browse files
authored
Merge pull request #32 from privacy-scaling-explorations/docs
Moving documentation to repository
2 parents 7096794 + 58ba26b commit 2da8355

File tree

6 files changed

+556
-3
lines changed

6 files changed

+556
-3
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ It provides a set of abstract and flexible smart contracts, known as "gatekeeper
66

77
This approach enables seamless interoperability across different protocols. For instance, a single check could combine verifiable attributes from Semaphore and MACI, ensuring flexible and composable access control. Indeed, for example, you can define criteria to verify token ownership and/or validate a zero-knowledge proof (ZKP). Using these criteria, you can create a policy to enforce the checks and integrate it seamlessly into your smart contract logic. A practical use case might involve requiring verification before registering a new voter for a poll (e.g., in a MACI-based voting system).
88

9-
You can learn more in this [technical reference document](https://hackmd.io/@0xjei/B1RXoTh71e).
9+
You can learn more in the [documentation](https://github.com/privacy-scaling-explorations/excubiae/tree/main/documentation) folder.
1010

1111
> [!IMPORTANT]
1212
> Excubiae is currently in the MVP stage. Audits are not yet available. Expect fast development cycles with potential breaking changes — use at your own risk! Please, refer to [release](https://github.com/privacy-scaling-explorations/excubiae/releases) section for latest changes and updates.

documentation/01_introduction.md

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Introduction
2+
3+
## What is Excubiae?
4+
5+
Excubiae is a composable framework for implementing custom, attribute-based access control policies on EVM-compatible networks. At its core, it separates the concerns of **policy** definition (_what rules to enforce_) from policy **checking** (_how to validate those rules_), enabling flexible and reusable access control patterns.
6+
7+
The framework's mission is to enable policy enforcement through three key components: **Policies** that define access rules, **Checkers** that validate evidence, and _enforcement_ mechanisms that manage the validation flow. Built on values of modularity, reusability, and security, Excubiae provides protocol developers with building blocks to create robust access control systems.
8+
9+
The name "[Excubiae](https://www.nihilscio.it/Manuali/Lingua%20latina/Verbi/Coniugazione_latino.aspx?verbo=excubia&lang=IT_#:~:text=1&text=excubia%20%3D%20sentinella...%20guardia,%2C%20excubia%20%2D%20Sostantivo%201%20decl.)" comes from the ancient Roman guards who kept watch and enforced access control - an apt metaphor for a system designed to protect smart contract access through configurable policies.
10+
11+
## Vision
12+
13+
In the evolving blockchain ecosystem, protocols continuously generate new forms of verifiable evidence and proofs. While these protocols excel at producing such evidence, integrating them into access control systems outside their standard ways of doing it (e.g., APIs / apps / libs / modules) remains challenging. Excubiae aims to bridge this gap by providing a universal framework for composing and enforcing access policies based and making interoperable forms of on-chain evidence, serving as a foundational layer for access control across the ecosystem.
14+
15+
## Understanding Excubiae
16+
17+
The framework serves multiple audiences: protocol developers integrating access control into their systems, as smart contract engineers implementing custom validation logic for access control on-chain.
18+
19+
The architecture consists of two main types of contracts working in concert:
20+
21+
```
22+
┌──────────────┐ enforces ┌──────────────┐
23+
│ Policy │ ───────────────> │ Checker │
24+
└──────────────┘ └──────────────┘
25+
│ │
26+
│ protects │ checks
27+
│ │
28+
▼ ▼
29+
┌──────────────┐ ┌──────────────┐
30+
│ Target │ │ Subject │
31+
└──────────────┘ └──────────────┘
32+
```
33+
34+
When a **subject** (i.e., EOA or smart contract address) attempts to access a protected **target** (i.e., smart contract protected method / resource), the enforcement flow follows a clear path:
35+
36+
1. Subject provides evidence to a policy.
37+
2. Policy delegates validation to its checker.
38+
3. Checker verifies the evidence.
39+
4. Policy enforces the checker's decision & keeps track of the subject.
40+
41+
## Core Design Philosophy
42+
43+
Excubiae embraces modularity through a clear separation between policy and checking logic. Each component maintains a single responsibility, enabling independent auditing and evolution. The framework emphasizes reusability—checkers and policies can be shared and composed across different contexts, allowing developers to build complex access control systems from verified building blocks.
44+
45+
This architectural approach not only reduces development time but also strengthens security by enabling thorough component validation, gas optimization, and extension (e.g., `BaseChecker`, `AdvancedPolicy`, and more). Protocols benefit from standardized interfaces that ensure interoperability, while users experience consistent access control with clear validation requirements across different systems.
46+
47+
### Minimal Proxy Pattern
48+
49+
Under the hood, Excubiae leverages the [minimal proxy pattern with immutable args](https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)minimal proxy pattern with immutable args for `Policy` and `Checker` contracts. This design improves efficiency, reducing gas costs for contract deployment while ensuring immutability for critical parameters.
50+
51+
A **Factory** contract is responsible for deploying these minimal proxy clones. Instead of deploying new instances of `Policy` and `Checker` from scratch, the factory replicates an existing implementation while enforcing correct initialization.
52+
53+
This results in a modular architecture where:
54+
55+
- A `PolicyFactory` contract ensures customizable & cheap policy instance deploy (i.e., Policy contract instance with potentially different and specific sets of parameter values).
56+
- A `CheckerFactory` contract ensures customizable & cheap checker instance deploy (i.e., Checker contract instance with potentially different and specific sets of parameter values).
57+
- `Policy` and `Checker` clones are initialized post-deployment only once, preventing unauthorized usage before setup. At initialization time, the args can be read from deployment bytecode and accessed / stored for further usage.
58+
59+
### Multi-Stage Validation
60+
61+
Excubiae introduces a multi-stage validation system through `AdvancedChecker`, supporting `PRE`, `MAIN`, and `POST` validation phases. This allows protocols to enforce progressively complex access control mechanisms, combining multiple validation steps into a single enforcement flow.
62+
63+
For instance, a protocol might require:
64+
65+
- **Pre-validation**: Ensuring the subject holds a specific token.
66+
- **Main validation**: Checking additional factors such as governance approval or multi-signature confirmation.
67+
- **Post-validation**: Logging the access event and updating permission states.
68+
69+
By combining minimal proxy pattern, reusability of already deployed Policy & Checker contracts, multi-phase validation, and more; Excubiae provides an efficient and flexible access control solution for smart contracts, ensuring seamless interoperability while maintaining robust security guarantees.
70+
71+
## Roadmap
72+
73+
Excubiae began as a prototype within [zk-kit.solidity](https://www.npmjs.com/package/@zk-kit/excubiae), quickly evolving into a standalone framework with its dedicated [monorepo](https://github.com/privacy-scaling-explorations/excubiae). The current [v0.3.2](https://github.com/privacy-scaling-explorations/excubiae/releases/tag/v0.3.2) release provides a robust foundation with a flexible policy framework supporting both basic and advanced verification mechanisms, the minimal proxy pattern with immutable args, the possibility to reuse already deployed instances of Checker & Policy contracts, and a set of extensions ready to use for your specific needs. The framework includes comprehensive test coverage across [Hardhat and Foundry](https://hardhat.org/hardhat-runner/docs/advanced/hardhat-and-foundry) environments, making it ready for initial adoption & integration experiments. Please, note that **we have not conducted any audit yet**.
74+
75+
The framework is structured in three distinct yet interconnected areas. At its core lies the smart contract framework (purple big blockk), focusing on composability, reuse, and cost-efficient deployments—this has been completed with [v0.2.0](https://github.com/privacy-scaling-explorations/excubiae/releases/tag/v0.2.0). Complementing this are integration-focused tools, including templates and registries, while user-facing applications provide contract management and exploration capabilities. This architecture allows for natural expansion while maintaining a clear separation of concerns, as represented in the diagram below. The green blocks indicate completed milestones in the latest [release](https://github.com/privacy-scaling-explorations/excubiae/releases).
76+
77+
:warning: Please note that the orange and blue big blocks are currently on hold. We consider Excubiae’s core features for adoption complete as of v0.3.2. However, we are still working on extensions set & tasks for deployments (yellow small blocks).
78+
79+
![image](https://hackmd.io/_uploads/HkWq5cDFyx.png)
80+
81+
With v0.3.2, Excubiae has reached a fully-fledged MVP. Moving forward, the focus will be on adoption and integration, aiming to extend the set of extensions, along with deployment scripts, guides, and examples. The orange and blue blocks are not an immediate priority but may be revisited based on adoption and team or organization-wide plans (see warning above).
82+
83+
Excubiae’s long-term vision is to become a standard component in protocol authentication stacks, enabling sophisticated access control through composable building blocks. The framework’s flexibility ensures it can adapt to emerging verification methods and protocols, fostering an ecosystem of reusable, audited checkers that address evolving access control requirements.
84+
85+
The success of this vision depends on close collaboration with early adopters and the careful expansion of the framework’s capabilities. If you are interested in contributing, integrating, or building your own Policy or Checker, or if you have feedback or comments, please reach out on the [PSE Discord](https://discord.com/invite/sF5CT5rzrR) (`🚪-excubiae` channel) or open a new [issue](https://github.com/privacy-scaling-explorations/excubiae/issues/new) / [PR](https://github.com/privacy-scaling-explorations/excubiae/compare) on the [monorepo](https://github.com/privacy-scaling-explorations/excubiae).

documentation/02_usecases.md

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Use Cases
2+
3+
## Basic Access Control for Voting
4+
5+
Access control in voting systems presents a common challenge in smart contract development. For example, when implementing restrictions to check voters identity, developers often face the decision of where to place validation logic. Traditional approaches tend to embed these checks directly within voting contracts, leading to tightly coupled systems that prove difficult to maintain or adapt.
6+
7+
Excubiae addresses this challenge through its fundamental principle of separation between voting logic and access control. The framework enables a clean architecture where voting contracts remain focused on their core purpose while delegating all validation to specialized components.
8+
9+
Consider this implementation using Excubiae's base components to check voters identity through the possession of an NFT (see [BaseVoting](https://github.com/privacy-scaling-explorations/excubiae/blob/main/packages/contracts/contracts/test/examples/base/BaseVoting.sol) example).
10+
11+
```solidity
12+
contract BaseVoting {
13+
BasePolicy public immutable POLICY;
14+
mapping(address => bool) public hasVoted;
15+
mapping(uint8 => uint256) public voteCounts;
16+
17+
constructor(BaseERC721Policy _policy) {
18+
POLICY = _policy;
19+
}
20+
21+
function register(uint256 tokenId) external {
22+
bytes[] memory _evidence = new bytes[](1);
23+
_evidence[0] = abi.encode(tokenId);
24+
25+
POLICY.enforce(msg.sender, _evidence);
26+
27+
emit Registered(msg.sender);
28+
}
29+
30+
function vote(uint8 option) external {
31+
if (!POLICY.enforced(msg.sender)) revert NotRegistered();
32+
if (hasVoted[msg.sender]) revert AlreadyVoted();
33+
if (option >= 2) revert InvalidOption();
34+
35+
hasVoted[msg.sender] = true;
36+
voteCounts[option]++;
37+
38+
emit Voted(msg.sender, option);
39+
}
40+
}
41+
```
42+
43+
The validation logic resides in its own set of specialized contracts (see [BaseERC721Policy](https://github.com/privacy-scaling-explorations/excubiae/blob/main/packages/contracts/contracts/test/examples/base/BaseERC721Policy.sol) and [BaseERC721Checker](https://github.com/privacy-scaling-explorations/excubiae/blob/main/packages/contracts/contracts/test/examples/base/BaseERC721Checker.sol) examples) along with the respective Factory contracts (see [BaseERC721PolicyFactory](https://github.com/privacy-scaling-explorations/excubiae/blob/main/packages/contracts/contracts/test/examples/base/BaseERC721PolicyFactory.sol) and [BaseERC721CheckerFactory](https://github.com/privacy-scaling-explorations/excubiae/blob/main/packages/contracts/contracts/test/examples/base/BaseERC721CheckerFactory.sol) examples)
44+
45+
This architecture demonstrates the core strengths of Excubiae's design. The voting contract maintains singular responsibility for vote management, while the policy and checker contracts handle all aspects of access control. This separation enables easy modification of validation rules without affecting the voting logic itself. Indeed, through minimal proxy pattern, anyone is able to deploy, for example, a new Checker with a different NFT address as reference for the checks and a new Policy referencing to another Checker.
46+
47+
You can explore complete implementations, including comprehensive test cases ([Solidity](https://github.com/privacy-scaling-explorations/excubiae/blob/main/packages/contracts/contracts/test/examples/Base.t.sol) & [Typescript](https://github.com/privacy-scaling-explorations/excubiae/blob/main/packages/contracts/test/Base.test.ts)) on the monorepo. These examples provide practical insights into integration patterns and usage scenarios.
48+
49+
The framework's capabilities extend beyond this basic implementation. For scenarios requiring multi-step validation or combined verification rules, Excubiae provides advanced components that we'll explore next.
50+
51+
## Advanced Multi-Phase Voting System
52+
53+
Building upon our [basic voting example](#basic-access-control-for-voting), Excubiae's advanced components enable more sophisticated access control patterns. Consider a voting system that requires registration, allows multiple votes, and includes a reward mechanism - each phase with its own validation requirements.
54+
55+
The advanced system leverages Excubiae's multi-phase validation through the [AdvancedChecker](https://github.com/privacy-scaling-explorations/excubiae/blob/main/packages/contracts/contracts/test/examples/advanced/AdvancedERC721Checker.sol) and [AdvancedPolicy](https://github.com/privacy-scaling-explorations/excubiae/blob/main/packages/contracts/contracts/test/examples/advanced/AdvancedERC721Policy.sol) contracts and their respective factories. This enables pre-conditions for registration, ongoing validation during voting, and post-conditions for reward distribution (see [AdvancedVoting](https://github.com/privacy-scaling-explorations/excubiae/blob/main/packages/contracts/contracts/test/examples/advanced/AdvancedVoting.sol) example).
56+
57+
```solidity
58+
contract AdvancedVoting {
59+
AdvancedPolicy public immutable POLICY;
60+
mapping(uint8 => uint256) public voteCounts;
61+
62+
function register(uint256 tokenId) external {
63+
bytes[] memory _evidence = new bytes[](1);
64+
_evidence[0] = abi.encode(tokenId);
65+
66+
POLICY.enforce(msg.sender, evidence, Check.PRE);
67+
68+
emit Registered(msg.sender);
69+
}
70+
71+
function vote(uint8 option) external {
72+
(bool pre, , ) = POLICY.enforced(address(this), msg.sender);
73+
74+
if (!pre) revert NotRegistered();
75+
if (option >= 2) revert InvalidOption();
76+
77+
bytes[] memory _evidence = new bytes[](1);
78+
_evidence[0] = abi.encode(option);
79+
80+
POLICY.enforce(msg.sender, evidence, Check.MAIN);
81+
82+
voteCounts[option]++;
83+
84+
emit Voted(msg.sender, option);
85+
}
86+
87+
function reward(uint256 rewardId) external {
88+
(bool pre, uint8 main, bool post) = POLICY.enforced(address(this), msg.sender);
89+
90+
if (!pre) revert NotRegistered();
91+
if (main == 0) revert NotVoted();
92+
if (post) revert AlreadyClaimed();
93+
94+
POLICY.enforce(msg.sender, new bytes[](1), Check.POST);
95+
96+
emit RewardClaimed(msg.sender, rewardId);
97+
}
98+
}
99+
```
100+
101+
The system introduces distinct validation phases through the [Check](https://github.com/privacy-scaling-explorations/excubiae/blob/07bf4d60353f5b044cfead856d872177f9e48aff/packages/contracts/contracts/src/interfaces/IAdvancedChecker.sol#L8) enumeration:
102+
103+
- PRE: Validates initial registration requirements
104+
- MAIN: Enables repeated voting with ongoing validation
105+
- POST: Controls one-time reward claiming
106+
107+
This advanced implementation maintains Excubiae's core principle of separation of concerns while enabling complex state management and multi-phase validation. The complete implementation, including the corresponding checker contracts and test cases, can be found [here](https://github.com/privacy-scaling-explorations/excubiae/tree/main/packages/contracts/contracts/test/examples/advanced).
108+
109+
The pattern demonstrated here extends beyond voting systems. Any protocol requiring staged access control, multiple validation steps, or state-dependent permissions can leverage this same architecture. For instance, similar patterns could manage staged token unlocks, tiered protocol access, or multi-signature operations.

0 commit comments

Comments
 (0)