|
| 1 | +// SPDX-License-Identifier: MIT |
| 2 | + |
| 3 | +pragma solidity ^0.8.0; |
| 4 | + |
| 5 | +import "../../arbitration/IArbitrable.sol"; |
| 6 | +import "../../arbitration/IArbitrator.sol"; |
| 7 | +import "../../bridge/arbitrum/L1Bridge.sol"; |
| 8 | + |
| 9 | +import "./HomeGateway.sol"; |
| 10 | + |
| 11 | +contract ForeignGateway is IArbitrator { |
| 12 | + // L1 bridge with the HomeGateway as the l2target |
| 13 | + L1Bridge internal l1bridge; |
| 14 | + |
| 15 | + // For now this is just a constant, but we'd probably need to |
| 16 | + // implement the same arbitrationCost calculation code we'll have |
| 17 | + // in the V2 court. |
| 18 | + uint256 internal internalArbitrationCost; |
| 19 | + |
| 20 | + constructor(uint256 _arbitrationCost, L1Bridge _l1bridge) { |
| 21 | + internalArbitrationCost = _arbitrationCost; |
| 22 | + l1bridge = _l1bridge; |
| 23 | + } |
| 24 | + |
| 25 | + function createDispute(uint256 _choices, bytes calldata _extraData) external payable returns (uint256 disputeID) { |
| 26 | + require(msg.value >= arbitrationCost(_extraData), "Not paid enough for arbitration"); |
| 27 | + |
| 28 | + bytes4 methodSelector = HomeGateway.relayCreateDispute.selector; |
| 29 | + bytes memory data = abi.encodeWithSelector(methodSelector, msg.data); |
| 30 | + |
| 31 | + uint256 bridgeCost = l1bridge.getSubmissionPrice(data.length); |
| 32 | + // We only pay for the submissionPrice gas cost |
| 33 | + // which is minimum gas cost required for submitting a |
| 34 | + // arbitrum retryable ticket to the retry buffer for |
| 35 | + // bridge to L2. |
| 36 | + // For immediate inclusion a user/bot needs to pay (GasPrice x MaxGas) |
| 37 | + // with the associated ticketId that is emitted by this function |
| 38 | + // after the ticket is successfully submitted. |
| 39 | + // For more details, see: |
| 40 | + // https://developer.offchainlabs.com/docs/l1_l2_messages#retryable-tickets-contract-api |
| 41 | + // |
| 42 | + // We do NOT forward the arbitrationCost to the HomeGateway yet, |
| 43 | + // only the calldata. |
| 44 | + l1bridge.sendCrossDomainMessage{value: bridgeCost}(data, 0, 0); |
| 45 | + |
| 46 | + disputeId = 0; // TODO: map to the actual disputeID we get from the V2 court |
| 47 | + emit DisputeCreation(disputeId, IArbitrable(msg.sender)); |
| 48 | + return disputeId; |
| 49 | + } |
| 50 | + |
| 51 | + function arbitrationCost(bytes calldata _extraData) public view returns (uint256 cost) { |
| 52 | + // Calculate the size of calldata that will be passed to the L2 bridge |
| 53 | + // as that is a factor for the bridging cost. |
| 54 | + // Calldata size of relayCreateDispute: |
| 55 | + // relayCreateDispute methodId + |
| 56 | + // (createDispute methodId + uint256 _choices + bytes _extraData) |
| 57 | + // 4 + 4 + 32 + dynamic |
| 58 | + uint256 calldatasize = 40 + _extraData.length; |
| 59 | + |
| 60 | + uint256 bridgeCost = l1bridge.getSubmissionPrice(calldatasize); |
| 61 | + return bridgeCost + internalArbitrationCost; |
| 62 | + } |
| 63 | + |
| 64 | + /** |
| 65 | + * Relay the rule call from the home gateway to the arbitrable. |
| 66 | + * |
| 67 | + * @param _data The calldata to relay |
| 68 | + */ |
| 69 | + function relayRule(bytes memory _data) external { |
| 70 | + address arbitrable = address(0); // see the TODO above about the disputeId |
| 71 | + |
| 72 | + // solhint-disable-next-line avoid-low-level-calls |
| 73 | + (bool success, ) = arbitrable.call(_data); |
| 74 | + require(success, "Failed to call contract"); |
| 75 | + } |
| 76 | +} |
0 commit comments