Commit f0618023 authored by Maurelian's avatar Maurelian

contracts-bedrock: Add pausability to L1xDM reading from SuperchainConfig

parent 657333de
...@@ -38,7 +38,7 @@ library ChainAssertions { ...@@ -38,7 +38,7 @@ library ChainAssertions {
require(keccak256(abi.encode(rcfg)) == keccak256(abi.encode(dflt))); require(keccak256(abi.encode(rcfg)) == keccak256(abi.encode(dflt)));
checkSystemConfig({ _contracts: _prox, _cfg: _cfg, _isProxy: true }); checkSystemConfig({ _contracts: _prox, _cfg: _cfg, _isProxy: true });
checkL1CrossDomainMessenger(_prox, _vm); checkL1CrossDomainMessenger({ _contracts: _prox, _vm: _vm, _isProxy: true });
checkL1StandardBridge(_prox); checkL1StandardBridge(_prox);
checkL2OutputOracle(_prox, _cfg, _l2OutputOracleStartingTimestamp, _l2OutputOracleStartingBlockNumber); checkL2OutputOracle(_prox, _cfg, _l2OutputOracleStartingTimestamp, _l2OutputOracleStartingBlockNumber);
checkOptimismMintableERC20Factory(_prox); checkOptimismMintableERC20Factory(_prox);
...@@ -76,12 +76,18 @@ library ChainAssertions { ...@@ -76,12 +76,18 @@ library ChainAssertions {
} }
/// @notice Asserts that the L1CrossDomainMessenger is setup correctly /// @notice Asserts that the L1CrossDomainMessenger is setup correctly
function checkL1CrossDomainMessenger(Types.ContractSet memory _contracts, Vm _vm) internal view { function checkL1CrossDomainMessenger(Types.ContractSet memory _contracts, Vm _vm, bool _isProxy) internal view {
L1CrossDomainMessenger messenger = L1CrossDomainMessenger(_contracts.L1CrossDomainMessenger); L1CrossDomainMessenger messenger = L1CrossDomainMessenger(_contracts.L1CrossDomainMessenger);
require(address(messenger.portal()) == _contracts.OptimismPortal); require(address(messenger.portal()) == _contracts.OptimismPortal);
require(address(messenger.PORTAL()) == _contracts.OptimismPortal); require(address(messenger.PORTAL()) == _contracts.OptimismPortal);
bytes32 xdmSenderSlot = _vm.load(address(messenger), bytes32(uint256(204))); if (_isProxy) {
require(address(uint160(uint256(xdmSenderSlot))) == Constants.DEFAULT_L2_SENDER); require(address(messenger.superchainConfig()) == _contracts.SuperchainConfig);
bytes32 xdmSenderSlot = _vm.load(address(messenger), bytes32(uint256(204)));
require(address(uint160(uint256(xdmSenderSlot))) == Constants.DEFAULT_L2_SENDER);
} else {
require(address(messenger.superchainConfig()) == address(0));
}
} }
/// @notice Asserts that the L1StandardBridge is setup correctly /// @notice Asserts that the L1StandardBridge is setup correctly
......
...@@ -487,7 +487,7 @@ contract Deploy is Deployer { ...@@ -487,7 +487,7 @@ contract Deploy is Deployer {
// are always proxies. // are always proxies.
Types.ContractSet memory contracts = _proxiesUnstrict(); Types.ContractSet memory contracts = _proxiesUnstrict();
contracts.L1CrossDomainMessenger = address(messenger); contracts.L1CrossDomainMessenger = address(messenger);
ChainAssertions.checkL1CrossDomainMessenger(contracts, vm); ChainAssertions.checkL1CrossDomainMessenger({ _contracts: contracts, _vm: vm, _isProxy: false });
require(loadInitializedSlot("L1CrossDomainMessenger", false) == 1, "L1CrossDomainMessenger is not initialized"); require(loadInitializedSlot("L1CrossDomainMessenger", false) == 1, "L1CrossDomainMessenger is not initialized");
...@@ -500,7 +500,6 @@ contract Deploy is Deployer { ...@@ -500,7 +500,6 @@ contract Deploy is Deployer {
L2OutputOracle l2OutputOracle = L2OutputOracle(mustGetAddress("L2OutputOracleProxy")); L2OutputOracle l2OutputOracle = L2OutputOracle(mustGetAddress("L2OutputOracleProxy"));
SystemConfig systemConfig = SystemConfig(mustGetAddress("SystemConfigProxy")); SystemConfig systemConfig = SystemConfig(mustGetAddress("SystemConfigProxy"));
SuperchainConfig superchainConfig = SuperchainConfig(mustGetAddress("SuperchainConfigProxy"));
OptimismPortal portal = new OptimismPortal{ salt: _implSalt() }({ OptimismPortal portal = new OptimismPortal{ salt: _implSalt() }({
_l2Oracle: l2OutputOracle, _l2Oracle: l2OutputOracle,
...@@ -857,6 +856,7 @@ contract Deploy is Deployer { ...@@ -857,6 +856,7 @@ contract Deploy is Deployer {
ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin")); ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin"));
address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy"); address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy");
address l1CrossDomainMessenger = mustGetAddress("L1CrossDomainMessenger"); address l1CrossDomainMessenger = mustGetAddress("L1CrossDomainMessenger");
SuperchainConfig superchainConfigProxy = SuperchainConfig(mustGetAddress("SuperchainConfigProxy"));
uint256 proxyType = uint256(proxyAdmin.proxyType(l1CrossDomainMessengerProxy)); uint256 proxyType = uint256(proxyAdmin.proxyType(l1CrossDomainMessengerProxy));
if (proxyType != uint256(ProxyAdmin.ProxyType.RESOLVED)) { if (proxyType != uint256(ProxyAdmin.ProxyType.RESOLVED)) {
...@@ -883,14 +883,14 @@ contract Deploy is Deployer { ...@@ -883,14 +883,14 @@ contract Deploy is Deployer {
_upgradeAndCallViaSafe({ _upgradeAndCallViaSafe({
_proxy: payable(l1CrossDomainMessengerProxy), _proxy: payable(l1CrossDomainMessengerProxy),
_implementation: l1CrossDomainMessenger, _implementation: l1CrossDomainMessenger,
_innerCallData: abi.encodeCall(L1CrossDomainMessenger.initialize, ()) _innerCallData: abi.encodeCall(L1CrossDomainMessenger.initialize, (superchainConfigProxy))
}); });
L1CrossDomainMessenger messenger = L1CrossDomainMessenger(l1CrossDomainMessengerProxy); L1CrossDomainMessenger messenger = L1CrossDomainMessenger(l1CrossDomainMessengerProxy);
string memory version = messenger.version(); string memory version = messenger.version();
console.log("L1CrossDomainMessenger version: %s", version); console.log("L1CrossDomainMessenger version: %s", version);
ChainAssertions.checkL1CrossDomainMessenger(_proxies(), vm); ChainAssertions.checkL1CrossDomainMessenger({ _contracts: _proxies(), _vm: vm, _isProxy: true });
require( require(
loadInitializedSlot("L1CrossDomainMessenger", true) == 1, "L1CrossDomainMessengerProxy is not initialized" loadInitializedSlot("L1CrossDomainMessenger", true) == 1, "L1CrossDomainMessengerProxy is not initialized"
......
...@@ -5,7 +5,7 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; ...@@ -5,7 +5,7 @@ import { Predeploys } from "src/libraries/Predeploys.sol";
import { OptimismPortal } from "src/L1/OptimismPortal.sol"; import { OptimismPortal } from "src/L1/OptimismPortal.sol";
import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol";
import { ISemver } from "src/universal/ISemver.sol"; import { ISemver } from "src/universal/ISemver.sol";
import { Constants } from "src/libraries/Constants.sol"; import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
/// @custom:proxied /// @custom:proxied
/// @title L1CrossDomainMessenger /// @title L1CrossDomainMessenger
...@@ -18,19 +18,24 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver { ...@@ -18,19 +18,24 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver {
/// @custom:legacy /// @custom:legacy
OptimismPortal public immutable PORTAL; OptimismPortal public immutable PORTAL;
/// @notice Address of the other SuperchainConfig contract.
SuperchainConfig public superchainConfig;
/// @notice Semantic version. /// @notice Semantic version.
/// @custom:semver 1.8.0 /// @custom:semver 2.0.0
string public constant version = "1.8.0"; string public constant version = "2.0.0";
/// @notice Constructs the L1CrossDomainMessenger contract. /// @notice Constructs the L1CrossDomainMessenger contract.
/// @param _portal Address of the OptimismPortal contract on this network. /// @param _portal Address of the OptimismPortal contract on this network.
constructor(OptimismPortal _portal) CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER) { constructor(OptimismPortal _portal) CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER) {
PORTAL = _portal; PORTAL = _portal;
initialize(); initialize({ _superchainConfig: SuperchainConfig(address(0)) });
} }
/// @notice Initializes the contract. /// @notice Initializes the contract.
function initialize() public initializer { /// @param _superchainConfig Address of the SuperchainConfig contract on this network.
function initialize(SuperchainConfig _superchainConfig) public initializer {
superchainConfig = _superchainConfig;
__CrossDomainMessenger_init(); __CrossDomainMessenger_init();
} }
...@@ -53,4 +58,9 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver { ...@@ -53,4 +58,9 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver {
function _isUnsafeTarget(address _target) internal view override returns (bool) { function _isUnsafeTarget(address _target) internal view override returns (bool) {
return _target == address(this) || _target == address(PORTAL); return _target == address(this) || _target == address(PORTAL);
} }
/// @inheritdoc CrossDomainMessenger
function paused() public view override returns (bool) {
return superchainConfig.paused();
}
} }
...@@ -219,6 +219,10 @@ abstract contract CrossDomainMessenger is ...@@ -219,6 +219,10 @@ abstract contract CrossDomainMessenger is
external external
payable payable
{ {
// On L1 this function will check the Portal for its paused status.
// On L2 this function should be a no-op, because paused will always return false.
require(paused() == false, "CrossDomainMessenger: paused");
(, uint16 version) = Encoding.decodeVersionedNonce(_nonce); (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);
require(version < 2, "CrossDomainMessenger: only version 0 or 1 messages are supported at this time"); require(version < 2, "CrossDomainMessenger: only version 0 or 1 messages are supported at this time");
...@@ -376,4 +380,12 @@ abstract contract CrossDomainMessenger is ...@@ -376,4 +380,12 @@ abstract contract CrossDomainMessenger is
/// @param _target Address of the contract to check. /// @param _target Address of the contract to check.
/// @return Whether or not the address is an unsafe system address. /// @return Whether or not the address is an unsafe system address.
function _isUnsafeTarget(address _target) internal view virtual returns (bool); function _isUnsafeTarget(address _target) internal view virtual returns (bool);
/// @notice This function should return true if the contract is paused.
/// On L1 this function will check the SuperchainConfig for its paused status.
/// On L2 this function should be a no-op.
/// @return Whether or not the contract is paused.
function paused() public view virtual returns (bool) {
return false;
}
} }
...@@ -47,7 +47,7 @@ contract Initializer_Test is Bridge_Initializer { ...@@ -47,7 +47,7 @@ contract Initializer_Test is Bridge_Initializer {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
target: address(l1CrossDomainMessenger), target: address(l1CrossDomainMessenger),
initCalldata: abi.encodeCall(l1CrossDomainMessenger.initialize, ()), initCalldata: abi.encodeCall(l1CrossDomainMessenger.initialize, (superchainConfig)),
initializedSlotVal: deploy.loadInitializedSlot("L1CrossDomainMessenger", true) initializedSlotVal: deploy.loadInitializedSlot("L1CrossDomainMessenger", true)
}) })
); );
......
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