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
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.
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.
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.
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;
}
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;
}
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
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
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
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
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)
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
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?