Skip to content

Commit

Permalink
Test/tasks (#120)
Browse files Browse the repository at this point in the history
* refactor: registerTask(s) return value

* test: init registerTasks, creatContributions

* refactor: contribution{'' => 'Id'}sInPeriod

* test: taskFactory.createContributions pass test draft

* test: draft TaskManager create, commit, give contributions

* chore: compile

* test: pass
  • Loading branch information
pegahcarter authored Oct 17, 2024
1 parent 8ddfc75 commit 85414df
Show file tree
Hide file tree
Showing 14 changed files with 420 additions and 25 deletions.
13 changes: 9 additions & 4 deletions contracts/tasks/TaskFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ contract TaskFactory is ITaskFactory, Initializable, PeriodUtils, AccessUtils {

EnumerableSet.Bytes32Set private _contributionIds;
mapping(bytes32 => Contribution) public _contributions;
mapping(uint32 periodId => bytes32[] contributionIds) public _contributionsInPeriod;
mapping(uint32 periodId => bytes32[] contributionIds) public _contributionIdsInPeriod;

constructor() {
_disableInitializers();
Expand Down Expand Up @@ -79,13 +79,18 @@ contract TaskFactory is ITaskFactory, Initializable, PeriodUtils, AccessUtils {
if (!ITaskRegistry(taskRegistry()).isTaskId(contribution.taskId)) revert TaskIdNotRegistered();
if (contribution.quantity == 0) revert InvalidContributionQuantity(); // TODO: max quantity?
if (contribution.points == 0 || contribution.points > 10) revert InvalidContributionPoints();
/// @dev: startDate can be in the past but endDate must be in the future
if (block.timestamp > contribution.endDate || contribution.startDate >= contribution.endDate)
revert InvalidContributionPeriod();
// TODO: additional contribution checks

bytes memory encodedContribution = encodeContribution(contribution);
bytes32 contributionId = keccak256(encodedContribution);
if (!_contributionIds.add(contributionId)) revert ContributionIdAlreadyExists();

_contributions[contributionId] = contribution;
_contributionsInPeriod[currentPeriodId()].push(contributionId);
// TODO: for each period contribution is active, push
_contributionIdsInPeriod[currentPeriodId()].push(contributionId);

ITaskManager(taskManager()).addContribution(contributionId, contribution);

Expand Down Expand Up @@ -179,8 +184,8 @@ contract TaskFactory is ITaskFactory, Initializable, PeriodUtils, AccessUtils {
}

/// @inheritdoc ITaskFactory
function contributionsInPeriod(uint32 periodId) external view returns (bytes32[] memory) {
return _contributionsInPeriod[periodId];
function contributionIdsInPeriod(uint32 periodId) external view returns (bytes32[] memory) {
return _contributionIdsInPeriod[periodId];
}

/// @inheritdoc ITaskFactory
Expand Down
10 changes: 8 additions & 2 deletions contracts/tasks/TaskManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ contract TaskManager is ITaskManager, Initializable, PeriodUtils, AccessUtils {
quantityRemaining: contribution.quantity
});
contributionStatuses[contributionId] = contributionStatus;
pointsActive += contribution.points * contribution.quantity;

emit AddContribution(contributionId, encodeContributionStatus(contributionStatus));
}
Expand Down Expand Up @@ -151,7 +152,7 @@ contract TaskManager is ITaskManager, Initializable, PeriodUtils, AccessUtils {

/// @inheritdoc ITaskManager
function giveContributions(bytes32[] calldata contributionIds, address[] calldata whos) external {
if (!isContributionManager(msg.sender) && _isAdmin(msg.sender)) revert UnauthorizedContributionManager();
if (!isContributionManager(msg.sender) && !_isAdmin(msg.sender)) revert UnauthorizedContributionManager();
writePointSummary();

uint256 length = contributionIds.length;
Expand All @@ -163,7 +164,7 @@ contract TaskManager is ITaskManager, Initializable, PeriodUtils, AccessUtils {

/// @inheritdoc ITaskManager
function giveContribution(bytes32 contributionId, address who) external {
if (!isContributionManager(msg.sender) && _isAdmin(msg.sender)) revert UnauthorizedContributionManager();
if (!isContributionManager(msg.sender) && !_isAdmin(msg.sender)) revert UnauthorizedContributionManager();
writePointSummary();
_giveContribution(contributionId, who);
}
Expand Down Expand Up @@ -257,6 +258,11 @@ contract TaskManager is ITaskManager, Initializable, PeriodUtils, AccessUtils {
return contributionStatuses[contributionId];
}

/// @inheritdoc ITaskManager
function getMemberActivity(address who, uint32 periodId) external view returns (MemberActivity memory) {
return memberActivities[who][periodId];
}

/// @inheritdoc ITaskManager
function getContributionPoints(bytes32 contributionId) external view returns (uint128) {
return contributionStatuses[contributionId].points;
Expand Down
2 changes: 2 additions & 0 deletions contracts/tasks/TaskRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ contract TaskRegistry is ITaskRegistry {
EnumerableSet.Bytes32Set private _taskIds;
mapping(bytes32 => Task) private _tasks;

// TODO: access control ?

/// @inheritdoc ITaskRegistry
function registerTasks(Task[] calldata tasks) external returns (bytes32[] memory) {
uint256 length = tasks.length;
Expand Down
3 changes: 2 additions & 1 deletion contracts/tasks/interfaces/ITaskFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ interface ITaskFactory {
error ContributionIdAlreadyExists();
error InvalidContributionQuantity();
error InvalidContributionPoints();
error InvalidContributionPeriod();
error DescriptionAlreadyRegistered();

event CreateContribution(bytes32 indexed contributionId, address indexed sender, bytes encodedContribution);
Expand Down Expand Up @@ -72,7 +73,7 @@ interface ITaskFactory {
function contributionIds() external view returns (bytes32[] memory);

/// @notice return all Contribution ids created within a given period
function contributionsInPeriod(uint32 periodId) external view returns (bytes32[] memory);
function contributionIdsInPeriod(uint32 periodId) external view returns (bytes32[] memory);

/// @notice convert a Description struct into its' respective bytes
function encodeDescription(Description memory description) external pure returns (bytes memory);
Expand Down
3 changes: 3 additions & 0 deletions contracts/tasks/interfaces/ITaskManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ interface ITaskManager {
/// @notice return the ContributionStatus of a given contributionId
function getContributionStatus(bytes32 contributionId) external view returns (ContributionStatus memory);

/// @notice Return the MemberActivity of a given address and periodId
function getMemberActivity(address who, uint32 periodId) external view returns (MemberActivity memory);

/// @notice return the amount of points associated to a contributionId
function getContributionPoints(bytes32 contributionId) external view returns (uint128);

Expand Down
2 changes: 1 addition & 1 deletion test/AutDeployedSetup.t.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
pragma solidity ^0.8.20;

// import "ds-test/test.sol";
// import "forge-std/Vm.sol";
Expand Down
61 changes: 57 additions & 4 deletions test/BaseTest.sol
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
pragma solidity ^0.8.20;

import "script/DeployAll.s.sol";
import { Hub } from "contracts/hub/Hub.sol";
import { TaskRegistry, ITaskRegistry, Task } from "contracts/tasks/TaskRegistry.sol";
import { TaskFactory, ITaskFactory, Contribution, Description } from "contracts/tasks/TaskFactory.sol";
import { TaskManager, ITaskManager, MemberActivity } from "contracts/tasks/TaskManager.sol";

import { console, StdAssertions, StdChains, StdCheats, stdError, StdInvariant, stdJson, stdMath, StdStorage, stdStorage, StdUtils, Vm, StdStyle, TestBase, Test } from "forge-std/Test.sol";

abstract contract BaseTest is Test {
AutID public autId;
HubRegistry public hubRegistry;
TaskRegistry public taskRegistry;
GlobalParameters public globalParameters;
HubDomainsRegistry public hubDomainsRegistry;

Hub public hub;
TaskFactory public taskFactory;
TaskManager public taskManager;

address public owner = address(this);
address public alice = address(0x411Ce);
address public bob = address(0xb0b);
address public bot = address(0xb01);

function setUp() public virtual {
// setup and run deployment script
Expand All @@ -30,8 +38,14 @@ abstract contract BaseTest is Test {
hubRegistry = deploy.hubRegistry();
globalParameters = deploy.globalParameters();
hubDomainsRegistry = deploy.hubDomainsRegistry();
taskRegistry = deploy.taskRegistry();

hub = _deployHub();
taskFactory = TaskFactory(hub.taskFactory());
taskManager = TaskManager(hub.taskManager());

_deployHub();
// initial setup: alice is first member
_joinHub(alice, address(hub), "alice");

// labeling
vm.label(owner, "Owner");
Expand All @@ -44,7 +58,7 @@ abstract contract BaseTest is Test {
}

/// @dev deploy a basic hub
function _deployHub() internal {
function _deployHub() internal returns (Hub) {
uint256[] memory roles = new uint256[](3);
roles[0] = 1;
roles[1] = 2;
Expand All @@ -56,6 +70,45 @@ abstract contract BaseTest is Test {
metadata: "Mock Metadata",
commitment: 1
});
hub = Hub(hubAddress);
return Hub(hubAddress);
}

function _joinHub(
address who,
address hubAddress,
string memory username) internal {
vm.prank(who);
autId.createRecordAndJoinHub({
role: 1,
commitment: 1,
hub: hubAddress,
username: username,
optionalURI: "https://facebook.com/someUser"
});
}

function _createContribution(
address who,
address hubAddress,
bytes32 taskId,
bytes32 descriptionId,
uint256 role,
uint32 startDate,
uint32 endDate,
uint32 points,
uint128 quantity
) internal {
vm.prank(who);
Contribution memory contribution = Contribution({
taskId: taskId,
descriptionId: descriptionId,
role: role,
startDate: startDate,
endDate: endDate,
points: points,
quantity: quantity
});
TaskFactory(Hub(hubAddress).taskFactory()).createContribution(contribution);

}
}
6 changes: 3 additions & 3 deletions test/unit/autId/AutIDCreateRecordAndJoinNovaUnitTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ contract AutIDCreateRecordandJoinHubUnitTest is BaseTest {

function test_createRecordAndJoinHub_succeeds() public {

vm.prank(alice);
vm.prank(bob);
autId.createRecordAndJoinHub({
role: 1,
commitment: 1,
hub: address(hub),
username: "alice",
optionalURI: "https://facebook.com/alice"
username: "bob",
optionalURI: "https://facebook.com/bob"
});

// check autId.mintedAt()
Expand Down
18 changes: 8 additions & 10 deletions test/unit/autId/AutIDJoinNovaUnitTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ contract AutIDJoinHubUnitTest is BaseTest {
}

function test_CreateRecordAndJoinHub_Succeeds() public {
vm.prank(alice);
autId.createRecordAndJoinHub(
{
role: 1,
commitment: 3,
hub: address(hub),
username: "alice",
optionalURI: "ipfs://QmXZnZ"
}
);
vm.prank(bob);
autId.createRecordAndJoinHub({
role: 1,
commitment: 3,
hub: address(hub),
username: "bob",
optionalURI: "https://facebook.com/bob"
});
}
}
78 changes: 78 additions & 0 deletions test/unit/tasks/TaskFactory/CreateContributionsTest.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "test/BaseTest.sol";

contract TaskFactoryCreateContributionsTest is BaseTest {

// Generic contribution values
bytes32 taskId;
bytes32 descriptionId;
uint256 role = 1;
uint32 startDate;
uint32 endDate;
uint32 points = 6;
uint128 quantity = 10;
Contribution contribution;

function setUp() public override {
super.setUp();

// register alice as an admin
vm.prank(hub.owner());
hub.addAdmin(alice);

// init Contribution for testing
taskId = taskRegistry.registerTask(Task({uri: "abcde"}));
descriptionId = taskFactory.registerDescription(Description({uri: "fghij"}));

startDate = uint32(block.timestamp);
endDate = startDate + 7 days;
contribution = Contribution({
taskId: taskId,
descriptionId: descriptionId,
role: role,
startDate: startDate,
endDate: endDate,
points: points,
quantity: quantity
});
}

function test_CreateContribution_succeeds() public {
// pre-action asserts
bytes32[] memory contributionIds = taskFactory.contributionIds();
assertEq(contributionIds.length, 0);

uint32 currentPeriodId = taskFactory.currentPeriodId();
bytes32[] memory contributionIdsInPeriod = taskFactory.contributionIdsInPeriod(currentPeriodId);
assertEq(contributionIdsInPeriod.length, 0);

// action
vm.prank(alice);
bytes32 contributionId = taskFactory.createContribution(contribution);

// post-action asserts
assertTrue(contributionId != bytes32(0x0));
assertTrue(taskFactory.isContributionId(contributionId));

Contribution memory queriedContribution = taskFactory.getContributionById(contributionId);
assertEq(queriedContribution.taskId, taskId);
assertEq(queriedContribution.descriptionId, descriptionId);
assertEq(queriedContribution.role, role);
assertEq(queriedContribution.startDate, startDate);
assertEq(queriedContribution.endDate, endDate);
assertEq(queriedContribution.points, points);
assertEq(queriedContribution.quantity, quantity);

contributionIds = taskFactory.contributionIds();
assertEq(contributionIds.length, 1);
assertEq(contributionIds[0], contributionId);

contributionIdsInPeriod = taskFactory.contributionIdsInPeriod(currentPeriodId);
assertEq(contributionIdsInPeriod.length, 1);
assertEq(contributionIdsInPeriod[0], contributionId);
}

// TODO: revert cases
}
Loading

0 comments on commit 85414df

Please sign in to comment.