diff --git a/.changeset/tidy-pans-camp.md b/.changeset/tidy-pans-camp.md new file mode 100644 index 00000000..d879c885 --- /dev/null +++ b/.changeset/tidy-pans-camp.md @@ -0,0 +1,5 @@ +--- +"@cartesi/rollups": minor +--- + +Add `IAuthority` interface diff --git a/contracts/consensus/authority/Authority.sol b/contracts/consensus/authority/Authority.sol index ab8fccb0..a4518e00 100644 --- a/contracts/consensus/authority/Authority.sol +++ b/contracts/consensus/authority/Authority.sol @@ -5,13 +5,15 @@ pragma solidity ^0.8.8; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {IAuthority} from "./IAuthority.sol"; import {IConsensus} from "../IConsensus.sol"; import {AbstractConsensus} from "../AbstractConsensus.sol"; +import {IOwnable} from "../../access/IOwnable.sol"; /// @notice A consensus contract controlled by a single address, the owner. /// @dev This contract inherits from OpenZeppelin's `Ownable` contract. /// For more information on `Ownable`, please consult OpenZeppelin's official documentation. -contract Authority is AbstractConsensus, Ownable { +contract Authority is IAuthority, AbstractConsensus, Ownable { /// @param initialOwner The initial contract owner /// @param epochLength The epoch length /// @dev Reverts if the epoch length is zero. @@ -30,7 +32,7 @@ contract Authority is AbstractConsensus, Ownable { address appContract, uint256 lastProcessedBlockNumber, bytes32 claim - ) external onlyOwner { + ) external override onlyOwner { emit ClaimSubmission( msg.sender, appContract, @@ -39,4 +41,18 @@ contract Authority is AbstractConsensus, Ownable { ); _acceptClaim(appContract, lastProcessedBlockNumber, claim); } + + function owner() public view override(IOwnable, Ownable) returns (address) { + return super.owner(); + } + + function renounceOwnership() public override(IOwnable, Ownable) { + super.renounceOwnership(); + } + + function transferOwnership( + address newOwner + ) public override(IOwnable, Ownable) { + super.transferOwnership(newOwner); + } } diff --git a/contracts/consensus/authority/IAuthority.sol b/contracts/consensus/authority/IAuthority.sol new file mode 100644 index 00000000..f2843860 --- /dev/null +++ b/contracts/consensus/authority/IAuthority.sol @@ -0,0 +1,10 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +pragma solidity ^0.8.8; + +import {IOwnable} from "../../access/IOwnable.sol"; +import {IConsensus} from "../IConsensus.sol"; + +/// @notice A consensus contract controlled by a single address, the owner. +interface IAuthority is IConsensus, IOwnable {} diff --git a/test/foundry/consensus/authority/Authority.t.sol b/test/foundry/consensus/authority/Authority.t.sol index 16aec45c..62ba9beb 100644 --- a/test/foundry/consensus/authority/Authority.t.sol +++ b/test/foundry/consensus/authority/Authority.t.sol @@ -8,21 +8,34 @@ import {Vm} from "forge-std/Vm.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Authority} from "contracts/consensus/authority/Authority.sol"; +import {IAuthority} from "contracts/consensus/authority/IAuthority.sol"; import {IConsensus} from "contracts/consensus/IConsensus.sol"; +import {IOwnable} from "contracts/access/IOwnable.sol"; import {TestBase} from "../../util/TestBase.sol"; import {LibTopic} from "../../util/LibTopic.sol"; +import {OwnableTest} from "../../util/OwnableTest.sol"; -contract AuthorityTest is TestBase { +contract AuthorityTest is TestBase, OwnableTest { using LibTopic for address; + IAuthority _authority; + + function setUp() external { + _authority = new Authority(vm.addr(1), 1); + } + + function _getOwnableContract() internal view override returns (IOwnable) { + return _authority; + } + function testConstructor(address owner, uint256 epochLength) public { vm.assume(owner != address(0)); vm.assume(epochLength > 0); vm.recordLogs(); - Authority authority = new Authority(owner, epochLength); + IAuthority authority = new Authority(owner, epochLength); Vm.Log[] memory entries = vm.getRecordedLogs(); @@ -80,7 +93,7 @@ contract AuthorityTest is TestBase { vm.assume(owner != notOwner); vm.assume(epochLength > 0); - Authority authority = new Authority(owner, epochLength); + IAuthority authority = new Authority(owner, epochLength); vm.expectRevert( abi.encodeWithSelector( @@ -103,7 +116,7 @@ contract AuthorityTest is TestBase { vm.assume(owner != address(0)); vm.assume(epochLength > 0); - Authority authority = new Authority(owner, epochLength); + IAuthority authority = new Authority(owner, epochLength); _expectClaimEvents( authority, @@ -128,13 +141,13 @@ contract AuthorityTest is TestBase { vm.assume(owner != address(0)); vm.assume(epochLength > 0); - Authority authority = new Authority(owner, epochLength); + IAuthority authority = new Authority(owner, epochLength); assertFalse(authority.wasClaimAccepted(appContract, claim)); } function _expectClaimEvents( - Authority authority, + IAuthority authority, address owner, address appContract, uint256 lastProcessedBlockNumber,