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.

address public unwrappedDepositToken;

distribution

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

address public distribution;

depositTokenConfig

Configuration details for bridging the stETH token.

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.

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.

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.

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.

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.

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.

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.

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.

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

Last updated

Was this helpful?