# L1SenderV2

## Introduction

The `L1SenderV2` 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.

The contract automatically receives deposit tokens from the `Distributor` contract. These tokens represent the yield generated by various `DepositPools` and may come in different ERC-20 formats depending on the underlying staking strategy. To unify these assets for bridging, the `L1SenderV2` integrates with Uniswap v3, enabling it to swap the received tokens into wstETH. Once converted, the resulting wstETH is sent through the Arbitrum Bridge to the `L2TokenReceiverV2` contract on Arbitrum, ensuring the protocol’s yield is properly transferred and made available for liquidity and reward mechanisms 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 `DepositPool` 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. Automated deposit handling:

   Receives various yield tokens directly from the `Distributor` contract.
5. Uniswap V3 integration for token conversion:

   Swaps received tokens into wstETH before bridging to L2.

## Storage

### stETH

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

```solidity
address public stETH;
```

### distributor

The address of the `Distributor` contract.

```solidity
address public distributor;
```

### arbitrumBridgeConfig

Configuration details for bridging the stETH token via Arbitrum Bridge.

```solidity
ArbitrumBridgeConfig public arbitrumBridgeConfig;

struct ArbitrumBridgeConfig {
  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.                  |

### layerZeroConfig

Configuration for the LayerZero cross-chain messaging.

```solidity
LayerZeroConfig public layerZeroConfig;

struct LayerZeroConfig {
  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

### L1SenderV2\_\_init

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

```solidity
function L1SenderV2__init() external initializer
```

### setStETh

Allows the contract owner to set or update the address of the stETH token.

```solidity
function setStETh(address value_) external onlyOwner
```

| Name     | Description             |
| -------- | ----------------------- |
| `value_` | The stETH token address |

### setDistributor

Allows the contract owner to set or update the address of the `Distributor` contract.

```solidity
function setDistributor(address value_) public onlyOwner
```

| Name     | Description                        |
| -------- | ---------------------------------- |
| `value_` | The `Distributor` contract address |

### setUniswapSwapRouter

Allows the contract owner to set the Uniswap v3 `SwapRouter` contract address.

```solidity
function setUniswapSwapRouter(address value_) external onlyOwner
```

| Name     | Description                       |
| -------- | --------------------------------- |
| `value_` | The `SwapRouter` contract address |

### setLayerZeroConfig

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

```solidity
function setLayerZeroConfig(
  LayerZeroConfig calldata layerZeroConfig_
) external onlyOwner
```

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

### setArbitrumBridgeConfig

Allows the contract owner to update the Arbitrum Bridge configuration.

```solidity
function setArbitrumBridgeConfig(
  ArbitrumBridgeConfig calldata newConfig_
) external onlyOwner
```

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

### sendWstETH

Transfers tokens on the contract balance (e.g., stETH and wstETH) from L1 to L2 using the Arbitrum Bridge.

```solidity
function sendWstETH(
  uint256 gasLimit_,
  uint256 maxFeePerGas_,
  uint256 maxSubmissionCost_
) external payable onlyOwner returns (bytes memory)
```

| Name                 | Description                                    |
| -------------------- | ---------------------------------------------- |
| `eth_value`          | Payable amount, value, in the ETH.             |
| `gasLimit_`          | Gas limit for the L2 execution.                |
| `maxFeePerGas_`      | Max fee for L2 execution.                      |
| `maxSubmissionCost_` | Base submission cost for the retryable ticket. |

### swapExactInputMultihop

Allows the contract owner to swap deposit asset to the wstETH via Uniswap v3. Support multihop swaps (e.g. USDC/wETH, wETH/wstETH).

```solidity
function swapExactInputMultihop(
  address[] calldata tokens_,
  uint24[] calldata poolsFee_,
  uint256 amountIn_,
  uint256 amountOutMinimum_,
  uint256 deadline_
) external onlyOwner returns (uint256)
```

| Name                | Description                                                                                      |
| ------------------- | ------------------------------------------------------------------------------------------------ |
| `tokens_`           | Tokens addresses. \[USDC, wETH, wstETH]                                                          |
| `poolsFee_`         | Uniswap v3 pool fee (e.g., 3000 = 0.3%).                                                         |
| `amountIn_`         | The input token amount to swap. See the token decimals for the precision.                        |
| `amountOutMinimum_` | The minimal tokens amount at the end of swap (wstETH). See the token decimals for the precision. |
| `deadline_`         | Expiry timestamp in seconds for the transaction.                                                 |

#### Explanation

Uniswap UI can be used to detect the best route. With the help of this, it is possible to form all TX params exept `deadline_`&#x20;

<figure><img src="/files/gTXqSjSAm9YFa6ai80aF" alt=""><figcaption></figcaption></figure>

For example, we want to swap `wstETH->tBTC` (in real practice, you will do the swap in reverse `USDC->wstETH`, `wBTC->wstETH`...; this screenshot is for illustrative purposes only.

* `tokens_`: look at the order routing on the UI, `[wstETH, wETH, tBTC]`.
* `poolsFee_`: look at the percent near the pool icons, `[100, 2000]`. It is equals to `[0.01%, 0.2%]`.
* `amountIn_`: amount to swap, `0.00040790..`. wstETH, `407900000000000` wei in token decimals.
* `amountOutMinimum_`: amount to receive, `0.0000181086` tBTC, `18108600000000` wei in token decimals. You can decrease this value on 1-3%.
* `deadline_`: TX execution timestamp in seconds + 1 or 2 minutes.

## Write functions for the Distributor contract

### 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
```

| Name        | Description                                  |
| ----------- | -------------------------------------------- |
| `user_`     | Recipient address on L2.                     |
| `amount_`   | Amount of tokens to mint. Wei.               |
| `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 `IL1SenderV2`, `IERC165`.

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

### version

Returns the current version of the contract.

```solidity
function version() external pure returns (uint256)
```


---

# 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://gitbook.mor.org/smart-contracts/documentation/distribution-protocol/v7-protocol/contracts/l1senderv2.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.
