Skip to content

Commit

Permalink
feat(gateway): add access control functions
Browse files Browse the repository at this point in the history
Note they will always revert right now as the actual sender of
the cross domain message will be the wrapper bridge contracts.
We need to either have the bridge contracts be inherited or
pass their address to the constructor of the other bridge in
addition to the address of the gateway.
  • Loading branch information
shalzz committed Dec 30, 2021
1 parent 2f0542b commit 8d95e33
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 2 deletions.
39 changes: 39 additions & 0 deletions contracts/src/bridge/arbitrum/AddressAliasHelper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: Apache-2.0

/*
* Copyright 2019-2021, Offchain Labs, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

pragma solidity >=0.7.0;

library AddressAliasHelper {
uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);

/// @notice Utility function that converts the address in the L1 that submitted a tx to
/// the inbox to the msg.sender viewed in the L2
/// @param l1Address the address in the L1 that triggered the tx to L2
/// @return l2Address L2 address as viewed in msg.sender
function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {
l2Address = address(uint160(l1Address) + offset);
}

/// @notice Utility function that converts the msg.sender viewed in the L2 to the
/// address in the L1 that submitted a tx to the inbox
/// @param l2Address L2 address as viewed in msg.sender
/// @return l1Address the address in the L1 that triggered the tx to L2
function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {
l1Address = address(uint160(l2Address) - offset);
}
}
7 changes: 7 additions & 0 deletions contracts/src/bridge/arbitrum/L1Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pragma solidity ^0.8.0;

import "./interfaces/IInbox.sol";
import "./interfaces/IOutbox.sol";
import "./interfaces/IArbRetryableTx.sol";

contract L1Bridge {
Expand Down Expand Up @@ -60,4 +61,10 @@ contract L1Bridge {
(uint256 submissionCost, ) = arbRetryableTx.getSubmissionPrice(_calldatasize);
return submissionCost;
}

function onlyAuthorized(address _sender) external {
IOutbox outbox = IOutbox(inbox.bridge().activeOutbox());
address l2Sender = outbox.l2ToL1Sender();
require(l2Sender == l2Target, "Only L2 target");
}
}
5 changes: 5 additions & 0 deletions contracts/src/bridge/arbitrum/L2Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pragma solidity ^0.8.0;

import "./interfaces/IArbSys.sol";
import "./AddressAliasHelper.sol";

contract L2Bridge {
address public l1Target;
Expand All @@ -26,4 +27,8 @@ contract L2Bridge {
emit L2ToL1TxCreated(withdrawalId);
return withdrawalId;
}

function onlyAuthorized(address _sender) external {
require(_sender == AddressAliasHelper.applyL1ToL2Alias(l1Target), "Only L1 target");
}
}
8 changes: 7 additions & 1 deletion contracts/src/gateway/arbitrum/ArbitrumGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@ import "../IForeignGateway.sol";

contract ArbitrumGateway is IHomeGateway {
// L2 bridge with the ForeignGateway as the l1target

L2Bridge internal l2bridge;
address public arbitrator;

modifier onlyFromL1() {
l2bridge.onlyAuthorized(msg.sender);
_;
}

constructor(address _arbitrator, L2Bridge _l2bridge) {
arbitrator = _arbitrator;
l2bridge = _l2bridge;
Expand All @@ -35,7 +41,7 @@ contract ArbitrumGateway is IHomeGateway {
* for it to maintain it's internal mapping.
* @param _data The calldata to relay
*/
function relayCreateDispute(bytes memory _data) external {
function relayCreateDispute(bytes memory _data) external onlyFromL1 {
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = arbitrator.call(_data);
require(success, "Failed to call contract");
Expand Down
7 changes: 6 additions & 1 deletion contracts/src/gateway/arbitrum/EthereumGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ contract EthereumGateway is IForeignGateway {
// in the V2 court.
uint256 internal internalArbitrationCost;

modifier onlyFromL2() {
l1bridge.onlyAuthorized(msg.sender);
_;
}

constructor(uint256 _arbitrationCost, L1Bridge _l1bridge) {
internalArbitrationCost = _arbitrationCost;
l1bridge = _l1bridge;
Expand Down Expand Up @@ -66,7 +71,7 @@ contract EthereumGateway is IForeignGateway {
*
* @param _data The calldata to relay
*/
function relayRule(bytes memory _data) external {
function relayRule(bytes memory _data) external onlyFromL2 {
address arbitrable = address(0); // see the TODO above about the disputeId

// solhint-disable-next-line avoid-low-level-calls
Expand Down

0 comments on commit 8d95e33

Please sign in to comment.