Skip to content

Commit

Permalink
test(contracts): add missing base tests to reach max code coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
0xjei committed Nov 27, 2024
1 parent c4be681 commit 0b07847
Show file tree
Hide file tree
Showing 5 changed files with 851 additions and 51 deletions.
11 changes: 10 additions & 1 deletion packages/contracts/.solcover.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
module.exports = {

Check warning on line 1 in packages/contracts/.solcover.js

View workflow job for this annotation

GitHub Actions / style

File ignored by default.
istanbulFolder: "../../coverage/contracts"
istanbulFolder: "../../coverage/contracts",
skipFiles: [
"test/Base.t.sol",
"test/base/BaseERC721Checker.sol",
"test/base/BaseERC721Policy.sol",
"test/base/BaseVoting.sol",
"test/utils/NFT.sol",
"test/wrappers/BaseERC721CheckerHarness.sol",
"test/wrappers/BaseERC721PolicyHarness.sol"
]
}
8 changes: 7 additions & 1 deletion packages/contracts/contracts/src/Policy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ abstract contract Policy is IPolicy, Ownable(msg.sender) {
/// @dev The target can be any contract address that requires a prior check to enable logic.
/// For example, the target is a Semaphore group that requires the subject
/// to meet certain criteria before joining.
address public target;
address internal target;

/// @notice Modifier that restricts access to the target address.
modifier onlyTarget() {
Expand All @@ -30,4 +30,10 @@ abstract contract Policy is IPolicy, Ownable(msg.sender) {

emit TargetSet(_target);
}

/// @notice Retrieves the current target address.
/// @return The address of the current target.
function getTarget() public view returns (address) {
return target;
}
}
338 changes: 338 additions & 0 deletions packages/contracts/contracts/src/test/Base.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ pragma solidity 0.8.27;
import {Test} from "forge-std/src/Test.sol";
import {NFT} from "./utils/NFT.sol";
import {BaseERC721Checker} from "./base/BaseERC721Checker.sol";
import {BaseERC721Policy} from "./base/BaseERC721Policy.sol";
import {BaseVoting} from "./base/BaseVoting.sol";
import {BaseERC721CheckerHarness} from "./wrappers/BaseERC721CheckerHarness.sol";
import {BaseERC721PolicyHarness} from "./wrappers/BaseERC721PolicyHarness.sol";
import {IPolicy} from "../interfaces/IPolicy.sol";
import {IBasePolicy} from "../interfaces/IBasePolicy.sol";
import {IERC721Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract BaseChecker is Test {
NFT internal nft;
Expand Down Expand Up @@ -85,3 +91,335 @@ contract BaseChecker is Test {
vm.stopPrank();
}
}

contract BasePolicy is Test {
NFT internal nft;
BaseERC721Checker internal checker;
BaseERC721Policy internal policy;
BaseERC721CheckerHarness internal checkerHarness;
BaseERC721PolicyHarness internal policyHarness;

address public deployer = vm.addr(0x1);
address public target = vm.addr(0x2);
address public subject = vm.addr(0x3);
address public notOwner = vm.addr(0x4);

function setUp() public virtual {
vm.startPrank(deployer);

nft = new NFT();
checker = new BaseERC721Checker(nft);
checkerHarness = new BaseERC721CheckerHarness(nft);
policy = new BaseERC721Policy(checker);
policyHarness = new BaseERC721PolicyHarness(checker);

vm.stopPrank();
}

function test_trait() public view {
assertEq(policy.trait(), "BaseERC721");
}

function test_setTarget_RevertWhen_OwnableUnauthorizedAccount() public {
vm.startPrank(notOwner);

vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, notOwner));
policy.setTarget(target);

vm.stopPrank();
}

function test_setTarget_RevertWhen_ZeroAddress() public {
vm.startPrank(deployer);

vm.expectRevert(abi.encodeWithSelector(IPolicy.ZeroAddress.selector));
policy.setTarget(address(0));

vm.stopPrank();
}

function test_setTarget() public {
vm.startPrank(deployer);

vm.expectEmit(true, true, true, true);
emit IPolicy.TargetSet(target);

policy.setTarget(target);

vm.stopPrank();
}

function test_setTarget_RevertWhen_TargetAlreadySet() public {
vm.startPrank(deployer);

policy.setTarget(target);

vm.expectRevert(abi.encodeWithSelector(IPolicy.TargetAlreadySet.selector));
policy.setTarget(target);

vm.stopPrank();
}

function test_enforce_RevertWhen_TargetOnly() public {
vm.startPrank(deployer);

policy.setTarget(target);

vm.stopPrank();

vm.startPrank(subject);

vm.expectRevert(abi.encodeWithSelector(IPolicy.TargetOnly.selector));
policy.enforce(subject, abi.encode(0x0));

vm.stopPrank();
}

function test_enforce_RevertWhen_ERC721NonexistentToken() public {
vm.startPrank(deployer);

policy.setTarget(target);

vm.stopPrank();

vm.startPrank(target);

vm.expectRevert(abi.encodeWithSelector(IERC721Errors.ERC721NonexistentToken.selector, uint256(0)));
policy.enforce(subject, abi.encode(0x0));

vm.stopPrank();
}

function test_enforce_RevertWhen_UnsuccessfulCheck() public {
vm.startPrank(deployer);

policy.setTarget(target);
nft.mint(subject);

vm.stopPrank();

vm.startPrank(target);

vm.expectRevert(abi.encodeWithSelector(IPolicy.UnsuccessfulCheck.selector));
policy.enforce(notOwner, abi.encode(0x0));

vm.stopPrank();
}

function test_enforce() public {
vm.startPrank(deployer);

policy.setTarget(target);
nft.mint(subject);

vm.stopPrank();

vm.startPrank(target);

vm.expectEmit(true, true, true, true);
emit IBasePolicy.Enforced(subject, target, abi.encode(0x0));

policy.enforce(subject, abi.encode(0x0));

vm.stopPrank();
}

function test_enforce_RevertWhen_AlreadyEnforced() public {
vm.startPrank(deployer);

policy.setTarget(target);
nft.mint(subject);

vm.stopPrank();

vm.startPrank(target);

policy.enforce(subject, abi.encode(0x0));

vm.expectRevert(abi.encodeWithSelector(IPolicy.AlreadyEnforced.selector));
policy.enforce(subject, abi.encode(0x0));

vm.stopPrank();
}
}

contract Voting is Test {
NFT internal nft;
BaseERC721Checker internal checker;
BaseERC721Policy internal policy;
BaseVoting internal voting;
BaseERC721CheckerHarness internal checkerHarness;
BaseERC721PolicyHarness internal policyHarness;

address public deployer = vm.addr(0x1);
address public subject = vm.addr(0x2);
address public notOwner = vm.addr(0x3);

function setUp() public virtual {
vm.startPrank(deployer);

nft = new NFT();
checker = new BaseERC721Checker(nft);
checkerHarness = new BaseERC721CheckerHarness(nft);
policy = new BaseERC721Policy(checker);
policyHarness = new BaseERC721PolicyHarness(checker);
voting = new BaseVoting(policy);

vm.stopPrank();
}

function test_register_RevertWhen_TargetOnly() public {
vm.startPrank(deployer);

policy.setTarget(deployer);
nft.mint(subject);

vm.stopPrank();

vm.startPrank(notOwner);

vm.expectRevert(abi.encodeWithSelector(IPolicy.TargetOnly.selector));
voting.register(0);

vm.stopPrank();
}

function test_register_RevertWhen_ERC721NonexistentToken() public {
vm.startPrank(deployer);

policy.setTarget(address(voting));
nft.mint(subject);

vm.stopPrank();

vm.startPrank(subject);

vm.expectRevert(abi.encodeWithSelector(IERC721Errors.ERC721NonexistentToken.selector, uint256(1)));
voting.register(1);

vm.stopPrank();
}

function test_register_RevertWhen_UnsuccessfulCheck() public {
vm.startPrank(deployer);

policy.setTarget(address(voting));
nft.mint(subject);

vm.stopPrank();

vm.startPrank(notOwner);

vm.expectRevert(abi.encodeWithSelector(IPolicy.UnsuccessfulCheck.selector));
voting.register(0);

vm.stopPrank();
}

function test_register() public {
vm.startPrank(deployer);

policy.setTarget(address(voting));
nft.mint(subject);

vm.stopPrank();

vm.startPrank(subject);

vm.expectEmit(true, true, true, true);
emit BaseVoting.Registered(subject);

voting.register(0);

vm.stopPrank();
}

function test_register_RevertWhen_AlreadyEnforced() public {
vm.startPrank(deployer);

policy.setTarget(address(voting));
nft.mint(subject);

vm.stopPrank();

vm.startPrank(subject);

voting.register(0);

vm.expectRevert(abi.encodeWithSelector(IPolicy.AlreadyEnforced.selector));
voting.register(0);

vm.stopPrank();
}

function test_vote_RevertWhen_NotRegistered() public {
vm.startPrank(deployer);

policy.setTarget(address(voting));
nft.mint(subject);

vm.stopPrank();

vm.startPrank(subject);

vm.expectRevert(abi.encodeWithSelector(BaseVoting.NotRegistered.selector));
voting.vote(0);

vm.stopPrank();
}

function test_vote_RevertWhen_InvalidOption() public {
vm.startPrank(deployer);

policy.setTarget(address(voting));
nft.mint(subject);

vm.stopPrank();

vm.startPrank(subject);
voting.register(0);

vm.expectRevert(abi.encodeWithSelector(BaseVoting.InvalidOption.selector));
voting.vote(3);

vm.stopPrank();
}

function test_vote() public {
vm.startPrank(deployer);

policy.setTarget(address(voting));
nft.mint(subject);

vm.stopPrank();

vm.startPrank(subject);
voting.register(0);

vm.expectEmit(true, true, true, true);
emit BaseVoting.Voted(subject, 0);

voting.vote(0);

vm.stopPrank();
}

function test_vote_RevertWhen_AlreadyVoted() public {
vm.startPrank(deployer);

policy.setTarget(address(voting));
nft.mint(subject);

vm.stopPrank();

vm.startPrank(subject);

voting.register(0);
voting.vote(0);

vm.expectRevert(abi.encodeWithSelector(BaseVoting.AlreadyVoted.selector));
voting.vote(0);

vm.stopPrank();
}
}
Loading

0 comments on commit 0b07847

Please sign in to comment.