# Semaphore

<figure><img src="https://2715533927-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FiCNdy1jDW7p2hoMSUff8%2Fuploads%2FxIcj7uREq0OVVRaDvFnu%2FDocs%20Assets%20-%2022%20-%20Semaphore.jpg?alt=media&#x26;token=9f2de4d6-4f5f-48bd-8f69-1c28f94a867d" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Source code: <https://github.com/firm-org/firm-protocol/blob/beautify-readme/src/semaphore/Semaphore.sol>
{% endhint %}

## Overview

Semaphore is an opt-in component of Firm protocol which can be used to limit which actions certain modules can perform within an instantiation of the system.

It was originally designed to balance power between what owners of the Safe can do via multisig transactions (board actions) and which actions only Voting can perform.

It is called Semaphore because its intended way of being used is by balancing permissions of specific action pairs, blocking access to one while allowing access to the other.

It is attached to a Safe by setting it as its guard. This will cause the Safe to check with Semaphore before performing any multisig transaction executed by its owners. Firm module transactions (i.e. those coming from Budget or Voting) bypass this check and must explicitly perform their own Semaphore checks (Voting does if it has a Semaphore attached).

## Lifecycle

### Setting semaphore state

Only the Safe can set the global semaphore state for callers using `Semaphore:setSemaphoreState(address caller, DefaultMode defaultMode, bool allowDelegateCalls, bool allowValueCalls)`

Each caller (i.e. Safe or module performing calls) has a global configuration or semaphore state. It’s comprised of three variables:

* **Default mode:** dictates which is the default authorization state for the caller for all calls which do not have an explicit exception.
* **Allow delegatecall:** some callers, like Safe, may have the ability to perform delegatecalls (which by their nature makes it really hard to know exactly what their sideeffects will be unless the target is known or trusted). This boolean setting acts as a blanket switch for delegatecalls (exceptions do not apply here.)
* **Allow value calls:** some callers may perform calls whose value is greater than zero which will cause the Safe to transfer some amount of the native asset (i.e. ETH on Ethereum). This boolean setting acts as a blanket switch for delegatecalls (exceptions do not apply here.)

### Setting exceptions

Only the Safe can add exceptions to the default mode of operation using `Semaphore:addExceptions(ExceptionInput[] exceptions)`

Exception types:

* **Signature exceptions:** applies exception to all calls with that selector for all targets
* **Target exceptions:** applies exception to all calls to a specific target
* **Signature and target exceptions:** applies exceptions only to the specific signature target pair.

### Checking access control

Semaphore exposes two functions to check whether it allows a certain caller to perform a call to a target.

`Semaphore:canPerform(address *caller*, address *target*, uint256 *value*, bytes calldata *data*, bool *isDelegateCall*)` is used to perform a single check and `Semaphore:canPerformMany(address *caller*, address[] calldata *targets*, uint256[] calldata *values*, bytes[] calldata *calldatas*, bool *isDelegateCall*)` is the optimized version to check several calls for a single caller.

The base contract [SemaphoreAuth](https://github.com/firm-org/firm-protocol/blob/master/src/bases/SemaphoreAuth.sol) is provided for modules that want to perform checks against Semaphore before performing a call.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.firm.org/firm-protocol-v1/main-components/semaphore.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
