Skip to content

Commit c86b9b6

Browse files
committed
refactor(gateway): inherit bridge contracts
1 parent f536bd6 commit c86b9b6

File tree

14 files changed

+243
-226
lines changed

14 files changed

+243
-226
lines changed

contracts/src/bridge/IL1Bridge.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ interface IL1Bridge {
2828

2929
function getSubmissionPrice(uint256 _calldatasize) external view returns (uint256);
3030

31-
function onlyAuthorized(address _sender) external;
31+
function onlyAuthorized() external;
3232
}

contracts/src/bridge/IL2Bridge.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ interface IL2Bridge {
1111
*/
1212
function sendCrossDomainMessage(bytes memory _calldata) external returns (uint256);
1313

14-
function onlyAuthorized(address _sender) external;
14+
function onlyAuthorized() external;
1515
}

contracts/src/bridge/arbitrum/L1Bridge.sol renamed to contracts/src/bridge/arbitrum/ArbL1Bridge.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import "./interfaces/IArbRetryableTx.sol";
88

99
import "../IL1Bridge.sol";
1010

11-
contract L1Bridge is IL1Bridge {
11+
contract ArbL1Bridge is IL1Bridge {
1212
address public l2Target;
1313
IInbox public inbox;
1414
IArbRetryableTx constant arbRetryableTx = IArbRetryableTx(address(110));
@@ -43,7 +43,7 @@ contract L1Bridge is IL1Bridge {
4343
uint256 _gasPriceBid
4444
) external payable returns (uint256) {
4545
uint256 baseSubmissionCost = getSubmissionPrice(_calldata.length);
46-
require(msg.value >= baseSubmissionCost);
46+
require(msg.value >= baseSubmissionCost + (_maxGas * _gasPriceBid));
4747

4848
uint256 ticketID = inbox.createRetryableTicket{value: msg.value}(
4949
l2Target,
@@ -65,7 +65,7 @@ contract L1Bridge is IL1Bridge {
6565
return submissionCost;
6666
}
6767

68-
function onlyAuthorized(address _sender) external {
68+
function onlyAuthorized() external {
6969
IOutbox outbox = IOutbox(inbox.bridge().activeOutbox());
7070
address l2Sender = outbox.l2ToL1Sender();
7171
require(l2Sender == l2Target, "Only L2 target");

contracts/src/bridge/arbitrum/L2Bridge.sol renamed to contracts/src/bridge/arbitrum/ArbL2Bridge.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import "./AddressAliasHelper.sol";
77

88
import "../IL2Bridge.sol";
99

10-
contract L2Bridge is IL2Bridge {
10+
contract ArbL2Bridge is IL2Bridge {
1111
address public l1Target;
1212
IArbSys constant arbsys = IArbSys(address(100));
1313

@@ -30,7 +30,7 @@ contract L2Bridge is IL2Bridge {
3030
return withdrawalId;
3131
}
3232

33-
function onlyAuthorized(address _sender) external {
34-
require(_sender == AddressAliasHelper.applyL1ToL2Alias(l1Target), "Only L1 target");
33+
function onlyAuthorized() external {
34+
require(msg.sender == AddressAliasHelper.applyL1ToL2Alias(l1Target), "Only L1 target");
3535
}
3636
}

contracts/src/bridge/xdai/L1Bridge.sol renamed to contracts/src/bridge/xdai/xDaiL1Bridge.sol

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import "./interfaces/IAMB.sol";
66

77
import "../IL1Bridge.sol";
88

9-
contract L1Bridge is IL1Bridge {
9+
contract xDaiL1Bridge is IL1Bridge {
1010
address public l2Target;
1111
IAMB amb;
1212

@@ -34,9 +34,9 @@ contract L1Bridge is IL1Bridge {
3434
return 0;
3535
}
3636

37-
function onlyAuthorized(address _sender) external {
38-
require(_sender == address(amb), "Only AMB allowed");
39-
//require(amb.messageSourceChainId() == homeChainId, "Only home chain allowed");
40-
require(amb.messageSender() == l2Target, "Only home proxy allowed");
37+
function onlyAuthorized() external {
38+
require(msg.sender == address(amb), "Only AMB allowed");
39+
// require(amb.messageSourceChainId() == foreignChainId, "Only foreign chain allowed");
40+
require(amb.messageSender() == l2Target, "Only foreign gateway allowed");
4141
}
4242
}

contracts/src/bridge/xdai/L2Bridge.sol renamed to contracts/src/bridge/xdai/xDaiL2Bridge.sol

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import "./interfaces/IAMB.sol";
66

77
import "../IL2Bridge.sol";
88

9-
contract L2Bridge is IL2Bridge {
9+
contract xDaiL2Bridge is IL2Bridge {
1010
address public l1Target;
1111
IAMB amb;
1212

@@ -20,9 +20,9 @@ contract L2Bridge is IL2Bridge {
2020
return uint256(id);
2121
}
2222

23-
function onlyAuthorized(address _sender) external {
24-
require(_sender == address(amb), "Only AMB allowed");
25-
//require(amb.messageSourceChainId() == homeChainId, "Only home chain allowed");
26-
require(amb.messageSender() == l1Target, "Only home proxy allowed");
23+
function onlyAuthorized() external {
24+
require(msg.sender == address(amb), "Only AMB allowed");
25+
// require(amb.messageSourceChainId() == homeChainId, "Only home chain allowed");
26+
require(amb.messageSender() == l1Target, "Only home gateway allowed");
2727
}
2828
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.0;
4+
5+
import "../arbitration/IArbitrable.sol";
6+
import "../bridge/IL1Bridge.sol";
7+
8+
import "./interfaces/IHomeGateway.sol";
9+
import "./interfaces/IForeignGateway.sol";
10+
11+
abstract contract BaseForeignGateway is IL1Bridge, IForeignGateway {
12+
uint256 internal localDisputeID;
13+
14+
// For now this is just a constant, but we'd probably need to
15+
// implement the same arbitrationCost calculation code we'll have
16+
// in the V2 court.
17+
uint256 internal internalArbitrationCost;
18+
19+
struct DisputeData {
20+
uint256 id;
21+
address arbitrable;
22+
}
23+
mapping(uint256 => bytes32) public disputeIDtoHash;
24+
mapping(bytes32 => DisputeData) public disputeHashtoDisputeData;
25+
26+
IHomeGateway public homeGateway;
27+
uint256 public chainID;
28+
29+
modifier onlyFromL2() {
30+
this.onlyAuthorized();
31+
_;
32+
}
33+
34+
constructor(uint256 _arbitrationCost, IHomeGateway _homeGateway) {
35+
internalArbitrationCost = _arbitrationCost;
36+
homeGateway = _homeGateway;
37+
38+
uint256 id;
39+
assembly {
40+
id := chainid()
41+
}
42+
chainID = id;
43+
}
44+
45+
function createDispute(uint256 _choices, bytes calldata _extraData) external payable returns (uint256 disputeID) {
46+
require(msg.value >= arbitrationCost(_extraData), "Not paid enough for arbitration");
47+
48+
disputeID = localDisputeID++;
49+
bytes32 disputeHash = keccak256(
50+
abi.encodePacked(
51+
chainID,
52+
blockhash(block.number - 1),
53+
"createDispute",
54+
disputeID,
55+
arbitrationCost(_extraData),
56+
_extraData
57+
)
58+
);
59+
disputeIDtoHash[disputeID] = disputeHash;
60+
disputeHashtoDisputeData[disputeHash] = DisputeData({id: disputeID, arbitrable: msg.sender});
61+
62+
bytes4 methodSelector = IHomeGateway.relayCreateDispute.selector;
63+
bytes memory data = abi.encodeWithSelector(methodSelector, disputeHash, _choices, _extraData);
64+
65+
uint256 bridgeCost = this.getSubmissionPrice(data.length);
66+
// We only pay for the submissionPrice gas cost
67+
// which is minimum gas cost required for submitting a
68+
// arbitrum retryable ticket to the retry buffer for
69+
// bridge to L2.
70+
// For immediate inclusion a user/bot needs to pay (GasPrice x MaxGas)
71+
// with the associated ticketId that is emitted by this function
72+
// after the ticket is successfully submitted.
73+
// For more details, see:
74+
// https://developer.offchainlabs.com/docs/l1_l2_messages#retryable-tickets-contract-api
75+
//
76+
// We do NOT forward the arbitrationCost ETH funds to the HomeGateway yet,
77+
// only the calldata.
78+
this.sendCrossDomainMessage{value: bridgeCost}(data, 0, 0);
79+
80+
emit DisputeCreation(disputeID, IArbitrable(msg.sender));
81+
}
82+
83+
function arbitrationCost(bytes calldata _extraData) public view returns (uint256 cost) {
84+
// Calculate the size of calldata that will be passed to the L2 bridge
85+
// as that is a factor for the bridging cost.
86+
// Calldata size of relayCreateDispute:
87+
// relayCreateDispute methodId +
88+
// (createDispute methodId + uint256 _choices + bytes _extraData)
89+
// 4 + 4 + 32 + dynamic
90+
uint256 calldatasize = 40 + _extraData.length;
91+
92+
uint256 bridgeCost = this.getSubmissionPrice(calldatasize);
93+
return bridgeCost + internalArbitrationCost;
94+
}
95+
96+
/**
97+
* Relay the rule call from the home gateway to the arbitrable.
98+
*/
99+
function relayRule(bytes32 _disputeHash, uint256 _ruling) external onlyFromL2 {
100+
DisputeData memory dispute = disputeHashtoDisputeData[_disputeHash];
101+
102+
IArbitrable arbitrable = IArbitrable(dispute.arbitrable);
103+
arbitrable.rule(dispute.id, _ruling);
104+
}
105+
106+
function foreignDisputeHashToID(bytes32 _disputeHash) external view returns (uint256) {
107+
return disputeHashtoDisputeData[_disputeHash].id;
108+
}
109+
110+
function disputeID(uint256 _foreignDisputeID) external view returns (uint256) {
111+
bytes32 disputeHash = disputeIDtoHash[_foreignDisputeID];
112+
require(disputeHash != 0, "Dispute does not exist");
113+
114+
return homeGateway.homeDisputeHashToID(disputeHash);
115+
}
116+
117+
function homeChainID(uint256 _disputeID) external view returns (uint256) {
118+
return homeGateway.chainID();
119+
}
120+
121+
function homeBridge(uint256 _disputeID) external view returns (address) {
122+
return address(homeGateway);
123+
}
124+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.0;
4+
5+
import "../arbitration/IArbitrator.sol";
6+
import "../bridge/IL2Bridge.sol";
7+
8+
import "./interfaces/IHomeGateway.sol";
9+
import "./interfaces/IForeignGateway.sol";
10+
11+
abstract contract BaseHomeGateway is IL2Bridge, IHomeGateway {
12+
mapping(uint256 => bytes32) public disputeIDtoHash;
13+
mapping(bytes32 => uint256) public disputeHashtoID;
14+
15+
IForeignGateway public foreignGateway;
16+
IArbitrator public arbitrator;
17+
uint256 public chainID;
18+
19+
modifier onlyFromL1() {
20+
this.onlyAuthorized();
21+
_;
22+
}
23+
24+
constructor(IArbitrator _arbitrator, IForeignGateway _foreignGateway) {
25+
arbitrator = _arbitrator;
26+
foreignGateway = _foreignGateway;
27+
28+
uint256 id;
29+
assembly {
30+
id := chainid()
31+
}
32+
chainID = id;
33+
34+
emit MetaEvidence(0, "BRIDGE");
35+
}
36+
37+
function rule(uint256 _disputeID, uint256 _ruling) external {
38+
require(msg.sender == address(arbitrator), "Only Arbitrator");
39+
40+
bytes4 methodSelector = IForeignGateway.relayRule.selector;
41+
bytes memory data = abi.encodeWithSelector(methodSelector, disputeIDtoHash[_disputeID], _ruling);
42+
43+
this.sendCrossDomainMessage(data);
44+
}
45+
46+
/**
47+
* Relay the createDispute call from the foreign gateway to the arbitrator.
48+
*/
49+
function relayCreateDispute(
50+
bytes32 _disputeHash,
51+
uint256 _choices,
52+
bytes calldata _extraData
53+
) external onlyFromL1 {
54+
uint256 disputeID = arbitrator.createDispute(_choices, _extraData);
55+
disputeIDtoHash[disputeID] = _disputeHash;
56+
disputeHashtoID[_disputeHash] = disputeID;
57+
58+
emit Dispute(arbitrator, disputeID, 0, 0);
59+
}
60+
61+
function homeDisputeHashToID(bytes32 _disputeHash) external view returns (uint256) {
62+
return disputeHashtoID[_disputeHash];
63+
}
64+
65+
function homeToForeignDisputeID(uint256 _homeDisputeID) external view returns (uint256) {
66+
bytes32 disputeHash = disputeIDtoHash[_homeDisputeID];
67+
require(disputeHash != 0, "Dispute does not exist");
68+
69+
return foreignGateway.foreignDisputeHashToID(disputeHash);
70+
}
71+
72+
function foreignChainID(uint256 _homeDisputeID) external view returns (uint256) {
73+
return foreignGateway.chainID();
74+
}
75+
76+
function foreignBridge(uint256 _homeDisputeID) external view returns (address) {
77+
return address(foreignGateway);
78+
}
79+
}

0 commit comments

Comments
 (0)