Commit ccb544d0 authored by AgusDuha's avatar AgusDuha Committed by GitHub

feat: add dependency set check to L2ToL2CDM (#134) (#13019)

parent 34046982
...@@ -247,6 +247,11 @@ ...@@ -247,6 +247,11 @@
"name": "IdOriginNotL2ToL2CrossDomainMessenger", "name": "IdOriginNotL2ToL2CrossDomainMessenger",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "InvalidChainId",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "MessageAlreadyRelayed", "name": "MessageAlreadyRelayed",
......
...@@ -100,8 +100,8 @@ ...@@ -100,8 +100,8 @@
"sourceCodeHash": "0xd08a2e6514dbd44e16aa312a1b27b2841a9eab5622cbd05a39c30f543fad673c" "sourceCodeHash": "0xd08a2e6514dbd44e16aa312a1b27b2841a9eab5622cbd05a39c30f543fad673c"
}, },
"src/L2/L2ToL2CrossDomainMessenger.sol": { "src/L2/L2ToL2CrossDomainMessenger.sol": {
"initCodeHash": "0x2a1a1ee4f47175ce661ee8e4e50cfa879b082dcb5278b1d66ddda00ed77bb744", "initCodeHash": "0xc1c80c662aafebb639f62f17d9fefd6954947fd43dc31c278950727491471a94",
"sourceCodeHash": "0xa76133db7f449ae742f9ba988ad86ccb5672475f61298b9fefe411b63b63e9f6" "sourceCodeHash": "0xac12ab96ffe91c75bfe74768271a725e1cbe3996b16284171440dd71bcc215b6"
}, },
"src/L2/OptimismSuperchainERC20.sol": { "src/L2/OptimismSuperchainERC20.sol": {
"initCodeHash": "0x22fed5371ad9b4c2711ce5cbee889d332887aa5f5ff6b37e36c31acefe3bbeee", "initCodeHash": "0x22fed5371ad9b4c2711ce5cbee889d332887aa5f5ff6b37e36c31acefe3bbeee",
......
...@@ -8,6 +8,7 @@ import { CrossL2Inbox, Identifier } from "src/L2/CrossL2Inbox.sol"; ...@@ -8,6 +8,7 @@ import { CrossL2Inbox, Identifier } from "src/L2/CrossL2Inbox.sol";
import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { ISemver } from "src/universal/interfaces/ISemver.sol";
import { SafeCall } from "src/libraries/SafeCall.sol"; import { SafeCall } from "src/libraries/SafeCall.sol";
import { TransientReentrancyAware } from "src/libraries/TransientContext.sol"; import { TransientReentrancyAware } from "src/libraries/TransientContext.sol";
import { IDependencySet } from "src/L2/interfaces/IDependencySet.sol";
/// @notice Thrown when a non-written slot in transient storage is attempted to be read from. /// @notice Thrown when a non-written slot in transient storage is attempted to be read from.
error NotEntered(); error NotEntered();
...@@ -39,6 +40,9 @@ error ReentrantCall(); ...@@ -39,6 +40,9 @@ error ReentrantCall();
/// @notice Thrown when a call to the target contract during message relay fails. /// @notice Thrown when a call to the target contract during message relay fails.
error TargetCallFailed(); error TargetCallFailed();
/// @notice Thrown when attempting to use a chain ID that is not in the dependency set.
error InvalidChainId();
/// @custom:proxied true /// @custom:proxied true
/// @custom:predeploy 0x4200000000000000000000000000000000000023 /// @custom:predeploy 0x4200000000000000000000000000000000000023
/// @title L2ToL2CrossDomainMessenger /// @title L2ToL2CrossDomainMessenger
...@@ -65,8 +69,8 @@ contract L2ToL2CrossDomainMessenger is ISemver, TransientReentrancyAware { ...@@ -65,8 +69,8 @@ contract L2ToL2CrossDomainMessenger is ISemver, TransientReentrancyAware {
uint16 public constant messageVersion = uint16(0); uint16 public constant messageVersion = uint16(0);
/// @notice Semantic version. /// @notice Semantic version.
/// @custom:semver 1.0.0-beta.10 /// @custom:semver 1.0.0-beta.11
string public constant version = "1.0.0-beta.10"; string public constant version = "1.0.0-beta.11";
/// @notice Mapping of message hashes to boolean receipt values. Note that a message will only be present in this /// @notice Mapping of message hashes to boolean receipt values. Note that a message will only be present in this
/// mapping if it has successfully been relayed on this chain, and can therefore not be relayed again. /// mapping if it has successfully been relayed on this chain, and can therefore not be relayed again.
...@@ -130,6 +134,7 @@ contract L2ToL2CrossDomainMessenger is ISemver, TransientReentrancyAware { ...@@ -130,6 +134,7 @@ contract L2ToL2CrossDomainMessenger is ISemver, TransientReentrancyAware {
if (_destination == block.chainid) revert MessageDestinationSameChain(); if (_destination == block.chainid) revert MessageDestinationSameChain();
if (_target == Predeploys.CROSS_L2_INBOX) revert MessageTargetCrossL2Inbox(); if (_target == Predeploys.CROSS_L2_INBOX) revert MessageTargetCrossL2Inbox();
if (_target == Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER) revert MessageTargetL2ToL2CrossDomainMessenger(); if (_target == Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER) revert MessageTargetL2ToL2CrossDomainMessenger();
if (!IDependencySet(Predeploys.L1_BLOCK_ATTRIBUTES).isInDependencySet(_destination)) revert InvalidChainId();
uint256 nonce = messageNonce(); uint256 nonce = messageNonce();
emit SentMessage(_destination, _target, nonce, msg.sender, _message); emit SentMessage(_destination, _target, nonce, msg.sender, _message);
......
...@@ -42,6 +42,9 @@ interface IL2ToL2CrossDomainMessenger { ...@@ -42,6 +42,9 @@ interface IL2ToL2CrossDomainMessenger {
/// @notice Thrown when a call to the target contract during message relay fails. /// @notice Thrown when a call to the target contract during message relay fails.
error TargetCallFailed(); error TargetCallFailed();
/// @notice Thrown when attempting to use a chain ID that is not in the dependency set.
error InvalidChainId();
/// @notice Emitted whenever a message is sent to a destination /// @notice Emitted whenever a message is sent to a destination
/// @param destination Chain ID of the destination chain. /// @param destination Chain ID of the destination chain.
/// @param target Target contract or wallet address. /// @param target Target contract or wallet address.
......
...@@ -22,7 +22,9 @@ import { ...@@ -22,7 +22,9 @@ import {
MessageTargetL2ToL2CrossDomainMessenger, MessageTargetL2ToL2CrossDomainMessenger,
MessageAlreadyRelayed, MessageAlreadyRelayed,
ReentrantCall, ReentrantCall,
TargetCallFailed TargetCallFailed,
IDependencySet,
InvalidChainId
} from "src/L2/L2ToL2CrossDomainMessenger.sol"; } from "src/L2/L2ToL2CrossDomainMessenger.sol";
/// @title L2ToL2CrossDomainMessengerWithModifiableTransientStorage /// @title L2ToL2CrossDomainMessengerWithModifiableTransientStorage
...@@ -85,6 +87,13 @@ contract L2ToL2CrossDomainMessengerTest is Test { ...@@ -85,6 +87,13 @@ contract L2ToL2CrossDomainMessengerTest is Test {
// Ensure that the target contract is not CrossL2Inbox or L2ToL2CrossDomainMessenger // Ensure that the target contract is not CrossL2Inbox or L2ToL2CrossDomainMessenger
vm.assume(_target != Predeploys.CROSS_L2_INBOX && _target != Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); vm.assume(_target != Predeploys.CROSS_L2_INBOX && _target != Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER);
// Mock the call over the `isInDependencySet` function to return true
vm.mockCall(
Predeploys.L1_BLOCK_ATTRIBUTES,
abi.encodeCall(IDependencySet.isInDependencySet, (_destination)),
abi.encode(true)
);
// Get the current message nonce // Get the current message nonce
uint256 messageNonce = l2ToL2CrossDomainMessenger.messageNonce(); uint256 messageNonce = l2ToL2CrossDomainMessenger.messageNonce();
...@@ -193,6 +202,34 @@ contract L2ToL2CrossDomainMessengerTest is Test { ...@@ -193,6 +202,34 @@ contract L2ToL2CrossDomainMessengerTest is Test {
}); });
} }
/// @notice Tests the `sendMessage` function reverts when the `destination` is not in the dependency set.
function testFuzz_sendMessage_notInDependencySet_reverts(
uint256 _destination,
address _target,
bytes calldata _message
)
external
{
// Ensure the destination is not the same as the source, otherwise the function will revert
vm.assume(_destination != block.chainid);
// Ensure that the target contract is not CrossL2Inbox or L2ToL2CrossDomainMessenger
vm.assume(_target != Predeploys.CROSS_L2_INBOX && _target != Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER);
// Mock the call over the `isInDependencySet` function to return false
vm.mockCall(
Predeploys.L1_BLOCK_ATTRIBUTES,
abi.encodeCall(IDependencySet.isInDependencySet, (_destination)),
abi.encode(false)
);
// Expect a revert with the InvalidChainId selector
vm.expectRevert(InvalidChainId.selector);
// Call `sendMessage` with a destination that is not in the dependency set to provoke revert
l2ToL2CrossDomainMessenger.sendMessage(_destination, _target, _message);
}
/// @dev Tests that the `relayMessage` function succeeds and emits the correct RelayedMessage event. /// @dev Tests that the `relayMessage` function succeeds and emits the correct RelayedMessage event.
function testFuzz_relayMessage_succeeds( function testFuzz_relayMessage_succeeds(
uint256 _source, uint256 _source,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment