# SymmioPartyB

The `SymmioPartyB` contract acts as a management contract for solvers or "Party B" . This contract allows for controlled interaction with the Symmio platform and external addresses for managing roles and permissions.

> **Key Changes in 0.8.4:**
>
> * **Reentrancy Protection:**\
>   The `_executeCall` method now uses a custom `nonReentrant` modifier to prevent reentrancy attacks without altering the storage layout.
> * **Access Control & Multicast Whitelisting:**\
>   The contract restricts calls based on roles (e.g., MANAGER\_ROLE, TRUSTED\_ROLE) and maintains a whitelist for destinations allowed in multicast operations

***

## Initialization

The **SymmioPartyB** contract uses upgradeable libraries for pausing and access control. During initialization, it sets the admin roles and the address of the Symmio contract.

### initialize()

**Function Signature:**

```solidity
function initialize(address admin, address symmioAddress_) public initializer;
```

**Parameters:**

* **admin:** The address to receive the `DEFAULT_ADMIN_ROLE`, `TRUSTED_ROLE`, and `MANAGER_ROLE`.
* **symmioAddress\_:** The address of the Symmio contract with which this contract will interact.

**Example:**

```solidity
symmioPartyB.initialize(adminAddress, symmioAddress);
```

***

### Configuration

### setSymmioAddress()

**Description:**\
Updates the address of the Symmio contract. Only callable by users with the DEFAULT\_ADMIN\_ROLE.

**Function Signature:**

```solidity
function setSymmioAddress(address addr) external onlyRole(DEFAULT_ADMIN_ROLE);
```

**Parameters:**

* **addr:** The new Symmio contract address.

**Example:**

```solidity
symmioPartyB.setSymmioAddress(newSymmioAddress);
```

**Events Emitted:**

* `SetSymmioAddress(address oldSymmioAddress, address newSymmioAddress)`

***

### setRestrictedSelector()

**Description:**\
Restricts or lifts restrictions on specific function selectors. If a selector is restricted, only callers with the `MANAGER_ROLE` may invoke the function on the Symmio contract.

**Function Signature:**

```solidity
function setRestrictedSelector(bytes4 selector, bool state) external onlyRole(DEFAULT_ADMIN_ROLE);
```

**Parameters:**

* **selector:** The function selector to restrict/unrestrict.
* **state:** `true` to restrict, `false` to unrestrict.

**Example:**

```solidity
bytes4 selector = bytes4(keccak256("someFunction()"));
symmioPartyB.setRestrictedSelector(selector, true);
```

**Events Emitted:**

* `SetRestrictedSelector(bytes4 selector, bool state)`

***

### setMulticastWhitelist()

**Description:**\
Allows a manager to add or remove an address from the multicast whitelist. Only addresses on the whitelist can be called via the multicasting functionality.

**Function Signature:**

```solidity
function setMulticastWhitelist(address addr, bool state) external onlyRole(MANAGER_ROLE);
```

**Parameters:**

* **addr:** The address to update.
* **state:** `true` to whitelist, `false` to remove.

**Example:**

```solidity
symmioPartyB.setMulticastWhitelist(targetAddress, true);
```

**Events Emitted:**

* `SetMulticastWhitelist(address addr, bool state)`

***

## Token Approvals

### \_approve()

**Description:**\
Approves a specified ERC20 token amount for spending by the Symmio contract. Only callable by users with the `TRUSTED_ROLE` and when the contract is not paused.

**Function Signature:**

```solidity
function _approve(address token, uint256 amount) external onlyRole(TRUSTED_ROLE) whenNotPaused;
```

**Parameters:**

* **token:** The ERC20 token address.
* **amount:** The amount to approve.

**Example:**

```solidity
symmioPartyB._approve(tokenAddress, 1000);
```

***

### Execution Functions

### \_executeCall()

**Description:**\
Executes a low-level call to a destination address using the provided call data. This function now includes a custom `nonReentrant` modifier to prevent reentrancy attacks. It enforces role-based access control depending on the destination and function selector.

**Function Signature:**

```solidity
function _executeCall(address destAddress, bytes memory callData) internal nonReentrant;
```

**Parameters:**

* **destAddress:** The destination address for the call.
* **callData:** The call data (must be at least 4 bytes).

**Key Logic:**

* Validates that `destAddress` is not zero.
* Checks the length of `callData`.
* If calling the Symmio contract (`destAddress == symmioAddress`), extracts the function selector and enforces:
  * If restricted, the caller must have MANAGER\_ROLE.
  * Otherwise, the caller must have either MANAGER\_ROLE or TRUSTED\_ROLE.
* If calling another contract, verifies that the destination is whitelisted.
* Executes the call and reverts if it fails.

***

### \_call()

Executes multiple calls to the Symmio contract by iterating over an array of call data, using `_executeCall` for each entry.

**Function Signature:**

```solidity
function _call(bytes[] calldata _callDatas) external whenNotPaused;
```

**Parameters:**

* **\_callDatas:** An array of call data bytes.

**Example Usage:**

```solidity
bytes[] memory calls = new bytes[](2);
// Populate calls with call data...
symmioPartyB._call(calls);
```

***

### \_multicastCall()

**Description:**\
Allows the caller to execute multiple calls to various destination addresses in a single transaction. Each destination address must correspond to a call data element, and reentrancy protection is enforced on each call.

**Function Signature:**

```solidity
function _multicastCall(address[] calldata destAddresses, bytes[] calldata _callDatas) external whenNotPaused;
```

**Parameters:**

* **destAddresses:** An array of destination addresses.
* **\_callDatas:** An array of call data bytes.

**Example Usage:**

```solidity
address[] memory targets = new address[](2);
targets[0] = targetAddress1;
targets[1] = targetAddress2;
bytes[] memory callsData = new bytes[](2);
// Populate callsData...
symmioPartyB._multicastCall(targets, callsData);
```

***

## Token Withdrawal

### withdrawERC20()

Allows an authorized manager to withdraw ERC20 tokens from the contract to the caller's address.

**Function Signature:**

```solidity
function withdrawERC20(address token, uint256 amount) external onlyRole(MANAGER_ROLE);
```

**Parameters:**

* **token:** The ERC20 token address.
* **amount:** The amount to withdraw.

**Example Usage:**

```solidity
symmioPartyB.withdrawERC20(tokenAddress, 100);
```

***

### Pausable Functions

### pause() / unpause()

**Description:**\
Allows users with the PAUSER\_ROLE to pause the contract and users with the UNPAUSER\_ROLE to unpause it, thereby controlling the execution of functions.

**Function Signatures:**

```solidity
function pause() external onlyRole(PAUSER_ROLE);
function unpause() external onlyRole(UNPAUSER_ROLE);
```

**Example Usage:**

```solidity
symmioPartyB.pause();
symmioPartyB.unpause();
```
