Skip to content

Commit

Permalink
test: unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
moebius committed Nov 19, 2023
1 parent 493f56b commit 0f66730
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 61 deletions.
192 changes: 144 additions & 48 deletions solidity/test/unit/modules/resolution/PrivateERC20ResolutionModule.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
PrivateERC20ResolutionModule,
IPrivateERC20ResolutionModule
} from '../../../../contracts/modules/resolution/PrivateERC20ResolutionModule.sol';
import {IAccountingExtension} from '../../../../interfaces/extensions/IAccountingExtension.sol';

contract ForTest_PrivateERC20ResolutionModule is PrivateERC20ResolutionModule {
constructor(IOracle _oracle) PrivateERC20ResolutionModule(_oracle) {}
Expand Down Expand Up @@ -71,23 +72,29 @@ contract BaseTest is Test, Helpers {
* @dev Helper function to store commitments and reveal votes.
*/
function _populateVoters(
bytes32 _requestId,
bytes32 _disputeId,
IOracle.Request storage _request,
IOracle.Dispute storage _dispute,
uint256 _amountOfVoters,
uint256 _amountOfVotes
) internal returns (uint256 _totalVotesCast) {
bytes32 _disputeId = _getId(_dispute);
bytes32 _requestId = _getId(_request);

Check warning on line 81 in solidity/test/unit/modules/resolution/PrivateERC20ResolutionModule.t.sol

View workflow job for this annotation

GitHub Actions / Run Linters (16.x)

Variable "_requestId" is unused
for (uint256 _i = 1; _i <= _amountOfVoters;) {
vm.warp(120_000);
vm.startPrank(vm.addr(_i));
bytes32 _commitment = module.computeCommitment(_disputeId, _amountOfVotes, bytes32(_i)); // index as salt
module.commitVote(mockRequest, mockDispute, _commitment);
_mockAndExpect(address(oracle), abi.encodeCall(IOracle.createdAt, (_disputeId)), abi.encode(1));
_mockAndExpect(
address(oracle), abi.encodeCall(IOracle.disputeStatus, (_disputeId)), abi.encode(IOracle.DisputeStatus.None)
);
module.commitVote(_request, _dispute, _commitment);
vm.warp(140_001);
vm.mockCall(
address(token),
abi.encodeCall(IERC20.transferFrom, (vm.addr(_i), address(module), _amountOfVotes)),
abi.encode()
);
module.revealVote(mockRequest, mockDispute, _amountOfVotes, bytes32(_i));
module.revealVote(_request, _dispute, _amountOfVotes, bytes32(_i));
vm.stopPrank();
_totalVotesCast += _amountOfVotes;
unchecked {
Expand Down Expand Up @@ -135,21 +142,26 @@ contract PrivateERC20ResolutionModule_Unit_CommitVote is BaseTest {
/**
* @notice Test that a user can store a vote commitment for a dispute
*/
function test_commitVote(
bytes32 _requestId,
bytes32 _disputeId,
uint256 _amountOfVotes,
bytes32 _salt,
address _voter
) public {
function test_commitVote(uint256 _amountOfVotes, bytes32 _salt, address _voter) public {
// Set mock request data with 40_000 committing time window
mockRequest.resolutionModuleData = abi.encode(
IPrivateERC20ResolutionModule.RequestParameters({
accountingExtension: IAccountingExtension(makeAddr('AccountingExtension')),
votingToken: token,
minVotesForQuorum: 1,
committingTimeWindow: 40_000,
revealingTimeWindow: 40_000
})
);

// Compute proper ids
bytes32 _requestId = _getId(mockRequest);
mockDispute.requestId = _requestId;
bytes32 _disputeId = _getId(mockDispute);

// Store mock escalation data with startTime 100_000
module.forTest_setStartTime(_disputeId, 100_000);

// Store mock request data with 40_000 committing time window
uint256 _minVotesForQuorum = 1;
uint256 _committingTimeWindow = 40_000;
uint256 _revealingTimeWindow = 40_000;

// Set timestamp for valid committingTimeWindow
vm.warp(123_456);

Expand All @@ -161,6 +173,11 @@ contract PrivateERC20ResolutionModule_Unit_CommitVote is BaseTest {
vm.expectEmit(true, true, true, true);
emit VoteCommitted(_voter, _disputeId, _commitment);

_mockAndExpect(address(oracle), abi.encodeCall(IOracle.createdAt, (_disputeId)), abi.encode(1));
_mockAndExpect(
address(oracle), abi.encodeCall(IOracle.disputeStatus, (_disputeId)), abi.encode(IOracle.DisputeStatus.None)
);

// Check: does it revert if no commitment is given?
vm.expectRevert(IPrivateERC20ResolutionModule.PrivateERC20ResolutionModule_EmptyCommitment.selector);
module.commitVote(mockRequest, mockDispute, bytes32(''));
Expand Down Expand Up @@ -188,7 +205,11 @@ contract PrivateERC20ResolutionModule_Unit_CommitVote is BaseTest {
/**
* @notice Test that `commitVote` reverts if there is no dispute with the given`_disputeId`
*/
function test_revertIfNonExistentDispute(bytes32 _requestId, bytes32 _disputeId, bytes32 _commitment) public {
function test_revertIfNonExistentDispute(bytes32 _requestId, bytes32 _commitment) public {
mockDispute.requestId = _requestId;
bytes32 _disputeId = _getId(mockDispute);
_mockAndExpect(address(oracle), abi.encodeCall(IOracle.createdAt, (_disputeId)), abi.encode(0));

// Check: does it revert if no dispute exists?
vm.expectRevert(IPrivateERC20ResolutionModule.PrivateERC20ResolutionModule_NonExistentDispute.selector);
module.commitVote(mockRequest, mockDispute, _commitment);
Expand All @@ -197,8 +218,16 @@ contract PrivateERC20ResolutionModule_Unit_CommitVote is BaseTest {
/**
* @notice Test that `commitVote` reverts if called with `_disputeId` of an already resolved dispute.
*/
function test_revertIfAlreadyResolved(bytes32 _requestId, bytes32 _disputeId, bytes32 _commitment) public {
function test_revertIfAlreadyResolved(bytes32 _requestId, bytes32 _commitment) public {
mockDispute.requestId = _requestId;
bytes32 _disputeId = _getId(mockDispute);

// Mock dispute already resolved => DisputeStatus.Lost
_mockAndExpect(address(oracle), abi.encodeCall(IOracle.createdAt, (_disputeId)), abi.encode(1));
_mockAndExpect(
address(oracle), abi.encodeCall(IOracle.disputeStatus, (_disputeId)), abi.encode(IOracle.DisputeStatus.Lost)
);

// Check: does it revert if the dispute is already resolved?
vm.expectRevert(IPrivateERC20ResolutionModule.PrivateERC20ResolutionModule_AlreadyResolved.selector);
module.commitVote(mockRequest, mockDispute, _commitment);
Expand All @@ -207,8 +236,14 @@ contract PrivateERC20ResolutionModule_Unit_CommitVote is BaseTest {
/**
* @notice Test that `commitVote` reverts if called with `_disputeId` of a non-escalated dispute.
*/
function test_revertIfNotEscalated(bytes32 _requestId, bytes32 _disputeId, bytes32 _commitment) public {
function test_revertIfNotEscalated(bytes32 _requestId, bytes32 _commitment) public {
mockDispute.requestId = _requestId;
bytes32 _disputeId = _getId(mockDispute);

_mockAndExpect(address(oracle), abi.encodeCall(IOracle.createdAt, (_disputeId)), abi.encode(1));
_mockAndExpect(
address(oracle), abi.encodeCall(IOracle.disputeStatus, (_disputeId)), abi.encode(IOracle.DisputeStatus.None)
);

// Check: reverts if dispute is not escalated? == no escalation data
vm.expectRevert(IPrivateERC20ResolutionModule.PrivateERC20ResolutionModule_DisputeNotEscalated.selector);
Expand All @@ -218,17 +253,35 @@ contract PrivateERC20ResolutionModule_Unit_CommitVote is BaseTest {
/**
* @notice Test that `commitVote` reverts if called outside of the committing time window.
*/
function test_revertIfCommittingPhaseOver(bytes32 _requestId, bytes32 _disputeId, bytes32 _commitment) public {
function test_revertIfCommittingPhaseOver(uint256 _timestamp, bytes32 _commitment) public {
_timestamp = bound(_timestamp, 140_000, type(uint96).max);

// Set mock request data with 40_000 committing time window
mockRequest.resolutionModuleData = abi.encode(
IPrivateERC20ResolutionModule.RequestParameters({
accountingExtension: IAccountingExtension(makeAddr('AccountingExtension')),
votingToken: token,
minVotesForQuorum: 1,
committingTimeWindow: 40_000,
revealingTimeWindow: 40_000
})
);

// Compute proper IDs
bytes32 _requestId = _getId(mockRequest);
mockDispute.requestId = _requestId;
bytes32 _disputeId = _getId(mockDispute);

// Store mock escalation data with startTime 100_000
module.forTest_setStartTime(_disputeId, 100_000);

uint256 _minVotesForQuorum = 1;
uint256 _committingTimeWindow = 40_000;
uint256 _revealingTimeWindow = 40_000;

// Warp to invalid timestamp for commitment
vm.warp(150_000);
vm.warp(_timestamp);

_mockAndExpect(address(oracle), abi.encodeCall(IOracle.createdAt, (_disputeId)), abi.encode(1));
_mockAndExpect(
address(oracle), abi.encodeCall(IOracle.disputeStatus, (_disputeId)), abi.encode(IOracle.DisputeStatus.None)
);

// Check: does it revert if the committing phase is over?
vm.expectRevert(IPrivateERC20ResolutionModule.PrivateERC20ResolutionModule_CommittingPhaseOver.selector);
Expand All @@ -240,13 +293,23 @@ contract PrivateERC20ResolutionModule_Unit_RevealVote is BaseTest {
/**
* @notice Test revealing votes with proper timestamp, dispute status and commitment data.
*/
function test_revealVote(
bytes32 _requestId,
bytes32 _disputeId,
uint256 _amountOfVotes,
bytes32 _salt,
address _voter
) public {
function test_revealVote(uint256 _amountOfVotes, bytes32 _salt, address _voter) public {
// Set mock request data with 40_000 committing time window
mockRequest.resolutionModuleData = abi.encode(
IPrivateERC20ResolutionModule.RequestParameters({
accountingExtension: IAccountingExtension(makeAddr('AccountingExtension')),
votingToken: token,
minVotesForQuorum: 1,
committingTimeWindow: 40_000,
revealingTimeWindow: 40_000
})
);

// Compute proper ids
bytes32 _requestId = _getId(mockRequest);
mockDispute.requestId = _requestId;
bytes32 _disputeId = _getId(mockDispute);

// Store mock escalation data with startTime 100_000
module.forTest_setStartTime(_disputeId, 100_000);

Expand Down Expand Up @@ -298,21 +361,24 @@ contract PrivateERC20ResolutionModule_Unit_RevealVote is BaseTest {
/**
* @notice Test that `revealVote` reverts if called outside the revealing time window.
*/
function test_revertIfInvalidPhase(
bytes32 _requestId,
bytes32 _disputeId,
uint256 _numberOfVotes,
bytes32 _salt,
uint256 _timestamp
) public {
function test_revertIfInvalidPhase(uint256 _numberOfVotes, bytes32 _salt, uint256 _timestamp) public {
vm.assume(_timestamp >= 100_000 && (_timestamp <= 140_000 || _timestamp > 180_000));

module.forTest_setStartTime(_disputeId, 100_000);
mockRequest.resolutionModuleData = abi.encode(
IPrivateERC20ResolutionModule.RequestParameters({
accountingExtension: IAccountingExtension(makeAddr('AccountingExtension')),
votingToken: token,
minVotesForQuorum: 1,
committingTimeWindow: 40_000,
revealingTimeWindow: 40_000
})
);

// Store request data
uint256 _minVotesForQuorum = 1;
uint256 _committingTimeWindow = 40_000;
uint256 _revealingTimeWindow = 40_000;
// Compute proper ids
bytes32 _requestId = _getId(mockRequest);
mockDispute.requestId = _requestId;
bytes32 _disputeId = _getId(mockDispute);
module.forTest_setStartTime(_disputeId, 100_000);

// Jump to timestamp
vm.warp(_timestamp);
Expand Down Expand Up @@ -346,6 +412,21 @@ contract PrivateERC20ResolutionModule_Unit_RevealVote is BaseTest {
vm.assume(_salt != _wrongSalt);
vm.assume(_voter != _wrongVoter);

mockRequest.resolutionModuleData = abi.encode(
IPrivateERC20ResolutionModule.RequestParameters({
accountingExtension: IAccountingExtension(makeAddr('AccountingExtension')),
votingToken: token,
minVotesForQuorum: 1,
committingTimeWindow: 40_000,
revealingTimeWindow: 40_000
})
);

// Compute proper ids
bytes32 _requestId = _getId(mockRequest);
mockDispute.requestId = _requestId;
bytes32 _disputeId = _getId(mockDispute);

module.forTest_setStartTime(_disputeId, 100_000);

// Store request data
Expand Down Expand Up @@ -381,15 +462,30 @@ contract PrivateERC20ResolutionModule_Unit_ResolveDispute is BaseTest {
/**
* @notice Test that a dispute is resolved, the tokens are transferred back to the voters and the dispute status updated.
*/
function test_resolveDispute(bytes32 _requestId, bytes32 _disputeId, uint16 _minVotesForQuorum) public {
//asdf
function test_resolveDispute(uint16 _minVotesForQuorum) public {
// Store request data
uint256 _committingTimeWindow = 40_000;
uint256 _revealingTimeWindow = 40_000;
mockRequest.resolutionModuleData = abi.encode(
IPrivateERC20ResolutionModule.RequestParameters({
accountingExtension: IAccountingExtension(makeAddr('AccountingExtension')),
votingToken: token,
minVotesForQuorum: 1,
committingTimeWindow: 40_000,
revealingTimeWindow: 40_000
})
);

// Compute proper ids
bytes32 _requestId = _getId(mockRequest);
mockDispute.requestId = _requestId;
bytes32 _disputeId = _getId(mockDispute);

module.forTest_setStartTime(_disputeId, 100_000);

// Store escalation data with startTime 100_000 and votes 0
uint256 _votersAmount = 5;
// Make 5 addresses cast 100 votes each
uint256 _totalVotesCast = _populateVoters(_requestId, _disputeId, _votersAmount, 100);
uint256 _totalVotesCast = _populateVoters(mockRequest, mockDispute, _votersAmount, 100);

// Warp to resolving phase
vm.warp(190_000);
Expand Down
20 changes: 7 additions & 13 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1181,14 +1181,13 @@ dotgitignore@^2.1.0:
find-up "^3.0.0"
minimatch "^3.0.4"

"ds-test@git+https://github.com/dapphub/ds-test.git", "ds-test@git+https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0":
"ds-test@https://github.com/dapphub/ds-test":
version "1.0.0"
uid e282159d5170298eb2455a6c05280ab5a73a4ef0
resolved "git+https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0"
resolved "https://github.com/dapphub/ds-test#e282159d5170298eb2455a6c05280ab5a73a4ef0"

"ds-test@https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0":
version "1.0.0"
uid e282159d5170298eb2455a6c05280ab5a73a4ef0
resolved "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0"

eastasianwidth@^0.2.0:
Expand Down Expand Up @@ -1566,13 +1565,13 @@ for-each@^0.3.3:
dependencies:
is-callable "^1.1.3"

"forge-std@git+https://github.com/foundry-rs/forge-std.git":
version "1.7.1"
resolved "git+https://github.com/foundry-rs/forge-std.git#37a37ab73364d6644bfe11edf88a07880f99bd56"
"forge-std@https://github.com/foundry-rs/forge-std":
version "1.7.2"
resolved "https://github.com/foundry-rs/forge-std#c22437a63d1c3418869bc35a7c55a5175a09b701"

"forge-std@git+https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e":
"forge-std@https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e":
version "1.5.6"
resolved "git+https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e"
resolved "https://github.com/foundry-rs/forge-std.git#e8a047e3f40f13fa37af6fe14e6e06283d9a060e"

"forge-std@https://github.com/foundry-rs/forge-std.git#f73c73d2018eb6a111f35e4dae7b4f27401e9421":
version "1.7.1"
Expand Down Expand Up @@ -3275,13 +3274,8 @@ [email protected]:
handlebars "^4.7.7"
solidity-ast "^0.4.38"

"solmate@git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c":
version "6.1.0"
resolved "git+https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c"

"solmate@https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c":
version "6.1.0"
uid bfc9c25865a274a7827fea5abf6e4fb64fc64e6c
resolved "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c"

sort-object-keys@^1.1.3:
Expand Down

0 comments on commit 0f66730

Please sign in to comment.