The L2MessageReceiver contract can be left uninitialized with the necessary parameters: rewardToken and config. Subsequently, all cross-chain mint messages will be blocked.
The L2MessageReceiver contract can be initialized via the L2MessageReceiver__init(). However, while executing the L2MessageReceiver__init(), the function does not configure the parameters rewardToken and config.
Specifically, an admin is required to execute the setParams() to configure them explicitly. If this step is overlooked, the rewardToken and config parameters will be left uninitialized. Subsequently, a cross-chain message will be blocked in the lzReceive().
@1 -- The L2MessageReceiver contract is initialized without setting the 'rewardToken' and 'config' params: https://github.com/Cyfrin/2024-01-Morpheus/blob/07c900d22073911afa23b7fa69a4249ab5b713c8/contracts/L2MessageReceiver.sol#L21-L24
@2 -- An admin is required to execute the setParams() to configure the 'rewardToken' and 'config' params: https://github.com/Cyfrin/2024-01-Morpheus/blob/07c900d22073911afa23b7fa69a4249ab5b713c8/contracts/L2MessageReceiver.sol#L26-L29
@3 -- If the step 2 is overlooked, a cross-chain message will be blocked here: https://github.com/Cyfrin/2024-01-Morpheus/blob/07c900d22073911afa23b7fa69a4249ab5b713c8/contracts/L2MessageReceiver.sol#L37
To elaborate on the vulnerability, while the lzEndpoint contract invokes the L2MessageReceiver::lzReceive(), the transaction will be reverted. Then, the message payload will be cached in the lzEndpoint's storage. As a result, the cached message will block all upcoming cross-chain mint messages.
@4 -- While the lzEndpoint contract invokes the L2MessageReceiver::lzReceive(), the transaction will get reverted in step 3: https://github.com/LayerZero-Labs/LayerZero/blob/48c21c3921931798184367fc02d3a8132b041942/contracts/Endpoint.sol#L118
@5 -- Consequently, the message payload will be cached in the lzEndpoint's storage: https://github.com/LayerZero-Labs/LayerZero/blob/48c21c3921931798184367fc02d3a8132b041942/contracts/Endpoint.sol#L122
@6 -- The cached message will block all upcoming cross-chain mint messages: https://github.com/LayerZero-Labs/LayerZero/blob/48c21c3921931798184367fc02d3a8132b041942/contracts/Endpoint.sol#L116
To remedy the issue, an admin must execute the L2MessageReceiver::setParams() to configure the rewardToken and config parameters. Then, they must invoke the lzEndpoint::retryPayload() to re-submit the cached message. Lastly, all prior blocked messages must be re-submitted via the lzRelayer's validateTransactionProofV1() or validateTransactionProofV2().
As you can see, this remediation step can require a lot of gas (which can be prevented; see the Recommendations section for the solution). Moreover, this vulnerability also breaks the reward-claiming feature (i.e., Distribution::claim()) which is one of the core protocol's features.
@7 -- To remedy the issue, an admin must execute the L2MessageReceiver::setParams() to configure the 'rewardToken' and 'config' params, then invoke the lzEndpoint::retryPayload() to re-submit the cached message, later all prior blocked messages must be re-submitted via the lzRelayer's validateTransactionProofV1() or validateTransactionProofV2(): https://github.com/LayerZero-Labs/LayerZero/blob/48c21c3921931798184367fc02d3a8132b041942/contracts/Endpoint.sol#L140
After the issue occurs, an admin must execute the L2MessageReceiver::setParams() to configure the rewardToken and config parameters. Then, they must invoke the lzEndpoint::retryPayload() to re-submit the cached message. Lastly, all prior blocked messages must be re-submitted via the lzRelayer's validateTransactionProofV1() or validateTransactionProofV2().
As you can see, this remediation step can require a lot of gas. Moreover, this vulnerability also breaks the reward-claiming feature (i.e., Distribution::claim()) which is one of the core protocol's features.
Manual Review
Initialize the rewardToken and config parameters while executing the L2MessageReceiver__init(), like the below snippet.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.