# Protocol Module

## Overview

The `satay::protocol` module manages the protocol-level configuration, governance, and fee structure in the Satay ecosystem. It provides functionality for setting and managing the protocol's governance, protocol fees, and protocol fee recipients.

## Structs

### Protocol

The `Protocol` struct represents the protocol-level configuration. It stores governance-related information, including the current governance address, pending governance, the router, pending router and the configuration of the fee and protocol features.

```rust
struct Protocol has key {
    governance: address,
    pending_governance: Option<address>,
    router: Option<address>,
    pending_router: Option<address>,
    fee_config: FeeConfig,
    feature_config: FeatureConfig
}
```

### ProtocolController

The `ProtocolController` struct provides the control and signing capabilities for the protocol, storing the `ExtendRef` used for extending the protocol's object.

```rust
struct ProtocolController has key {
    extend_ref: ExtendRef
}
```

### FeeConfig

The `FeeConfig` struct stores information about the protocol fee, protocol fee recipient and the protocol's performance and management fees.

```rust
struct FeeConfig has store, drop {
    protocol_fee: u64,
    protocol_fee_recipient: address,
    performance_fee: u64,
    management_fee: u64
}
```

### FeatureConfig

The `FeatureConfig` struct stores information about the configuration of the protocol, which currently has a single boolean to enable/disable auto harvest.

```rust
struct FeatureConfig has store, drop {
    auto_harvest: bool
}
```

### RouterRef

The `RouterRef` struct stores the address of the router module.

```rust
struct RouterRef has store, drop {
    router: address
}
```

## Events

### **GovernanceChanged**

Emitted when the governance of the protocol is changed.

```rust
#[event]
struct GovernanceChanged has store, drop {
    governance: address
}
```

## Constants

* **PROTOCOL\_SEED**: `vector<u8> = b"00000000Protocol"` – Seed used to create the protocol object.

The other constants are declared in the module `satay::constants`.

* **MAX\_PROTOCOL\_FEE**: `u64 = 500` – Maximum protocol fee allowed (in BPS).
* **MAX\_MANAGEMENT\_FEE**: `u64 = 300` - Maximum management fee (in BPS).
* **MAX\_PERFORMANCE\_FEE**: `u64 = 2000` - Maximum performance fee (in BPS).
* **DEFAULT\_PROTOCOL\_FEE**: `u64 = 1500` – Default protocol fee (in BPS).
* **DEFAULT\_MANAGEMENT\_FEE**: `u64 = 200` – Default management fee (in BPS).
* **DEFAULT\_PERFORMANCE\_FEE**: `u64 = 500` – Default performance fee (in BPS).

## Error Codes

* **EPROTOCOL\_NOT\_INITIALIZED**: The protocol has not been initialized.
* **ENOT\_GOVERNANCE**: The account is not the governance account.
* **ENOT\_PENDING\_GOVERNANCE**: The account is not the pending governance account.
* **EINVALID\_FEE**: The fee is invalid.
* **ERESERVED\_ADDRESS**: The address is reserved.
* **ENO\_PENDING\_ROUTER**: There is no pending router.
* **EINVALID\_PENDING\_ROUTER**: Pending router does not match expected.

## Public Functions

1. **Module Initialization**
   * `init_module(signer: &signer)`: Initializes the protocol module by creating the protocol and protocol controller objects.
2. **Governance Management**
   * `set_governance(account: &signer, governance: address)`: Sets the pending governance account. Only the current governance account can call this function.
   * `accept_governance(account: &signer)`: Accepts the pending governance address, promoting it to the current governance address. Only the pending governance account can call this function.
3. **Fee Management**
   * `set_protocol_fee(account: &signer, protocol_fee: u64)`: Sets the protocol fee. The fee must not exceed the maximum allowed (`MAX_PROTOCOL_FEE`).
   * `set_performance_fee(account: &signer, performance_fee: u64)`: Sets the performance fee. The fee must not exceed the maximum allowed (`MAX_PERFORMANCE_FEE`).
   * `set_management_fee(account: &signer, management_fee: u64)`: Sets the management fee. The fee must not exceed the maximum allowed (`MAX_MANAGEMENT_FEE`).
   * `set_protocol_fee_recipient(account: &signer, recipient: address)`: Sets the recipient of the protocol fee. The recipient address must not be zero.
4. **Router Management**
   * `approve_pending_router(account: &signer, router: address)`: Verifies if pending\_router matches router value passed to the function. If it matches, sets the router address for the protocol to the value stored in pending\_router and set pending\_router to None. Only the current governance account can call this function.
   * `request_router_ref(router_signer: &signer)`: Creates a new RouterRef based on the router\_signer and updates pending\_router field in the protocol. Returns the RouterRef corresponding to the router\_signer.
5. **Feature Management**
   * `set_auto_harvest(account: &signer, auto_harvest: bool)`: Updates the auto harvest bool in FeatureConfig. Only the current governance account can call this function.

## Friend Functions

* `get_signer(): signer`: Returns the signer for extending the protocol, used by friend modules to interact with the protocol.

## View Functions

* `is_governance(account: address): bool`: Checks if the provided account is the current governance account.
* `is_pending_governance(account: address): bool`: Checks if the provided account is the pending governance account.
* `get_governance(): address`: Returns the current governance address.
* `get_pending_governance(): Option<address>`: Returns the pending governance address, if any.
* `get_address(): address`: Returns the address of the protocol.
* `get_protocol_fee(): u64`: Returns the current protocol fee.
* `get_protocol_fee_recipient(): address`: Returns the address that receives the protocol fee.
* `get_deployer(): address`: Returns the address of the deployer (the account that deployed the protocol).
* `get_performance_fee(): u64`: Returns the performance fee for the protocol.
* `get_management_fee(): u64`: Returns the management fee for the protocol.
* `get_protocol_fee_recipient_store(metadata: Object<Metadata>): Object<FungibleStore>`: Returns the primary fungible store for the protocol fee recipient.
* `get_router(): Option<address>`: Returns the router address.
* `should_auto_harvest(): bool`: Returns the bool indicating if auto harvest is enabled.

## Access Control

* **Governance Account**: The account designated as the governance account has full control over the protocol's configuration, including changing fees and governance.
* **Pending Governance**: When a governance transition is in progress, the pending governance account must accept its role to finalize the change.
* **Friend Functions**: The `satay::base_strategy`, and `satay::vault` modules are friends of `satay::protocol`, giving them access to certain internal protocol functions.
