# L1Sender

## Introduction

The `L1Sender` contract serves as a critical component in the cross-chain infrastructure of the protocol. Its primary responsibility is to transfer both reward data and yield assets from Ethereum (L1) to Arbitrum (L2), ensuring that users receive accurate MOR token rewards and that the protocol’s yield is available for conversion and distribution on L2.

### Key Responsibilities

1. Cross-chain reward messaging via LayerZero:
   * The contract communicates with the `L2MessageReceiver` on Arbitrum using LayerZero.
   * It packages the user’s reward data (including recipient address and reward amount) and sends it securely across chains.
   * This action is triggered by the `DistributionV5` contract after calculating a user’s rewards.
   * On arrival to L2, the message is decoded, and MOR tokens are minted to the user.
2. Bridging stETH yield via Arbitrum Bridge:
   * The contract manages the bridging of yield generated from stETH held by the Morpheus protocol.
   * It wraps stETH into wstETH and uses Arbitrum Bridge to transfer tokens to the `L2TokenReceiver` contract.
3. Token configuration management:
   * The contract stores configuration data for both deposit and reward tokens:
     * Deposit token: the wrapped stETH token to be bridged.
     * Reward token: LayerZero configuration for sending mint instructions.
   * It handles dynamic updates to these configurations, allowing the protocol to change tokens or gateways without redeploying the contract.
4. Access control and upgradeability:
   * The contract uses OpenZeppelin’s Ownable and UUPSUpgradeable modules to ensure secure ownership and upgradability.
   * Only the `DistributionV5` contract can trigger core functions like sending rewards or bridging yield.
   * The contract supports interface discovery (via ERC165) for interoperability and integration with other tools or protocols.

## Storage

### unwrappedDepositToken

The address of the original deposit token (e.g., stETH) before it is wrapped for cross-chain transfer.

```solidity
address public unwrappedDepositToken;
```

### distribution

The address of the `DistributionV5` contract that handles staking logic and reward distribution.

```solidity
address public distribution;
```

### depositTokenConfig

Configuration details for bridging the stETH token.

```solidity
DepositTokenConfig public depositTokenConfig;

struct DepositTokenConfig {
  address token;
  address gateway;
  address receiver;
}
```

| Name     | Description                                       |
| -------- | ------------------------------------------------- |
| token    | The address of wstETH.                            |
| gateway  | The address of token's gateway, `L1GatewayRouter` |
| receiver | The `L2MessageReceiver` address.                  |

### rewardTokenConfig

Configuration for the LayerZero cross-chain messaging.

```solidity
RewardTokenConfig public rewardTokenConfig;

struct RewardTokenConfig {
  address gateway;
  address receiver;
  uint16 receiverChainId;
  address zroPaymentAddress;
  bytes adapterParams;
}
```

| Name              | Description                                                        |
| ----------------- | ------------------------------------------------------------------ |
| gateway           | The LayerZero `EnpointV1` address.                                 |
| receiver          | The `L2MessageReceiver` address.                                   |
| receiverChainId   | The receiver chain ID, from the LZ doc.                            |
| zroPaymentAddress | The LayerZero ZRO payment address for gas fees.                    |
| adapterParams     | LayerZero adapter parameters used to customize messaging behavior. |

## Write functions for the contract owner

### L1Sender\_\_init

Initializes the contract. This is a one-time setup function, used during deployment via proxies.

```solidity
function L1Sender__init(
 address distribution_,
 RewardTokenConfig calldata rewardTokenConfig_,
 DepositTokenConfig calldata depositTokenConfig_
) external initializer
```

| Name                  | Description                                            |
| --------------------- | ------------------------------------------------------ |
| `distribution_`       | The `DistributionV5` contract address                  |
| `rewardTokenConfig_`  | Configuration for the LayerZero cross-chain messaging. |
| `depositTokenConfig_` | Configuration details for bridging the stETH token.    |

### setDistribution

Allows the contract owner to set or update the address of the DistributionV5 contract.

```solidity
function setDistribution(address distribution_) public onlyOwner
```

| Name            | Description                           |
| --------------- | ------------------------------------- |
| `distribution_` | The `DistributionV5` contract address |

### setRewardTokenConfig

Allows the contract owner to update the LayerZero MOR token configuration used for cross-chain messaging.

```solidity
function setRewardTokenConfig(
  RewardTokenConfig calldata newConfig_
) public onlyOwner
```

| Name                 | Description                                            |
| -------------------- | ------------------------------------------------------ |
| `rewardTokenConfig_` | Configuration for the LayerZero cross-chain messaging. |

### setDepositTokenConfig

Allows the contract owner to update the stETH token configuration.

```solidity
function setDepositTokenConfig(
  DepositTokenConfig calldata newConfig_
) public onlyOwner
```

| Name                  | Description                                         |
| --------------------- | --------------------------------------------------- |
| `depositTokenConfig_` | Configuration details for bridging the stETH token. |

## Write functions for the DistributionV5 contract

### sendDepositToken

Transfers deposit tokens (e.g., stETH wrapped to wstETH) from L1 to L2 using the Arbitrum Bridge.

```solidity
function sendDepositToken(
  uint256 gasLimit_,
  uint256 maxFeePerGas_,
  uint256 maxSubmissionCost_
) external payable onlyDistribution returns (bytes memory)
```

| Name                 | Description                                    |
| -------------------- | ---------------------------------------------- |
| `gasLimit_`          | Gas limit for the L2 execution.                |
| `maxFeePerGas_`      | Max fee for L2 execution.                      |
| `maxSubmissionCost_` | Base submission cost for the retryable ticket. |

### sendMintMessage

Sends a cross-chain message via LayerZero to L2, instructing minting of MOR tokens to the user.

```solidity
function sendMintMessage(
  address user_, 
  uint256 amount_, 
  address refundTo_
) external payable onlyDistribution
```

| Name       | Description                                  |
| ---------- | -------------------------------------------- |
| user\_     | Recipient address on L2.                     |
| amount\_   | Amount of tokens to mint.                    |
| refundTo\_ | Address that receives any unspent msg.value. |

## Read functions

### supportsInterface

Used for interface detection (ERC165). Returns true if the contract supports a specific `interfaceId_`. Supports `IL1Sender`, `IERC165`.

```solidity
function supportsInterface(bytes4 interfaceId_) external pure returns (bool)
```
