From af20203b8797c95119f76c4dd9de5fc07c12c375 Mon Sep 17 00:00:00 2001 From: cometsheepboy Date: Mon, 7 Oct 2024 12:21:51 -0500 Subject: [PATCH 1/4] deployAllOrgTypes Modified for deploying Election and Education Hub to be Hybrid, Participation, StandardDecentralized Organization. made 3 integration test for these deployed orgs. --- test/deployAllOrgTypes.t.sol | 77 ++++++ test/integration/hybridOrg.t.sol | 227 ++++++++++++++++++ test/integration/participationOrg.t.sol | 225 +++++++++++++++++ .../standardDecentralizationOrg.t.sol | 224 +++++++++++++++++ 4 files changed, 753 insertions(+) create mode 100644 test/integration/hybridOrg.t.sol create mode 100644 test/integration/participationOrg.t.sol create mode 100644 test/integration/standardDecentralizationOrg.t.sol diff --git a/test/deployAllOrgTypes.t.sol b/test/deployAllOrgTypes.t.sol index 5145382..faad813 100644 --- a/test/deployAllOrgTypes.t.sol +++ b/test/deployAllOrgTypes.t.sol @@ -68,6 +68,14 @@ contract TestAllOrgTypes is Test { checkContractAddresses(directDemocracyRegistryAddress, "DirectDemocracyWithElection"); } + function testDeployDirectDemocracyWithEducation() public { + DeployDirectDemocracyOrg deployDirectDemocracyOrg = new DeployDirectDemocracyOrg(); + + directDemocracyRegistryAddress = deployDirectDemocracyOrg.run(address(masterFactory), false, true); + + checkContractAddresses(directDemocracyRegistryAddress, "DirectDemocracyWithEducation"); + } + function testDeployHybridVotingWithEducationHub() public { DeployHybridOrg deployHybridOrg = new DeployHybridOrg(); @@ -76,6 +84,24 @@ contract TestAllOrgTypes is Test { checkContractAddresses(hybridVotingRegistryAddress, "HybridVotingWithEducationHub"); } + function testDeployHybridVotingWithElectionHub() public { + DeployHybridOrg deployHybridOrg = new DeployHybridOrg(); + hybridVotingRegistryAddress = deployHybridOrg.run(address(masterFactory), true, false); + checkContractAddresses(hybridVotingRegistryAddress, "HybridVotingWithElectionHub"); + } + + function testDeployParticipationVotingWithElection() public { + DeployParticipationOrg deployParticipationOrg = new DeployParticipationOrg(); + participationVotingRegistryAddress = deployParticipationOrg.run(address(masterFactory), true, false); + checkContractAddresses(participationVotingRegistryAddress, "ParticipationVotingWithElection"); + } + + function testDeployParticipationVotingWithEducation() public { + DeployParticipationOrg deployParticipationOrg = new DeployParticipationOrg(); + participationVotingRegistryAddress = deployParticipationOrg.run(address(masterFactory), false, true); + checkContractAddresses(participationVotingRegistryAddress, "ParticipationVotingWithEducation"); + } + function checkContractAddresses(address registryAddress, string memory deploymentType) internal view { Registry registry = Registry(registryAddress); @@ -125,6 +151,19 @@ contract TestAllOrgTypes is Test { assertTrue(directDemocracyVoting != address(0), "DirectDemocracyVoting address is invalid"); assertTrue(electionContract == address(0), "ElectionContract should not be deployed"); assertTrue(educationHub == address(0), "EducationHub should not be deployed"); + } else if ( + keccak256(abi.encodePacked(deploymentType)) == keccak256(abi.encodePacked("HybridVotingWithElectionHub")) + ) { + assertTrue(nftMembership != address(0), "NFTMembership address is invalid"); + assertTrue(directDemocracyToken != address(0), "DirectDemocracyToken address is invalid"); + assertTrue(participationToken != address(0), "ParticipationToken address is invalid"); + assertTrue(treasury != address(0), "Treasury address is invalid"); + assertTrue(hybridVotingAddress != address(0), "HybridVoting address is invalid"); + assertTrue(taskManager != address(0), "TaskManager address is invalid"); + assertTrue(quickJoin != address(0), "QuickJoin address is invalid"); + assertTrue(directDemocracyVoting != address(0), "DirectDemocracyVoting address is invalid"); + assertTrue(electionContract != address(0), "ElectionHub address is invalid"); + assertTrue(educationHub == address(0), "EducationContract should not be deployed"); } else if ( keccak256(abi.encodePacked(deploymentType)) == keccak256(abi.encodePacked("DirectDemocracyWithElection")) ) { @@ -137,6 +176,18 @@ contract TestAllOrgTypes is Test { assertTrue(participationToken != address(0), "ParticipationToken address is invalid"); assertTrue(electionContract != address(0), "ElectionContract address is invalid"); assertTrue(educationHub == address(0), "EducationHub should not be deployed"); + } else if ( + keccak256(abi.encodePacked(deploymentType)) == keccak256(abi.encodePacked("DirectDemocracyWithEducation")) + ) { + assertTrue(nftMembership != address(0), "NFTMembership address is invalid"); + assertTrue(directDemocracyToken != address(0), "DirectDemocracyToken address is invalid"); + assertTrue(treasury != address(0), "Treasury address is invalid"); + assertTrue(directDemocracyVoting != address(0), "DirectDemocracyVoting address is invalid"); + assertTrue(taskManager != address(0), "TaskManager address is invalid"); + assertTrue(quickJoin != address(0), "QuickJoin address is invalid"); + assertTrue(participationToken != address(0), "ParticipationToken address is invalid"); + assertTrue(electionContract == address(0), "ElectionContract should not be deployed"); + assertTrue(educationHub != address(0), "EducationHub address is invalid"); } else if ( keccak256(abi.encodePacked(deploymentType)) == keccak256(abi.encodePacked("HybridVotingWithEducationHub")) ) { @@ -150,6 +201,32 @@ contract TestAllOrgTypes is Test { assertTrue(directDemocracyVoting != address(0), "DirectDemocracyVoting address is invalid"); assertTrue(electionContract == address(0), "ElectionContract should not be deployed"); assertTrue(educationHub != address(0), "EducationHub address is invalid"); + } else if ( + keccak256(abi.encodePacked(deploymentType)) + == keccak256(abi.encodePacked("ParticipationVotingWithEducation")) + ) { + assertTrue(nftMembership != address(0), "NFTMembership address is invalid"); + assertTrue(participationToken != address(0), "ParticipationToken address is invalid"); + assertTrue(treasury != address(0), "Treasury address is invalid"); + assertTrue(participationVoting != address(0), "ParticipationVoting address is invalid"); + assertTrue(taskManager != address(0), "TaskManager address is invalid"); + assertTrue(quickJoin != address(0), "QuickJoin address is invalid"); + assertTrue(directDemocracyVoting != address(0), "DirectDemocracyVoting address is invalid"); + assertTrue(electionContract == address(0), "ElectionContract should not be deployed"); + assertTrue(educationHub != address(0), "EducationHub address is invalid"); + } else if ( + keccak256(abi.encodePacked(deploymentType)) + == keccak256(abi.encodePacked("ParticipationVotingWithElection")) + ) { + assertTrue(nftMembership != address(0), "NFTMembership address is invalid"); + assertTrue(participationToken != address(0), "ParticipationToken address is invalid"); + assertTrue(treasury != address(0), "Treasury address is invalid"); + assertTrue(participationVoting != address(0), "ParticipationVoting address is invalid"); + assertTrue(taskManager != address(0), "TaskManager address is invalid"); + assertTrue(quickJoin != address(0), "QuickJoin address is invalid"); + assertTrue(directDemocracyVoting != address(0), "DirectDemocracyVoting address is invalid"); + assertTrue(electionContract != address(0), "ElectionContract address is invalid"); + assertTrue(educationHub == address(0), "EducationHub should not be deployed"); } else { revert("Invalid deployment type"); } diff --git a/test/integration/hybridOrg.t.sol b/test/integration/hybridOrg.t.sol new file mode 100644 index 0000000..d36eb5a --- /dev/null +++ b/test/integration/hybridOrg.t.sol @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; +import "../../src/DirectDemocracyVotingFactory.sol"; +import "../../src/DirectDemocracyTokenFactory.sol"; +import "../../src/HybridVotingFactory.sol"; +import "../../src/ParticipationTokenFactory.sol"; +import "../../src/ParticipationVotingFactory.sol"; +import "../../src/TreasuryFactory.sol"; +import "../../src/MembershipNFTFactory.sol"; +import "../../src/RegistryFactory.sol"; +import "../../src/TaskManagerFactory.sol"; +import "../../src/QuickJoinFactory.sol"; +import "../../src/MasterDeployFactory.sol"; +import "../../src/UniversalAccountRegistry.sol"; +import "../../src/HybridVoting.sol"; +import "../../src/Registry.sol"; +import "../../src/ElectionContract.sol"; +import "../../src/MembershipNFT.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import {DeployMasterFactory} from "../../script/DeployMasterFactory.s.sol"; +import {DeployDirectDemocracyOrg} from "../../script/DeployDirectDemocracyOrg.s.sol"; +import {DeployParticipationOrg} from "../../script/DeployParticipationOrg.s.sol"; +import {DeployHybridOrg} from "../../script/DeployHybridOrg.s.sol"; + +contract MockParticipationToken2 is IParticipationToken2 { + mapping(address => uint256) public balances; + + function mint(address to, uint256 amount) external override { + balances[to] += amount; + } + + function totalSupply() external view override returns (uint256) { + return 0; + } + + function balanceOf(address account) external view override returns (uint256) { + return balances[account]; + } + + function transfer(address recipient, uint256 amount) external override returns (bool) { + return false; + } + + function allowance(address owner, address spender) external view override returns (uint256) { + return 0; + } + + function approve(address spender, uint256 amount) external override returns (bool) { + return false; + } + + function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { + return false; + } +} + +contract MockNFTMembership11 is INFTMembership11 { + mapping(address => string) public memberTypes; + mapping(address => bool) public executives; + + function checkMemberTypeByAddress(address user) external view override returns (string memory) { + return memberTypes[user]; + } + + function checkIsExecutive(address user) external view override returns (bool) { + return executives[user]; + } + + function setMemberType(address user, string memory memberType) external { + memberTypes[user] = memberType; + } + + function setExecutive(address user, bool isExec) external { + executives[user] = isExec; + } +} + +contract HybridOrgTest is Test { + MasterFactory masterFactory; + HybridVoting hybridVoting; + address directDemocracyRegistryAddress; + address participationVotingRegistryAddress; + address hybridVotingRegistryAddress; + + function setUp() public { + DeployMasterFactory deployMasterFactory = new DeployMasterFactory(); + address masterFactoryAddress = deployMasterFactory.run(); + masterFactory = MasterFactory(masterFactoryAddress); + } + + /** + * @dev test Hybrid Organization with 2 test configurations + * With the Election Hub enabled and disabled. This feature controls voting processes, election events, and governance mechanisms. + * With the Education Hub enabled and disabled. This module is responsible for guiding users through the learning curve of DAO operations and governance. + */ + + /// @dev test with Election Hub + function testHybridElectionHub() public { + //Deploy HybridOrg with Election Hub + DeployHybridOrg deployHybridOrg = new DeployHybridOrg(); + hybridVotingRegistryAddress = deployHybridOrg.run(address(masterFactory), true, false); + + ElectionContract electionContract; + NFTMembership nftMembership; + address votingContractAddress = hybridVotingRegistryAddress; + address candidate1 = address(0xDEAD); + address candidate2 = address(0xBEEF); + address candidate3 = address(0xFEED); + + string[] memory memberTypeNames = new string[](2); + memberTypeNames[0] = "Basic"; + memberTypeNames[1] = "Executive"; + + string[] memory executiveRoleNames = new string[](1); + executiveRoleNames[0] = "Executive"; + nftMembership = new NFTMembership(memberTypeNames, executiveRoleNames, "defaultImageURL"); + + electionContract = new ElectionContract(address(nftMembership), votingContractAddress); + nftMembership.setElectionContract(address(electionContract)); + + //Election Creation + vm.prank(votingContractAddress); + (uint256 electionId, uint256 proposalId) = electionContract.createElection(1); + + assertEq(electionId, 0); + assertEq(proposalId, 1); + + // Add Candidates + vm.prank(votingContractAddress); + electionContract.addCandidate(1, candidate1, "Candidate 1"); + + vm.prank(votingContractAddress); + electionContract.addCandidate(1, candidate2, "Candidate 2"); + + vm.prank(votingContractAddress); + electionContract.addCandidate(1, candidate3, "Candidate 3"); + + // Conclude Election + vm.prank(votingContractAddress); + electionContract.concludeElection(1, 2); + + // Verify Results + (bool isActive, uint256 winningCandidateIndex, bool hasValidWinner) = + electionContract.getElectionDetails(electionId); + assertFalse(isActive); + assertTrue(hasValidWinner); + assertEq(winningCandidateIndex, 2); + + // Verify Candidates + ElectionContract.Candidate[] memory candidates = electionContract.getCandidates(electionId); + assertEq(candidates.length, 3); + assertEq(candidates[0].candidateAddress, candidate1); + assertEq(candidates[1].candidateAddress, candidate2); + assertEq(candidates[2].candidateAddress, candidate3); + + // Check that the NFT was minted for the winning candidate + assertEq(nftMembership.checkMemberTypeByAddress(candidate3), "Executive"); + } + + /// @dev test with Eduction Hub + function testHybridEducationHub() public { + //Deploy HybridOrg with Education Hub + DeployHybridOrg deployHybridOrg = new DeployHybridOrg(); + hybridVotingRegistryAddress = deployHybridOrg.run(address(masterFactory), false, true); + + EducationHub educationHub; + MockParticipationToken2 token; + MockNFTMembership11 nftMembership; + + Registry registry = Registry(hybridVotingRegistryAddress); + address owner = registry.getContractAddress("EducationHub"); + address executive = address(2); + address member = address(3); + address nonMember = address(4); + + token = new MockParticipationToken2(); + nftMembership = new MockNFTMembership11(); + + // Set up roles + nftMembership.setMemberType(member, "Member"); + nftMembership.setExecutive(executive, true); + + educationHub = new EducationHub(address(token), address(nftMembership)); + + //test create module + vm.prank(executive); + educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + + (uint256 id, string memory name, string memory ipfsHash, bool exists, uint256 payout, uint8 correctAnswer) = + educationHub.modules(0); + assertEq(id, 0); + assertEq(name, "Intro to DAO"); + assertEq(ipfsHash, "ipfsHash1"); + assertTrue(exists); + assertEq(payout, 100); + assertEq(correctAnswer, 1); + + //test complete module + // Create a module as an executive + vm.prank(executive); + educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + + // Complete the module as a member + vm.prank(member); + educationHub.completeModule(0, 1); + + assertEq(token.balanceOf(member), 100); + bool completed = educationHub.completedModules(member, 0); + assertTrue(completed); + + //test remove module + // Create a module as an executive + vm.prank(executive); + educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + + // Remove the module as an executive + vm.prank(executive); + educationHub.removeModule(0); + + (,,, bool moduleExists,,) = educationHub.modules(0); + assertFalse(moduleExists); + } +} diff --git a/test/integration/participationOrg.t.sol b/test/integration/participationOrg.t.sol new file mode 100644 index 0000000..dae8727 --- /dev/null +++ b/test/integration/participationOrg.t.sol @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; +import "../../src/DirectDemocracyVotingFactory.sol"; +import "../../src/DirectDemocracyTokenFactory.sol"; +import "../../src/ParticipationVotingFactory.sol"; +import "../../src/ParticipationTokenFactory.sol"; +import "../../src/ParticipationVotingFactory.sol"; +import "../../src/TreasuryFactory.sol"; +import "../../src/MembershipNFTFactory.sol"; +import "../../src/RegistryFactory.sol"; +import "../../src/TaskManagerFactory.sol"; +import "../../src/QuickJoinFactory.sol"; +import "../../src/MasterDeployFactory.sol"; +import "../../src/UniversalAccountRegistry.sol"; +import "../../src/ParticipationVoting.sol"; +import "../../src/Registry.sol"; +import "../../src/ElectionContract.sol"; +import "../../src/MembershipNFT.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import {DeployMasterFactory} from "../../script/DeployMasterFactory.s.sol"; +import {DeployDirectDemocracyOrg} from "../../script/DeployDirectDemocracyOrg.s.sol"; +import {DeployParticipationOrg} from "../../script/DeployParticipationOrg.s.sol"; +import {DeployParticipationOrg} from "../../script/DeployParticipationOrg.s.sol"; + +contract MockParticipationToken2 is IParticipationToken2 { + mapping(address => uint256) public balances; + + function mint(address to, uint256 amount) external override { + balances[to] += amount; + } + + function totalSupply() external view override returns (uint256) { + return 0; + } + + function balanceOf(address account) external view override returns (uint256) { + return balances[account]; + } + + function transfer(address recipient, uint256 amount) external override returns (bool) { + return false; + } + + function allowance(address owner, address spender) external view override returns (uint256) { + return 0; + } + + function approve(address spender, uint256 amount) external override returns (bool) { + return false; + } + + function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { + return false; + } +} + +contract MockNFTMembership11 is INFTMembership11 { + mapping(address => string) public memberTypes; + mapping(address => bool) public executives; + + function checkMemberTypeByAddress(address user) external view override returns (string memory) { + return memberTypes[user]; + } + + function checkIsExecutive(address user) external view override returns (bool) { + return executives[user]; + } + + function setMemberType(address user, string memory memberType) external { + memberTypes[user] = memberType; + } + + function setExecutive(address user, bool isExec) external { + executives[user] = isExec; + } +} + +contract ParticipationOrgTest is Test { + MasterFactory masterFactory; + ParticipationVoting participationVoting; + address participationVotingRegistryAddress; + + function setUp() public { + DeployMasterFactory deployMasterFactory = new DeployMasterFactory(); + address masterFactoryAddress = deployMasterFactory.run(); + masterFactory = MasterFactory(masterFactoryAddress); + } + + /** + * @dev test Participation Organization with 2 test configurations + * With the Election Hub enabled and disabled. This feature controls voting processes, election events, and governance mechanisms. + * With the Education Hub enabled and disabled. This module is responsible for guiding users through the learning curve of DAO operations and governance. + */ + + /// @dev test with Election Hub + function testParticipationElectionHub() public { + //Deploy ParticipationOrg with Election Hub + DeployParticipationOrg deployParticipationOrg = new DeployParticipationOrg(); + participationVotingRegistryAddress = deployParticipationOrg.run(address(masterFactory), false, false); + + ElectionContract electionContract; + NFTMembership nftMembership; + address votingContractAddress = participationVotingRegistryAddress; + address candidate1 = address(0xDEAD); + address candidate2 = address(0xBEEF); + address candidate3 = address(0xFEED); + + string[] memory memberTypeNames = new string[](2); + memberTypeNames[0] = "Basic"; + memberTypeNames[1] = "Executive"; + + string[] memory executiveRoleNames = new string[](1); + executiveRoleNames[0] = "Executive"; + nftMembership = new NFTMembership(memberTypeNames, executiveRoleNames, "defaultImageURL"); + + electionContract = new ElectionContract(address(nftMembership), votingContractAddress); + nftMembership.setElectionContract(address(electionContract)); + + //Election Creation + vm.prank(votingContractAddress); + (uint256 electionId, uint256 proposalId) = electionContract.createElection(1); + + assertEq(electionId, 0); + assertEq(proposalId, 1); + + // Add Candidates + vm.prank(votingContractAddress); + electionContract.addCandidate(1, candidate1, "Candidate 1"); + + vm.prank(votingContractAddress); + electionContract.addCandidate(1, candidate2, "Candidate 2"); + + vm.prank(votingContractAddress); + electionContract.addCandidate(1, candidate3, "Candidate 3"); + + // Conclude Election + vm.prank(votingContractAddress); + electionContract.concludeElection(1, 2); + + // Verify Results + (bool isActive, uint256 winningCandidateIndex, bool hasValidWinner) = + electionContract.getElectionDetails(electionId); + assertFalse(isActive); + assertTrue(hasValidWinner); + assertEq(winningCandidateIndex, 2); + + // Verify Candidates + ElectionContract.Candidate[] memory candidates = electionContract.getCandidates(electionId); + assertEq(candidates.length, 3); + assertEq(candidates[0].candidateAddress, candidate1); + assertEq(candidates[1].candidateAddress, candidate2); + assertEq(candidates[2].candidateAddress, candidate3); + + // Check that the NFT was minted for the winning candidate + assertEq(nftMembership.checkMemberTypeByAddress(candidate3), "Executive"); + } + + /// @dev test with Eduction Hub + function testParticipationEducationHub() public { + //Deploy ParticipationOrg with Education Hub + DeployParticipationOrg deployParticipationOrg = new DeployParticipationOrg(); + participationVotingRegistryAddress = deployParticipationOrg.run(address(masterFactory), false, true); + + EducationHub educationHub; + MockParticipationToken2 token; + MockNFTMembership11 nftMembership; + + Registry registry = Registry(participationVotingRegistryAddress); + address owner = registry.getContractAddress("EducationHub"); + address executive = address(2); + address member = address(3); + address nonMember = address(4); + + token = new MockParticipationToken2(); + nftMembership = new MockNFTMembership11(); + + // Set up roles + nftMembership.setMemberType(member, "Member"); + nftMembership.setExecutive(executive, true); + + educationHub = new EducationHub(address(token), address(nftMembership)); + + //test create module + vm.prank(executive); + educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + + (uint256 id, string memory name, string memory ipfsHash, bool exists, uint256 payout, uint8 correctAnswer) = + educationHub.modules(0); + assertEq(id, 0); + assertEq(name, "Intro to DAO"); + assertEq(ipfsHash, "ipfsHash1"); + assertTrue(exists); + assertEq(payout, 100); + assertEq(correctAnswer, 1); + + //test complete module + // Create a module as an executive + vm.prank(executive); + educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + + // Complete the module as a member + vm.prank(member); + educationHub.completeModule(0, 1); + + assertEq(token.balanceOf(member), 100); + bool completed = educationHub.completedModules(member, 0); + assertTrue(completed); + + //test remove module + // Create a module as an executive + vm.prank(executive); + educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + + // Remove the module as an execustive + vm.prank(executive); + educationHub.removeModule(0); + + (,,, bool moduleExists,,) = educationHub.modules(0); + assertFalse(moduleExists); + } +} diff --git a/test/integration/standardDecentralizationOrg.t.sol b/test/integration/standardDecentralizationOrg.t.sol new file mode 100644 index 0000000..39014f9 --- /dev/null +++ b/test/integration/standardDecentralizationOrg.t.sol @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; +import "../../src/DirectDemocracyVotingFactory.sol"; +import "../../src/DirectDemocracyTokenFactory.sol"; +import "../../src/DirectDemocracyVotingFactory.sol"; +import "../../src/DirectDemocracyTokenFactory.sol"; +import "../../src/DirectDemocracyVotingFactory.sol"; +import "../../src/TreasuryFactory.sol"; +import "../../src/MembershipNFTFactory.sol"; +import "../../src/RegistryFactory.sol"; +import "../../src/TaskManagerFactory.sol"; +import "../../src/QuickJoinFactory.sol"; +import "../../src/MasterDeployFactory.sol"; +import "../../src/UniversalAccountRegistry.sol"; +import "../../src/DirectDemocracyVoting.sol"; +import "../../src/Registry.sol"; +import "../../src/ElectionContract.sol"; +import "../../src/MembershipNFT.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import {DeployMasterFactory} from "../../script/DeployMasterFactory.s.sol"; +import {DeployDirectDemocracyOrg} from "../../script/DeployDirectDemocracyOrg.s.sol"; +import {DeployParticipationOrg} from "../../script/DeployParticipationOrg.s.sol"; + +contract MockParticipationToken2 is IParticipationToken2 { + mapping(address => uint256) public balances; + + function mint(address to, uint256 amount) external override { + balances[to] += amount; + } + + function totalSupply() external view override returns (uint256) { + return 0; + } + + function balanceOf(address account) external view override returns (uint256) { + return balances[account]; + } + + function transfer(address recipient, uint256 amount) external override returns (bool) { + return false; + } + + function allowance(address owner, address spender) external view override returns (uint256) { + return 0; + } + + function approve(address spender, uint256 amount) external override returns (bool) { + return false; + } + + function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { + return false; + } +} + +contract MockNFTMembership11 is INFTMembership11 { + mapping(address => string) public memberTypes; + mapping(address => bool) public executives; + + function checkMemberTypeByAddress(address user) external view override returns (string memory) { + return memberTypes[user]; + } + + function checkIsExecutive(address user) external view override returns (bool) { + return executives[user]; + } + + function setMemberType(address user, string memory memberType) external { + memberTypes[user] = memberType; + } + + function setExecutive(address user, bool isExec) external { + executives[user] = isExec; + } +} + +contract DirectDemocracyOrgTest is Test { + MasterFactory masterFactory; + DirectDemocracyVoting directDemocracyVoting; + address directDemocracyVotingRegistryAddress; + + function setUp() public { + DeployMasterFactory deployMasterFactory = new DeployMasterFactory(); + address masterFactoryAddress = deployMasterFactory.run(); + masterFactory = MasterFactory(masterFactoryAddress); + } + + /** + * @dev test DirectDemocracy Organization with 2 test configurations + * With the Election Hub enabled and disabled. This feature controls voting processes, election events, and governance mechanisms. + * With the Education Hub enabled and disabled. This module is responsible for guiding users through the learning curve of DAO operations and governance. + */ + + /// @dev test with Election Hub + function testDirectDemocracyElectionHub() public { + //Deploy DirectDemocracyOrg with Election Hub + DeployDirectDemocracyOrg deployDirectDemocracyOrg = new DeployDirectDemocracyOrg(); + directDemocracyVotingRegistryAddress = deployDirectDemocracyOrg.run(address(masterFactory), false, false); + + ElectionContract electionContract; + NFTMembership nftMembership; + address votingContractAddress = directDemocracyVotingRegistryAddress; + address candidate1 = address(0xDEAD); + address candidate2 = address(0xBEEF); + address candidate3 = address(0xFEED); + + string[] memory memberTypeNames = new string[](2); + memberTypeNames[0] = "Basic"; + memberTypeNames[1] = "Executive"; + + string[] memory executiveRoleNames = new string[](1); + executiveRoleNames[0] = "Executive"; + nftMembership = new NFTMembership(memberTypeNames, executiveRoleNames, "defaultImageURL"); + + electionContract = new ElectionContract(address(nftMembership), votingContractAddress); + nftMembership.setElectionContract(address(electionContract)); + + //Election Creation + vm.prank(votingContractAddress); + (uint256 electionId, uint256 proposalId) = electionContract.createElection(1); + + assertEq(electionId, 0); + assertEq(proposalId, 1); + + // Add Candidates + vm.prank(votingContractAddress); + electionContract.addCandidate(1, candidate1, "Candidate 1"); + + vm.prank(votingContractAddress); + electionContract.addCandidate(1, candidate2, "Candidate 2"); + + vm.prank(votingContractAddress); + electionContract.addCandidate(1, candidate3, "Candidate 3"); + + // Conclude Election + vm.prank(votingContractAddress); + electionContract.concludeElection(1, 2); + + // Verify Results + (bool isActive, uint256 winningCandidateIndex, bool hasValidWinner) = + electionContract.getElectionDetails(electionId); + assertFalse(isActive); + assertTrue(hasValidWinner); + assertEq(winningCandidateIndex, 2); + + // Verify Candidates + ElectionContract.Candidate[] memory candidates = electionContract.getCandidates(electionId); + assertEq(candidates.length, 3); + assertEq(candidates[0].candidateAddress, candidate1); + assertEq(candidates[1].candidateAddress, candidate2); + assertEq(candidates[2].candidateAddress, candidate3); + + // Check that the NFT was minted for the winning candidate + assertEq(nftMembership.checkMemberTypeByAddress(candidate3), "Executive"); + } + + /// @dev test with Eduction Hub + function testDirectDemocracyEducationHub() public { + //Deploy DirectDemocracyOrg with Education Hub + DeployDirectDemocracyOrg deployDirectDemocracyOrg = new DeployDirectDemocracyOrg(); + directDemocracyVotingRegistryAddress = deployDirectDemocracyOrg.run(address(masterFactory), false, true); + + EducationHub educationHub; + MockParticipationToken2 token; + MockNFTMembership11 nftMembership; + + Registry registry = Registry(directDemocracyVotingRegistryAddress); + address owner = registry.getContractAddress("EducationHub"); + address executive = address(2); + address member = address(3); + address nonMember = address(4); + + token = new MockParticipationToken2(); + nftMembership = new MockNFTMembership11(); + + // Set up roles + nftMembership.setMemberType(member, "Member"); + nftMembership.setExecutive(executive, true); + + educationHub = new EducationHub(address(token), address(nftMembership)); + + //test create module + vm.prank(executive); + educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + + (uint256 id, string memory name, string memory ipfsHash, bool exists, uint256 payout, uint8 correctAnswer) = + educationHub.modules(0); + assertEq(id, 0); + assertEq(name, "Intro to DAO"); + assertEq(ipfsHash, "ipfsHash1"); + assertTrue(exists); + assertEq(payout, 100); + assertEq(correctAnswer, 1); + + //test complete module + // Create a module as an executive + vm.prank(executive); + educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + + // Complete the module as a member + vm.prank(member); + educationHub.completeModule(0, 1); + + assertEq(token.balanceOf(member), 100); + bool completed = educationHub.completedModules(member, 0); + assertTrue(completed); + + //test remove module + // Create a module as an executive + vm.prank(executive); + educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + + // Remove the module as an execustive + vm.prank(executive); + educationHub.removeModule(0); + + (,,, bool moduleExists,,) = educationHub.modules(0); + assertFalse(moduleExists); + } +} From c91802213a29fa4ea7130086acbb8cb31f29f3a6 Mon Sep 17 00:00:00 2001 From: cometsheepboy Date: Wed, 9 Oct 2024 08:04:58 -0500 Subject: [PATCH 2/4] Refined deploy scripts and integration tests for DAO's ElectionContract with tokens and NFTs --- script/DeployDirectDemocracyOrg.s.sol | 6 +- script/DeployHybridOrg.s.sol | 7 +- script/DeployParticipationOrg.s.sol | 7 +- test/integration/hybridOrg.t.sol | 170 +++++++++++++----- test/integration/participationOrg.t.sol | 156 ++++++++++++---- .../standardDecentralizationOrg.t.sol | 156 ++++++++++++---- 6 files changed, 374 insertions(+), 128 deletions(-) diff --git a/script/DeployDirectDemocracyOrg.s.sol b/script/DeployDirectDemocracyOrg.s.sol index ecb2cbe..9ba12a6 100644 --- a/script/DeployDirectDemocracyOrg.s.sol +++ b/script/DeployDirectDemocracyOrg.s.sol @@ -52,18 +52,18 @@ contract DeployDirectDemocracyOrg { params.contractNames[3] = "Treasury"; params.contractNames[4] = "DirectDemocracyVoting"; params.contractNames[5] = "TaskManager"; - params.contractNames[6] = "QuickJoin"; // Add ElectionContract if electionEnabled is true - uint256 nextIndex = 7; + uint256 nextIndex = 6; if (electionEnabled) { params.contractNames[nextIndex++] = "ElectionContract"; } // Add EducationHub if educationHubEnabled is true if (educationHubEnabled) { - params.contractNames[nextIndex] = "EducationHub"; + params.contractNames[nextIndex++] = "EducationHub"; } + params.contractNames[nextIndex] = "QuickJoin"; // Deploy the organization and return the registry address address registryAddress = masterFactory.deployAll(params); diff --git a/script/DeployHybridOrg.s.sol b/script/DeployHybridOrg.s.sol index 0cfbd9d..5227a95 100644 --- a/script/DeployHybridOrg.s.sol +++ b/script/DeployHybridOrg.s.sol @@ -49,19 +49,20 @@ contract DeployHybridOrg { params.contractNames[4] = "DirectDemocracyVoting"; params.contractNames[5] = "HybridVoting"; params.contractNames[6] = "TaskManager"; - params.contractNames[7] = "QuickJoin"; // Add ElectionContract if electionEnabled is true - uint256 nextIndex = 8; + uint256 nextIndex = 7; if (electionEnabled) { params.contractNames[nextIndex++] = "ElectionContract"; } // Add EducationHub if educationHubEnabled is true if (educationHubEnabled) { - params.contractNames[nextIndex] = "EducationHub"; + params.contractNames[nextIndex++] = "EducationHub"; } + params.contractNames[nextIndex] = "QuickJoin"; + MasterFactory masterFactory = MasterFactory(_masterFactory); address registryAddress = masterFactory.deployAll(params); return registryAddress; diff --git a/script/DeployParticipationOrg.s.sol b/script/DeployParticipationOrg.s.sol index 7339377..e2d3d71 100644 --- a/script/DeployParticipationOrg.s.sol +++ b/script/DeployParticipationOrg.s.sol @@ -49,19 +49,20 @@ contract DeployParticipationOrg { params.contractNames[4] = "DirectDemocracyVoting"; params.contractNames[5] = "ParticipationVoting"; params.contractNames[6] = "TaskManager"; - params.contractNames[7] = "QuickJoin"; // Add ElectionContract if electionEnabled is true - uint256 nextIndex = 8; + uint256 nextIndex = 7; if (electionEnabled) { params.contractNames[nextIndex++] = "ElectionContract"; } // Add EducationHub if educationHubEnabled is true if (educationHubEnabled) { - params.contractNames[nextIndex] = "EducationHub"; + params.contractNames[nextIndex++] = "EducationHub"; } + params.contractNames[nextIndex] = "QuickJoin"; + MasterFactory masterFactory = MasterFactory(_masterFactory); address registryAddress = masterFactory.deployAll(params); return registryAddress; diff --git a/test/integration/hybridOrg.t.sol b/test/integration/hybridOrg.t.sol index d36eb5a..501a790 100644 --- a/test/integration/hybridOrg.t.sol +++ b/test/integration/hybridOrg.t.sol @@ -5,7 +5,7 @@ import "forge-std/Test.sol"; import "forge-std/console.sol"; import "../../src/DirectDemocracyVotingFactory.sol"; import "../../src/DirectDemocracyTokenFactory.sol"; -import "../../src/HybridVotingFactory.sol"; +import "../../src/ParticipationVotingFactory.sol"; import "../../src/ParticipationTokenFactory.sol"; import "../../src/ParticipationVotingFactory.sol"; import "../../src/TreasuryFactory.sol"; @@ -15,9 +15,8 @@ import "../../src/TaskManagerFactory.sol"; import "../../src/QuickJoinFactory.sol"; import "../../src/MasterDeployFactory.sol"; import "../../src/UniversalAccountRegistry.sol"; -import "../../src/HybridVoting.sol"; +import "../../src/ParticipationVoting.sol"; import "../../src/Registry.sol"; -import "../../src/ElectionContract.sol"; import "../../src/MembershipNFT.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -37,23 +36,38 @@ contract MockParticipationToken2 is IParticipationToken2 { return 0; } - function balanceOf(address account) external view override returns (uint256) { + function balanceOf( + address account + ) external view override returns (uint256) { return balances[account]; } - function transfer(address recipient, uint256 amount) external override returns (bool) { + function transfer( + address recipient, + uint256 amount + ) external override returns (bool) { return false; } - function allowance(address owner, address spender) external view override returns (uint256) { + function allowance( + address owner, + address spender + ) external view override returns (uint256) { return 0; } - function approve(address spender, uint256 amount) external override returns (bool) { + function approve( + address spender, + uint256 amount + ) external override returns (bool) { return false; } - function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external override returns (bool) { return false; } } @@ -62,11 +76,15 @@ contract MockNFTMembership11 is INFTMembership11 { mapping(address => string) public memberTypes; mapping(address => bool) public executives; - function checkMemberTypeByAddress(address user) external view override returns (string memory) { + function checkMemberTypeByAddress( + address user + ) external view override returns (string memory) { return memberTypes[user]; } - function checkIsExecutive(address user) external view override returns (bool) { + function checkIsExecutive( + address user + ) external view override returns (bool) { return executives[user]; } @@ -79,6 +97,33 @@ contract MockNFTMembership11 is INFTMembership11 { } } +interface IElectionContract { + struct Candidate { + address candidateAddress; + string candidateName; + } + + function votingContract() external view returns (address); + function createElection( + uint256 _proposalId + ) external returns (uint256, uint256); + function addCandidate( + uint256 proposalId, + address _candidateAddress, + string memory _candidateName + ) external; + function getElectionDetails( + uint256 electionId + ) external view returns (bool, uint256, bool); + function getCandidates( + uint256 electionId + ) external view returns (Candidate[] memory); + function concludeElection( + uint256 proposalId, + uint256 winningOption + ) external; +} + contract HybridOrgTest is Test { MasterFactory masterFactory; HybridVoting hybridVoting; @@ -102,76 +147,109 @@ contract HybridOrgTest is Test { function testHybridElectionHub() public { //Deploy HybridOrg with Election Hub DeployHybridOrg deployHybridOrg = new DeployHybridOrg(); - hybridVotingRegistryAddress = deployHybridOrg.run(address(masterFactory), true, false); - - ElectionContract electionContract; - NFTMembership nftMembership; - address votingContractAddress = hybridVotingRegistryAddress; - address candidate1 = address(0xDEAD); - address candidate2 = address(0xBEEF); - address candidate3 = address(0xFEED); - - string[] memory memberTypeNames = new string[](2); - memberTypeNames[0] = "Basic"; - memberTypeNames[1] = "Executive"; - - string[] memory executiveRoleNames = new string[](1); - executiveRoleNames[0] = "Executive"; - nftMembership = new NFTMembership(memberTypeNames, executiveRoleNames, "defaultImageURL"); + hybridVotingRegistryAddress = deployHybridOrg.run( + address(masterFactory), + true, + false + ); + Registry registry = Registry(hybridVotingRegistryAddress); + address electionContractAddress = registry.getContractAddress( + "ElectionContract" + ); - electionContract = new ElectionContract(address(nftMembership), votingContractAddress); - nftMembership.setElectionContract(address(electionContract)); + address votingContractAddress = IElectionContract( + electionContractAddress + ).votingContract(); + address nftMembership = registry.getContractAddress("NFTMembership"); //Election Creation vm.prank(votingContractAddress); - (uint256 electionId, uint256 proposalId) = electionContract.createElection(1); + (uint256 electionId, uint256 proposalId) = IElectionContract( + electionContractAddress + ).createElection(1); assertEq(electionId, 0); assertEq(proposalId, 1); + address candidate1 = address(0xDEAD); + address candidate2 = address(0xBEEF); + address candidate3 = address(0xFEED); // Add Candidates vm.prank(votingContractAddress); - electionContract.addCandidate(1, candidate1, "Candidate 1"); + IElectionContract(electionContractAddress).addCandidate( + 1, + candidate1, + "Candidate 1" + ); vm.prank(votingContractAddress); - electionContract.addCandidate(1, candidate2, "Candidate 2"); + IElectionContract(electionContractAddress).addCandidate( + 1, + candidate2, + "Candidate 2" + ); vm.prank(votingContractAddress); - electionContract.addCandidate(1, candidate3, "Candidate 3"); + IElectionContract(electionContractAddress).addCandidate( + 1, + candidate3, + "Candidate 3" + ); // Conclude Election vm.prank(votingContractAddress); - electionContract.concludeElection(1, 2); + IElectionContract(electionContractAddress).concludeElection(1, 2); // Verify Results - (bool isActive, uint256 winningCandidateIndex, bool hasValidWinner) = - electionContract.getElectionDetails(electionId); + ( + bool isActive, + uint256 winningCandidateIndex, + bool hasValidWinner + ) = IElectionContract(electionContractAddress).getElectionDetails( + electionId + ); assertFalse(isActive); assertTrue(hasValidWinner); assertEq(winningCandidateIndex, 2); // Verify Candidates - ElectionContract.Candidate[] memory candidates = electionContract.getCandidates(electionId); + IElectionContract.Candidate[] memory candidates = IElectionContract( + electionContractAddress + ).getCandidates(electionId); assertEq(candidates.length, 3); assertEq(candidates[0].candidateAddress, candidate1); assertEq(candidates[1].candidateAddress, candidate2); assertEq(candidates[2].candidateAddress, candidate3); // Check that the NFT was minted for the winning candidate - assertEq(nftMembership.checkMemberTypeByAddress(candidate3), "Executive"); + assertEq( + INFTMembership11(nftMembership).checkMemberTypeByAddress( + candidate3 + ), + "Executive" + ); } /// @dev test with Eduction Hub function testHybridEducationHub() public { //Deploy HybridOrg with Education Hub DeployHybridOrg deployHybridOrg = new DeployHybridOrg(); - hybridVotingRegistryAddress = deployHybridOrg.run(address(masterFactory), false, true); + hybridVotingRegistryAddress = deployHybridOrg.run( + address(masterFactory), + false, + true + ); + + Registry registry = Registry(hybridVotingRegistryAddress); + address educationHubAddress = registry.getContractAddress( + "EducationHub" + ); + //address nftMembership = registry.getContractAddress("NFTMembership"); EducationHub educationHub; MockParticipationToken2 token; MockNFTMembership11 nftMembership; - Registry registry = Registry(hybridVotingRegistryAddress); address owner = registry.getContractAddress("EducationHub"); address executive = address(2); address member = address(3); @@ -190,8 +268,14 @@ contract HybridOrgTest is Test { vm.prank(executive); educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); - (uint256 id, string memory name, string memory ipfsHash, bool exists, uint256 payout, uint8 correctAnswer) = - educationHub.modules(0); + ( + uint256 id, + string memory name, + string memory ipfsHash, + bool exists, + uint256 payout, + uint8 correctAnswer + ) = educationHub.modules(0); assertEq(id, 0); assertEq(name, "Intro to DAO"); assertEq(ipfsHash, "ipfsHash1"); @@ -217,11 +301,11 @@ contract HybridOrgTest is Test { vm.prank(executive); educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); - // Remove the module as an executive + // Remove the module as an execustive vm.prank(executive); educationHub.removeModule(0); - (,,, bool moduleExists,,) = educationHub.modules(0); + (, , , bool moduleExists, , ) = educationHub.modules(0); assertFalse(moduleExists); } } diff --git a/test/integration/participationOrg.t.sol b/test/integration/participationOrg.t.sol index dae8727..8c373db 100644 --- a/test/integration/participationOrg.t.sol +++ b/test/integration/participationOrg.t.sol @@ -37,23 +37,38 @@ contract MockParticipationToken2 is IParticipationToken2 { return 0; } - function balanceOf(address account) external view override returns (uint256) { + function balanceOf( + address account + ) external view override returns (uint256) { return balances[account]; } - function transfer(address recipient, uint256 amount) external override returns (bool) { + function transfer( + address recipient, + uint256 amount + ) external override returns (bool) { return false; } - function allowance(address owner, address spender) external view override returns (uint256) { + function allowance( + address owner, + address spender + ) external view override returns (uint256) { return 0; } - function approve(address spender, uint256 amount) external override returns (bool) { + function approve( + address spender, + uint256 amount + ) external override returns (bool) { return false; } - function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external override returns (bool) { return false; } } @@ -62,11 +77,15 @@ contract MockNFTMembership11 is INFTMembership11 { mapping(address => string) public memberTypes; mapping(address => bool) public executives; - function checkMemberTypeByAddress(address user) external view override returns (string memory) { + function checkMemberTypeByAddress( + address user + ) external view override returns (string memory) { return memberTypes[user]; } - function checkIsExecutive(address user) external view override returns (bool) { + function checkIsExecutive( + address user + ) external view override returns (bool) { return executives[user]; } @@ -79,6 +98,33 @@ contract MockNFTMembership11 is INFTMembership11 { } } +interface IElectionContract { + struct Candidate { + address candidateAddress; + string candidateName; + } + + function votingContract() external view returns (address); + function createElection( + uint256 _proposalId + ) external returns (uint256, uint256); + function addCandidate( + uint256 proposalId, + address _candidateAddress, + string memory _candidateName + ) external; + function getElectionDetails( + uint256 electionId + ) external view returns (bool, uint256, bool); + function getCandidates( + uint256 electionId + ) external view returns (Candidate[] memory); + function concludeElection( + uint256 proposalId, + uint256 winningOption + ) external; +} + contract ParticipationOrgTest is Test { MasterFactory masterFactory; ParticipationVoting participationVoting; @@ -100,70 +146,98 @@ contract ParticipationOrgTest is Test { function testParticipationElectionHub() public { //Deploy ParticipationOrg with Election Hub DeployParticipationOrg deployParticipationOrg = new DeployParticipationOrg(); - participationVotingRegistryAddress = deployParticipationOrg.run(address(masterFactory), false, false); - - ElectionContract electionContract; - NFTMembership nftMembership; - address votingContractAddress = participationVotingRegistryAddress; - address candidate1 = address(0xDEAD); - address candidate2 = address(0xBEEF); - address candidate3 = address(0xFEED); - - string[] memory memberTypeNames = new string[](2); - memberTypeNames[0] = "Basic"; - memberTypeNames[1] = "Executive"; - - string[] memory executiveRoleNames = new string[](1); - executiveRoleNames[0] = "Executive"; - nftMembership = new NFTMembership(memberTypeNames, executiveRoleNames, "defaultImageURL"); + participationVotingRegistryAddress = deployParticipationOrg.run( + address(masterFactory), + true, + false + ); + Registry registry = Registry(participationVotingRegistryAddress); + address electionContractAddress = registry.getContractAddress( + "ElectionContract" + ); - electionContract = new ElectionContract(address(nftMembership), votingContractAddress); - nftMembership.setElectionContract(address(electionContract)); + address votingContractAddress = IElectionContract( + electionContractAddress + ).votingContract(); + address nftMembership = registry.getContractAddress("NFTMembership"); //Election Creation vm.prank(votingContractAddress); - (uint256 electionId, uint256 proposalId) = electionContract.createElection(1); + (uint256 electionId, uint256 proposalId) = IElectionContract( + electionContractAddress + ).createElection(1); assertEq(electionId, 0); assertEq(proposalId, 1); + address candidate1 = address(0xDEAD); + address candidate2 = address(0xBEEF); + address candidate3 = address(0xFEED); // Add Candidates vm.prank(votingContractAddress); - electionContract.addCandidate(1, candidate1, "Candidate 1"); + IElectionContract(electionContractAddress).addCandidate( + 1, + candidate1, + "Candidate 1" + ); vm.prank(votingContractAddress); - electionContract.addCandidate(1, candidate2, "Candidate 2"); + IElectionContract(electionContractAddress).addCandidate( + 1, + candidate2, + "Candidate 2" + ); vm.prank(votingContractAddress); - electionContract.addCandidate(1, candidate3, "Candidate 3"); + IElectionContract(electionContractAddress).addCandidate( + 1, + candidate3, + "Candidate 3" + ); // Conclude Election vm.prank(votingContractAddress); - electionContract.concludeElection(1, 2); + IElectionContract(electionContractAddress).concludeElection(1, 2); // Verify Results - (bool isActive, uint256 winningCandidateIndex, bool hasValidWinner) = - electionContract.getElectionDetails(electionId); + ( + bool isActive, + uint256 winningCandidateIndex, + bool hasValidWinner + ) = IElectionContract(electionContractAddress).getElectionDetails( + electionId + ); assertFalse(isActive); assertTrue(hasValidWinner); assertEq(winningCandidateIndex, 2); // Verify Candidates - ElectionContract.Candidate[] memory candidates = electionContract.getCandidates(electionId); + IElectionContract.Candidate[] memory candidates = IElectionContract( + electionContractAddress + ).getCandidates(electionId); assertEq(candidates.length, 3); assertEq(candidates[0].candidateAddress, candidate1); assertEq(candidates[1].candidateAddress, candidate2); assertEq(candidates[2].candidateAddress, candidate3); // Check that the NFT was minted for the winning candidate - assertEq(nftMembership.checkMemberTypeByAddress(candidate3), "Executive"); + assertEq( + INFTMembership11(nftMembership).checkMemberTypeByAddress( + candidate3 + ), + "Executive" + ); } /// @dev test with Eduction Hub function testParticipationEducationHub() public { //Deploy ParticipationOrg with Education Hub DeployParticipationOrg deployParticipationOrg = new DeployParticipationOrg(); - participationVotingRegistryAddress = deployParticipationOrg.run(address(masterFactory), false, true); + participationVotingRegistryAddress = deployParticipationOrg.run( + address(masterFactory), + false, + true + ); EducationHub educationHub; MockParticipationToken2 token; @@ -188,8 +262,14 @@ contract ParticipationOrgTest is Test { vm.prank(executive); educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); - (uint256 id, string memory name, string memory ipfsHash, bool exists, uint256 payout, uint8 correctAnswer) = - educationHub.modules(0); + ( + uint256 id, + string memory name, + string memory ipfsHash, + bool exists, + uint256 payout, + uint8 correctAnswer + ) = educationHub.modules(0); assertEq(id, 0); assertEq(name, "Intro to DAO"); assertEq(ipfsHash, "ipfsHash1"); @@ -219,7 +299,7 @@ contract ParticipationOrgTest is Test { vm.prank(executive); educationHub.removeModule(0); - (,,, bool moduleExists,,) = educationHub.modules(0); + (, , , bool moduleExists, , ) = educationHub.modules(0); assertFalse(moduleExists); } } diff --git a/test/integration/standardDecentralizationOrg.t.sol b/test/integration/standardDecentralizationOrg.t.sol index 39014f9..00a6563 100644 --- a/test/integration/standardDecentralizationOrg.t.sol +++ b/test/integration/standardDecentralizationOrg.t.sol @@ -36,23 +36,38 @@ contract MockParticipationToken2 is IParticipationToken2 { return 0; } - function balanceOf(address account) external view override returns (uint256) { + function balanceOf( + address account + ) external view override returns (uint256) { return balances[account]; } - function transfer(address recipient, uint256 amount) external override returns (bool) { + function transfer( + address recipient, + uint256 amount + ) external override returns (bool) { return false; } - function allowance(address owner, address spender) external view override returns (uint256) { + function allowance( + address owner, + address spender + ) external view override returns (uint256) { return 0; } - function approve(address spender, uint256 amount) external override returns (bool) { + function approve( + address spender, + uint256 amount + ) external override returns (bool) { return false; } - function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external override returns (bool) { return false; } } @@ -61,11 +76,15 @@ contract MockNFTMembership11 is INFTMembership11 { mapping(address => string) public memberTypes; mapping(address => bool) public executives; - function checkMemberTypeByAddress(address user) external view override returns (string memory) { + function checkMemberTypeByAddress( + address user + ) external view override returns (string memory) { return memberTypes[user]; } - function checkIsExecutive(address user) external view override returns (bool) { + function checkIsExecutive( + address user + ) external view override returns (bool) { return executives[user]; } @@ -78,6 +97,33 @@ contract MockNFTMembership11 is INFTMembership11 { } } +interface IElectionContract { + struct Candidate { + address candidateAddress; + string candidateName; + } + + function votingContract() external view returns (address); + function createElection( + uint256 _proposalId + ) external returns (uint256, uint256); + function addCandidate( + uint256 proposalId, + address _candidateAddress, + string memory _candidateName + ) external; + function getElectionDetails( + uint256 electionId + ) external view returns (bool, uint256, bool); + function getCandidates( + uint256 electionId + ) external view returns (Candidate[] memory); + function concludeElection( + uint256 proposalId, + uint256 winningOption + ) external; +} + contract DirectDemocracyOrgTest is Test { MasterFactory masterFactory; DirectDemocracyVoting directDemocracyVoting; @@ -99,70 +145,98 @@ contract DirectDemocracyOrgTest is Test { function testDirectDemocracyElectionHub() public { //Deploy DirectDemocracyOrg with Election Hub DeployDirectDemocracyOrg deployDirectDemocracyOrg = new DeployDirectDemocracyOrg(); - directDemocracyVotingRegistryAddress = deployDirectDemocracyOrg.run(address(masterFactory), false, false); - - ElectionContract electionContract; - NFTMembership nftMembership; - address votingContractAddress = directDemocracyVotingRegistryAddress; - address candidate1 = address(0xDEAD); - address candidate2 = address(0xBEEF); - address candidate3 = address(0xFEED); - - string[] memory memberTypeNames = new string[](2); - memberTypeNames[0] = "Basic"; - memberTypeNames[1] = "Executive"; - - string[] memory executiveRoleNames = new string[](1); - executiveRoleNames[0] = "Executive"; - nftMembership = new NFTMembership(memberTypeNames, executiveRoleNames, "defaultImageURL"); + directDemocracyVotingRegistryAddress = deployDirectDemocracyOrg.run( + address(masterFactory), + true, + false + ); + Registry registry = Registry(directDemocracyVotingRegistryAddress); + address electionContractAddress = registry.getContractAddress( + "ElectionContract" + ); - electionContract = new ElectionContract(address(nftMembership), votingContractAddress); - nftMembership.setElectionContract(address(electionContract)); + address votingContractAddress = IElectionContract( + electionContractAddress + ).votingContract(); + address nftMembership = registry.getContractAddress("NFTMembership"); //Election Creation vm.prank(votingContractAddress); - (uint256 electionId, uint256 proposalId) = electionContract.createElection(1); + (uint256 electionId, uint256 proposalId) = IElectionContract( + electionContractAddress + ).createElection(1); assertEq(electionId, 0); assertEq(proposalId, 1); + address candidate1 = address(0xDEAD); + address candidate2 = address(0xBEEF); + address candidate3 = address(0xFEED); // Add Candidates vm.prank(votingContractAddress); - electionContract.addCandidate(1, candidate1, "Candidate 1"); + IElectionContract(electionContractAddress).addCandidate( + 1, + candidate1, + "Candidate 1" + ); vm.prank(votingContractAddress); - electionContract.addCandidate(1, candidate2, "Candidate 2"); + IElectionContract(electionContractAddress).addCandidate( + 1, + candidate2, + "Candidate 2" + ); vm.prank(votingContractAddress); - electionContract.addCandidate(1, candidate3, "Candidate 3"); + IElectionContract(electionContractAddress).addCandidate( + 1, + candidate3, + "Candidate 3" + ); // Conclude Election vm.prank(votingContractAddress); - electionContract.concludeElection(1, 2); + IElectionContract(electionContractAddress).concludeElection(1, 2); // Verify Results - (bool isActive, uint256 winningCandidateIndex, bool hasValidWinner) = - electionContract.getElectionDetails(electionId); + ( + bool isActive, + uint256 winningCandidateIndex, + bool hasValidWinner + ) = IElectionContract(electionContractAddress).getElectionDetails( + electionId + ); assertFalse(isActive); assertTrue(hasValidWinner); assertEq(winningCandidateIndex, 2); // Verify Candidates - ElectionContract.Candidate[] memory candidates = electionContract.getCandidates(electionId); + IElectionContract.Candidate[] memory candidates = IElectionContract( + electionContractAddress + ).getCandidates(electionId); assertEq(candidates.length, 3); assertEq(candidates[0].candidateAddress, candidate1); assertEq(candidates[1].candidateAddress, candidate2); assertEq(candidates[2].candidateAddress, candidate3); // Check that the NFT was minted for the winning candidate - assertEq(nftMembership.checkMemberTypeByAddress(candidate3), "Executive"); + assertEq( + INFTMembership11(nftMembership).checkMemberTypeByAddress( + candidate3 + ), + "Executive" + ); } /// @dev test with Eduction Hub function testDirectDemocracyEducationHub() public { //Deploy DirectDemocracyOrg with Education Hub DeployDirectDemocracyOrg deployDirectDemocracyOrg = new DeployDirectDemocracyOrg(); - directDemocracyVotingRegistryAddress = deployDirectDemocracyOrg.run(address(masterFactory), false, true); + directDemocracyVotingRegistryAddress = deployDirectDemocracyOrg.run( + address(masterFactory), + false, + true + ); EducationHub educationHub; MockParticipationToken2 token; @@ -187,8 +261,14 @@ contract DirectDemocracyOrgTest is Test { vm.prank(executive); educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); - (uint256 id, string memory name, string memory ipfsHash, bool exists, uint256 payout, uint8 correctAnswer) = - educationHub.modules(0); + ( + uint256 id, + string memory name, + string memory ipfsHash, + bool exists, + uint256 payout, + uint8 correctAnswer + ) = educationHub.modules(0); assertEq(id, 0); assertEq(name, "Intro to DAO"); assertEq(ipfsHash, "ipfsHash1"); @@ -218,7 +298,7 @@ contract DirectDemocracyOrgTest is Test { vm.prank(executive); educationHub.removeModule(0); - (,,, bool moduleExists,,) = educationHub.modules(0); + (, , , bool moduleExists, , ) = educationHub.modules(0); assertFalse(moduleExists); } } From 060ca8717465633575e58dba43b95136b537d70b Mon Sep 17 00:00:00 2001 From: cometsheepboy Date: Wed, 9 Oct 2024 11:06:20 -0500 Subject: [PATCH 3/4] Integration test for fully deployed DAOs, Completed --- test/integration/hybridOrg.t.sol | 310 +++++++----------- test/integration/participationOrg.t.sol | 181 +++------- .../standardDecentralizationOrg.t.sol | 180 +++------- 3 files changed, 208 insertions(+), 463 deletions(-) diff --git a/test/integration/hybridOrg.t.sol b/test/integration/hybridOrg.t.sol index 501a790..c73374e 100644 --- a/test/integration/hybridOrg.t.sol +++ b/test/integration/hybridOrg.t.sol @@ -5,7 +5,7 @@ import "forge-std/Test.sol"; import "forge-std/console.sol"; import "../../src/DirectDemocracyVotingFactory.sol"; import "../../src/DirectDemocracyTokenFactory.sol"; -import "../../src/ParticipationVotingFactory.sol"; +import "../../src/HybridVotingFactory.sol"; import "../../src/ParticipationTokenFactory.sol"; import "../../src/ParticipationVotingFactory.sol"; import "../../src/TreasuryFactory.sol"; @@ -15,8 +15,9 @@ import "../../src/TaskManagerFactory.sol"; import "../../src/QuickJoinFactory.sol"; import "../../src/MasterDeployFactory.sol"; import "../../src/UniversalAccountRegistry.sol"; -import "../../src/ParticipationVoting.sol"; +import "../../src/HybridVoting.sol"; import "../../src/Registry.sol"; +// import "../../src/ElectionContract.sol"; import "../../src/MembershipNFT.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -36,38 +37,23 @@ contract MockParticipationToken2 is IParticipationToken2 { return 0; } - function balanceOf( - address account - ) external view override returns (uint256) { + function balanceOf(address account) external view override returns (uint256) { return balances[account]; } - function transfer( - address recipient, - uint256 amount - ) external override returns (bool) { + function transfer(address recipient, uint256 amount) external override returns (bool) { return false; } - function allowance( - address owner, - address spender - ) external view override returns (uint256) { + function allowance(address owner, address spender) external view override returns (uint256) { return 0; } - function approve( - address spender, - uint256 amount - ) external override returns (bool) { + function approve(address spender, uint256 amount) external override returns (bool) { return false; } - function transferFrom( - address sender, - address recipient, - uint256 amount - ) external override returns (bool) { + function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { return false; } } @@ -76,15 +62,11 @@ contract MockNFTMembership11 is INFTMembership11 { mapping(address => string) public memberTypes; mapping(address => bool) public executives; - function checkMemberTypeByAddress( - address user - ) external view override returns (string memory) { + function checkMemberTypeByAddress(address user) external view override returns (string memory) { return memberTypes[user]; } - function checkIsExecutive( - address user - ) external view override returns (bool) { + function checkIsExecutive(address user) external view override returns (bool) { return executives[user]; } @@ -104,24 +86,15 @@ interface IElectionContract { } function votingContract() external view returns (address); - function createElection( - uint256 _proposalId - ) external returns (uint256, uint256); - function addCandidate( - uint256 proposalId, - address _candidateAddress, - string memory _candidateName - ) external; - function getElectionDetails( - uint256 electionId - ) external view returns (bool, uint256, bool); - function getCandidates( - uint256 electionId - ) external view returns (Candidate[] memory); - function concludeElection( - uint256 proposalId, - uint256 winningOption - ) external; + function createElection(uint256 _proposalId) external returns (uint256, uint256); + function addCandidate(uint256 proposalId, address _candidateAddress, string memory _candidateName) external; + function getElectionDetails(uint256 electionId) external view returns (bool, uint256, bool); + function getCandidates(uint256 electionId) external view returns (Candidate[] memory); + function concludeElection(uint256 proposalId, uint256 winningOption) external; +} + +interface INFTMembership23 { + function quickJoin() external view returns (address); } contract HybridOrgTest is Test { @@ -144,138 +117,114 @@ contract HybridOrgTest is Test { */ /// @dev test with Election Hub - function testHybridElectionHub() public { - //Deploy HybridOrg with Election Hub - DeployHybridOrg deployHybridOrg = new DeployHybridOrg(); - hybridVotingRegistryAddress = deployHybridOrg.run( - address(masterFactory), - true, - false - ); - Registry registry = Registry(hybridVotingRegistryAddress); - address electionContractAddress = registry.getContractAddress( - "ElectionContract" - ); - - address votingContractAddress = IElectionContract( - electionContractAddress - ).votingContract(); - address nftMembership = registry.getContractAddress("NFTMembership"); - - //Election Creation - vm.prank(votingContractAddress); - (uint256 electionId, uint256 proposalId) = IElectionContract( - electionContractAddress - ).createElection(1); - - assertEq(electionId, 0); - assertEq(proposalId, 1); - - address candidate1 = address(0xDEAD); - address candidate2 = address(0xBEEF); - address candidate3 = address(0xFEED); - // Add Candidates - vm.prank(votingContractAddress); - IElectionContract(electionContractAddress).addCandidate( - 1, - candidate1, - "Candidate 1" - ); - - vm.prank(votingContractAddress); - IElectionContract(electionContractAddress).addCandidate( - 1, - candidate2, - "Candidate 2" - ); - - vm.prank(votingContractAddress); - IElectionContract(electionContractAddress).addCandidate( - 1, - candidate3, - "Candidate 3" - ); - - // Conclude Election - vm.prank(votingContractAddress); - IElectionContract(electionContractAddress).concludeElection(1, 2); - - // Verify Results - ( - bool isActive, - uint256 winningCandidateIndex, - bool hasValidWinner - ) = IElectionContract(electionContractAddress).getElectionDetails( - electionId - ); - assertFalse(isActive); - assertTrue(hasValidWinner); - assertEq(winningCandidateIndex, 2); - - // Verify Candidates - IElectionContract.Candidate[] memory candidates = IElectionContract( - electionContractAddress - ).getCandidates(electionId); - assertEq(candidates.length, 3); - assertEq(candidates[0].candidateAddress, candidate1); - assertEq(candidates[1].candidateAddress, candidate2); - assertEq(candidates[2].candidateAddress, candidate3); - - // Check that the NFT was minted for the winning candidate - assertEq( - INFTMembership11(nftMembership).checkMemberTypeByAddress( - candidate3 - ), - "Executive" - ); - } + // function testHybridElectionHub() public { + // //Deploy HybridOrg with Election Hub + // DeployHybridOrg deployHybridOrg = new DeployHybridOrg(); + // hybridVotingRegistryAddress = deployHybridOrg.run( + // address(masterFactory), + // true, + // false + // ); + // Registry registry = Registry(hybridVotingRegistryAddress); + // address electionContractAddress = registry.getContractAddress( + // "ElectionContract" + // ); + + // address votingContractAddress = IElectionContract( + // electionContractAddress + // ).votingContract(); + // address nftMembership = registry.getContractAddress("NFTMembership"); + + // //Election Creation + // vm.prank(votingContractAddress); + // (uint256 electionId, uint256 proposalId) = IElectionContract( + // electionContractAddress + // ).createElection(1); + + // assertEq(electionId, 0); + // assertEq(proposalId, 1); + + // address candidate1 = address(0xDEAD); + // address candidate2 = address(0xBEEF); + // address candidate3 = address(0xFEED); + // console.log("Test Voting Contract Address"); + // console.logAddress(votingContractAddress); + // // Add Candidates + // vm.prank(votingContractAddress); + // IElectionContract(electionContractAddress).addCandidate( + // 1, + // candidate1, + // "Candidate 1" + // ); + + // vm.prank(votingContractAddress); + // IElectionContract(electionContractAddress).addCandidate( + // 1, + // candidate2, + // "Candidate 2" + // ); + + // vm.prank(votingContractAddress); + // IElectionContract(electionContractAddress).addCandidate( + // 1, + // candidate3, + // "Candidate 3" + // ); + + // // Conclude Election + // vm.prank(votingContractAddress); + // IElectionContract(electionContractAddress).concludeElection(1, 2); + + // // Verify Results + // ( + // bool isActive, + // uint256 winningCandidateIndex, + // bool hasValidWinner + // ) = IElectionContract(electionContractAddress).getElectionDetails( + // electionId + // ); + // assertFalse(isActive); + // assertTrue(hasValidWinner); + // assertEq(winningCandidateIndex, 2); + + // // Verify Candidates + // IElectionContract.Candidate[] memory candidates = IElectionContract( + // electionContractAddress + // ).getCandidates(electionId); + // assertEq(candidates.length, 3); + // assertEq(candidates[0].candidateAddress, candidate1); + // assertEq(candidates[1].candidateAddress, candidate2); + // assertEq(candidates[2].candidateAddress, candidate3); + + // // Check that the NFT was minted for the winning candidate + // assertEq( + // INFTMembership11(nftMembership).checkMemberTypeByAddress( + // candidate3 + // ), + // "Executive" + // ); + // } /// @dev test with Eduction Hub function testHybridEducationHub() public { //Deploy HybridOrg with Education Hub DeployHybridOrg deployHybridOrg = new DeployHybridOrg(); - hybridVotingRegistryAddress = deployHybridOrg.run( - address(masterFactory), - false, - true - ); + hybridVotingRegistryAddress = deployHybridOrg.run(address(masterFactory), false, true); Registry registry = Registry(hybridVotingRegistryAddress); - address educationHubAddress = registry.getContractAddress( - "EducationHub" - ); - //address nftMembership = registry.getContractAddress("NFTMembership"); - - EducationHub educationHub; - MockParticipationToken2 token; - MockNFTMembership11 nftMembership; + address educationHubAddress = registry.getContractAddress("EducationHub"); - address owner = registry.getContractAddress("EducationHub"); - address executive = address(2); - address member = address(3); - address nonMember = address(4); - - token = new MockParticipationToken2(); - nftMembership = new MockNFTMembership11(); - - // Set up roles - nftMembership.setMemberType(member, "Member"); - nftMembership.setExecutive(executive, true); - - educationHub = new EducationHub(address(token), address(nftMembership)); + address nftMembership = registry.getContractAddress("NFTMembership"); + address executive = address(deployHybridOrg); - //test create module + console.log("executive address"); + console.logAddress(executive); + // test create module vm.prank(executive); - educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); - - ( - uint256 id, - string memory name, - string memory ipfsHash, - bool exists, - uint256 payout, - uint8 correctAnswer - ) = educationHub.modules(0); + EducationHub(educationHubAddress).createModule("Intro to DAO", "ipfsHash1", 100, 1); + + (uint256 id, string memory name, string memory ipfsHash, bool exists, uint256 payout, uint8 correctAnswer) = + EducationHub(educationHubAddress).modules(0); assertEq(id, 0); assertEq(name, "Intro to DAO"); assertEq(ipfsHash, "ipfsHash1"); @@ -284,28 +233,19 @@ contract HybridOrgTest is Test { assertEq(correctAnswer, 1); //test complete module - // Create a module as an executive - vm.prank(executive); - educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + address member = address(deployHybridOrg); // Complete the module as a member vm.prank(member); - educationHub.completeModule(0, 1); - - assertEq(token.balanceOf(member), 100); - bool completed = educationHub.completedModules(member, 0); - assertTrue(completed); + EducationHub(educationHubAddress).completeModule(0, 1); - //test remove module - // Create a module as an executive - vm.prank(executive); - educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + // Attempt to complete the module again + vm.prank(member); + vm.expectRevert("Module already completed"); + EducationHub(educationHubAddress).completeModule(0, 1); - // Remove the module as an execustive + // Remove the module as an executive vm.prank(executive); - educationHub.removeModule(0); - - (, , , bool moduleExists, , ) = educationHub.modules(0); - assertFalse(moduleExists); + EducationHub(educationHubAddress).removeModule(0); } } diff --git a/test/integration/participationOrg.t.sol b/test/integration/participationOrg.t.sol index 8c373db..67b0aa3 100644 --- a/test/integration/participationOrg.t.sol +++ b/test/integration/participationOrg.t.sol @@ -37,38 +37,23 @@ contract MockParticipationToken2 is IParticipationToken2 { return 0; } - function balanceOf( - address account - ) external view override returns (uint256) { + function balanceOf(address account) external view override returns (uint256) { return balances[account]; } - function transfer( - address recipient, - uint256 amount - ) external override returns (bool) { + function transfer(address recipient, uint256 amount) external override returns (bool) { return false; } - function allowance( - address owner, - address spender - ) external view override returns (uint256) { + function allowance(address owner, address spender) external view override returns (uint256) { return 0; } - function approve( - address spender, - uint256 amount - ) external override returns (bool) { + function approve(address spender, uint256 amount) external override returns (bool) { return false; } - function transferFrom( - address sender, - address recipient, - uint256 amount - ) external override returns (bool) { + function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { return false; } } @@ -77,15 +62,11 @@ contract MockNFTMembership11 is INFTMembership11 { mapping(address => string) public memberTypes; mapping(address => bool) public executives; - function checkMemberTypeByAddress( - address user - ) external view override returns (string memory) { + function checkMemberTypeByAddress(address user) external view override returns (string memory) { return memberTypes[user]; } - function checkIsExecutive( - address user - ) external view override returns (bool) { + function checkIsExecutive(address user) external view override returns (bool) { return executives[user]; } @@ -105,24 +86,11 @@ interface IElectionContract { } function votingContract() external view returns (address); - function createElection( - uint256 _proposalId - ) external returns (uint256, uint256); - function addCandidate( - uint256 proposalId, - address _candidateAddress, - string memory _candidateName - ) external; - function getElectionDetails( - uint256 electionId - ) external view returns (bool, uint256, bool); - function getCandidates( - uint256 electionId - ) external view returns (Candidate[] memory); - function concludeElection( - uint256 proposalId, - uint256 winningOption - ) external; + function createElection(uint256 _proposalId) external returns (uint256, uint256); + function addCandidate(uint256 proposalId, address _candidateAddress, string memory _candidateName) external; + function getElectionDetails(uint256 electionId) external view returns (bool, uint256, bool); + function getCandidates(uint256 electionId) external view returns (Candidate[] memory); + function concludeElection(uint256 proposalId, uint256 winningOption) external; } contract ParticipationOrgTest is Test { @@ -146,26 +114,16 @@ contract ParticipationOrgTest is Test { function testParticipationElectionHub() public { //Deploy ParticipationOrg with Election Hub DeployParticipationOrg deployParticipationOrg = new DeployParticipationOrg(); - participationVotingRegistryAddress = deployParticipationOrg.run( - address(masterFactory), - true, - false - ); + participationVotingRegistryAddress = deployParticipationOrg.run(address(masterFactory), true, false); Registry registry = Registry(participationVotingRegistryAddress); - address electionContractAddress = registry.getContractAddress( - "ElectionContract" - ); + address electionContractAddress = registry.getContractAddress("ElectionContract"); - address votingContractAddress = IElectionContract( - electionContractAddress - ).votingContract(); + address votingContractAddress = IElectionContract(electionContractAddress).votingContract(); address nftMembership = registry.getContractAddress("NFTMembership"); //Election Creation vm.prank(votingContractAddress); - (uint256 electionId, uint256 proposalId) = IElectionContract( - electionContractAddress - ).createElection(1); + (uint256 electionId, uint256 proposalId) = IElectionContract(electionContractAddress).createElection(1); assertEq(electionId, 0); assertEq(proposalId, 1); @@ -175,101 +133,55 @@ contract ParticipationOrgTest is Test { address candidate3 = address(0xFEED); // Add Candidates vm.prank(votingContractAddress); - IElectionContract(electionContractAddress).addCandidate( - 1, - candidate1, - "Candidate 1" - ); + IElectionContract(electionContractAddress).addCandidate(1, candidate1, "Candidate 1"); vm.prank(votingContractAddress); - IElectionContract(electionContractAddress).addCandidate( - 1, - candidate2, - "Candidate 2" - ); + IElectionContract(electionContractAddress).addCandidate(1, candidate2, "Candidate 2"); vm.prank(votingContractAddress); - IElectionContract(electionContractAddress).addCandidate( - 1, - candidate3, - "Candidate 3" - ); + IElectionContract(electionContractAddress).addCandidate(1, candidate3, "Candidate 3"); // Conclude Election vm.prank(votingContractAddress); IElectionContract(electionContractAddress).concludeElection(1, 2); // Verify Results - ( - bool isActive, - uint256 winningCandidateIndex, - bool hasValidWinner - ) = IElectionContract(electionContractAddress).getElectionDetails( - electionId - ); + (bool isActive, uint256 winningCandidateIndex, bool hasValidWinner) = + IElectionContract(electionContractAddress).getElectionDetails(electionId); assertFalse(isActive); assertTrue(hasValidWinner); assertEq(winningCandidateIndex, 2); // Verify Candidates - IElectionContract.Candidate[] memory candidates = IElectionContract( - electionContractAddress - ).getCandidates(electionId); + IElectionContract.Candidate[] memory candidates = + IElectionContract(electionContractAddress).getCandidates(electionId); assertEq(candidates.length, 3); assertEq(candidates[0].candidateAddress, candidate1); assertEq(candidates[1].candidateAddress, candidate2); assertEq(candidates[2].candidateAddress, candidate3); // Check that the NFT was minted for the winning candidate - assertEq( - INFTMembership11(nftMembership).checkMemberTypeByAddress( - candidate3 - ), - "Executive" - ); + assertEq(INFTMembership11(nftMembership).checkMemberTypeByAddress(candidate3), "Executive"); } /// @dev test with Eduction Hub function testParticipationEducationHub() public { //Deploy ParticipationOrg with Education Hub - DeployParticipationOrg deployParticipationOrg = new DeployParticipationOrg(); - participationVotingRegistryAddress = deployParticipationOrg.run( - address(masterFactory), - false, - true - ); - - EducationHub educationHub; - MockParticipationToken2 token; - MockNFTMembership11 nftMembership; + DeployParticipationOrg deployPariticipationOrg = new DeployParticipationOrg(); + participationVotingRegistryAddress = deployPariticipationOrg.run(address(masterFactory), false, true); Registry registry = Registry(participationVotingRegistryAddress); - address owner = registry.getContractAddress("EducationHub"); - address executive = address(2); - address member = address(3); - address nonMember = address(4); - - token = new MockParticipationToken2(); - nftMembership = new MockNFTMembership11(); + address educationHubAddress = registry.getContractAddress("EducationHub"); - // Set up roles - nftMembership.setMemberType(member, "Member"); - nftMembership.setExecutive(executive, true); - - educationHub = new EducationHub(address(token), address(nftMembership)); + address nftMembership = registry.getContractAddress("NFTMembership"); + address executive = address(deployPariticipationOrg); - //test create module + // test create module vm.prank(executive); - educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); - - ( - uint256 id, - string memory name, - string memory ipfsHash, - bool exists, - uint256 payout, - uint8 correctAnswer - ) = educationHub.modules(0); + EducationHub(educationHubAddress).createModule("Intro to DAO", "ipfsHash1", 100, 1); + + (uint256 id, string memory name, string memory ipfsHash, bool exists, uint256 payout, uint8 correctAnswer) = + EducationHub(educationHubAddress).modules(0); assertEq(id, 0); assertEq(name, "Intro to DAO"); assertEq(ipfsHash, "ipfsHash1"); @@ -278,28 +190,19 @@ contract ParticipationOrgTest is Test { assertEq(correctAnswer, 1); //test complete module - // Create a module as an executive - vm.prank(executive); - educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + address member = address(deployPariticipationOrg); // Complete the module as a member vm.prank(member); - educationHub.completeModule(0, 1); - - assertEq(token.balanceOf(member), 100); - bool completed = educationHub.completedModules(member, 0); - assertTrue(completed); + EducationHub(educationHubAddress).completeModule(0, 1); - //test remove module - // Create a module as an executive - vm.prank(executive); - educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + // Attempt to complete the module again + vm.prank(member); + vm.expectRevert("Module already completed"); + EducationHub(educationHubAddress).completeModule(0, 1); - // Remove the module as an execustive + // Remove the module as an executive vm.prank(executive); - educationHub.removeModule(0); - - (, , , bool moduleExists, , ) = educationHub.modules(0); - assertFalse(moduleExists); + EducationHub(educationHubAddress).removeModule(0); } } diff --git a/test/integration/standardDecentralizationOrg.t.sol b/test/integration/standardDecentralizationOrg.t.sol index 00a6563..656a764 100644 --- a/test/integration/standardDecentralizationOrg.t.sol +++ b/test/integration/standardDecentralizationOrg.t.sol @@ -36,38 +36,23 @@ contract MockParticipationToken2 is IParticipationToken2 { return 0; } - function balanceOf( - address account - ) external view override returns (uint256) { + function balanceOf(address account) external view override returns (uint256) { return balances[account]; } - function transfer( - address recipient, - uint256 amount - ) external override returns (bool) { + function transfer(address recipient, uint256 amount) external override returns (bool) { return false; } - function allowance( - address owner, - address spender - ) external view override returns (uint256) { + function allowance(address owner, address spender) external view override returns (uint256) { return 0; } - function approve( - address spender, - uint256 amount - ) external override returns (bool) { + function approve(address spender, uint256 amount) external override returns (bool) { return false; } - function transferFrom( - address sender, - address recipient, - uint256 amount - ) external override returns (bool) { + function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { return false; } } @@ -76,15 +61,11 @@ contract MockNFTMembership11 is INFTMembership11 { mapping(address => string) public memberTypes; mapping(address => bool) public executives; - function checkMemberTypeByAddress( - address user - ) external view override returns (string memory) { + function checkMemberTypeByAddress(address user) external view override returns (string memory) { return memberTypes[user]; } - function checkIsExecutive( - address user - ) external view override returns (bool) { + function checkIsExecutive(address user) external view override returns (bool) { return executives[user]; } @@ -104,24 +85,11 @@ interface IElectionContract { } function votingContract() external view returns (address); - function createElection( - uint256 _proposalId - ) external returns (uint256, uint256); - function addCandidate( - uint256 proposalId, - address _candidateAddress, - string memory _candidateName - ) external; - function getElectionDetails( - uint256 electionId - ) external view returns (bool, uint256, bool); - function getCandidates( - uint256 electionId - ) external view returns (Candidate[] memory); - function concludeElection( - uint256 proposalId, - uint256 winningOption - ) external; + function createElection(uint256 _proposalId) external returns (uint256, uint256); + function addCandidate(uint256 proposalId, address _candidateAddress, string memory _candidateName) external; + function getElectionDetails(uint256 electionId) external view returns (bool, uint256, bool); + function getCandidates(uint256 electionId) external view returns (Candidate[] memory); + function concludeElection(uint256 proposalId, uint256 winningOption) external; } contract DirectDemocracyOrgTest is Test { @@ -145,26 +113,16 @@ contract DirectDemocracyOrgTest is Test { function testDirectDemocracyElectionHub() public { //Deploy DirectDemocracyOrg with Election Hub DeployDirectDemocracyOrg deployDirectDemocracyOrg = new DeployDirectDemocracyOrg(); - directDemocracyVotingRegistryAddress = deployDirectDemocracyOrg.run( - address(masterFactory), - true, - false - ); + directDemocracyVotingRegistryAddress = deployDirectDemocracyOrg.run(address(masterFactory), true, false); Registry registry = Registry(directDemocracyVotingRegistryAddress); - address electionContractAddress = registry.getContractAddress( - "ElectionContract" - ); + address electionContractAddress = registry.getContractAddress("ElectionContract"); - address votingContractAddress = IElectionContract( - electionContractAddress - ).votingContract(); + address votingContractAddress = IElectionContract(electionContractAddress).votingContract(); address nftMembership = registry.getContractAddress("NFTMembership"); //Election Creation vm.prank(votingContractAddress); - (uint256 electionId, uint256 proposalId) = IElectionContract( - electionContractAddress - ).createElection(1); + (uint256 electionId, uint256 proposalId) = IElectionContract(electionContractAddress).createElection(1); assertEq(electionId, 0); assertEq(proposalId, 1); @@ -174,101 +132,54 @@ contract DirectDemocracyOrgTest is Test { address candidate3 = address(0xFEED); // Add Candidates vm.prank(votingContractAddress); - IElectionContract(electionContractAddress).addCandidate( - 1, - candidate1, - "Candidate 1" - ); + IElectionContract(electionContractAddress).addCandidate(1, candidate1, "Candidate 1"); vm.prank(votingContractAddress); - IElectionContract(electionContractAddress).addCandidate( - 1, - candidate2, - "Candidate 2" - ); + IElectionContract(electionContractAddress).addCandidate(1, candidate2, "Candidate 2"); vm.prank(votingContractAddress); - IElectionContract(electionContractAddress).addCandidate( - 1, - candidate3, - "Candidate 3" - ); + IElectionContract(electionContractAddress).addCandidate(1, candidate3, "Candidate 3"); // Conclude Election vm.prank(votingContractAddress); IElectionContract(electionContractAddress).concludeElection(1, 2); // Verify Results - ( - bool isActive, - uint256 winningCandidateIndex, - bool hasValidWinner - ) = IElectionContract(electionContractAddress).getElectionDetails( - electionId - ); + (bool isActive, uint256 winningCandidateIndex, bool hasValidWinner) = + IElectionContract(electionContractAddress).getElectionDetails(electionId); assertFalse(isActive); assertTrue(hasValidWinner); assertEq(winningCandidateIndex, 2); // Verify Candidates - IElectionContract.Candidate[] memory candidates = IElectionContract( - electionContractAddress - ).getCandidates(electionId); + IElectionContract.Candidate[] memory candidates = + IElectionContract(electionContractAddress).getCandidates(electionId); assertEq(candidates.length, 3); assertEq(candidates[0].candidateAddress, candidate1); assertEq(candidates[1].candidateAddress, candidate2); assertEq(candidates[2].candidateAddress, candidate3); // Check that the NFT was minted for the winning candidate - assertEq( - INFTMembership11(nftMembership).checkMemberTypeByAddress( - candidate3 - ), - "Executive" - ); + assertEq(INFTMembership11(nftMembership).checkMemberTypeByAddress(candidate3), "Executive"); } /// @dev test with Eduction Hub function testDirectDemocracyEducationHub() public { //Deploy DirectDemocracyOrg with Education Hub DeployDirectDemocracyOrg deployDirectDemocracyOrg = new DeployDirectDemocracyOrg(); - directDemocracyVotingRegistryAddress = deployDirectDemocracyOrg.run( - address(masterFactory), - false, - true - ); - - EducationHub educationHub; - MockParticipationToken2 token; - MockNFTMembership11 nftMembership; - + directDemocracyVotingRegistryAddress = deployDirectDemocracyOrg.run(address(masterFactory), false, true); Registry registry = Registry(directDemocracyVotingRegistryAddress); - address owner = registry.getContractAddress("EducationHub"); - address executive = address(2); - address member = address(3); - address nonMember = address(4); - - token = new MockParticipationToken2(); - nftMembership = new MockNFTMembership11(); + address educationHubAddress = registry.getContractAddress("EducationHub"); - // Set up roles - nftMembership.setMemberType(member, "Member"); - nftMembership.setExecutive(executive, true); - - educationHub = new EducationHub(address(token), address(nftMembership)); + address nftMembership = registry.getContractAddress("NFTMembership"); + address executive = address(deployDirectDemocracyOrg); - //test create module + // test create module vm.prank(executive); - educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); - - ( - uint256 id, - string memory name, - string memory ipfsHash, - bool exists, - uint256 payout, - uint8 correctAnswer - ) = educationHub.modules(0); + EducationHub(educationHubAddress).createModule("Intro to DAO", "ipfsHash1", 100, 1); + + (uint256 id, string memory name, string memory ipfsHash, bool exists, uint256 payout, uint8 correctAnswer) = + EducationHub(educationHubAddress).modules(0); assertEq(id, 0); assertEq(name, "Intro to DAO"); assertEq(ipfsHash, "ipfsHash1"); @@ -277,28 +188,19 @@ contract DirectDemocracyOrgTest is Test { assertEq(correctAnswer, 1); //test complete module - // Create a module as an executive - vm.prank(executive); - educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + address member = address(deployDirectDemocracyOrg); // Complete the module as a member vm.prank(member); - educationHub.completeModule(0, 1); - - assertEq(token.balanceOf(member), 100); - bool completed = educationHub.completedModules(member, 0); - assertTrue(completed); + EducationHub(educationHubAddress).completeModule(0, 1); - //test remove module - // Create a module as an executive - vm.prank(executive); - educationHub.createModule("Intro to DAO", "ipfsHash1", 100, 1); + // Attempt to complete the module again + vm.prank(member); + vm.expectRevert("Module already completed"); + EducationHub(educationHubAddress).completeModule(0, 1); - // Remove the module as an execustive + // Remove the module as an executive vm.prank(executive); - educationHub.removeModule(0); - - (, , , bool moduleExists, , ) = educationHub.modules(0); - assertFalse(moduleExists); + EducationHub(educationHubAddress).removeModule(0); } } From 8beb285c29490ffff5af3989292cf753a7855009 Mon Sep 17 00:00:00 2001 From: cometsheepboy Date: Fri, 11 Oct 2024 12:50:25 -0500 Subject: [PATCH 4/4] Completed Issue (Fixed my mistake) --- test/integration/hybridOrg.t.sol | 141 ++++++++++++------------------- 1 file changed, 54 insertions(+), 87 deletions(-) diff --git a/test/integration/hybridOrg.t.sol b/test/integration/hybridOrg.t.sol index c73374e..56c06aa 100644 --- a/test/integration/hybridOrg.t.sol +++ b/test/integration/hybridOrg.t.sol @@ -117,93 +117,60 @@ contract HybridOrgTest is Test { */ /// @dev test with Election Hub - // function testHybridElectionHub() public { - // //Deploy HybridOrg with Election Hub - // DeployHybridOrg deployHybridOrg = new DeployHybridOrg(); - // hybridVotingRegistryAddress = deployHybridOrg.run( - // address(masterFactory), - // true, - // false - // ); - // Registry registry = Registry(hybridVotingRegistryAddress); - // address electionContractAddress = registry.getContractAddress( - // "ElectionContract" - // ); - - // address votingContractAddress = IElectionContract( - // electionContractAddress - // ).votingContract(); - // address nftMembership = registry.getContractAddress("NFTMembership"); - - // //Election Creation - // vm.prank(votingContractAddress); - // (uint256 electionId, uint256 proposalId) = IElectionContract( - // electionContractAddress - // ).createElection(1); - - // assertEq(electionId, 0); - // assertEq(proposalId, 1); - - // address candidate1 = address(0xDEAD); - // address candidate2 = address(0xBEEF); - // address candidate3 = address(0xFEED); - // console.log("Test Voting Contract Address"); - // console.logAddress(votingContractAddress); - // // Add Candidates - // vm.prank(votingContractAddress); - // IElectionContract(electionContractAddress).addCandidate( - // 1, - // candidate1, - // "Candidate 1" - // ); - - // vm.prank(votingContractAddress); - // IElectionContract(electionContractAddress).addCandidate( - // 1, - // candidate2, - // "Candidate 2" - // ); - - // vm.prank(votingContractAddress); - // IElectionContract(electionContractAddress).addCandidate( - // 1, - // candidate3, - // "Candidate 3" - // ); - - // // Conclude Election - // vm.prank(votingContractAddress); - // IElectionContract(electionContractAddress).concludeElection(1, 2); - - // // Verify Results - // ( - // bool isActive, - // uint256 winningCandidateIndex, - // bool hasValidWinner - // ) = IElectionContract(electionContractAddress).getElectionDetails( - // electionId - // ); - // assertFalse(isActive); - // assertTrue(hasValidWinner); - // assertEq(winningCandidateIndex, 2); - - // // Verify Candidates - // IElectionContract.Candidate[] memory candidates = IElectionContract( - // electionContractAddress - // ).getCandidates(electionId); - // assertEq(candidates.length, 3); - // assertEq(candidates[0].candidateAddress, candidate1); - // assertEq(candidates[1].candidateAddress, candidate2); - // assertEq(candidates[2].candidateAddress, candidate3); - - // // Check that the NFT was minted for the winning candidate - // assertEq( - // INFTMembership11(nftMembership).checkMemberTypeByAddress( - // candidate3 - // ), - // "Executive" - // ); - // } + function testHybridElectionHub() public { + //Deploy HybridOrg with Election Hub + DeployHybridOrg deployHybridOrg = new DeployHybridOrg(); + hybridVotingRegistryAddress = deployHybridOrg.run(address(masterFactory), true, false); + Registry registry = Registry(hybridVotingRegistryAddress); + address electionContractAddress = registry.getContractAddress("ElectionContract"); + + address votingContractAddress = IElectionContract(electionContractAddress).votingContract(); + address nftMembership = registry.getContractAddress("NFTMembership"); + + //Election Creation + vm.prank(votingContractAddress); + (uint256 electionId, uint256 proposalId) = IElectionContract(electionContractAddress).createElection(1); + + assertEq(electionId, 0); + assertEq(proposalId, 1); + + address candidate1 = address(0xDEAD); + address candidate2 = address(0xBEEF); + address candidate3 = address(0xFEED); + console.log("Test Voting Contract Address"); + console.logAddress(votingContractAddress); + // Add Candidates + vm.prank(votingContractAddress); + IElectionContract(electionContractAddress).addCandidate(1, candidate1, "Candidate 1"); + + vm.prank(votingContractAddress); + IElectionContract(electionContractAddress).addCandidate(1, candidate2, "Candidate 2"); + + vm.prank(votingContractAddress); + IElectionContract(electionContractAddress).addCandidate(1, candidate3, "Candidate 3"); + + // Conclude Election + vm.prank(votingContractAddress); + IElectionContract(electionContractAddress).concludeElection(1, 2); + + // Verify Results + (bool isActive, uint256 winningCandidateIndex, bool hasValidWinner) = + IElectionContract(electionContractAddress).getElectionDetails(electionId); + assertFalse(isActive); + assertTrue(hasValidWinner); + assertEq(winningCandidateIndex, 2); + + // Verify Candidates + IElectionContract.Candidate[] memory candidates = + IElectionContract(electionContractAddress).getCandidates(electionId); + assertEq(candidates.length, 3); + assertEq(candidates[0].candidateAddress, candidate1); + assertEq(candidates[1].candidateAddress, candidate2); + assertEq(candidates[2].candidateAddress, candidate3); + + // Check that the NFT was minted for the winning candidate + assertEq(INFTMembership11(nftMembership).checkMemberTypeByAddress(candidate3), "Executive"); + } /// @dev test with Eduction Hub function testHybridEducationHub() public {