diff --git a/solidity/apps/contracts/governance/GovernanceRouter.sol b/solidity/apps/contracts/governance/GovernanceRouter.sol index 42d53bf28..d18f98c5f 100644 --- a/solidity/apps/contracts/governance/GovernanceRouter.sol +++ b/solidity/apps/contracts/governance/GovernanceRouter.sol @@ -7,7 +7,7 @@ import {GovernanceMessage} from "./GovernanceMessage.sol"; // ============ External Imports ============ import {Version0} from "@abacus-network/core/contracts/Version0.sol"; import {Router} from "@abacus-network/core/contracts/router/Router.sol"; -import {TypeCasts} from "@abacus-network/core/contracts/XAppConnectionManager.sol"; +import {TypeCasts} from "@abacus-network/core/libs/TypeCasts.sol"; import {Initializable} from "@openzeppelin/contracts/proxy/Initializable.sol"; import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; import {TypedMemView} from "@summa-tx/memview-sol/contracts/TypedMemView.sol"; diff --git a/solidity/apps/contracts/ping-pong/PingPongRouter.sol b/solidity/apps/contracts/ping-pong/PingPongRouter.sol index 1da3f5e2a..4e5b24090 100644 --- a/solidity/apps/contracts/ping-pong/PingPongRouter.sol +++ b/solidity/apps/contracts/ping-pong/PingPongRouter.sol @@ -154,11 +154,7 @@ contract PingPongRouter is Router { ? PingPongMessage.formatPing(_match, _count) : PingPongMessage.formatPong(_match, _count); // send the message to the xApp Router - (_outbox()).dispatch( - _destinationDomain, - _remoteRouterAddress, - _message - ); + _outbox().dispatch(_destinationDomain, _remoteRouterAddress, _message); // emit a Sent event emit Sent(_destinationDomain, _match, _count, _isPing); } diff --git a/solidity/core/contracts/Common.sol b/solidity/core/contracts/Common.sol index 46857504d..ba13d624d 100644 --- a/solidity/core/contracts/Common.sol +++ b/solidity/core/contracts/Common.sol @@ -3,6 +3,7 @@ pragma solidity >=0.6.11; // ============ Internal Imports ============ import {IValidatorManager} from "../interfaces/IValidatorManager.sol"; +import {ICommon} from "../interfaces/ICommon.sol"; // ============ External Imports ============ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; @@ -12,11 +13,11 @@ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; * @author Celo Labs Inc. * @notice Shared utilities between Outbox and Inbox. */ -abstract contract Common is OwnableUpgradeable { +abstract contract Common is ICommon, OwnableUpgradeable { // ============ Immutable Variables ============ // Domain of chain on which the contract is deployed - uint32 public immutable localDomain; + uint32 public immutable override localDomain; // ============ Public Variables ============ @@ -88,6 +89,7 @@ abstract contract Common is OwnableUpgradeable { function latestCheckpoint() external view + override returns (bytes32 root, uint256 index) { root = checkpointedRoot; diff --git a/solidity/core/contracts/Inbox.sol b/solidity/core/contracts/Inbox.sol index 46633e197..181fae568 100644 --- a/solidity/core/contracts/Inbox.sol +++ b/solidity/core/contracts/Inbox.sol @@ -7,6 +7,7 @@ import {Common} from "./Common.sol"; import {MerkleLib} from "../libs/Merkle.sol"; import {Message} from "../libs/Message.sol"; import {IMessageRecipient} from "../interfaces/IMessageRecipient.sol"; +import {IInbox} from "../interfaces/IInbox.sol"; // ============ External Imports ============ import {TypedMemView} from "@summa-tx/memview-sol/contracts/TypedMemView.sol"; @@ -16,7 +17,7 @@ import {TypedMemView} from "@summa-tx/memview-sol/contracts/TypedMemView.sol"; * @notice Track root updates on Outbox, prove and dispatch messages to end * recipients. */ -contract Inbox is Version0, Common { +contract Inbox is IInbox, Version0, Common { // ============ Libraries ============ using MerkleLib for MerkleLib.Tree; @@ -39,7 +40,7 @@ contract Inbox is Version0, Common { // ============ Public Storage ============ // Domain of outbox chain - uint32 public remoteDomain; + uint32 public override remoteDomain; // re-entrancy guard uint8 private entered; // Mapping of message leaves to MessageStatus @@ -90,7 +91,7 @@ contract Inbox is Version0, Common { bytes32 _root, uint256 _index, bytes calldata _signature - ) external { + ) external override { // ensure that update is more recent than the latest we've seen require(_index > checkpoints[checkpointedRoot], "old checkpoint"); // validate validator signature @@ -119,7 +120,7 @@ contract Inbox is Version0, Common { bytes calldata _message, bytes32[32] calldata _proof, uint256 _index - ) external { + ) external override { require(prove(keccak256(_message), _proof, _index), "!prove"); process(_message); } diff --git a/solidity/core/contracts/Outbox.sol b/solidity/core/contracts/Outbox.sol index a234a9bfa..748d10d35 100644 --- a/solidity/core/contracts/Outbox.sol +++ b/solidity/core/contracts/Outbox.sol @@ -7,6 +7,7 @@ import {Common} from "./Common.sol"; import {MerkleLib} from "../libs/Merkle.sol"; import {Message} from "../libs/Message.sol"; import {MerkleTreeManager} from "./Merkle.sol"; +import {IOutbox} from "../interfaces/IOutbox.sol"; /** * @title Outbox @@ -18,7 +19,7 @@ import {MerkleTreeManager} from "./Merkle.sol"; * Accepts submissions of fraudulent signatures * by the Validator and slashes the Validator in this case. */ -contract Outbox is Version0, MerkleTreeManager, Common { +contract Outbox is IOutbox, Version0, MerkleTreeManager, Common { // ============ Libraries ============ using MerkleLib for MerkleLib.Tree; @@ -121,7 +122,7 @@ contract Outbox is Version0, MerkleTreeManager, Common { uint32 _destinationDomain, bytes32 _recipientAddress, bytes memory _messageBody - ) external notFailed returns (uint256) { + ) external override notFailed returns (uint256) { require(_messageBody.length <= MAX_MESSAGE_BODY_BYTES, "msg too long"); // get the next nonce for the destination domain, then increment it uint32 _nonce = nonces[_destinationDomain]; @@ -157,7 +158,7 @@ contract Outbox is Version0, MerkleTreeManager, Common { * relayed to the Inbox contracts. * @dev emits Checkpoint event */ - function checkpoint() external notFailed { + function checkpoint() external override notFailed { uint256 count = count(); require(count > 0, "!count"); bytes32 root = root(); diff --git a/solidity/core/contracts/XAppConnectionManager.sol b/solidity/core/contracts/XAppConnectionManager.sol index befa2247f..f71d71cf1 100644 --- a/solidity/core/contracts/XAppConnectionManager.sol +++ b/solidity/core/contracts/XAppConnectionManager.sol @@ -2,12 +2,9 @@ pragma solidity >=0.6.11; // ============ Internal Imports ============ -import {Outbox} from "./Outbox.sol"; -import {Inbox} from "./Inbox.sol"; +import {IOutbox} from "../interfaces/IOutbox.sol"; import {IInterchainGasPaymaster} from "../interfaces/IInterchainGasPaymaster.sol"; -import {TypeCasts} from "../libs/TypeCasts.sol"; // ============ External Imports ============ -import {ECDSA} from "@openzeppelin/contracts/cryptography/ECDSA.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; /** @@ -20,7 +17,7 @@ contract XAppConnectionManager is Ownable { // ============ Public Storage ============ // Outbox contract - Outbox public outbox; + IOutbox public outbox; // Interchain Gas Paymaster contract. The off-chain processor associated with // the paymaster contract must be willing to process messages dispatched from // the current Outbox contract, otherwise payments made to the paymaster will @@ -122,7 +119,7 @@ contract XAppConnectionManager is Ownable { * @param _outbox The address of the new local Outbox contract. */ function setOutbox(address _outbox) public onlyOwner { - outbox = Outbox(_outbox); + outbox = IOutbox(_outbox); emit NewOutbox(_outbox); } diff --git a/solidity/core/contracts/router/XAppConnectionClient.sol b/solidity/core/contracts/router/XAppConnectionClient.sol index 5420e6a04..bbfdcddc9 100644 --- a/solidity/core/contracts/router/XAppConnectionClient.sol +++ b/solidity/core/contracts/router/XAppConnectionClient.sol @@ -3,7 +3,7 @@ pragma solidity >=0.6.11; // ============ Internal Imports ============ import {IInterchainGasPaymaster} from "../../interfaces/IInterchainGasPaymaster.sol"; -import {Outbox} from "../Outbox.sol"; +import {IOutbox} from "../../interfaces/IOutbox.sol"; import {XAppConnectionManager} from "../XAppConnectionManager.sol"; // ============ External Imports ============ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; @@ -73,7 +73,7 @@ abstract contract XAppConnectionClient is OwnableUpgradeable { * @notice Get the local Outbox contract from the xAppConnectionManager * @return The local Outbox contract */ - function _outbox() internal view returns (Outbox) { + function _outbox() internal view returns (IOutbox) { return xAppConnectionManager.outbox(); } diff --git a/solidity/core/interfaces/ICommon.sol b/solidity/core/interfaces/ICommon.sol new file mode 100644 index 000000000..f2840ccc9 --- /dev/null +++ b/solidity/core/interfaces/ICommon.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.6.11; + +interface ICommon { + function localDomain() external view returns (uint32); + + function latestCheckpoint() + external + view + returns (bytes32 root, uint256 index); +} diff --git a/solidity/core/interfaces/IInbox.sol b/solidity/core/interfaces/IInbox.sol new file mode 100644 index 000000000..f5ce5a172 --- /dev/null +++ b/solidity/core/interfaces/IInbox.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.6.11; + +import {ICommon} from "./ICommon.sol"; + +interface IInbox is ICommon { + function checkpoint( + bytes32 _root, + uint256 _index, + bytes calldata _signature + ) external; + + function remoteDomain() external returns (uint32); + + function proveAndProcess( + bytes calldata _message, + bytes32[32] calldata _proof, + uint256 _index + ) external; +} diff --git a/solidity/core/interfaces/IOutbox.sol b/solidity/core/interfaces/IOutbox.sol new file mode 100644 index 000000000..4b8d2df0c --- /dev/null +++ b/solidity/core/interfaces/IOutbox.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.6.11; + +import {ICommon} from "./ICommon.sol"; + +interface IOutbox is ICommon { + function dispatch( + uint32 _destinationDomain, + bytes32 _recipientAddress, + bytes calldata _messageBody + ) external returns (uint256); + + function checkpoint() external; +}