# Consensus

#### Purpose

The `Consensus` contract manages a permissioned set of signers and enforces **multi-signature validation logic** using either EIP-712 or EIP-1271 signatures. It is a lightweight module designed for verifying **offchain consensus** before executing critical actions such as deposit and redemptions via SignatureQueues.

It supports:

* Threshold-based consensus
* Two signature modes: EIP712 (EOA) and EIP1271 (contract-based)
* Dynamic signer set management
* Stateless, reusable verification interface

#### Core Concepts

#### Threshold-Based Verification

To validate an action, a set of authorized signers must collectively submit signatures. The number of valid signatures must be **greater than or equal to** the configured `threshold`.

#### Signature Types

Each signer is associated with a `SignatureType`:

* `EIP712` – Used for externally owned accounts (standard `ECDSA.recover`)
* `EIP1271` – Used for contract accounts (via `isValidSignature()`)

#### Storage Layout

```solidity
struct ConsensusStorage {
    uint256 threshold;
    EnumerableMap.AddressToUintMap signers;
}
```

* `threshold`: Minimum number of valid signatures required for verification to succeed.
* `signers`: Mapping of signer addresses → their configured signature type.

#### Initialization

```solidity
function initialize(bytes calldata data)
```

* Expects `abi.encode(owner)` as input.
* Sets the initial owner using `OwnableUpgradeable`.

#### Signature Verification

#### checkSignatures

```solidity
function checkSignatures(bytes32 orderHash, Signature[] calldata signatures) public view returns (bool)
```

* Returns `true` if:
  * At least `threshold` signatures are present
  * Each signature is:
    * From an authorized signer
    * Valid according to the signer’s configured signature type
* Returns `false` otherwise

Signature validation behavior:

* `EIP712`: Uses `ECDSA.recover(orderHash, sig)` and matches signer
* `EIP1271`: Calls `isValidSignature(orderHash, sig)` on the contract

#### requireValidSignatures

```solidity
function requireValidSignatures(bytes32 orderHash, Signature[] calldata signatures) external view
```

* Same logic as `checkSignatures`, but reverts with `InvalidSignatures` error if validation fails

#### Signer Management (Owner-only)

#### setThreshold

```solidity
function setThreshold(uint256 threshold_) external onlyOwner
```

* Sets a new threshold
* Must be `> 0` and `≤ signers.length()`
* Emits `ThresholdSet`

#### addSigner

```solidity
function addSigner(address signer, uint256 threshold_, SignatureType sigType) external onlyOwner
```

* Adds a new signer with specified signature type
* Updates threshold (as part of signer addition)
* Reverts if:
  * `signer == address(0)`
  * Signer already exists
* Emits `SignerAdded` and `ThresholdSet`

#### removeSigner

```solidity
function removeSigner(address signer, uint256 threshold_) external onlyOwner
```

* Removes signer from consensus set
* Updates threshold
* Reverts if signer not found
* Emits `SignerRemoved` and `ThresholdSet`

#### View Functions

| Function            | Returns                                   |
| ------------------- | ----------------------------------------- |
| `threshold()`       | Current consensus threshold               |
| `signers()`         | Total number of signers                   |
| `signerAt(uint256)` | Signer address and type at index          |
| `isSigner(address)` | Boolean indicating if address is a signer |

#### Events

* `Initialized(bytes)`
* `ThresholdSet(uint256)`
* `SignerAdded(address signer, SignatureType)`
* `SignerRemoved(address signer)`
* `InvalidSignatures(bytes32 hash, Signature[] signatures)` (used in revert)

#### Security Considerations

* Only the owner (via `OwnableUpgradeable`) may update signer set or threshold
* Signatures are stateless and externally verifiable
* Replay protection (e.g., nonce checks) must be handled by upstream systems (nonces)
* Signers using `EIP1271` are trusted for contract logic – contracts must not be mutable without governance


---

# 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.mellow.finance/core-vaults/architecture/permissions/consensus.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.
