# Affiliate Facet

The Affiliate Facet manages the lifecycle of affiliates (frontends/brokers) within the Account Layer. It handles registration, admin management, fee distribution configuration, hook contracts, operator permissions, express deposit settings, and delegated calls to Symmio core.

The Account Layer is a separate diamond from the Symmio Core diamond. It provides account management, affiliate infrastructure, and deposit routing on top of the core trading protocol.

***

### Overview

The Affiliate Facet provides the following key functionalities:

* **Registration:** Affiliates submit registration requests which are approved by an `APPROVER_ROLE`. Upon approval, an AccountManager contract is deployed and the affiliate is registered on its Symmio cores.
* **Admin Management:** Two-step admin transfer (propose → accept), display name/brand updates, and affiliate pause/unpause.
* **Fee Management:** Two-step fee configuration updates (request → approve). Fees are split between stakeholders and a Symmio protocol share, summing to 100% (1e18 precision). Any stakeholder or `DISTRIBUTOR_ROLE` can trigger fee claims.
* **Hook Management:** Affiliates can set hook contracts per function selector that are called during account lifecycle events (account creation, call execution, deletion).
* **Operator Management:** Affiliates authorize operators to call specific functions via `callAsAffiliate`.
* **Express Deposit Configuration:** Affiliates configure the express deposit rate and virtual provider for split deposits.
* **Delegated Calls:** `callAsAffiliate` allows the affiliate admin or authorized operators to execute whitelisted Symmio core functions on behalf of the affiliate.

***

### Affiliate Registration

#### requestToRegisterAffiliate()

Submits a registration request. The affiliate address is deterministic based on the registrant and name. The affiliate enters `PENDING` state.

```solidity
function requestToRegisterAffiliate(AffiliateRegistration memory reg) external whenNotPaused returns (address affiliateAddress);
```

**Events:** `AffiliateRegistered(address affiliate, string name)`

#### cancelRegistration()

Affiliate admin cancels a pending registration.

```solidity
function cancelRegistration(address affiliate) external whenNotPaused onlyAffiliateAdmin(affiliate);
```

**Events:** `RegistrationCancelled(address affiliate)`

#### rejectRegistration()

Approver rejects a pending registration.

```solidity
function rejectRegistration(address affiliate) external onlyRole(APPROVER_ROLE);
```

**Events:** `RegistrationRejected(address affiliate, address rejector)`

#### approveAffiliate()

Approver approves a pending affiliate. Deploys the AccountManager contract, generates a fee distributor address, registers the affiliate on all configured Symmio cores, and transitions to `ACTIVE` state.

```solidity
function approveAffiliate(address affiliate) external onlyRole(APPROVER_ROLE) whenNotPaused;
```

**Events:** `AffiliateApproved(address affiliate, address feeDistributor)`

***

### Admin Management

#### proposeAdminTransfer()

Proposes transferring the affiliate admin role to a new address (two-step).

```solidity
function proposeAdminTransfer(address affiliate, address newAdmin) external whenNotPaused onlyAffiliateAdmin(affiliate);
```

**Events:** `AdminTransferProposed(address affiliate, address newAdmin)`

#### acceptAdminTransfer()

The proposed new admin accepts the transfer.

```solidity
function acceptAdminTransfer(address affiliate) external whenNotPaused;
```

**Events:** `AdminTransferCompleted(address affiliate, address oldAdmin, address newAdmin)`

#### cancelAdminTransfer()

Cancels a pending admin transfer.

```solidity
function cancelAdminTransfer(address affiliate) external whenNotPaused onlyAffiliateAdmin(affiliate);
```

**Events:** `AdminTransferCancelled(address affiliate)`

#### updateAffiliateDetails()

Updates the display name and brand color.

```solidity
function updateAffiliateDetails(address affiliate, string memory name, string memory brandColor) external whenNotPaused onlyAffiliateAdmin(affiliate);
```

**Events:** `AffiliateUpdated(address affiliate, string name, string brandColor)`

#### pauseAffiliate() / unpauseAffiliate()

Pauses an affiliate (callable by admin or `PAUSER_ROLE`), preventing new account creation. Unpausing requires `UNPAUSER_ROLE`.

```solidity
function pauseAffiliate(address affiliate) external whenNotPaused;
function unpauseAffiliate(address affiliate) external onlyRole(UNPAUSER_ROLE);
```

**Events:** `AffiliatePaused(address affiliate)` / `AffiliateUnpaused(address affiliate)`

***

### Fee Management

Fee shares are configured as stakeholders (each with a receiver address and share) plus a Symmio protocol share. All shares must sum to exactly 1e18 (100%).

#### requestFeeUpdate()

Requests a fee configuration update (two-step). Must be approved by `APPROVER_ROLE`.

```solidity
function requestFeeUpdate(address affiliate, Stakeholder[] memory newStakeholders, uint256 newSymmioShare) external whenNotPaused onlyAffiliateAdmin(affiliate);
```

**Events:** `StakeholdersUpdateRequested(address affiliate)`

#### cancelFeeUpdate()

Cancels a pending fee update.

```solidity
function cancelFeeUpdate(address affiliate) external whenNotPaused onlyAffiliateAdmin(affiliate);
```

**Events:** `FeeUpdateCancelled(address affiliate)`

#### approveFeeUpdate()

Approver applies the pending fee update.

```solidity
function approveFeeUpdate(address affiliate) external onlyRole(APPROVER_ROLE) whenNotPaused;
```

**Events:** `StakeholdersUpdated(address affiliate)`

#### claimAllFees() / claimFees()

Claims accrued fees from a Symmio core and distributes to all stakeholders proportionally. Callable by any stakeholder or `DISTRIBUTOR_ROLE`.

```solidity
function claimAllFees(address affiliate, address symmio) external whenNotPaused nonReentrant;
function claimFees(address affiliate, address symmio, uint256 amount) external whenNotPaused nonReentrant;
```

**Events:** `FeesClaimed(address affiliate, address symmio, uint256 amount)` and `FeesDistributed(address receiver, uint256 amount)` per stakeholder

***

### Hook & Operator Management

#### setHook() / removeHook()

Sets or removes a hook contract for a specific function selector.

```solidity
function setHook(address affiliate, bytes4 selector, address hook) external whenNotPaused onlyAffiliateAdmin(affiliate);
function removeHook(address affiliate, bytes4 selector) external whenNotPaused onlyAffiliateAdmin(affiliate);
```

**Events:** `HookSet(address affiliate, bytes4 selector, address hook)` / `HookRemoved(address affiliate, bytes4 selector)`

#### setOperator()

Grants or revokes operator permission for a function selector.

```solidity
function setOperator(address affiliate, bytes4 selector, address operator, bool status) external whenNotPaused onlyAffiliateAdmin(affiliate);
```

**Events:** `OperatorSet(address affiliate, bytes4 selector, address operator, bool status)`

***

### Express Deposit Configuration

#### setExpressRate()

Sets the fraction of deposits routed to the virtual provider (1e18 precision, e.g., 0.1e18 = 10%).

```solidity
function setExpressRate(address affiliate, uint256 expressRate) external whenNotPaused onlyAffiliateAdmin(affiliate);
```

**Events:** `ExpressRateSet(address affiliate, uint256 expressRate)`

#### setVirtualProvider()

Sets the virtual provider contract for express deposits. Required when `expressRate > 0`.

```solidity
function setVirtualProvider(address affiliate, address virtualProvider) external whenNotPaused onlyAffiliateAdmin(affiliate);
```

**Events:** `VirtualProviderSet(address affiliate, address virtualProvider)`

***

### Delegated Calls

#### callAsAffiliate()

Executes a whitelisted function call on a Symmio core as the affiliate. The caller must be the affiliate admin or an authorized operator for the function selector. The selector must be in `callAllowedSelectors` for the affiliate.

```solidity
function callAsAffiliate(address affiliate, address symmio, bytes calldata callData) external whenNotPaused nonReentrant returns (bytes memory result);
```

**Access:** Affiliate admin or authorized operator. Symmio core must be in the affiliate's registered cores.
