From d32d0a19c650ec9369ca4e985e0ecdc4e902f7ea Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Tue, 29 Apr 2025 18:48:17 +0600 Subject: [PATCH 01/41] Update the description of env example --- env.example | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/env.example b/env.example index 4c5b7440..6927e0bd 100644 --- a/env.example +++ b/env.example @@ -4,14 +4,35 @@ PRIVATE_KEY= RPC_URL= + +# ------------------------- +# Contract Addresses +# ------------------------- # Optionally set this to reuse already-deployed contracts. # If any are left blank, they will be freshly deployed. +TEST_USD_ADDRESS= +GLOBAL_PARAMS_ADDRESS= +TREASURY_FACTORY_ADDRESS= +CAMPAIGN_INFO_FACTORY_ADDRESS= + # ------------------------- -# Contract Addresses +# Protocol & Platform Multisig Admin Addresses +# ------------------------- +PROTOCOL_ADMIN_ADDRESS= +PLATFORM_ADMIN_ADDRESS= + +# ------------------------- +# Backer Addresses # ------------------------- -TEST_USD_ADDRESS="" -GLOBAL_PARAMS_ADDRESS="" -TREASURY_FACTORY_ADDRESS="" -CAMPAIGN_INFO_FACTORY_ADDRESS="" -SIMULATE=true \ No newline at end of file +# Only required if TEST_USD needs to be pre-minted + +BACKER1_ADDRESS= +BACKER2_ADDRESS= + +# ------------------------- +# Simulation +# ------------------------- +# Can be true or false only. + +SIMULATE= \ No newline at end of file From 35712c24effe75ac45f13e66d1387ce3f530526a Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Tue, 29 Apr 2025 18:49:37 +0600 Subject: [PATCH 02/41] Modularize deploy scripts --- script/DeployCampaignInfoFactory.s.sol | 72 +++++++++++-------- script/DeployCampaignInfoImplementation.s.sol | 34 +++++++++ 2 files changed, 75 insertions(+), 31 deletions(-) create mode 100644 script/DeployCampaignInfoImplementation.s.sol diff --git a/script/DeployCampaignInfoFactory.s.sol b/script/DeployCampaignInfoFactory.s.sol index 6fc116d0..018a4224 100644 --- a/script/DeployCampaignInfoFactory.s.sol +++ b/script/DeployCampaignInfoFactory.s.sol @@ -1,47 +1,57 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; -import {CampaignInfo} from "../src/CampaignInfo.sol"; -import {CampaignInfoFactory} from "../src/CampaignInfoFactory.sol"; -import {GlobalParams} from "../src/GlobalParams.sol"; -import {TreasuryFactory} from "../src/TreasuryFactory.sol"; +import "forge-std/Script.sol"; +import "forge-std/console2.sol"; +import {CampaignInfoFactory} from "src/CampaignInfoFactory.sol"; +import {CampaignInfo} from "src/CampaignInfo.sol"; +import {GlobalParams} from "src/GlobalParams.sol"; import {DeployBase} from "./lib/DeployBase.s.sol"; contract DeployCampaignInfoFactory is DeployBase { function deploy( - address _globalParams, - address _treasuryFactory + address globalParams, + address treasuryFactory ) public returns (address) { - require(_globalParams != address(0), "GlobalParams not set"); - require(_treasuryFactory != address(0), "TreasuryFactory not set"); - - // Deploy CampaignInfo implementation - CampaignInfo campaignInfo = new CampaignInfo(msg.sender); - - // Deploy CampaignInfoFactory - CampaignInfoFactory factory = new CampaignInfoFactory( - GlobalParams(_globalParams), - address(campaignInfo) + console2.log("Deploying CampaignInfoFactory..."); + + // Properly deploy CampaignInfo with direct instantiation + CampaignInfo campaignInfoImpl = new CampaignInfo(address(this)); + address campaignInfo = address(campaignInfoImpl); + console2.log("CampaignInfo implementation deployed at:", campaignInfo); + + // Create and initialize the factory + CampaignInfoFactory campaignInfoFactory = new CampaignInfoFactory( + GlobalParams(globalParams), + campaignInfo ); - - // Initialize the factory - factory._initialize(_treasuryFactory, _globalParams); - - return address(factory); + + campaignInfoFactory._initialize( + treasuryFactory, + globalParams + ); + + console2.log("CampaignInfoFactory deployed and initialized at:", address(campaignInfoFactory)); + return address(campaignInfoFactory); } function run() external { - address globalParams = vm.envOr("GLOBAL_PARAMS_ADDRESS", address(0)); - address treasuryFactory = vm.envOr( - "TREASURY_FACTORY_ADDRESS", - address(0) - ); + uint256 deployerKey = vm.envUint("PRIVATE_KEY"); + bool simulate = vm.envOr("SIMULATE", false); + + address globalParams = vm.envAddress("GLOBAL_PARAMS_ADDRESS"); + address treasuryFactory = vm.envAddress("TREASURY_FACTORY_ADDRESS"); + + if (!simulate) { + vm.startBroadcast(deployerKey); + } + + address factoryAddress = deploy(globalParams, treasuryFactory); - require(globalParams != address(0), "GlobalParams must be set"); - require(treasuryFactory != address(0), "TreasuryFactory must be set"); + if (!simulate) { + vm.stopBroadcast(); + } - vm.startBroadcast(vm.envUint("PRIVATE_KEY")); - deploy(globalParams, treasuryFactory); - vm.stopBroadcast(); + console2.log("CAMPAIGN_INFO_FACTORY_ADDRESS", factoryAddress); } } \ No newline at end of file diff --git a/script/DeployCampaignInfoImplementation.s.sol b/script/DeployCampaignInfoImplementation.s.sol new file mode 100644 index 00000000..41f72486 --- /dev/null +++ b/script/DeployCampaignInfoImplementation.s.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import "forge-std/Script.sol"; +import "forge-std/console.sol"; +import {CampaignInfo} from "src/CampaignInfo.sol"; + +contract DeployCampaignInfoImplementation is Script { + function deploy() public returns (address) { + console.log("Deploying CampaignInfo implementation..."); + // Implementation will use the script address as admin, but this will be replaced + // when the factory creates new instances + CampaignInfo campaignInfo = new CampaignInfo(address(this)); + console.log("CampaignInfo implementation deployed at:", address(campaignInfo)); + return address(campaignInfo); + } + + function run() external { + uint256 deployerKey = vm.envUint("PRIVATE_KEY"); + bool simulate = vm.envOr("SIMULATE", false); + + if (!simulate) { + vm.startBroadcast(deployerKey); + } + + address implementationAddress = deploy(); + + if (!simulate) { + vm.stopBroadcast(); + } + + console.log("CAMPAIGN_INFO_ADDRESS", implementationAddress); + } +} \ No newline at end of file From 5c826c141e9b7235f8d3ab2cf1cd5ce603127464 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Tue, 29 Apr 2025 18:49:55 +0600 Subject: [PATCH 03/41] Add Implementation deployment script --- script/DeployAllOrNothingImplementation.s.sol | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 script/DeployAllOrNothingImplementation.s.sol diff --git a/script/DeployAllOrNothingImplementation.s.sol b/script/DeployAllOrNothingImplementation.s.sol new file mode 100644 index 00000000..6c10a227 --- /dev/null +++ b/script/DeployAllOrNothingImplementation.s.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import "forge-std/Script.sol"; +import "forge-std/console.sol"; +import {AllOrNothing} from "src/treasuries/AllOrNothing.sol"; + +contract DeployAllOrNothingImplementation is Script { + function deploy() public returns (address) { + console.log("Deploying AllOrNothingImplementation..."); + AllOrNothing allOrNothingImplementation = new AllOrNothing(); + console.log("AllOrNothingImplementation deployed at:", address(allOrNothingImplementation)); + return address(allOrNothingImplementation); + } + + function run() external { + uint256 deployerKey = vm.envUint("PRIVATE_KEY"); + bool simulate = vm.envOr("SIMULATE", false); + + if (!simulate) { + vm.startBroadcast(deployerKey); + } + + address implementationAddress = deploy(); + + if (!simulate) { + vm.stopBroadcast(); + } + + console.log("ALL_OR_NOTHING_IMPLEMENTATION_ADDRESS", implementationAddress); + } +} \ No newline at end of file From 11dc746b6e4e327029f1a3333272eccdce1b30ef Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Tue, 29 Apr 2025 18:50:09 +0600 Subject: [PATCH 04/41] Update import --- script/DeployAll.s.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/script/DeployAll.s.sol b/script/DeployAll.s.sol index 741a3208..16d53179 100644 --- a/script/DeployAll.s.sol +++ b/script/DeployAll.s.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.20; import "forge-std/Script.sol"; +import "forge-std/console2.sol"; import "./DeployGlobalParams.s.sol"; import "./DeployTestUSD.s.sol"; import "./DeployCampaignInfoFactory.s.sol"; @@ -58,4 +59,4 @@ contract DeployAll is Script { console2.log("TREASURY_FACTORY_ADDRESS", treasuryFactory); console2.log("CAMPAIGN_INFO_FACTORY_ADDRESS", campaignFactory); } -} +} \ No newline at end of file From ff76aae58f7f266e734908968b01783dd65d3f79 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Tue, 29 Apr 2025 18:53:01 +0600 Subject: [PATCH 05/41] Update env to specify fee params --- env.example | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/env.example b/env.example index 6927e0bd..d8366856 100644 --- a/env.example +++ b/env.example @@ -4,7 +4,6 @@ PRIVATE_KEY= RPC_URL= - # ------------------------- # Contract Addresses # ------------------------- @@ -16,6 +15,13 @@ GLOBAL_PARAMS_ADDRESS= TREASURY_FACTORY_ADDRESS= CAMPAIGN_INFO_FACTORY_ADDRESS= +# ------------------------- +# Fee Parameters +# ------------------------- +# If any are left blank, a default value will be used. +PROTOCOL_FEE_PERCENT= +PROTOCOL_FEE_PERCENT= + # ------------------------- # Protocol & Platform Multisig Admin Addresses # ------------------------- From 1131b2455e393ffb0748ca76356d03cde3e26a20 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Tue, 29 Apr 2025 19:15:17 +0600 Subject: [PATCH 06/41] Update .env structure --- env.example | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/env.example b/env.example index d8366856..c57b4c9d 100644 --- a/env.example +++ b/env.example @@ -16,23 +16,24 @@ TREASURY_FACTORY_ADDRESS= CAMPAIGN_INFO_FACTORY_ADDRESS= # ------------------------- -# Fee Parameters +# Protocol Params # ------------------------- -# If any are left blank, a default value will be used. -PROTOCOL_FEE_PERCENT= +PROTOCOL_ADMIN_ADDRESS= PROTOCOL_FEE_PERCENT= # ------------------------- -# Protocol & Platform Multisig Admin Addresses +# Platform Params # ------------------------- -PROTOCOL_ADMIN_ADDRESS= +PLATFORM_NAME= PLATFORM_ADMIN_ADDRESS= +PLATFORM_FEE_PERCENT= # ------------------------- -# Backer Addresses +# TEST_USD Setups # ------------------------- -# Only required if TEST_USD needs to be pre-minted +# Only required if TEST_USD needs to be pre-minted. +TOKEN_MINT_AMOUNT= BACKER1_ADDRESS= BACKER2_ADDRESS= From ca5d6d7419c97563699bffb3690fccf88c49fe41 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Tue, 29 Apr 2025 19:15:38 +0600 Subject: [PATCH 07/41] Add setup script for platform --- script/DeployAllAndSetup.s.sol | 346 +++++++++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 script/DeployAllAndSetup.s.sol diff --git a/script/DeployAllAndSetup.s.sol b/script/DeployAllAndSetup.s.sol new file mode 100644 index 00000000..3f7ef4ab --- /dev/null +++ b/script/DeployAllAndSetup.s.sol @@ -0,0 +1,346 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import "forge-std/Script.sol"; +import "forge-std/console2.sol"; +import "src/TestUSD.sol"; +import "src/GlobalParams.sol"; +import "src/CampaignInfoFactory.sol"; +import "src/CampaignInfo.sol"; +import "src/TreasuryFactory.sol"; +import "src/treasuries/AllOrNothing.sol"; + +/** + * @notice Script to deploy and setup all needed contracts for the protocol + */ +contract DeployAllAndSetup is Script { + // Customizable values (set through environment variables) + bytes32 platformHash; + uint256 protocolFeePercent; + uint256 platformFeePercent; + uint256 tokenMintAmount; + bool simulate; + + // Contract addresses + address testUSD; + address globalParams; + address campaignInfo; + address treasuryFactory; + address campaignInfoFactory; + address allOrNothingImplementation; + + // User addresses + address deployerAddress; + address finalProtocolAdmin; + address finalPlatformAdmin; + address backer1; + address backer2; + + // Flags to track what was completed + bool platformEnlisted = false; + bool implementationRegistered = false; + bool implementationApproved = false; + bool adminRightsTransferred = false; + + // Flags for contract deployment or reuse + bool testUsdDeployed = false; + bool globalParamsDeployed = false; + bool treasuryFactoryDeployed = false; + bool campaignInfoFactoryDeployed = false; + bool allOrNothingDeployed = false; + + // Configure parameters based on environment variables + function setupParams() internal { + // Get customizable values + string memory platformName = vm.envOr("PLATFORM_NAME", string("MiniFunder")); + platformHash = keccak256(abi.encodePacked(platformName)); + protocolFeePercent = vm.envOr("PROTOCOL_FEE_PERCENT", uint256(100)); // Default 1% + platformFeePercent = vm.envOr("PLATFORM_FEE_PERCENT", uint256(400)); // Default 4% + tokenMintAmount = vm.envOr("TOKEN_MINT_AMOUNT", uint256(10000000e18)); + simulate = vm.envOr("SIMULATE", false); + + // Get user addresses + uint256 deployerKey = vm.envUint("PRIVATE_KEY"); + deployerAddress = vm.addr(deployerKey); + + // These are the final admin addresses that will receive control + finalProtocolAdmin = vm.envOr("PROTOCOL_ADMIN_ADDRESS", deployerAddress); + finalPlatformAdmin = vm.envOr("PLATFORM_ADMIN_ADDRESS", deployerAddress); + backer1 = vm.envOr("BACKER1_ADDRESS", address(0)); + backer2 = vm.envOr("BACKER2_ADDRESS", address(0)); + + // Check for existing contract addresses + testUSD = vm.envOr("TEST_USD_ADDRESS", address(0)); + globalParams = vm.envOr("GLOBAL_PARAMS_ADDRESS", address(0)); + treasuryFactory = vm.envOr("TREASURY_FACTORY_ADDRESS", address(0)); + campaignInfoFactory = vm.envOr("CAMPAIGN_INFO_FACTORY_ADDRESS", address(0)); + allOrNothingImplementation = vm.envOr("ALL_OR_NOTHING_IMPLEMENTATION_ADDRESS", address(0)); + + console2.log("Using platform hash for:", platformName); + console2.log("Protocol fee percent:", protocolFeePercent); + console2.log("Platform fee percent:", platformFeePercent); + console2.log("Simulation mode:", simulate); + console2.log("Deployer address:", deployerAddress); + console2.log("Final protocol admin:", finalProtocolAdmin); + console2.log("Final platform admin:", finalPlatformAdmin); + } + + // Deploy or reuse contracts + function deployContracts() internal { + console2.log("Setting up contracts..."); + + // Deploy or reuse TestUSD + if (testUSD == address(0)) { + testUSD = address(new TestUSD()); + testUsdDeployed = true; + console2.log("TestUSD deployed at:", testUSD); + } else { + console2.log("Reusing TestUSD at:", testUSD); + } + + // Deploy or reuse GlobalParams + if (globalParams == address(0)) { + globalParams = address(new GlobalParams( + deployerAddress, // Initially deployer is protocol admin + testUSD, + protocolFeePercent + )); + globalParamsDeployed = true; + console2.log("GlobalParams deployed at:", globalParams); + } else { + console2.log("Reusing GlobalParams at:", globalParams); + } + + // We need at least TestUSD and GlobalParams to continue + require(testUSD != address(0), "TestUSD address is required"); + require(globalParams != address(0), "GlobalParams address is required"); + + // Deploy CampaignInfo implementation if needed for new deployments + if (campaignInfoFactory == address(0)) { + campaignInfo = address(new CampaignInfo(address(this))); + console2.log("CampaignInfo deployed at:", campaignInfo); + } + + // Deploy or reuse TreasuryFactory + if (treasuryFactory == address(0)) { + treasuryFactory = address(new TreasuryFactory(GlobalParams(globalParams))); + treasuryFactoryDeployed = true; + console2.log("TreasuryFactory deployed at:", treasuryFactory); + } else { + console2.log("Reusing TreasuryFactory at:", treasuryFactory); + } + + // Deploy or reuse CampaignInfoFactory + if (campaignInfoFactory == address(0)) { + campaignInfoFactory = address(new CampaignInfoFactory( + GlobalParams(globalParams), + campaignInfo + )); + CampaignInfoFactory(campaignInfoFactory)._initialize( + treasuryFactory, + globalParams + ); + campaignInfoFactoryDeployed = true; + console2.log("CampaignInfoFactory deployed and initialized at:", campaignInfoFactory); + } else { + console2.log("Reusing CampaignInfoFactory at:", campaignInfoFactory); + } + + // Deploy or reuse AllOrNothing implementation + if (allOrNothingImplementation == address(0)) { + allOrNothingImplementation = address(new AllOrNothing()); + allOrNothingDeployed = true; + console2.log("AllOrNothing implementation deployed at:", allOrNothingImplementation); + } else { + console2.log("Reusing AllOrNothing implementation at:", allOrNothingImplementation); + } + } + + // Setup steps when deployer has all roles + function enlistPlatform() internal { + // Skip if we didn't deploy GlobalParams (assuming it's already set up) + if (!globalParamsDeployed) { + console2.log("Skipping enlistPlatform - using existing GlobalParams"); + platformEnlisted = true; + return; + } + + console2.log("Setting up: enlistPlatform"); + // Only use startPrank in simulation mode + if (simulate) { + vm.startPrank(deployerAddress); + } + + GlobalParams(globalParams).enlistPlatform( + platformHash, + deployerAddress, // Initially deployer is platform admin + platformFeePercent + ); + + if (simulate) { + vm.stopPrank(); + } + platformEnlisted = true; + console2.log("Platform enlisted successfully"); + } + + function registerTreasuryImplementation() internal { + // Skip if we didn't deploy TreasuryFactory (assuming it's already set up) + if (!treasuryFactoryDeployed || !allOrNothingDeployed) { + console2.log("Skipping registerTreasuryImplementation - using existing contracts"); + implementationRegistered = true; + return; + } + + console2.log("Setting up: registerTreasuryImplementation"); + // Only use startPrank in simulation mode + if (simulate) { + vm.startPrank(deployerAddress); + } + + TreasuryFactory(treasuryFactory).registerTreasuryImplementation( + platformHash, + 0, // Implementation ID + allOrNothingImplementation + ); + + if (simulate) { + vm.stopPrank(); + } + implementationRegistered = true; + console2.log("Treasury implementation registered successfully"); + } + + function approveTreasuryImplementation() internal { + // Skip if we didn't deploy TreasuryFactory (assuming it's already set up) + if (!treasuryFactoryDeployed || !allOrNothingDeployed) { + console2.log("Skipping approveTreasuryImplementation - using existing contracts"); + implementationApproved = true; + return; + } + + console2.log("Setting up: approveTreasuryImplementation"); + // Only use startPrank in simulation mode + if (simulate) { + vm.startPrank(deployerAddress); + } + + TreasuryFactory(treasuryFactory).approveTreasuryImplementation( + platformHash, + 0 // Implementation ID + ); + + if (simulate) { + vm.stopPrank(); + } + implementationApproved = true; + console2.log("Treasury implementation approved successfully"); + } + + function mintTokens() internal { + // Only mint tokens if we deployed TestUSD + if (!testUsdDeployed) { + console2.log("Skipping mintTokens - using existing TestUSD"); + return; + } + + if (backer1 != address(0) && backer2 != address(0)) { + console2.log("Minting tokens to test backers"); + TestUSD(testUSD).mint(backer1, tokenMintAmount); + if (backer1 != backer2) { + TestUSD(testUSD).mint(backer2, tokenMintAmount); + } + console2.log("Tokens minted successfully"); + } + } + + // Transfer admin rights to final addresses + function transferAdminRights() internal { + // Skip if we didn't deploy GlobalParams (assuming it's already set up) + if (!globalParamsDeployed) { + console2.log("Skipping transferAdminRights - using existing GlobalParams"); + adminRightsTransferred = true; + return; + } + + console2.log("Transferring admin rights to final addresses..."); + + // Only transfer if the final addresses are different from deployer + if (finalProtocolAdmin != deployerAddress) { + console2.log("Transferring protocol admin rights to:", finalProtocolAdmin); + GlobalParams(globalParams).updateProtocolAdminAddress(finalProtocolAdmin); + } + + if (finalPlatformAdmin != deployerAddress) { + console2.log("Updating platform admin address for platform hash:", vm.toString(platformHash)); + GlobalParams(globalParams).updatePlatformAdminAddress(platformHash, finalPlatformAdmin); + } + + adminRightsTransferred = true; + console2.log("Admin rights transferred successfully"); + } + + function run() external { + // Load configuration + setupParams(); + + uint256 deployerKey = vm.envUint("PRIVATE_KEY"); + + // Start broadcast with deployer key + vm.startBroadcast(deployerKey); + + // Deploy or reuse contracts + deployContracts(); + + // Setup the protocol with individual transactions in the correct order + // Since deployer is both protocol and platform admin initially, we can do all steps + enlistPlatform(); + registerTreasuryImplementation(); + approveTreasuryImplementation(); + + // Mint tokens if needed + mintTokens(); + + // Finally, transfer admin rights to the final addresses + transferAdminRights(); + + // Stop broadcast + vm.stopBroadcast(); + + // Output summary + console2.log("\n--- Deployment & Setup Summary ---"); + console2.log("Platform Name Hash:", vm.toString(platformHash)); + console2.log("TEST_USD_ADDRESS:", testUSD); + console2.log("GLOBAL_PARAMS_ADDRESS:", globalParams); + if (campaignInfo != address(0)) { + console2.log("CAMPAIGN_INFO_ADDRESS:", campaignInfo); + } + console2.log("TREASURY_FACTORY_ADDRESS:", treasuryFactory); + console2.log("CAMPAIGN_INFO_FACTORY_ADDRESS:", campaignInfoFactory); + console2.log("ALL_OR_NOTHING_IMPLEMENTATION_ADDRESS:", allOrNothingImplementation); + console2.log("Protocol Admin:", finalProtocolAdmin); + console2.log("Platform Admin:", finalPlatformAdmin); + + if (backer1 != address(0)) { + console2.log("Backer1 (tokens minted):", backer1); + } + if (backer2 != address(0) && backer1 != backer2) { + console2.log("Backer2 (tokens minted):", backer2); + } + + console2.log("\nDeployment status:"); + console2.log("- TestUSD:", testUsdDeployed ? "Newly deployed" : "Reused existing"); + console2.log("- GlobalParams:", globalParamsDeployed ? "Newly deployed" : "Reused existing"); + console2.log("- TreasuryFactory:", treasuryFactoryDeployed ? "Newly deployed" : "Reused existing"); + console2.log("- CampaignInfoFactory:", campaignInfoFactoryDeployed ? "Newly deployed" : "Reused existing"); + console2.log("- AllOrNothing Implementation:", allOrNothingDeployed ? "Newly deployed" : "Reused existing"); + + console2.log("\nSetup steps:"); + console2.log("1. Platform enlisted:", platformEnlisted); + console2.log("2. Treasury implementation registered:", implementationRegistered); + console2.log("3. Treasury implementation approved:", implementationApproved); + console2.log("4. Admin rights transferred:", adminRightsTransferred); + + console2.log("\nDeployment and setup completed successfully!"); + } +} \ No newline at end of file From cb38d13a71e35d05f22b37d31ae271d31f5e4002 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 9 May 2025 01:18:21 +0600 Subject: [PATCH 08/41] Improve validations and fix logical issues - Rename `s_selectedPlatformHash` to `isSelectedPlatform - Add mapping s_isApprovedPlatform - Rename `s_approvedplatformHash` to `s_approvedPlatformHashes` - Remove event `CampaignInfoPlatformSelected` - Add error `CampaignInfoPlatformAlreadyApproved` - Add view function `checkIfPlatformApproved` - Improve validations, and replace && logic with || - Fix updateGoalAmount() logic - Add restriction to not allow already approved platform to be updated - Reset fees to 0 when platform is no longer a selected platform in `updateSelectedPlatform` - Add check in `_setPlatformInfo` to not allow setting platform info more than once - Update mapping for `s_isApprovedPlatform` in `_setPlatformInfo` --- src/CampaignInfo.sol | 72 +++++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/src/CampaignInfo.sol b/src/CampaignInfo.sol index d3b795fb..a542dd44 100644 --- a/src/CampaignInfo.sol +++ b/src/CampaignInfo.sol @@ -28,31 +28,22 @@ contract CampaignInfo is { CampaignData private s_campaignData; - mapping(bytes32 => bool) private s_selectedPlatformHash; mapping(bytes32 => address) private s_platformTreasuryAddress; mapping(bytes32 => uint256) private s_platformFeePercent; + mapping(bytes32 => bool) private s_isSelectedPlatform; + mapping(bytes32 => bool) private s_isApprovedPlatform; mapping(bytes32 => bytes32) private s_platformData; - bytes32[] private s_approvedplatformHash; + bytes32[] private s_approvedPlatformHashes; function getApprovedPlatformHashes() external view returns (bytes32[] memory) { - return s_approvedplatformHash; + return s_approvedPlatformHashes; } - /** - * @dev Emitted when a platform is selected for the campaign. - * @param platformHash The bytes32 identifier of the platform. - * @param platformTreasury The address of the platform's treasury. - */ - event CampaignInfoPlatformSelected( - bytes32 indexed platformHash, - address indexed platformTreasury - ); - /** * @dev Emitted when the launch time of the campaign is updated. * @param newLaunchTime The new launch time. @@ -127,6 +118,12 @@ contract CampaignInfo is */ error CampaignInfoPlatformNotSelected(bytes32 platformHash); + /** + * @dev Emitted when a platform is already approved for the campaign. + * @param platformHash The bytes32 identifier of the platform. + */ + error CampaignInfoPlatformAlreadyApproved(bytes32 platformHash); + constructor(address creator) Ownable(creator) {} function initialize( @@ -144,7 +141,7 @@ contract CampaignInfo is for (uint256 i = 0; i < len; ++i) { s_platformFeePercent[selectedPlatformHash[i]] = GLOBAL_PARAMS .getPlatformFeePercent(selectedPlatformHash[i]); - s_selectedPlatformHash[selectedPlatformHash[i]] = true; + s_isSelectedPlatform[selectedPlatformHash[i]] = true; } len = platformDataKey.length; bool isValid; @@ -182,7 +179,18 @@ contract CampaignInfo is function checkIfPlatformSelected( bytes32 platformHash ) public view override returns (bool) { - return s_selectedPlatformHash[platformHash]; + return s_isSelectedPlatform[platformHash]; + } + + /** + * @dev Check if a platform is already approved + * @param platformHash The bytes32 identifier of the platform. + * @return True if the platform is already approved, false otherwise. + */ + function checkIfPlatformApproved( + bytes32 platformHash + ) public view returns (bool) { + return s_isApprovedPlatform[platformHash]; } /** @@ -208,8 +216,8 @@ contract CampaignInfo is * @inheritdoc ICampaignInfo */ function getTotalRaisedAmount() external view override returns (uint256) { - bytes32[] memory tempPlatforms = s_approvedplatformHash; - uint256 length = s_approvedplatformHash.length; + bytes32[] memory tempPlatforms = s_approvedPlatformHashes; + uint256 length = s_approvedPlatformHashes.length; uint256 amount; address tempTreasury; for (uint256 i = 0; i < length; i++) { @@ -324,7 +332,13 @@ contract CampaignInfo is */ function transferOwnership( address newOwner - ) public override(ICampaignInfo, Ownable) onlyOwner whenNotPaused whenNotCancelled { + ) + public + override(ICampaignInfo, Ownable) + onlyOwner + whenNotPaused + whenNotCancelled + { super.transferOwnership(newOwner); } @@ -341,7 +355,7 @@ contract CampaignInfo is whenNotPaused whenNotCancelled { - if (launchTime < block.timestamp && getDeadline() <= launchTime) { + if (launchTime < block.timestamp || getDeadline() <= launchTime) { revert CampaignInfoInvalidInput(); } s_campaignData.launchTime = launchTime; @@ -385,6 +399,7 @@ contract CampaignInfo is if (goalAmount == 0) { revert CampaignInfoInvalidInput(); } + s_campaignData.goalAmount = goalAmount; emit CampaignInfoGoalAmountUpdated(goalAmount); } @@ -408,7 +423,17 @@ contract CampaignInfo is if (!GLOBAL_PARAMS.checkIfPlatformIsListed(platformHash)) { revert CampaignInfoInvalidPlatformUpdate(platformHash, selection); } - s_selectedPlatformHash[platformHash] = selection; + + if (!selection && checkIfPlatformApproved(platformHash)) { + revert CampaignInfoPlatformAlreadyApproved(platformHash); + } + s_isSelectedPlatform[platformHash] = selection; + if (selection) { + s_platformFeePercent[platformHash] = GLOBAL_PARAMS + .getPlatformFeePercent(platformHash); + } else { + s_platformFeePercent[platformHash] = 0; + } emit CampaignInfoSelectedPlatformUpdated(platformHash, selection); } @@ -453,8 +478,13 @@ contract CampaignInfo is if (!selected) { revert CampaignInfoPlatformNotSelected(platformHash); } + if (s_isApprovedPlatform[platformHash]) { + revert CampaignInfoPlatformAlreadyApproved(platformHash); + } s_platformTreasuryAddress[platformHash] = platformTreasuryAddress; - s_approvedplatformHash.push(platformHash); + s_approvedPlatformHashes.push(platformHash); + s_isApprovedPlatform[platformHash] = true; + emit CampaignInfoPlatformInfoUpdated( platformHash, platformTreasuryAddress From 9575d7a921a097a860575a79b050f3f11ca8e5a0 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 9 May 2025 01:19:05 +0600 Subject: [PATCH 09/41] Improve validation --- src/CampaignInfoFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CampaignInfoFactory.sol b/src/CampaignInfoFactory.sol index f5d554f4..e2a648fb 100644 --- a/src/CampaignInfoFactory.sol +++ b/src/CampaignInfoFactory.sol @@ -82,7 +82,7 @@ contract CampaignInfoFactory is Initializable, ICampaignInfoFactory, Ownable { CampaignData calldata campaignData ) external override { if ( - campaignData.launchTime < block.timestamp && + campaignData.launchTime < block.timestamp || campaignData.deadline <= campaignData.launchTime ) { revert CampaignInfoFactoryInvalidInput(); From aa2c93e0fa65e38d09d570c0be9c5fb320ed1007 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 9 May 2025 01:23:13 +0600 Subject: [PATCH 10/41] Improve validation in GlobalParams - Remove redundant validation `platformIsListed`and `ZERO_BYTES` check in `getPlatformDataOwner` - Remove redundant validation `platformAdminAddress` in `enlistPlatform` - Optimize logic and remove redundant validation of `s_platformDataOwner` comparison - Optimize validation in `removePlatformData` --- src/GlobalParams.sol | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/GlobalParams.sol b/src/GlobalParams.sol index b228e0a5..1778de76 100644 --- a/src/GlobalParams.sol +++ b/src/GlobalParams.sol @@ -261,13 +261,9 @@ contract GlobalParams is IGlobalParams, Ownable { external view override - platformIsListed(platformHash) returns (bytes32 platformHash) { platformHash = s_platformDataOwner[platformDataKey]; - if (platformHash == ZERO_BYTES) { - revert GlobalParamsInvalidInput(); - } } /** @@ -300,7 +296,7 @@ contract GlobalParams is IGlobalParams, Ownable { address platformAdminAddress, uint256 platformFeePercent ) external onlyOwner notAddressZero(platformAdminAddress) { - if (platformHash == ZERO_BYTES || platformAdminAddress == address(0)) { + if (platformHash == ZERO_BYTES) { revert GlobalParamsInvalidInput(); } if (s_platformIsListed[platformHash]) { @@ -344,12 +340,9 @@ contract GlobalParams is IGlobalParams, Ownable { if (platformDataKey == ZERO_BYTES) { revert GlobalParamsInvalidInput(); } - if (s_platformData[platformDataKey] != false) { + if (s_platformData[platformDataKey]) { revert GlobalParamsPlatformDataAlreadySet(); } - if (s_platformDataOwner[platformDataKey] == platformHash) { - revert GlobalParamsPlatformDataSlotTaken(); - } s_platformData[platformDataKey] = true; s_platformDataOwner[platformDataKey] = platformHash; emit PlatformDataAdded(platformHash, platformDataKey); @@ -367,7 +360,7 @@ contract GlobalParams is IGlobalParams, Ownable { if (platformDataKey == ZERO_BYTES) { revert GlobalParamsInvalidInput(); } - if (s_platformData[platformDataKey] == false) { + if (!s_platformData[platformDataKey]) { revert GlobalParamsPlatformDataNotSet(); } s_platformData[platformDataKey] = false; From bde405338b023dc40d02c50a4e32a655fa32200c Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 9 May 2025 01:24:39 +0600 Subject: [PATCH 11/41] Update code docs --- src/interfaces/ICampaignInfo.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/interfaces/ICampaignInfo.sol b/src/interfaces/ICampaignInfo.sol index 509769b1..5deb2e3c 100644 --- a/src/interfaces/ICampaignInfo.sol +++ b/src/interfaces/ICampaignInfo.sol @@ -122,6 +122,7 @@ interface ICampaignInfo { /** * @notice Updates the selection status of a platform for the campaign. + * @dev It can only be called for a platform if its not approved i.e. the platform treasury is not deployed * @param platformHash The bytes32 identifier of the platform. * @param selection The new selection status (true or false). */ From a4ffc80a1ada1ca01914cac26df8cc0b268d14bd Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 9 May 2025 01:25:22 +0600 Subject: [PATCH 12/41] Remove redundant variable `CAMPAIGN_INFO` --- src/utils/BaseTreasury.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/utils/BaseTreasury.sol b/src/utils/BaseTreasury.sol index 33bb602b..8064dd5b 100644 --- a/src/utils/BaseTreasury.sol +++ b/src/utils/BaseTreasury.sol @@ -30,7 +30,6 @@ abstract contract BaseTreasury is bytes32 internal PLATFORM_HASH; uint256 internal PLATFORM_FEE_PERCENT; IERC20 internal TOKEN; - ICampaignInfo internal CAMPAIGN_INFO; uint256 internal s_pledgedAmount; bool internal s_feesDisbursed; @@ -80,7 +79,6 @@ abstract contract BaseTreasury is ) internal { __CampaignAccessChecker_init(infoAddress); PLATFORM_HASH = platformHash; - CAMPAIGN_INFO = ICampaignInfo(infoAddress); TOKEN = IERC20(INFO.getTokenAddress()); PLATFORM_FEE_PERCENT = INFO.getPlatformFeePercent(platformHash); } From 32b7b1617200d0c6f3248845ef972180411f1f65 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 9 May 2025 01:26:34 +0600 Subject: [PATCH 13/41] Call `_safeMint` after state changes in `_pledge` --- src/treasuries/AllOrNothing.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/treasuries/AllOrNothing.sol b/src/treasuries/AllOrNothing.sol index 75046efc..d7c7443a 100644 --- a/src/treasuries/AllOrNothing.sol +++ b/src/treasuries/AllOrNothing.sol @@ -384,10 +384,10 @@ contract AllOrNothing is uint256 totalAmount = pledgeAmount + shippingFee; TOKEN.safeTransferFrom(backer, address(this), totalAmount); s_tokenIdCounter.increment(); - _safeMint(backer, tokenId, abi.encodePacked(backer, reward)); s_tokenToPledgedAmount[tokenId] = pledgeAmount; s_tokenToTotalCollectedAmount[tokenId] = totalAmount; s_pledgedAmount += pledgeAmount; + _safeMint(backer, tokenId, abi.encodePacked(backer, reward, rewards)); emit Receipt( backer, reward, From c1595f41fa9d742378bdcbd2c1f2b14c43ebbe0e Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 15 May 2025 05:58:38 +0600 Subject: [PATCH 14/41] Update docs --- docs/src/README.md | 153 ++++++--- docs/src/SUMMARY.md | 1 - .../CampaignInfo.sol/contract.CampaignInfo.md | 131 +++++--- .../contract.CampaignInfoFactory.md | 38 ++- .../GlobalParams.sol/contract.GlobalParams.md | 64 ++-- docs/src/src/TestUSD.sol/contract.TestUSD.md | 2 +- .../contract.TreasuryFactory.md | 12 +- .../interface.ICampaignData.md | 2 +- .../interface.ICampaignInfo.md | 4 +- .../interface.ICampaignInfoFactory.md | 25 +- .../interface.ICampaignTreasury.md | 2 +- .../interface.IGlobalParams.md | 2 +- .../interfaces/IItem.sol/interface.IItem.md | 2 +- .../IReward.sol/interface.IReward.md | 2 +- .../interface.ITreasuryFactory.md | 2 +- .../AllOrNothing.sol/contract.AllOrNothing.md | 85 +++-- .../MinimumOrder.sol/contract.MinimumOrder.md | 290 ------------------ .../OutOfStock.sol/contract.OutOfStock.md | 58 ---- .../library.AddressCalculator.md | 55 ---- .../abstract.AdminAccessChecker.md | 2 +- .../BaseTreasury.sol/abstract.BaseTreasury.md | 9 +- .../abstract.CampaignAccessChecker.md | 2 +- .../utils/Counters.sol/library.Counters.md | 18 +- .../FiatEnabled.sol/abstract.FiatEnabled.md | 2 +- .../ItemRegistry.sol/contract.ItemRegistry.md | 11 +- .../abstract.PausableCancellable.md | 2 +- .../abstract.PausableWithMsg.md | 110 ------- docs/src/src/utils/README.md | 1 - .../abstract.TimestampChecker.md | 20 +- 29 files changed, 380 insertions(+), 727 deletions(-) delete mode 100644 docs/src/src/treasuries/MinimumOrder.sol/contract.MinimumOrder.md delete mode 100644 docs/src/src/treasuries/OutOfStock.sol/contract.OutOfStock.md delete mode 100644 docs/src/src/utils/AddressCalculator.sol/library.AddressCalculator.md delete mode 100644 docs/src/src/utils/PausableWithMsg.sol/abstract.PausableWithMsg.md diff --git a/docs/src/README.md b/docs/src/README.md index a5e70a42..5522623e 100644 --- a/docs/src/README.md +++ b/docs/src/README.md @@ -1,67 +1,140 @@ -# CCP Contracts -This repository contains the smart contracts source code and campaign configuration for Creative Crowdfunding Protocol - CCP. The repository uses Foundry as development environment for compilation, testing and deployment tasks. +# Creative Crowdfunding Protocol (CC Protocol) Smart Contracts -## What is CCP? -CCP is a protocol for crowdfunding campaigns that allows creators to multilist campaigns across different crowdfunding platforms. It provides infrastructure tooling and support for platforms to create and manage campaigns in web3. +## Overview -## Documentation -The detailed technical documentation for the protocol can be found in the [docs](./docs/src/SUMMARY.md) folder. +CC Protocol is a decentralized crowdfunding protocol designed to help creators launch and manage campaigns across multiple platforms. By providing a standardized infrastructure, the protocol simplifies the process of creating, funding, and managing crowdfunding initiatives in web3 across different platforms. + +## Features + +- Cross-listable campaign creation +- Multiple treasury models +- Secure fund management +- Customizable protocol parameters + +## Prerequisites -## Getting Started -### Prerequisites -The following tools are required to be installed in your system: -- [Foundry](https://book.getfoundry.sh/getting-started/installation) -- [Node.js](https://nodejs.org/en/download/) +- [Foundry](https://book.getfoundry.sh/) +- Solidity ^0.8.20 +- Node.js (recommended) -### Installation +## Installation -```shell -$ npm install +1. Clone the repository: + +```bash +git clone https://github.com/ccprotocol/ccprotocol-contracts.git +cd ccprotocol-contracts ``` -### Build +2. Install dependencies: -```shell -$ forge build +```bash +forge install ``` -### Test +3. Copy environment template: -```shell -$ forge test +```bash +cp .env.example .env ``` -### Format +4. Configure your `.env` file with: + +- Private key +- RPC URL +- (Optional) Contract addresses for reuse + +## Documentation + +Comprehensive documentation is available in the `docs/` folder: + +- Technical specifications +- Contract interfaces +- Deployment guides +- Development setup instructions + +To view the documentation: + +```bash +# Navigate to docs folder +cd docs +``` + +## Development + +### Compile Contracts -```shell -$ forge fmt +```bash +forge build ``` -### Gas Snapshots +### Run Tests -```shell -$ forge snapshot +```bash +# Run all tests +forge test + +# Run specific test +forge test --match-test testFunctionName + +# Run tests with more verbose output +forge test -vvv ``` -## Deploy -### Environment Variables +### Deploy Contracts -Create an environment file named `.env`, fill the environment variables following the `.env.example` file and source the file using the following command: +#### Local Deployment -```shell -$ source .env +```bash +# Start local blockchain +anvil + +# Deploy to local network +forge script script/DeployAll.s.sol:DeployAll --rpc-url http://localhost:8545 --private-key $PRIVATE_KEY --broadcast ``` -### Local Deployment -To deploy the contracts locally, run the following command: +#### Testnet Deployment -```shell -$ forge script script/Setup.s.sol:SetupScript +```bash +# Deploy to testnet +forge script script/DeployAll.s.sol:DeployAll --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast -vvvv ``` -### Remote Deployment -To deploy the contracts to a remote network, run the following command: +## Contract Architecture + +### Core Contracts + +- `TestUSD`: Mock ERC20 token for testing +- `GlobalParams`: Protocol-wide parameter management +- `CampaignInfoFactory`: Campaign creation and management +- `TreasuryFactory`: Treasury contract deployment + +### Treasury Models + +- `AllOrNothing`: Funds refunded if campaign goal not met + +## Deployment Workflow + +1. Deploy `TestUSD` +2. Deploy `GlobalParams` +3. Deploy `TreasuryFactory` +4. Deploy `CampaignInfoFactory` + +## Environment Variables + +Key environment variables in `.env`: + +- `PRIVATE_KEY`: Deployment wallet private key +- `RPC_URL`: Network RPC endpoint +- `SIMULATE`: Toggle simulation mode +- Contract address variables for reuse + +## Troubleshooting + +- Ensure sufficient network gas tokens +- Verify RPC URL connectivity +- Check contract dependencies + +## License -```shell -$ forge script script/Setup.s.sol:SetupScript --rpc-url $RPC_URL --private-key $PRIVATE_KEY -``` \ No newline at end of file +[SPDX-License-Identifier: MIT] diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index ca711d33..d2c85d09 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -13,7 +13,6 @@ - [❱ treasuries](src/treasuries/README.md) - [AllOrNothing](src/treasuries/AllOrNothing.sol/contract.AllOrNothing.md) - [❱ utils](src/utils/README.md) - - [AddressCalculator](src/utils/AddressCalculator.sol/library.AddressCalculator.md) - [AdminAccessChecker](src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md) - [BaseTreasury](src/utils/BaseTreasury.sol/abstract.BaseTreasury.md) - [CampaignAccessChecker](src/utils/CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md) diff --git a/docs/src/src/CampaignInfo.sol/contract.CampaignInfo.md b/docs/src/src/CampaignInfo.sol/contract.CampaignInfo.md index dfb8fae7..7d1b5dd3 100644 --- a/docs/src/src/CampaignInfo.sol/contract.CampaignInfo.md +++ b/docs/src/src/CampaignInfo.sol/contract.CampaignInfo.md @@ -1,5 +1,5 @@ # CampaignInfo -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/CampaignInfo.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/CampaignInfo.sol) **Inherits:** [ICampaignData](/src/interfaces/ICampaignData.sol/interface.ICampaignData.md), [ICampaignInfo](/src/interfaces/ICampaignInfo.sol/interface.ICampaignInfo.md), Ownable, [PausableCancellable](/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md), [TimestampChecker](/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md), [AdminAccessChecker](/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md), Initializable @@ -15,24 +15,31 @@ CampaignData private s_campaignData; ``` -### s_selectedPlatformHash +### s_platformTreasuryAddress ```solidity -mapping(bytes32 => bool) private s_selectedPlatformHash; +mapping(bytes32 => address) private s_platformTreasuryAddress; ``` -### s_platformTreasuryAddress +### s_platformFeePercent ```solidity -mapping(bytes32 => address) private s_platformTreasuryAddress; +mapping(bytes32 => uint256) private s_platformFeePercent; ``` -### s_platformFeePercent +### s_isSelectedPlatform ```solidity -mapping(bytes32 => uint256) private s_platformFeePercent; +mapping(bytes32 => bool) private s_isSelectedPlatform; +``` + + +### s_isApprovedPlatform + +```solidity +mapping(bytes32 => bool) private s_isApprovedPlatform; ``` @@ -43,10 +50,10 @@ mapping(bytes32 => bytes32) private s_platformData; ``` -### s_approvedplatformHash +### s_approvedPlatformHashes ```solidity -bytes32[] private s_approvedplatformHash; +bytes32[] private s_approvedPlatformHashes; ``` @@ -74,7 +81,8 @@ function initialize( IGlobalParams globalParams, bytes32[] calldata selectedPlatformHash, bytes32[] calldata platformDataKey, - bytes32[] calldata platformDataValue + bytes32[] calldata platformDataValue, + CampaignData calldata campaignData ) external initializer; ``` @@ -106,6 +114,27 @@ function checkIfPlatformSelected(bytes32 platformHash) public view override retu |``|`bool`|True if the platform is selected, false otherwise.| +### checkIfPlatformApproved + +*Check if a platform is already approved* + + +```solidity +function checkIfPlatformApproved(bytes32 platformHash) public view returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`platformHash`|`bytes32`|The bytes32 identifier of the platform.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|True if the platform is already approved, false otherwise.| + + ### owner Returns the owner of the contract. @@ -121,34 +150,34 @@ function owner() public view override(ICampaignInfo, Ownable) returns (address a |`account`|`address`|The address of the contract owner.| -### getTotalRaisedAmount +### getProtocolAdminAddress -Retrieves the total amount raised in the campaign. +Retrieves the address of the protocol administrator. ```solidity -function getTotalRaisedAmount() external view override returns (uint256); +function getProtocolAdminAddress() public view override returns (address); ``` **Returns** |Name|Type|Description| |----|----|-----------| -|``|`uint256`|The total amount raised in the campaign.| +|``|`address`|The address of the protocol administrator.| -### getProtocolAdminAddress +### getTotalRaisedAmount -Retrieves the address of the protocol administrator. +Retrieves the total amount raised in the campaign. ```solidity -function getProtocolAdminAddress() external view override returns (address); +function getTotalRaisedAmount() external view override returns (uint256); ``` **Returns** |Name|Type|Description| |----|----|-----------| -|``|`address`|The address of the protocol administrator.| +|``|`uint256`|The total amount raised in the campaign.| ### getPlatformAdminAddress @@ -193,7 +222,7 @@ Retrieves the campaign's deadline. ```solidity -function getDeadline() external view override returns (uint256); +function getDeadline() public view override returns (uint256); ``` **Returns** @@ -329,7 +358,12 @@ Can only be called by the current owner.* ```solidity -function transferOwnership(address newOwner) public override(ICampaignInfo, Ownable) onlyOwner whenNotPaused; +function transferOwnership(address newOwner) + public + override(ICampaignInfo, Ownable) + onlyOwner + whenNotPaused + whenNotCancelled; ``` ### updateLaunchTime @@ -338,7 +372,13 @@ Updates the campaign's launch time. ```solidity -function updateLaunchTime(uint256 launchTime) external override onlyOwner currentTimeIsLess(launchTime) whenNotPaused; +function updateLaunchTime(uint256 launchTime) + external + override + onlyOwner + currentTimeIsLess(getLaunchTime()) + whenNotPaused + whenNotCancelled; ``` **Parameters** @@ -358,7 +398,8 @@ function updateDeadline(uint256 deadline) override onlyOwner currentTimeIsLess(getLaunchTime()) - whenNotPaused; + whenNotPaused + whenNotCancelled; ``` **Parameters** @@ -377,8 +418,9 @@ function updateGoalAmount(uint256 goalAmount) external override onlyOwner - currentTimeIsLess(s_campaignData.launchTime) - whenNotPaused; + currentTimeIsLess(getLaunchTime()) + whenNotPaused + whenNotCancelled; ``` **Parameters** @@ -391,14 +433,17 @@ function updateGoalAmount(uint256 goalAmount) Updates the selection status of a platform for the campaign. +*It can only be called for a platform if its not approved i.e. the platform treasury is not deployed* + ```solidity function updateSelectedPlatform(bytes32 platformHash, bool selection) external override onlyOwner - currentTimeIsLess(s_campaignData.launchTime) - whenNotPaused; + currentTimeIsLess(getLaunchTime()) + whenNotPaused + whenNotCancelled; ``` **Parameters** @@ -432,7 +477,7 @@ function _unpauseCampaign(bytes32 message) external onlyProtocolAdmin; ```solidity -function _cancelCampaign(bytes32 message) external onlyProtocolAdmin; +function _cancelCampaign(bytes32 message) external; ``` ### _setPlatformInfo @@ -452,21 +497,6 @@ function _setPlatformInfo(bytes32 platformHash, address platformTreasuryAddress) ## Events -### CampaignInfoPlatformSelected -*Emitted when a platform is selected for the campaign.* - - -```solidity -event CampaignInfoPlatformSelected(bytes32 indexed platformHash, address indexed platformTreasury); -``` - -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`platformHash`|`bytes32`|The bytes32 identifier of the platform.| -|`platformTreasury`|`address`|The address of the platform's treasury.| - ### CampaignInfoLaunchTimeUpdated *Emitted when the launch time of the campaign is updated.* @@ -600,6 +630,20 @@ error CampaignInfoPlatformNotSelected(bytes32 platformHash); |----|----|-----------| |`platformHash`|`bytes32`|The bytes32 identifier of the platform.| +### CampaignInfoPlatformAlreadyApproved +*Emitted when a platform is already approved for the campaign.* + + +```solidity +error CampaignInfoPlatformAlreadyApproved(bytes32 platformHash); +``` + +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`platformHash`|`bytes32`|The bytes32 identifier of the platform.| + ## Structs ### Config @@ -609,9 +653,6 @@ struct Config { address token; uint256 protocolFeePercent; bytes32 identifierHash; - uint256 launchTime; - uint256 deadline; - uint256 goalAmount; } ``` diff --git a/docs/src/src/CampaignInfoFactory.sol/contract.CampaignInfoFactory.md b/docs/src/src/CampaignInfoFactory.sol/contract.CampaignInfoFactory.md index e987f012..ecf45080 100644 --- a/docs/src/src/CampaignInfoFactory.sol/contract.CampaignInfoFactory.md +++ b/docs/src/src/CampaignInfoFactory.sol/contract.CampaignInfoFactory.md @@ -1,8 +1,8 @@ # CampaignInfoFactory -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/CampaignInfoFactory.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/CampaignInfoFactory.sol) **Inherits:** -[ICampaignInfoFactory](/src/interfaces/ICampaignInfoFactory.sol/interface.ICampaignInfoFactory.md), Ownable +Initializable, [ICampaignInfoFactory](/src/interfaces/ICampaignInfoFactory.sol/interface.ICampaignInfoFactory.md), Ownable Factory contract for creating campaign information contracts. @@ -71,7 +71,7 @@ constructor(IGlobalParams globalParams, address campaignImplementation) Ownable( ```solidity -function _initialize(address treasuryFactoryAddress, address globalParams) external onlyOwner; +function _initialize(address treasuryFactoryAddress, address globalParams) external onlyOwner initializer; ``` **Parameters** @@ -83,6 +83,8 @@ function _initialize(address treasuryFactoryAddress, address globalParams) exter ### createCampaign +Creates a new campaign information contract. + ```solidity function createCampaign( @@ -94,6 +96,32 @@ function createCampaign( CampaignData calldata campaignData ) external override; ``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`creator`|`address`|The address of the creator of the campaign.| +|`identifierHash`|`bytes32`|The unique identifier hash of the campaign.| +|`selectedPlatformHash`|`bytes32[]`|An array of platform identifiers selected for the campaign.| +|`platformDataKey`|`bytes32[]`|An array of platform-specific data keys.| +|`platformDataValue`|`bytes32[]`|An array of platform-specific data values.| +|`campaignData`|`CampaignData`|The struct containing campaign launch details.| + + +### updateImplementation + +Updates the campaign implementation address. + + +```solidity +function updateImplementation(address newImplementation) external override onlyOwner; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newImplementation`|`address`|The address of the camapaignInfo implementation contract.| + ## Errors ### CampaignInfoFactoryAlreadyInitialized @@ -112,12 +140,12 @@ error CampaignInfoFactoryAlreadyInitialized(); error CampaignInfoFactoryInvalidInput(); ``` -### CampaignInfoFactoryCampaignCreationFailed +### CampaignInfoFactoryCampaignInitializationFailed *Emitted when campaign creation fails.* ```solidity -error CampaignInfoFactoryCampaignCreationFailed(); +error CampaignInfoFactoryCampaignInitializationFailed(); ``` ### CampaignInfoFactoryPlatformNotListed diff --git a/docs/src/src/GlobalParams.sol/contract.GlobalParams.md b/docs/src/src/GlobalParams.sol/contract.GlobalParams.md index 62896299..2cf9e304 100644 --- a/docs/src/src/GlobalParams.sol/contract.GlobalParams.md +++ b/docs/src/src/GlobalParams.sol/contract.GlobalParams.md @@ -1,8 +1,8 @@ # GlobalParams -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/GlobalParams.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/GlobalParams.sol) **Inherits:** -[IGlobalParams](/src/interfaces/IGlobalParams.sol/interface.IGlobalParams.md), Ownable, Pausable +[IGlobalParams](/src/interfaces/IGlobalParams.sol/interface.IGlobalParams.md), Ownable Manages global parameters and platform information. @@ -127,27 +127,6 @@ constructor(address protocolAdminAddress, address tokenAddress, uint256 protocol |`protocolFeePercent`|`uint256`|The protocol fee percentage.| -### checkIfPlatformIsListed - -Checks if a platform is listed in the protocol. - - -```solidity -function checkIfPlatformIsListed(bytes32 platformHash) public view override returns (bool); -``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`platformHash`|`bytes32`|| - -**Returns** - -|Name|Type|Description| -|----|----|-----------| -|``|`bool`|True if the platform is listed; otherwise, false.| - - ### getPlatformAdminAddress Retrieves the admin address of a platform. @@ -266,12 +245,7 @@ Retrieves the owner of platform-specific data. ```solidity -function getPlatformDataOwner(bytes32 platformDataKey) - external - view - override - platformIsListed(platformHash) - returns (bytes32 platformHash); +function getPlatformDataOwner(bytes32 platformDataKey) external view override returns (bytes32 platformHash); ``` **Parameters** @@ -286,6 +260,27 @@ function getPlatformDataOwner(bytes32 platformDataKey) |`platformHash`|`bytes32`|The platform identifier associated with the data.| +### checkIfPlatformIsListed + +Checks if a platform is listed in the protocol. + + +```solidity +function checkIfPlatformIsListed(bytes32 platformHash) public view override returns (bool); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`platformHash`|`bytes32`|| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`bool`|True if the platform is listed; otherwise, false.| + + ### checkIfPlatformDataKeyValid Checks if a platform-specific data key is valid. @@ -311,11 +306,14 @@ function checkIfPlatformDataKeyValid(bytes32 platformDataKey) external view over Enlists a platform with its admin address and fee percentage. +*The platformFeePercent can be any value including zero.* + ```solidity function enlistPlatform(bytes32 platformHash, address platformAdminAddress, uint256 platformFeePercent) external - onlyOwner; + onlyOwner + notAddressZero(platformAdminAddress); ``` **Parameters** @@ -332,7 +330,7 @@ Delists a platform. ```solidity -function delistPlatform(bytes32 platformHash) external onlyOwner; +function delistPlatform(bytes32 platformHash) external onlyOwner platformIsListed(platformHash); ``` **Parameters** @@ -449,13 +447,13 @@ function updatePlatformAdminAddress(bytes32 platformHash, address platformAdminA |`platformAdminAddress`|`address`|| -### _checkIfAddressZero +### _revertIfAddressZero *Reverts if the input address is zero.* ```solidity -function _checkIfAddressZero(address account) internal pure; +function _revertIfAddressZero(address account) internal pure; ``` ### _onlyPlatformAdmin diff --git a/docs/src/src/TestUSD.sol/contract.TestUSD.md b/docs/src/src/TestUSD.sol/contract.TestUSD.md index 37bc06f1..e317536d 100644 --- a/docs/src/src/TestUSD.sol/contract.TestUSD.md +++ b/docs/src/src/TestUSD.sol/contract.TestUSD.md @@ -1,5 +1,5 @@ # TestUSD -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/TestUSD.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/TestUSD.sol) **Inherits:** ERC20, Ownable diff --git a/docs/src/src/TreasuryFactory.sol/contract.TreasuryFactory.md b/docs/src/src/TreasuryFactory.sol/contract.TreasuryFactory.md index 8cc25e3f..7d26317c 100644 --- a/docs/src/src/TreasuryFactory.sol/contract.TreasuryFactory.md +++ b/docs/src/src/TreasuryFactory.sol/contract.TreasuryFactory.md @@ -1,5 +1,5 @@ # TreasuryFactory -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/TreasuryFactory.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/TreasuryFactory.sol) **Inherits:** [ITreasuryFactory](/src/interfaces/ITreasuryFactory.sol/interface.ITreasuryFactory.md), [AdminAccessChecker](/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md) @@ -9,14 +9,14 @@ ### implementationMap ```solidity -mapping(bytes32 => mapping(uint256 => address)) implementationMap; +mapping(bytes32 => mapping(uint256 => address)) private implementationMap; ``` ### approvedImplementations ```solidity -mapping(address => bool) approvedImplementations; +mapping(address => bool) private approvedImplementations; ``` @@ -185,3 +185,9 @@ error TreasuryFactoryImplementationNotSetOrApproved(); error TreasuryFactoryTreasuryInitializationFailed(); ``` +### TreasuryFactorySettingPlatformInfoFailed + +```solidity +error TreasuryFactorySettingPlatformInfoFailed(); +``` + diff --git a/docs/src/src/interfaces/ICampaignData.sol/interface.ICampaignData.md b/docs/src/src/interfaces/ICampaignData.sol/interface.ICampaignData.md index b2d2439e..00944837 100644 --- a/docs/src/src/interfaces/ICampaignData.sol/interface.ICampaignData.md +++ b/docs/src/src/interfaces/ICampaignData.sol/interface.ICampaignData.md @@ -1,5 +1,5 @@ # ICampaignData -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/interfaces/ICampaignData.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/ICampaignData.sol) An interface for managing campaign data in a CCP. diff --git a/docs/src/src/interfaces/ICampaignInfo.sol/interface.ICampaignInfo.md b/docs/src/src/interfaces/ICampaignInfo.sol/interface.ICampaignInfo.md index 8905cd40..af5a884a 100644 --- a/docs/src/src/interfaces/ICampaignInfo.sol/interface.ICampaignInfo.md +++ b/docs/src/src/interfaces/ICampaignInfo.sol/interface.ICampaignInfo.md @@ -1,5 +1,5 @@ # ICampaignInfo -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/interfaces/ICampaignInfo.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/ICampaignInfo.sol) An interface for managing campaign information in a crowdfunding system. @@ -288,6 +288,8 @@ function updateGoalAmount(uint256 goalAmount) external; Updates the selection status of a platform for the campaign. +*It can only be called for a platform if its not approved i.e. the platform treasury is not deployed* + ```solidity function updateSelectedPlatform(bytes32 platformHash, bool selection) external; diff --git a/docs/src/src/interfaces/ICampaignInfoFactory.sol/interface.ICampaignInfoFactory.md b/docs/src/src/interfaces/ICampaignInfoFactory.sol/interface.ICampaignInfoFactory.md index 59a31f5e..e28f1138 100644 --- a/docs/src/src/interfaces/ICampaignInfoFactory.sol/interface.ICampaignInfoFactory.md +++ b/docs/src/src/interfaces/ICampaignInfoFactory.sol/interface.ICampaignInfoFactory.md @@ -1,5 +1,5 @@ # ICampaignInfoFactory -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/interfaces/ICampaignInfoFactory.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/ICampaignInfoFactory.sol) **Inherits:** [ICampaignData](/src/interfaces/ICampaignData.sol/interface.ICampaignData.md) @@ -35,6 +35,21 @@ function createCampaign( |`campaignData`|`CampaignData`|The struct containing campaign launch details.| +### updateImplementation + +Updates the campaign implementation address. + + +```solidity +function updateImplementation(address newImplementation) external; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`newImplementation`|`address`|The address of the camapaignInfo implementation contract.| + + ## Events ### CampaignInfoFactoryCampaignCreated Emitted when a campaign is successfully created. @@ -51,3 +66,11 @@ event CampaignInfoFactoryCampaignCreated(bytes32 indexed identifierHash, address |`identifierHash`|`bytes32`|The unique identifier hash of the campaign.| |`campaignInfoAddress`|`address`|The address of the created campaign information contract.| +### CampaignInfoFactoryCampaignInitialized +Emitted when the campaign after creation is initialized. + + +```solidity +event CampaignInfoFactoryCampaignInitialized(); +``` + diff --git a/docs/src/src/interfaces/ICampaignTreasury.sol/interface.ICampaignTreasury.md b/docs/src/src/interfaces/ICampaignTreasury.sol/interface.ICampaignTreasury.md index bbfe9c72..bcede9cd 100644 --- a/docs/src/src/interfaces/ICampaignTreasury.sol/interface.ICampaignTreasury.md +++ b/docs/src/src/interfaces/ICampaignTreasury.sol/interface.ICampaignTreasury.md @@ -1,5 +1,5 @@ # ICampaignTreasury -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/interfaces/ICampaignTreasury.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/ICampaignTreasury.sol) An interface for managing campaign treasury contracts. diff --git a/docs/src/src/interfaces/IGlobalParams.sol/interface.IGlobalParams.md b/docs/src/src/interfaces/IGlobalParams.sol/interface.IGlobalParams.md index 840d1619..c23e2700 100644 --- a/docs/src/src/interfaces/IGlobalParams.sol/interface.IGlobalParams.md +++ b/docs/src/src/interfaces/IGlobalParams.sol/interface.IGlobalParams.md @@ -1,5 +1,5 @@ # IGlobalParams -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/interfaces/IGlobalParams.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/IGlobalParams.sol) An interface for accessing and managing global parameters of the protocol. diff --git a/docs/src/src/interfaces/IItem.sol/interface.IItem.md b/docs/src/src/interfaces/IItem.sol/interface.IItem.md index e1eef137..41b6afc0 100644 --- a/docs/src/src/interfaces/IItem.sol/interface.IItem.md +++ b/docs/src/src/interfaces/IItem.sol/interface.IItem.md @@ -1,5 +1,5 @@ # IItem -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/interfaces/IItem.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/IItem.sol) An interface for managing items and their attributes. diff --git a/docs/src/src/interfaces/IReward.sol/interface.IReward.md b/docs/src/src/interfaces/IReward.sol/interface.IReward.md index 46b2cc6d..bfbd0aa2 100644 --- a/docs/src/src/interfaces/IReward.sol/interface.IReward.md +++ b/docs/src/src/interfaces/IReward.sol/interface.IReward.md @@ -1,5 +1,5 @@ # IReward -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/interfaces/IReward.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/IReward.sol) An interface for managing rewards in a campaign. diff --git a/docs/src/src/interfaces/ITreasuryFactory.sol/interface.ITreasuryFactory.md b/docs/src/src/interfaces/ITreasuryFactory.sol/interface.ITreasuryFactory.md index 92e54b15..07b47fcf 100644 --- a/docs/src/src/interfaces/ITreasuryFactory.sol/interface.ITreasuryFactory.md +++ b/docs/src/src/interfaces/ITreasuryFactory.sol/interface.ITreasuryFactory.md @@ -1,5 +1,5 @@ # ITreasuryFactory -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/interfaces/ITreasuryFactory.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/ITreasuryFactory.sol) *Interface for the TreasuryFactory contract, which registers, approves, and deploys treasury clones.* diff --git a/docs/src/src/treasuries/AllOrNothing.sol/contract.AllOrNothing.md b/docs/src/src/treasuries/AllOrNothing.sol/contract.AllOrNothing.md index ef5a9767..21e280ad 100644 --- a/docs/src/src/treasuries/AllOrNothing.sol/contract.AllOrNothing.md +++ b/docs/src/src/treasuries/AllOrNothing.sol/contract.AllOrNothing.md @@ -1,5 +1,5 @@ # AllOrNothing -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/treasuries/AllOrNothing.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/treasuries/AllOrNothing.sol) **Inherits:** [IReward](/src/interfaces/IReward.sol/interface.IReward.md), [BaseTreasury](/src/utils/BaseTreasury.sol/abstract.BaseTreasury.md), [TimestampChecker](/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md), ERC721Burnable @@ -8,10 +8,17 @@ A contract for handling crowdfunding campaigns with rewards. ## State Variables -### s_tokenToCollectedAmount +### s_tokenToTotalCollectedAmount ```solidity -mapping(uint256 => uint256) private s_tokenToCollectedAmount; +mapping(uint256 => uint256) private s_tokenToTotalCollectedAmount; +``` + + +### s_tokenToPledgedAmount + +```solidity +mapping(uint256 => uint256) private s_tokenToPledgedAmount; ``` @@ -119,35 +126,18 @@ function getRaisedAmount() external view override returns (uint256); |``|`uint256`|The total raised amount as a uint256 value.| -### addReward - -Adds a reward to the campaign. - - -```solidity -function addReward(bytes32 rewardName, Reward calldata reward) - external - onlyCampaignOwner - whenCampaignNotPaused - whenNotPaused - whenCampaignNotCancelled - whenNotCancelled; -``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`rewardName`|`bytes32`|The name of the reward.| -|`reward`|`Reward`|The details of the reward as a `Reward` struct.| - - -### addRewardsBatch +### addRewards Adds multiple rewards in a batch. +*This function allows for both reward tiers and non-reward tiers. +For both types, rewards must have non-zero value. +If items are specified (non-empty arrays), the itemId, itemValue, and itemQuantity arrays must match in length. +Empty arrays are allowed for both reward tiers and non-reward tiers.* + ```solidity -function addRewardsBatch(bytes32[] calldata rewardNames, Reward[] calldata rewards) +function addRewards(bytes32[] calldata rewardNames, Reward[] calldata rewards) external onlyCampaignOwner whenCampaignNotPaused @@ -188,6 +178,9 @@ function removeReward(bytes32 rewardName) Allows a backer to pledge for a reward. +*The first element of the `reward` array must be a reward tier and the other elements can be either reward tiers or non-reward tiers. +The non-reward tiers cannot be pledged for without a reward.* + ```solidity function pledgeForAReward(address backer, uint256 shippingFee, bytes32[] calldata reward) @@ -275,20 +268,6 @@ function withdraw() public override whenNotPaused whenNotCancelled; function cancelTreasury(bytes32 message) public override; ``` -### _pledge - - -```solidity -function _pledge( - address backer, - bytes32 reward, - uint256 pledgeAmount, - uint256 shippingFee, - uint256 tokenId, - bytes32[] memory rewards -) internal; -``` - ### _checkSuccessCondition *Internal function to check the success condition for fee disbursement.* @@ -304,6 +283,20 @@ function _checkSuccessCondition() internal view virtual override returns (bool); |``|`bool`|Whether the success condition is met.| +### _pledge + + +```solidity +function _pledge( + address backer, + bytes32 reward, + uint256 pledgeAmount, + uint256 shippingFee, + uint256 tokenId, + bytes32[] memory rewards +) private; +``` + ### supportsInterface @@ -338,20 +331,20 @@ event Receipt( |`tokenId`|`uint256`|The ID of the token representing the pledge.| |`rewards`|`bytes32[]`|An array of reward names.| -### RewardAdded -*Emitted when a reward is added to the campaign.* +### RewardsAdded +*Emitted when rewards are added to the campaign.* ```solidity -event RewardAdded(bytes32 indexed rewardName, Reward reward); +event RewardsAdded(bytes32[] rewardNames, Reward[] rewards); ``` **Parameters** |Name|Type|Description| |----|----|-----------| -|`rewardName`|`bytes32`|The name of the reward.| -|`reward`|`Reward`|The details of the reward.| +|`rewardNames`|`bytes32[]`|The names of the rewards.| +|`rewards`|`Reward[]`|The details of the rewards.| ### RewardRemoved *Emitted when a reward is removed from the campaign.* diff --git a/docs/src/src/treasuries/MinimumOrder.sol/contract.MinimumOrder.md b/docs/src/src/treasuries/MinimumOrder.sol/contract.MinimumOrder.md deleted file mode 100644 index 2addf548..00000000 --- a/docs/src/src/treasuries/MinimumOrder.sol/contract.MinimumOrder.md +++ /dev/null @@ -1,290 +0,0 @@ -# MinimumOrder - -[Git Source](https://github.com/ccprotocol/campaign-utils-contracts-aggregator/blob/79d78188e565502f83e2c0309c9a4ea3b35cee91/src/treasuries/MinimumOrder.sol) - -**Inherits:** -[BaseTreasury](/src/utils/BaseTreasury.sol/abstract.BaseTreasury.md), ERC721Burnable, [TimestampChecker](/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md) - -A Solidity contract for managing minimum order-based campaigns. -Users can pre-order items or rewards, and when a predefined success metric is reached, -the campaign succeeds, and backers receive their rewards. - -## State Variables - -### SUCCESS_METRIC - -```solidity -uint256 internal immutable SUCCESS_METRIC; -``` - -### s_preOrderValueAmount - -```solidity -uint256 private s_preOrderValueAmount; -``` - -### s_platformFeePercent - -```solidity -uint256 private s_platformFeePercent; -``` - -### s_tokenToPledgedAmount - -```solidity -mapping(uint256 => uint256) private s_tokenToPledgedAmount; -``` - -### s_reward - -```solidity -mapping(bytes32 => Reward) private s_reward; -``` - -### s_tokenIdCounter - -```solidity -Counters.Counter private s_tokenIdCounter; -``` - -### s_numberOfPreOrders - -```solidity -Counters.Counter internal s_numberOfPreOrders; -``` - -## Functions - -### constructor - -_Constructor for the MinimumOrder contract._ - -```solidity -constructor(bytes32 platformHash, address infoAddress) ERC721("", "") BaseTreasury(platformHash, infoAddress); -``` - -**Parameters** - -| Name | Type | Description | -| -------------- | --------- | -------------------------------------------------------------------- | -| `platformHash` | `bytes32` | The unique identifier of the platform. | -| `infoAddress` | `address` | The address of the CampaignInfo contract providing campaign details. | - -### getNumberOfOrders - -bytes32 of `PreOrder0MinimumOrder(uint256)` - -Function to get the number of pre-orders made. - -```solidity -function getNumberOfOrders() internal view returns (uint256); -``` - -**Returns** - -| Name | Type | Description | -| -------- | --------- | ------------------------- | -| `` | `uint256` | The number of pre-orders. | - -### getReward - -Function to get reward details by name. - -```solidity -function getReward(bytes32 rewardName) external view returns (Reward memory); -``` - -**Parameters** - -| Name | Type | Description | -| ------------ | --------- | ----------------------- | -| `rewardName` | `bytes32` | The name of the reward. | - -**Returns** - -| Name | Type | Description | -| -------- | -------- | ---------------------------------------------------------------------- | -| `` | `Reward` | The reward details, including value, item IDs, values, and quantities. | - -### getRaisedAmount - -Function to get the total raised amount during the campaign. - -```solidity -function getRaisedAmount() external view returns (uint256); -``` - -**Returns** - -| Name | Type | Description | -| -------- | --------- | ------------------------ | -| `` | `uint256` | The total raised amount. | - -### addReward - -Function to add a new reward to the campaign. -Only the campaign owner can add rewards. - -```solidity -function addReward(bytes32 rewardName, Reward calldata reward) - external - onlyCampaignOwner - whenCampaignNotPaused - whenNotPaused; -``` - -**Parameters** - -| Name | Type | Description | -| ------------ | --------- | ---------------------------------------------------------------------- | -| `rewardName` | `bytes32` | The name of the reward. | -| `reward` | `Reward` | The reward details, including value, item IDs, values, and quantities. | - -### removeReward - -Function to remove a reward from the campaign. -Only the campaign owner can remove rewards. - -```solidity -function removeReward(bytes32 rewardName) external onlyCampaignOwner whenCampaignNotPaused whenNotPaused; -``` - -**Parameters** - -| Name | Type | Description | -| ------------ | --------- | ------------------------------------- | -| `rewardName` | `bytes32` | The name of the reward to be removed. | - -### preOrderForAReward - -Function for backers to pre-order a reward. -The pre-order can only be made within the specified campaign timeframe. - -```solidity -function preOrderForAReward(address backer, bytes32 rewardName) - public - virtual - currentTimeIsWithinRange(INFO.getLaunchTime(), INFO.getDeadline()) - whenCampaignNotPaused - whenNotPaused; -``` - -**Parameters** - -| Name | Type | Description | -| ------------ | --------- | ----------------------------------------------- | -| `backer` | `address` | The address of the backer making the pre-order. | -| `rewardName` | `bytes32` | The name of the reward to pre-order. | - -### claimRefund - -Function for backers to claim a refund if the campaign has not met the success metric. - -```solidity -function claimRefund(uint256 tokenId) external whenCampaignNotPaused whenNotPaused; -``` - -**Parameters** - -| Name | Type | Description | -| --------- | --------- | ----------------------------------------------- | -| `tokenId` | `uint256` | The unique token ID associated with the refund. | - -### \_checkSuccessCondition - -_Internal function to check the success condition for fee disbursement._ - -```solidity -function _checkSuccessCondition() internal view virtual override returns (bool); -``` - -**Returns** - -| Name | Type | Description | -| -------- | ------ | ------------------------------------- | -| `` | `bool` | Whether the success condition is met. | - -### supportsInterface - -Function to check if an address is supported by the ERC721 contract. - -```solidity -function supportsInterface(bytes4 interfaceId) public view override returns (bool); -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | -------- | --------------------------------- | -| `interfaceId` | `bytes4` | The ERC721 interface ID to check. | - -**Returns** - -| Name | Type | Description | -| -------- | ------ | ---------------------------------------------------- | -| `` | `bool` | True if the interface is supported, false otherwise. | - -## Events - -### Receipt - -_Event emitted when a backer makes a pledge._ - -```solidity -event Receipt(address indexed backer, bytes32 indexed reward, uint256 pledgeAmount, uint256 tokenId); -``` - -### RewardAdded - -_Event emitted when a reward is added to the campaign._ - -```solidity -event RewardAdded(bytes32 indexed rewardName, Reward reward); -``` - -### RewardRemoved - -_Event emitted when a reward is removed from the campaign._ - -```solidity -event RewardRemoved(bytes32 indexed rewardName); -``` - -### RefundClaimed - -_Event emitted when a refund is claimed by a backer._ - -```solidity -event RefundClaimed(uint256 tokenId, uint256 refundAmount, address claimer); -``` - -## Errors - -### PreOrderTransferFailed - -_Throws an error indicating that the pre-order transfer failed._ - -```solidity -error PreOrderTransferFailed(); -``` - -### PreOrderInvalidInput - -_Throws an error indicating that the pre-order input is invalid._ - -```solidity -error PreOrderInvalidInput(); -``` - -## Structs - -### Reward - -```solidity -struct Reward { - uint256 rewardValue; - bytes32[] itemId; - uint256[] itemValue; - uint256[] itemQuantity; -} -``` diff --git a/docs/src/src/treasuries/OutOfStock.sol/contract.OutOfStock.md b/docs/src/src/treasuries/OutOfStock.sol/contract.OutOfStock.md deleted file mode 100644 index 2c95f9d2..00000000 --- a/docs/src/src/treasuries/OutOfStock.sol/contract.OutOfStock.md +++ /dev/null @@ -1,58 +0,0 @@ -# OutOfStock - -[Git Source](https://github.com/ccprotocol/campaign-utils-contracts-aggregator/blob/79d78188e565502f83e2c0309c9a4ea3b35cee91/src/treasuries/OutOfStock.sol) - -**Inherits:** -[MinimumOrder](/src/treasuries/MinimumOrder.sol/contract.MinimumOrder.md) - -A Solidity contract for managing minimum order-based campaigns with an out-of-stock limit. -Users can pre-order items or rewards until the out-of-stock limit is reached. -When the predefined success metric is reached or the out-of-stock limit is reached, the campaign ends. - -## Functions - -### constructor - -_Constructor for the OutOfStock contract._ - -```solidity -constructor(bytes32 platformHash, address infoAddress) MinimumOrder(platformHash, infoAddress); -``` - -**Parameters** - -| Name | Type | Description | -| -------------- | --------- | -------------------------------------------------------------------- | -| `platformHash` | `bytes32` | The unique identifier of the platform. | -| `infoAddress` | `address` | The address of the CampaignInfo contract providing campaign details. | - -### preOrderForAReward - -Function for backers to pre-order a reward, checking against the out-of-stock limit. -The pre-order can only be made within the specified campaign timeframe. - -```solidity -function preOrderForAReward(address backer, bytes32 rewardName) - public - override - currentTimeIsWithinRange(INFO.getLaunchTime(), INFO.getDeadline()) - whenCampaignNotPaused - whenNotPaused; -``` - -**Parameters** - -| Name | Type | Description | -| ------------ | --------- | ----------------------------------------------- | -| `backer` | `address` | The address of the backer making the pre-order. | -| `rewardName` | `bytes32` | The name of the reward to pre-order. | - -## Errors - -### OutOfStockLimitReached - -_Throws an error indicating the out-of-stock limit has been reached._ - -```solidity -error OutOfStockLimitReached(); -``` diff --git a/docs/src/src/utils/AddressCalculator.sol/library.AddressCalculator.md b/docs/src/src/utils/AddressCalculator.sol/library.AddressCalculator.md deleted file mode 100644 index 6daa3a46..00000000 --- a/docs/src/src/utils/AddressCalculator.sol/library.AddressCalculator.md +++ /dev/null @@ -1,55 +0,0 @@ -# AddressCalculator -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/utils/AddressCalculator.sol) - -A Solidity library for computing contract addresses and checking if a contract is deployed at a given address. - - -## Functions -### computeAddress - -*Computes the contract address using CREATE2 and checks if the contract is deployed.* - - -```solidity -function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) - internal - view - returns (address addr, bool isValid); -``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`salt`|`bytes32`|The salt value used for address computation.| -|`bytecodeHash`|`bytes32`|The keccak256 hash of the contract's bytecode.| -|`deployer`|`address`|The address that deploys the contract.| - -**Returns** - -|Name|Type|Description| -|----|----|-----------| -|`addr`|`address`|The computed contract address.| -|`isValid`|`bool`|True if a contract is deployed at the address; otherwise, false.| - - -### checkIfContractDeployed - -*Checks if a contract is deployed at the given address.* - - -```solidity -function checkIfContractDeployed(address addr) internal view returns (bool isValid); -``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`addr`|`address`|The address to check for contract deployment.| - -**Returns** - -|Name|Type|Description| -|----|----|-----------| -|`isValid`|`bool`|True if a contract is deployed at the address; otherwise, false.| - - diff --git a/docs/src/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md b/docs/src/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md index 6249f4a2..ea05746a 100644 --- a/docs/src/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md +++ b/docs/src/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md @@ -1,5 +1,5 @@ # AdminAccessChecker -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/utils/AdminAccessChecker.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/AdminAccessChecker.sol) *This abstract contract provides access control mechanisms to restrict the execution of specific functions to authorized protocol administrators and platform administrators.* diff --git a/docs/src/src/utils/BaseTreasury.sol/abstract.BaseTreasury.md b/docs/src/src/utils/BaseTreasury.sol/abstract.BaseTreasury.md index 1f9d835e..de7920fe 100644 --- a/docs/src/src/utils/BaseTreasury.sol/abstract.BaseTreasury.md +++ b/docs/src/src/utils/BaseTreasury.sol/abstract.BaseTreasury.md @@ -1,5 +1,5 @@ # BaseTreasury -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/utils/BaseTreasury.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/BaseTreasury.sol) **Inherits:** Initializable, [ICampaignTreasury](/src/interfaces/ICampaignTreasury.sol/interface.ICampaignTreasury.md), [CampaignAccessChecker](/src/utils/CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md), [PausableCancellable](/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md) @@ -47,13 +47,6 @@ IERC20 internal TOKEN; ``` -### CAMPAIGN_INFO - -```solidity -ICampaignInfo internal CAMPAIGN_INFO; -``` - - ### s_pledgedAmount ```solidity diff --git a/docs/src/src/utils/CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md b/docs/src/src/utils/CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md index 4c39e4e8..05a8e870 100644 --- a/docs/src/src/utils/CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md +++ b/docs/src/src/utils/CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md @@ -1,5 +1,5 @@ # CampaignAccessChecker -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/utils/CampaignAccessChecker.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/CampaignAccessChecker.sol) *This abstract contract provides access control mechanisms to restrict the execution of specific functions to authorized protocol administrators, platform administrators, and campaign owners.* diff --git a/docs/src/src/utils/Counters.sol/library.Counters.md b/docs/src/src/utils/Counters.sol/library.Counters.md index d8d77f16..2c667abe 100644 --- a/docs/src/src/utils/Counters.sol/library.Counters.md +++ b/docs/src/src/utils/Counters.sol/library.Counters.md @@ -1,12 +1,5 @@ # Counters -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/utils/Counters.sol) - -**Author:** -Matt Condon (@shrugs) - -*Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number -of elements in a mapping, issuing ERC721 ids, or counting request ids. -Include with `using Counters for Counters.Counter;`* +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/Counters.sol) ## Functions @@ -38,6 +31,15 @@ function decrement(Counter storage counter) internal; function reset(Counter storage counter) internal; ``` +## Errors +### CounterDecrementOverflow +*Error thrown when attempting to decrement a counter with value 0.* + + +```solidity +error CounterDecrementOverflow(); +``` + ## Structs ### Counter diff --git a/docs/src/src/utils/FiatEnabled.sol/abstract.FiatEnabled.md b/docs/src/src/utils/FiatEnabled.sol/abstract.FiatEnabled.md index ee22132e..8a148bda 100644 --- a/docs/src/src/utils/FiatEnabled.sol/abstract.FiatEnabled.md +++ b/docs/src/src/utils/FiatEnabled.sol/abstract.FiatEnabled.md @@ -1,5 +1,5 @@ # FiatEnabled -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/utils/FiatEnabled.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/FiatEnabled.sol) A contract that provides functionality for tracking and managing fiat transactions. This contract allows tracking the amount of fiat raised, individual fiat transactions, and the state of fiat fee disbursement. diff --git a/docs/src/src/utils/ItemRegistry.sol/contract.ItemRegistry.md b/docs/src/src/utils/ItemRegistry.sol/contract.ItemRegistry.md index 7ac56706..217effc5 100644 --- a/docs/src/src/utils/ItemRegistry.sol/contract.ItemRegistry.md +++ b/docs/src/src/utils/ItemRegistry.sol/contract.ItemRegistry.md @@ -1,5 +1,5 @@ # ItemRegistry -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/utils/ItemRegistry.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/ItemRegistry.sol) **Inherits:** [IItem](/src/interfaces/IItem.sol/interface.IItem.md), Context @@ -87,3 +87,12 @@ event ItemAdded(address indexed owner, bytes32 indexed itemId, Item item); |`itemId`|`bytes32`|The unique identifier of the item.| |`item`|`Item`|The item details including actual weight, dimensions, category, and declared currency.| +## Errors +### ItemRegistryMismatchedArraysLength +*Thrown when the input arrays have mismatched lengths.* + + +```solidity +error ItemRegistryMismatchedArraysLength(); +``` + diff --git a/docs/src/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md b/docs/src/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md index d13dcff3..fda365d5 100644 --- a/docs/src/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md +++ b/docs/src/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md @@ -1,5 +1,5 @@ # PausableCancellable -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/utils/PausableCancellable.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/PausableCancellable.sol) Abstract contract providing pause and cancel state management with events and modifiers diff --git a/docs/src/src/utils/PausableWithMsg.sol/abstract.PausableWithMsg.md b/docs/src/src/utils/PausableWithMsg.sol/abstract.PausableWithMsg.md deleted file mode 100644 index b5ad4586..00000000 --- a/docs/src/src/utils/PausableWithMsg.sol/abstract.PausableWithMsg.md +++ /dev/null @@ -1,110 +0,0 @@ -# PausableWithMsg -[Git Source](https://github.com/ccprotocol/campaign-utils-contracts-aggregator/blob/79d78188e565502f83e2c0309c9a4ea3b35cee91/src/utils/PausableWithMsg.sol) - - -## State Variables -### _paused - -```solidity -bool private _paused; -``` - - -## Functions -### constructor - -*Initializes the contract in unpaused state.* - - -```solidity -constructor(); -``` - -### whenNotPaused - -*Modifier to make a function callable only when the contract is not paused. -Requirements: -- The contract must not be paused.* - - -```solidity -modifier whenNotPaused(); -``` - -### whenPaused - -*Modifier to make a function callable only when the contract is paused. -Requirements: -- The contract must be paused.* - - -```solidity -modifier whenPaused(); -``` - -### paused - -*Returns true if the contract is paused, and false otherwise.* - - -```solidity -function paused() public view virtual returns (bool); -``` - -### _requireNotPaused - -*Throws if the contract is paused.* - - -```solidity -function _requireNotPaused() internal view virtual; -``` - -### _requirePaused - -*Throws if the contract is not paused.* - - -```solidity -function _requirePaused() internal view virtual; -``` - -### _pause - -*Triggers stopped state. -Requirements: -- The contract must not be paused.* - - -```solidity -function _pause(bytes32 message) internal virtual whenNotPaused; -``` - -### _unpause - -*Returns to normal state. -Requirements: -- The contract must be paused.* - - -```solidity -function _unpause(bytes32 message) internal virtual whenPaused; -``` - -## Events -### Paused -*Emitted when the pause is triggered by `account`.* - - -```solidity -event Paused(address account, bytes32 message); -``` - -### Unpaused -*Emitted when the pause is lifted by `account`.* - - -```solidity -event Unpaused(address account, bytes32 message); -``` - diff --git a/docs/src/src/utils/README.md b/docs/src/src/utils/README.md index a8b376bf..41bc0ddb 100644 --- a/docs/src/src/utils/README.md +++ b/docs/src/src/utils/README.md @@ -1,7 +1,6 @@ # Contents -- [AddressCalculator](AddressCalculator.sol/library.AddressCalculator.md) - [AdminAccessChecker](AdminAccessChecker.sol/abstract.AdminAccessChecker.md) - [BaseTreasury](BaseTreasury.sol/abstract.BaseTreasury.md) - [CampaignAccessChecker](CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md) diff --git a/docs/src/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md b/docs/src/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md index d75b4cdd..0931066c 100644 --- a/docs/src/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md +++ b/docs/src/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md @@ -1,5 +1,5 @@ # TimestampChecker -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/13d9d746c7f79b76f03c178fe64b679ba803191a/src/utils/TimestampChecker.sol) +[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/TimestampChecker.sol) A contract that provides timestamp-related checks for contract functions. @@ -51,13 +51,13 @@ modifier currentTimeIsWithinRange(uint256 initialTime, uint256 finalTime); |`finalTime`|`uint256`|The final timestamp of the range.| -### _checkIfCurrentTimeIsLess +### _revertIfCurrentTimeIsNotLess -*Internal function to check if the current timestamp is less than or equal a specified time.* +*Internal function to revert if the current timestamp is less than or equal a specified time.* ```solidity -function _checkIfCurrentTimeIsLess(uint256 inputTime) internal view virtual; +function _revertIfCurrentTimeIsNotLess(uint256 inputTime) internal view virtual; ``` **Parameters** @@ -66,13 +66,13 @@ function _checkIfCurrentTimeIsLess(uint256 inputTime) internal view virtual; |`inputTime`|`uint256`|The timestamp being checked against.| -### _checkIfCurrentTimeIsGreater +### _revertIfCurrentTimeIsNotGreater -*Internal function to check if the current timestamp is greater than or equal a specified time.* +*Internal function to revert if the current timestamp is not greater than or equal a specified time.* ```solidity -function _checkIfCurrentTimeIsGreater(uint256 inputTime) internal view virtual; +function _revertIfCurrentTimeIsNotGreater(uint256 inputTime) internal view virtual; ``` **Parameters** @@ -81,13 +81,13 @@ function _checkIfCurrentTimeIsGreater(uint256 inputTime) internal view virtual; |`inputTime`|`uint256`|The timestamp being checked against.| -### _checkIfCurrentTimeIsWithinRange +### _revertIfCurrentTimeIsNotWithinRange -*Internal function to check if the current timestamp is within a specified time range.* +*Internal function to revert if the current timestamp is not within a specified time range.* ```solidity -function _checkIfCurrentTimeIsWithinRange(uint256 initialTime, uint256 finalTime) internal view virtual; +function _revertIfCurrentTimeIsNotWithinRange(uint256 initialTime, uint256 finalTime) internal view virtual; ``` **Parameters** From 9e26d614fb0eb076f1af2b8a8d59f0a908119261 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 15 May 2025 06:04:39 +0600 Subject: [PATCH 15/41] Update license type and imports --- README.md | 2 +- script/DeployAll.s.sol | 16 +- script/DeployAllAndSetup.s.sol | 254 ++++++++++++------ script/DeployAllOrNothingImplementation.s.sol | 20 +- script/DeployCampaignInfoFactory.s.sol | 26 +- script/DeployCampaignInfoImplementation.s.sol | 19 +- script/DeployGlobalParams.s.sol | 2 +- script/DeployTestUSD.s.sol | 2 +- script/DeployTreasuryFactory.s.sol | 4 +- script/lib/DeployBase.s.sol | 5 +- src/CampaignInfo.sol | 24 +- src/CampaignInfoFactory.sol | 12 +- src/GlobalParams.sol | 15 +- src/TestUSD.sol | 6 +- src/TreasuryFactory.sol | 13 +- src/interfaces/ICampaignData.sol | 2 +- src/interfaces/ICampaignInfo.sol | 2 +- src/interfaces/ICampaignInfoFactory.sol | 15 +- src/interfaces/ICampaignTreasury.sol | 2 +- src/interfaces/IGlobalParams.sol | 2 +- src/interfaces/IItem.sol | 2 +- src/interfaces/IReward.sol | 4 +- src/interfaces/ITreasuryFactory.sol | 2 +- src/treasuries/AllOrNothing.sol | 16 +- src/utils/AdminAccessChecker.sol | 4 +- src/utils/BaseTreasury.sol | 15 +- src/utils/CampaignAccessChecker.sol | 7 +- src/utils/FiatEnabled.sol | 2 +- src/utils/ItemRegistry.sol | 11 +- src/utils/PausableCancellable.sol | 2 +- src/utils/TimestampChecker.sol | 2 +- test/foundry/Base.t.sol | 7 +- .../AllOrNothing/AllOrNothing.t.sol | 2 +- .../AllOrNothing/AllOrNothingFunction.t.sol | 2 +- test/foundry/unit/CampaignInfoFactory.t.sol | 9 +- test/foundry/unit/GlobalParams.t.sol | 4 +- test/foundry/unit/TestUSD.t.sol | 4 +- test/foundry/unit/TreasuryFactory.t.sol | 2 +- test/foundry/utils/Constants.sol | 2 +- test/foundry/utils/Defaults.sol | 2 +- test/foundry/utils/Types.sol | 2 +- 41 files changed, 314 insertions(+), 232 deletions(-) diff --git a/README.md b/README.md index 79080955..5522623e 100644 --- a/README.md +++ b/README.md @@ -137,4 +137,4 @@ Key environment variables in `.env`: ## License -[SPDX-License-Identifier: UNLICENSED] +[SPDX-License-Identifier: MIT] diff --git a/script/DeployAll.s.sol b/script/DeployAll.s.sol index 16d53179..bce481fd 100644 --- a/script/DeployAll.s.sol +++ b/script/DeployAll.s.sol @@ -1,12 +1,12 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "forge-std/Script.sol"; -import "forge-std/console2.sol"; -import "./DeployGlobalParams.s.sol"; -import "./DeployTestUSD.s.sol"; -import "./DeployCampaignInfoFactory.s.sol"; -import "./DeployTreasuryFactory.s.sol"; +import {Script} from "forge-std/Script.sol"; +import {console2} from "forge-std/console2.sol"; +import {DeployGlobalParams} from "./DeployGlobalParams.s.sol"; +import {DeployTestUSD} from "./DeployTestUSD.s.sol"; +import {DeployCampaignInfoFactory} from "./DeployCampaignInfoFactory.s.sol"; +import {DeployTreasuryFactory} from "./DeployTreasuryFactory.s.sol"; contract DeployAll is Script { function deployTestUSD() internal returns (address) { @@ -59,4 +59,4 @@ contract DeployAll is Script { console2.log("TREASURY_FACTORY_ADDRESS", treasuryFactory); console2.log("CAMPAIGN_INFO_FACTORY_ADDRESS", campaignFactory); } -} \ No newline at end of file +} diff --git a/script/DeployAllAndSetup.s.sol b/script/DeployAllAndSetup.s.sol index 3f7ef4ab..0465b2ce 100644 --- a/script/DeployAllAndSetup.s.sol +++ b/script/DeployAllAndSetup.s.sol @@ -1,14 +1,14 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "forge-std/Script.sol"; -import "forge-std/console2.sol"; -import "src/TestUSD.sol"; -import "src/GlobalParams.sol"; -import "src/CampaignInfoFactory.sol"; -import "src/CampaignInfo.sol"; -import "src/TreasuryFactory.sol"; -import "src/treasuries/AllOrNothing.sol"; +import {Script} from "forge-std/Script.sol"; +import {console2} from "forge-std/console2.sol"; +import {TestUSD} from "src/TestUSD.sol"; +import {GlobalParams} from "src/GlobalParams.sol"; +import {CampaignInfoFactory} from "src/CampaignInfoFactory.sol"; +import {CampaignInfo} from "src/CampaignInfo.sol"; +import {TreasuryFactory} from "src/TreasuryFactory.sol"; +import {AllOrNothing} from "src/treasuries/AllOrNothing.sol"; /** * @notice Script to deploy and setup all needed contracts for the protocol @@ -20,7 +20,7 @@ contract DeployAllAndSetup is Script { uint256 platformFeePercent; uint256 tokenMintAmount; bool simulate; - + // Contract addresses address testUSD; address globalParams; @@ -28,20 +28,20 @@ contract DeployAllAndSetup is Script { address treasuryFactory; address campaignInfoFactory; address allOrNothingImplementation; - + // User addresses address deployerAddress; address finalProtocolAdmin; address finalPlatformAdmin; address backer1; address backer2; - + // Flags to track what was completed bool platformEnlisted = false; bool implementationRegistered = false; bool implementationApproved = false; bool adminRightsTransferred = false; - + // Flags for contract deployment or reuse bool testUsdDeployed = false; bool globalParamsDeployed = false; @@ -52,30 +52,45 @@ contract DeployAllAndSetup is Script { // Configure parameters based on environment variables function setupParams() internal { // Get customizable values - string memory platformName = vm.envOr("PLATFORM_NAME", string("MiniFunder")); + string memory platformName = vm.envOr( + "PLATFORM_NAME", + string("MiniFunder") + ); platformHash = keccak256(abi.encodePacked(platformName)); protocolFeePercent = vm.envOr("PROTOCOL_FEE_PERCENT", uint256(100)); // Default 1% platformFeePercent = vm.envOr("PLATFORM_FEE_PERCENT", uint256(400)); // Default 4% tokenMintAmount = vm.envOr("TOKEN_MINT_AMOUNT", uint256(10000000e18)); simulate = vm.envOr("SIMULATE", false); - + // Get user addresses uint256 deployerKey = vm.envUint("PRIVATE_KEY"); deployerAddress = vm.addr(deployerKey); - + // These are the final admin addresses that will receive control - finalProtocolAdmin = vm.envOr("PROTOCOL_ADMIN_ADDRESS", deployerAddress); - finalPlatformAdmin = vm.envOr("PLATFORM_ADMIN_ADDRESS", deployerAddress); + finalProtocolAdmin = vm.envOr( + "PROTOCOL_ADMIN_ADDRESS", + deployerAddress + ); + finalPlatformAdmin = vm.envOr( + "PLATFORM_ADMIN_ADDRESS", + deployerAddress + ); backer1 = vm.envOr("BACKER1_ADDRESS", address(0)); backer2 = vm.envOr("BACKER2_ADDRESS", address(0)); - + // Check for existing contract addresses testUSD = vm.envOr("TEST_USD_ADDRESS", address(0)); globalParams = vm.envOr("GLOBAL_PARAMS_ADDRESS", address(0)); treasuryFactory = vm.envOr("TREASURY_FACTORY_ADDRESS", address(0)); - campaignInfoFactory = vm.envOr("CAMPAIGN_INFO_FACTORY_ADDRESS", address(0)); - allOrNothingImplementation = vm.envOr("ALL_OR_NOTHING_IMPLEMENTATION_ADDRESS", address(0)); - + campaignInfoFactory = vm.envOr( + "CAMPAIGN_INFO_FACTORY_ADDRESS", + address(0) + ); + allOrNothingImplementation = vm.envOr( + "ALL_OR_NOTHING_IMPLEMENTATION_ADDRESS", + address(0) + ); + console2.log("Using platform hash for:", platformName); console2.log("Protocol fee percent:", protocolFeePercent); console2.log("Platform fee percent:", platformFeePercent); @@ -88,7 +103,7 @@ contract DeployAllAndSetup is Script { // Deploy or reuse contracts function deployContracts() internal { console2.log("Setting up contracts..."); - + // Deploy or reuse TestUSD if (testUSD == address(0)) { testUSD = address(new TestUSD()); @@ -97,62 +112,80 @@ contract DeployAllAndSetup is Script { } else { console2.log("Reusing TestUSD at:", testUSD); } - + // Deploy or reuse GlobalParams if (globalParams == address(0)) { - globalParams = address(new GlobalParams( - deployerAddress, // Initially deployer is protocol admin - testUSD, - protocolFeePercent - )); + globalParams = address( + new GlobalParams( + deployerAddress, // Initially deployer is protocol admin + testUSD, + protocolFeePercent + ) + ); globalParamsDeployed = true; console2.log("GlobalParams deployed at:", globalParams); } else { console2.log("Reusing GlobalParams at:", globalParams); } - + // We need at least TestUSD and GlobalParams to continue require(testUSD != address(0), "TestUSD address is required"); require(globalParams != address(0), "GlobalParams address is required"); - + // Deploy CampaignInfo implementation if needed for new deployments if (campaignInfoFactory == address(0)) { campaignInfo = address(new CampaignInfo(address(this))); console2.log("CampaignInfo deployed at:", campaignInfo); } - + // Deploy or reuse TreasuryFactory if (treasuryFactory == address(0)) { - treasuryFactory = address(new TreasuryFactory(GlobalParams(globalParams))); + treasuryFactory = address( + new TreasuryFactory(GlobalParams(globalParams)) + ); treasuryFactoryDeployed = true; console2.log("TreasuryFactory deployed at:", treasuryFactory); } else { console2.log("Reusing TreasuryFactory at:", treasuryFactory); } - + // Deploy or reuse CampaignInfoFactory if (campaignInfoFactory == address(0)) { - campaignInfoFactory = address(new CampaignInfoFactory( - GlobalParams(globalParams), - campaignInfo - )); + campaignInfoFactory = address( + new CampaignInfoFactory( + GlobalParams(globalParams), + campaignInfo + ) + ); CampaignInfoFactory(campaignInfoFactory)._initialize( treasuryFactory, globalParams ); campaignInfoFactoryDeployed = true; - console2.log("CampaignInfoFactory deployed and initialized at:", campaignInfoFactory); + console2.log( + "CampaignInfoFactory deployed and initialized at:", + campaignInfoFactory + ); } else { - console2.log("Reusing CampaignInfoFactory at:", campaignInfoFactory); + console2.log( + "Reusing CampaignInfoFactory at:", + campaignInfoFactory + ); } - + // Deploy or reuse AllOrNothing implementation if (allOrNothingImplementation == address(0)) { allOrNothingImplementation = address(new AllOrNothing()); allOrNothingDeployed = true; - console2.log("AllOrNothing implementation deployed at:", allOrNothingImplementation); + console2.log( + "AllOrNothing implementation deployed at:", + allOrNothingImplementation + ); } else { - console2.log("Reusing AllOrNothing implementation at:", allOrNothingImplementation); + console2.log( + "Reusing AllOrNothing implementation at:", + allOrNothingImplementation + ); } } @@ -160,90 +193,96 @@ contract DeployAllAndSetup is Script { function enlistPlatform() internal { // Skip if we didn't deploy GlobalParams (assuming it's already set up) if (!globalParamsDeployed) { - console2.log("Skipping enlistPlatform - using existing GlobalParams"); + console2.log( + "Skipping enlistPlatform - using existing GlobalParams" + ); platformEnlisted = true; return; } - + console2.log("Setting up: enlistPlatform"); // Only use startPrank in simulation mode if (simulate) { vm.startPrank(deployerAddress); } - + GlobalParams(globalParams).enlistPlatform( platformHash, - deployerAddress, // Initially deployer is platform admin + deployerAddress, // Initially deployer is platform admin platformFeePercent ); - + if (simulate) { vm.stopPrank(); } platformEnlisted = true; console2.log("Platform enlisted successfully"); } - + function registerTreasuryImplementation() internal { // Skip if we didn't deploy TreasuryFactory (assuming it's already set up) if (!treasuryFactoryDeployed || !allOrNothingDeployed) { - console2.log("Skipping registerTreasuryImplementation - using existing contracts"); + console2.log( + "Skipping registerTreasuryImplementation - using existing contracts" + ); implementationRegistered = true; return; } - + console2.log("Setting up: registerTreasuryImplementation"); // Only use startPrank in simulation mode if (simulate) { vm.startPrank(deployerAddress); } - + TreasuryFactory(treasuryFactory).registerTreasuryImplementation( platformHash, 0, // Implementation ID allOrNothingImplementation ); - + if (simulate) { vm.stopPrank(); } implementationRegistered = true; console2.log("Treasury implementation registered successfully"); } - + function approveTreasuryImplementation() internal { // Skip if we didn't deploy TreasuryFactory (assuming it's already set up) if (!treasuryFactoryDeployed || !allOrNothingDeployed) { - console2.log("Skipping approveTreasuryImplementation - using existing contracts"); + console2.log( + "Skipping approveTreasuryImplementation - using existing contracts" + ); implementationApproved = true; return; } - + console2.log("Setting up: approveTreasuryImplementation"); // Only use startPrank in simulation mode if (simulate) { vm.startPrank(deployerAddress); } - + TreasuryFactory(treasuryFactory).approveTreasuryImplementation( - platformHash, + platformHash, 0 // Implementation ID ); - + if (simulate) { vm.stopPrank(); } implementationApproved = true; console2.log("Treasury implementation approved successfully"); } - + function mintTokens() internal { // Only mint tokens if we deployed TestUSD if (!testUsdDeployed) { console2.log("Skipping mintTokens - using existing TestUSD"); return; } - + if (backer1 != address(0) && backer2 != address(0)) { console2.log("Minting tokens to test backers"); TestUSD(testUSD).mint(backer1, tokenMintAmount); @@ -253,29 +292,42 @@ contract DeployAllAndSetup is Script { console2.log("Tokens minted successfully"); } } - + // Transfer admin rights to final addresses function transferAdminRights() internal { // Skip if we didn't deploy GlobalParams (assuming it's already set up) if (!globalParamsDeployed) { - console2.log("Skipping transferAdminRights - using existing GlobalParams"); + console2.log( + "Skipping transferAdminRights - using existing GlobalParams" + ); adminRightsTransferred = true; return; } - + console2.log("Transferring admin rights to final addresses..."); - + // Only transfer if the final addresses are different from deployer if (finalProtocolAdmin != deployerAddress) { - console2.log("Transferring protocol admin rights to:", finalProtocolAdmin); - GlobalParams(globalParams).updateProtocolAdminAddress(finalProtocolAdmin); + console2.log( + "Transferring protocol admin rights to:", + finalProtocolAdmin + ); + GlobalParams(globalParams).updateProtocolAdminAddress( + finalProtocolAdmin + ); } - + if (finalPlatformAdmin != deployerAddress) { - console2.log("Updating platform admin address for platform hash:", vm.toString(platformHash)); - GlobalParams(globalParams).updatePlatformAdminAddress(platformHash, finalPlatformAdmin); + console2.log( + "Updating platform admin address for platform hash:", + vm.toString(platformHash) + ); + GlobalParams(globalParams).updatePlatformAdminAddress( + platformHash, + finalPlatformAdmin + ); } - + adminRightsTransferred = true; console2.log("Admin rights transferred successfully"); } @@ -285,25 +337,25 @@ contract DeployAllAndSetup is Script { setupParams(); uint256 deployerKey = vm.envUint("PRIVATE_KEY"); - + // Start broadcast with deployer key vm.startBroadcast(deployerKey); // Deploy or reuse contracts deployContracts(); - + // Setup the protocol with individual transactions in the correct order // Since deployer is both protocol and platform admin initially, we can do all steps enlistPlatform(); registerTreasuryImplementation(); approveTreasuryImplementation(); - + // Mint tokens if needed mintTokens(); - + // Finally, transfer admin rights to the final addresses transferAdminRights(); - + // Stop broadcast vm.stopBroadcast(); @@ -317,30 +369,54 @@ contract DeployAllAndSetup is Script { } console2.log("TREASURY_FACTORY_ADDRESS:", treasuryFactory); console2.log("CAMPAIGN_INFO_FACTORY_ADDRESS:", campaignInfoFactory); - console2.log("ALL_OR_NOTHING_IMPLEMENTATION_ADDRESS:", allOrNothingImplementation); + console2.log( + "ALL_OR_NOTHING_IMPLEMENTATION_ADDRESS:", + allOrNothingImplementation + ); console2.log("Protocol Admin:", finalProtocolAdmin); console2.log("Platform Admin:", finalPlatformAdmin); - + if (backer1 != address(0)) { console2.log("Backer1 (tokens minted):", backer1); } if (backer2 != address(0) && backer1 != backer2) { console2.log("Backer2 (tokens minted):", backer2); } - + console2.log("\nDeployment status:"); - console2.log("- TestUSD:", testUsdDeployed ? "Newly deployed" : "Reused existing"); - console2.log("- GlobalParams:", globalParamsDeployed ? "Newly deployed" : "Reused existing"); - console2.log("- TreasuryFactory:", treasuryFactoryDeployed ? "Newly deployed" : "Reused existing"); - console2.log("- CampaignInfoFactory:", campaignInfoFactoryDeployed ? "Newly deployed" : "Reused existing"); - console2.log("- AllOrNothing Implementation:", allOrNothingDeployed ? "Newly deployed" : "Reused existing"); - + console2.log( + "- TestUSD:", + testUsdDeployed ? "Newly deployed" : "Reused existing" + ); + console2.log( + "- GlobalParams:", + globalParamsDeployed ? "Newly deployed" : "Reused existing" + ); + console2.log( + "- TreasuryFactory:", + treasuryFactoryDeployed ? "Newly deployed" : "Reused existing" + ); + console2.log( + "- CampaignInfoFactory:", + campaignInfoFactoryDeployed ? "Newly deployed" : "Reused existing" + ); + console2.log( + "- AllOrNothing Implementation:", + allOrNothingDeployed ? "Newly deployed" : "Reused existing" + ); + console2.log("\nSetup steps:"); console2.log("1. Platform enlisted:", platformEnlisted); - console2.log("2. Treasury implementation registered:", implementationRegistered); - console2.log("3. Treasury implementation approved:", implementationApproved); + console2.log( + "2. Treasury implementation registered:", + implementationRegistered + ); + console2.log( + "3. Treasury implementation approved:", + implementationApproved + ); console2.log("4. Admin rights transferred:", adminRightsTransferred); - + console2.log("\nDeployment and setup completed successfully!"); } -} \ No newline at end of file +} diff --git a/script/DeployAllOrNothingImplementation.s.sol b/script/DeployAllOrNothingImplementation.s.sol index 6c10a227..7c017a50 100644 --- a/script/DeployAllOrNothingImplementation.s.sol +++ b/script/DeployAllOrNothingImplementation.s.sol @@ -1,15 +1,18 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "forge-std/Script.sol"; -import "forge-std/console.sol"; +import {Script} from "forge-std/Script.sol"; +import {console2} from "forge-std/console2.sol"; import {AllOrNothing} from "src/treasuries/AllOrNothing.sol"; contract DeployAllOrNothingImplementation is Script { function deploy() public returns (address) { - console.log("Deploying AllOrNothingImplementation..."); + console2.log("Deploying AllOrNothingImplementation..."); AllOrNothing allOrNothingImplementation = new AllOrNothing(); - console.log("AllOrNothingImplementation deployed at:", address(allOrNothingImplementation)); + console2.log( + "AllOrNothingImplementation deployed at:", + address(allOrNothingImplementation) + ); return address(allOrNothingImplementation); } @@ -27,6 +30,9 @@ contract DeployAllOrNothingImplementation is Script { vm.stopBroadcast(); } - console.log("ALL_OR_NOTHING_IMPLEMENTATION_ADDRESS", implementationAddress); + console2.log( + "ALL_OR_NOTHING_IMPLEMENTATION_ADDRESS", + implementationAddress + ); } -} \ No newline at end of file +} diff --git a/script/DeployCampaignInfoFactory.s.sol b/script/DeployCampaignInfoFactory.s.sol index 018a4224..cbf00748 100644 --- a/script/DeployCampaignInfoFactory.s.sol +++ b/script/DeployCampaignInfoFactory.s.sol @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "forge-std/Script.sol"; -import "forge-std/console2.sol"; +import {Script} from "forge-std/Script.sol"; +import {console2} from "forge-std/console2.sol"; import {CampaignInfoFactory} from "src/CampaignInfoFactory.sol"; import {CampaignInfo} from "src/CampaignInfo.sol"; import {GlobalParams} from "src/GlobalParams.sol"; @@ -14,31 +14,31 @@ contract DeployCampaignInfoFactory is DeployBase { address treasuryFactory ) public returns (address) { console2.log("Deploying CampaignInfoFactory..."); - + // Properly deploy CampaignInfo with direct instantiation CampaignInfo campaignInfoImpl = new CampaignInfo(address(this)); address campaignInfo = address(campaignInfoImpl); console2.log("CampaignInfo implementation deployed at:", campaignInfo); - + // Create and initialize the factory CampaignInfoFactory campaignInfoFactory = new CampaignInfoFactory( GlobalParams(globalParams), campaignInfo ); - - campaignInfoFactory._initialize( - treasuryFactory, - globalParams + + campaignInfoFactory._initialize(treasuryFactory, globalParams); + + console2.log( + "CampaignInfoFactory deployed and initialized at:", + address(campaignInfoFactory) ); - - console2.log("CampaignInfoFactory deployed and initialized at:", address(campaignInfoFactory)); return address(campaignInfoFactory); } function run() external { uint256 deployerKey = vm.envUint("PRIVATE_KEY"); bool simulate = vm.envOr("SIMULATE", false); - + address globalParams = vm.envAddress("GLOBAL_PARAMS_ADDRESS"); address treasuryFactory = vm.envAddress("TREASURY_FACTORY_ADDRESS"); @@ -54,4 +54,4 @@ contract DeployCampaignInfoFactory is DeployBase { console2.log("CAMPAIGN_INFO_FACTORY_ADDRESS", factoryAddress); } -} \ No newline at end of file +} diff --git a/script/DeployCampaignInfoImplementation.s.sol b/script/DeployCampaignInfoImplementation.s.sol index 41f72486..dd4f4dc6 100644 --- a/script/DeployCampaignInfoImplementation.s.sol +++ b/script/DeployCampaignInfoImplementation.s.sol @@ -1,17 +1,20 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "forge-std/Script.sol"; -import "forge-std/console.sol"; +import {Script} from "forge-std/Script.sol"; +import {console2} from "forge-std/console2.sol"; import {CampaignInfo} from "src/CampaignInfo.sol"; contract DeployCampaignInfoImplementation is Script { function deploy() public returns (address) { - console.log("Deploying CampaignInfo implementation..."); - // Implementation will use the script address as admin, but this will be replaced + console2.log("Deploying CampaignInfo implementation..."); + // Implementation will use the script address as admin, but this will be replaced // when the factory creates new instances CampaignInfo campaignInfo = new CampaignInfo(address(this)); - console.log("CampaignInfo implementation deployed at:", address(campaignInfo)); + console2.log( + "CampaignInfo implementation deployed at:", + address(campaignInfo) + ); return address(campaignInfo); } @@ -29,6 +32,6 @@ contract DeployCampaignInfoImplementation is Script { vm.stopBroadcast(); } - console.log("CAMPAIGN_INFO_ADDRESS", implementationAddress); + console2.log("CAMPAIGN_INFO_ADDRESS", implementationAddress); } -} \ No newline at end of file +} diff --git a/script/DeployGlobalParams.s.sol b/script/DeployGlobalParams.s.sol index 22e51ca3..1ed2abed 100644 --- a/script/DeployGlobalParams.s.sol +++ b/script/DeployGlobalParams.s.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {GlobalParams} from "../src/GlobalParams.sol"; diff --git a/script/DeployTestUSD.s.sol b/script/DeployTestUSD.s.sol index 3a955e91..5c0d7d2c 100644 --- a/script/DeployTestUSD.s.sol +++ b/script/DeployTestUSD.s.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {TestUSD} from "../src/TestUSD.sol"; diff --git a/script/DeployTreasuryFactory.s.sol b/script/DeployTreasuryFactory.s.sol index 068cb9ac..4689147f 100644 --- a/script/DeployTreasuryFactory.s.sol +++ b/script/DeployTreasuryFactory.s.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {TreasuryFactory} from "../src/TreasuryFactory.sol"; @@ -19,4 +19,4 @@ contract DeployTreasuryFactory is DeployBase { deploy(globalParams); vm.stopBroadcast(); } -} \ No newline at end of file +} diff --git a/script/lib/DeployBase.s.sol b/script/lib/DeployBase.s.sol index 14ed974b..e3b38fc7 100644 --- a/script/lib/DeployBase.s.sol +++ b/script/lib/DeployBase.s.sol @@ -1,7 +1,8 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "forge-std/Script.sol"; +import {Script} from "forge-std/Script.sol"; +import {console2} from "forge-std/console2.sol"; contract DeployBase is Script { function deployOrUse( diff --git a/src/CampaignInfo.sol b/src/CampaignInfo.sol index a542dd44..ac16d1d7 100644 --- a/src/CampaignInfo.sol +++ b/src/CampaignInfo.sol @@ -1,17 +1,17 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "@openzeppelin/contracts/proxy/Clones.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; - -import "./interfaces/ICampaignInfo.sol"; -import "./interfaces/ICampaignData.sol"; -import "./interfaces/ICampaignTreasury.sol"; -import "./interfaces/IGlobalParams.sol"; -import "./utils/TimestampChecker.sol"; -import "./utils/AdminAccessChecker.sol"; -import "./utils/PausableCancellable.sol"; +import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; + +import {ICampaignInfo} from "./interfaces/ICampaignInfo.sol"; +import {ICampaignData} from "./interfaces/ICampaignData.sol"; +import {ICampaignTreasury} from "./interfaces/ICampaignTreasury.sol"; +import {IGlobalParams} from "./interfaces/IGlobalParams.sol"; +import {TimestampChecker} from "./utils/TimestampChecker.sol"; +import {AdminAccessChecker} from "./utils/AdminAccessChecker.sol"; +import {PausableCancellable} from "./utils/PausableCancellable.sol"; /** * @title CampaignInfo diff --git a/src/CampaignInfoFactory.sol b/src/CampaignInfoFactory.sol index e2a648fb..8342956c 100644 --- a/src/CampaignInfoFactory.sol +++ b/src/CampaignInfoFactory.sol @@ -1,12 +1,12 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "@openzeppelin/contracts/proxy/Clones.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; -import "./interfaces/IGlobalParams.sol"; -import "./interfaces/ICampaignInfoFactory.sol"; +import {IGlobalParams} from "./interfaces/IGlobalParams.sol"; +import {ICampaignInfoFactory} from "./interfaces/ICampaignInfoFactory.sol"; /** * @title CampaignInfoFactory diff --git a/src/GlobalParams.sol b/src/GlobalParams.sol index 1778de76..202951c4 100644 --- a/src/GlobalParams.sol +++ b/src/GlobalParams.sol @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "@openzeppelin/contracts/access/Ownable.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import "./interfaces/IGlobalParams.sol"; -import "./utils/Counters.sol"; +import {IGlobalParams} from "./interfaces/IGlobalParams.sol"; +import {Counters} from "./utils/Counters.sol"; /** * @title GlobalParams @@ -257,12 +257,7 @@ contract GlobalParams is IGlobalParams, Ownable { */ function getPlatformDataOwner( bytes32 platformDataKey - ) - external - view - override - returns (bytes32 platformHash) - { + ) external view override returns (bytes32 platformHash) { platformHash = s_platformDataOwner[platformDataKey]; } diff --git a/src/TestUSD.sol b/src/TestUSD.sol index 19cf382e..71753eda 100644 --- a/src/TestUSD.sol +++ b/src/TestUSD.sol @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; /** * @title TestUSD diff --git a/src/TreasuryFactory.sol b/src/TreasuryFactory.sol index e989b8ad..44f05280 100644 --- a/src/TreasuryFactory.sol +++ b/src/TreasuryFactory.sol @@ -1,15 +1,14 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "@openzeppelin/contracts/proxy/Clones.sol"; +import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; -import "./CampaignInfo.sol"; -import "./interfaces/ITreasuryFactory.sol"; -import "./utils/AdminAccessChecker.sol"; +import {ITreasuryFactory} from "./interfaces/ITreasuryFactory.sol"; +import {IGlobalParams, AdminAccessChecker} from "./utils/AdminAccessChecker.sol"; contract TreasuryFactory is ITreasuryFactory, AdminAccessChecker { - mapping(bytes32 => mapping(uint256 => address)) implementationMap; - mapping(address => bool) approvedImplementations; + mapping(bytes32 => mapping(uint256 => address)) private implementationMap; + mapping(address => bool) private approvedImplementations; error TreasuryFactoryUnauthorized(); error TreasuryFactoryInvalidKey(); diff --git a/src/interfaces/ICampaignData.sol b/src/interfaces/ICampaignData.sol index cab7c378..abf5e0ac 100644 --- a/src/interfaces/ICampaignData.sol +++ b/src/interfaces/ICampaignData.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** diff --git a/src/interfaces/ICampaignInfo.sol b/src/interfaces/ICampaignInfo.sol index 5deb2e3c..43771b79 100644 --- a/src/interfaces/ICampaignInfo.sol +++ b/src/interfaces/ICampaignInfo.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** diff --git a/src/interfaces/ICampaignInfoFactory.sol b/src/interfaces/ICampaignInfoFactory.sol index 6481dfae..f8b53c35 100644 --- a/src/interfaces/ICampaignInfoFactory.sol +++ b/src/interfaces/ICampaignInfoFactory.sol @@ -1,7 +1,7 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "./ICampaignData.sol"; +import {ICampaignData} from "./ICampaignData.sol"; /** * @title ICampaignInfoFactory @@ -18,11 +18,10 @@ interface ICampaignInfoFactory is ICampaignData { address indexed campaignInfoAddress ); - /** + /** * @notice Emitted when the campaign after creation is initialized. - */ - event CampaignInfoFactoryCampaignInitialized( - ); + */ + event CampaignInfoFactoryCampaignInitialized(); /** * @notice Creates a new campaign information contract. @@ -46,7 +45,5 @@ interface ICampaignInfoFactory is ICampaignData { * @notice Updates the campaign implementation address. * @param newImplementation The address of the camapaignInfo implementation contract. */ - function updateImplementation( - address newImplementation - ) external; + function updateImplementation(address newImplementation) external; } diff --git a/src/interfaces/ICampaignTreasury.sol b/src/interfaces/ICampaignTreasury.sol index 578f3df2..5bac65ee 100644 --- a/src/interfaces/ICampaignTreasury.sol +++ b/src/interfaces/ICampaignTreasury.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** diff --git a/src/interfaces/IGlobalParams.sol b/src/interfaces/IGlobalParams.sol index fda1b617..4bc1f7dc 100644 --- a/src/interfaces/IGlobalParams.sol +++ b/src/interfaces/IGlobalParams.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** diff --git a/src/interfaces/IItem.sol b/src/interfaces/IItem.sol index e6971d16..95a1aad8 100644 --- a/src/interfaces/IItem.sol +++ b/src/interfaces/IItem.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** diff --git a/src/interfaces/IReward.sol b/src/interfaces/IReward.sol index 890aa12b..92a3212f 100644 --- a/src/interfaces/IReward.sol +++ b/src/interfaces/IReward.sol @@ -1,11 +1,11 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @title IReward * @notice An interface for managing rewards in a campaign. */ -interface IReward { +interface IReward { struct Reward { uint256 rewardValue; bool isRewardTier; diff --git a/src/interfaces/ITreasuryFactory.sol b/src/interfaces/ITreasuryFactory.sol index dfd8242b..ca3f4b74 100644 --- a/src/interfaces/ITreasuryFactory.sol +++ b/src/interfaces/ITreasuryFactory.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** diff --git a/src/treasuries/AllOrNothing.sol b/src/treasuries/AllOrNothing.sol index d7c7443a..2a400a9e 100644 --- a/src/treasuries/AllOrNothing.sol +++ b/src/treasuries/AllOrNothing.sol @@ -1,13 +1,15 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; +import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import {ERC721Burnable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; -import "../utils/Counters.sol"; -import "../utils/TimestampChecker.sol"; -import "../utils/BaseTreasury.sol"; -import "../interfaces/IReward.sol"; +import {Counters} from "../utils/Counters.sol"; +import {TimestampChecker} from "../utils/TimestampChecker.sol"; +import {ICampaignTreasury} from "../interfaces/ICampaignTreasury.sol"; +import {BaseTreasury} from "../utils/BaseTreasury.sol"; +import {IReward} from "../interfaces/IReward.sol"; /** * @title AllOrNothing diff --git a/src/utils/AdminAccessChecker.sol b/src/utils/AdminAccessChecker.sol index c798e730..7c025282 100644 --- a/src/utils/AdminAccessChecker.sol +++ b/src/utils/AdminAccessChecker.sol @@ -1,7 +1,7 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "../interfaces/IGlobalParams.sol"; +import {IGlobalParams} from "../interfaces/IGlobalParams.sol"; /** * @title AdminAccessChecker diff --git a/src/utils/BaseTreasury.sol b/src/utils/BaseTreasury.sol index 8064dd5b..f41f1572 100644 --- a/src/utils/BaseTreasury.sol +++ b/src/utils/BaseTreasury.sol @@ -1,14 +1,12 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; -import "../interfaces/ICampaignInfo.sol"; -import "../interfaces/ICampaignTreasury.sol"; -import "./CampaignAccessChecker.sol"; -import "./PausableCancellable.sol"; +import {ICampaignTreasury} from "../interfaces/ICampaignTreasury.sol"; +import {CampaignAccessChecker} from "./CampaignAccessChecker.sol"; +import {PausableCancellable} from "./PausableCancellable.sol"; /** * @title BaseTreasury @@ -23,6 +21,7 @@ abstract contract BaseTreasury is PausableCancellable { using SafeERC20 for IERC20; + bytes32 internal constant ZERO_BYTES = 0x0000000000000000000000000000000000000000000000000000000000000000; uint256 internal constant PERCENT_DIVIDER = 10000; diff --git a/src/utils/CampaignAccessChecker.sol b/src/utils/CampaignAccessChecker.sol index c292bef6..060cca68 100644 --- a/src/utils/CampaignAccessChecker.sol +++ b/src/utils/CampaignAccessChecker.sol @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "../interfaces/ICampaignInfo.sol"; -import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import {ICampaignInfo} from "../interfaces/ICampaignInfo.sol"; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; /** * @title CampaignAccessChecker @@ -22,7 +22,6 @@ abstract contract CampaignAccessChecker { * @dev Constructor to initialize the contract with the address of the campaign information contract. * @param campaignInfo The address of the ICampaignInfo contract. */ - function __CampaignAccessChecker_init(address campaignInfo) internal { INFO = ICampaignInfo(campaignInfo); } diff --git a/src/utils/FiatEnabled.sol b/src/utils/FiatEnabled.sol index 208ca91a..85d98f62 100644 --- a/src/utils/FiatEnabled.sol +++ b/src/utils/FiatEnabled.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** diff --git a/src/utils/ItemRegistry.sol b/src/utils/ItemRegistry.sol index 63f06100..0e6f4282 100644 --- a/src/utils/ItemRegistry.sol +++ b/src/utils/ItemRegistry.sol @@ -1,8 +1,9 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "@openzeppelin/contracts/utils/Context.sol"; -import "../interfaces/IItem.sol"; +import {Context} from "@openzeppelin/contracts/utils/Context.sol"; + +import {IItem} from "../interfaces/IItem.sol"; /** * @title ItemRegistry @@ -18,7 +19,7 @@ contract ItemRegistry is IItem, Context { * @param item The item details including actual weight, dimensions, category, and declared currency. */ event ItemAdded(address indexed owner, bytes32 indexed itemId, Item item); - + /** * @dev Thrown when the input arrays have mismatched lengths. */ @@ -63,4 +64,4 @@ contract ItemRegistry is IItem, Context { emit ItemAdded(_msgSender(), itemId, item); } } -} \ No newline at end of file +} diff --git a/src/utils/PausableCancellable.sol b/src/utils/PausableCancellable.sol index 6c65c268..db0994d0 100644 --- a/src/utils/PausableCancellable.sol +++ b/src/utils/PausableCancellable.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /// @title PausableCancellable diff --git a/src/utils/TimestampChecker.sol b/src/utils/TimestampChecker.sol index e5170999..21bb25e0 100644 --- a/src/utils/TimestampChecker.sol +++ b/src/utils/TimestampChecker.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** diff --git a/test/foundry/Base.t.sol b/test/foundry/Base.t.sol index a1c21181..7cc9e2da 100644 --- a/test/foundry/Base.t.sol +++ b/test/foundry/Base.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "forge-std/Test.sol"; @@ -49,7 +49,10 @@ abstract contract Base_Test is Test, Defaults { campaignInfo = new CampaignInfo(address(this)); console.log("CampaignInfo address: ", address(campaignInfo)); - campaignInfoFactory = new CampaignInfoFactory(globalParams, address(campaignInfo)); + campaignInfoFactory = new CampaignInfoFactory( + globalParams, + address(campaignInfo) + ); treasuryFactory = new TreasuryFactory(globalParams); //Initialize campaignInfoFactory diff --git a/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol b/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol index 38eba557..29f5379c 100644 --- a/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol +++ b/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {Base_Test} from "../../Base.t.sol"; diff --git a/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol b/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol index c5f0738a..a11b4428 100644 --- a/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol +++ b/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "./AllOrNothing.t.sol"; diff --git a/test/foundry/unit/CampaignInfoFactory.t.sol b/test/foundry/unit/CampaignInfoFactory.t.sol index 32a6d313..c94c12c1 100644 --- a/test/foundry/unit/CampaignInfoFactory.t.sol +++ b/test/foundry/unit/CampaignInfoFactory.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "forge-std/Test.sol"; @@ -20,7 +20,6 @@ contract CampaignInfoFactory_UnitTest is Test, Defaults { address internal admin = address(0xA11CE); function setUp() public { - testUSD = new TestUSD(); globalParams = new GlobalParams( admin, @@ -29,7 +28,10 @@ contract CampaignInfoFactory_UnitTest is Test, Defaults { ); campaignInfoImplementation = new CampaignInfo(address(this)); treasuryFactory = new TreasuryFactory(globalParams); - factory = new CampaignInfoFactory(globalParams, address(campaignInfoImplementation)); + factory = new CampaignInfoFactory( + globalParams, + address(campaignInfoImplementation) + ); vm.startPrank(admin); globalParams.enlistPlatform( PLATFORM_1_HASH, @@ -47,7 +49,6 @@ contract CampaignInfoFactory_UnitTest is Test, Defaults { // vm.stopPrank(); } - function testCreateCampaignDeploysSuccessfully() public { factory._initialize(address(treasuryFactory), address(globalParams)); diff --git a/test/foundry/unit/GlobalParams.t.sol b/test/foundry/unit/GlobalParams.t.sol index ca4f0608..333407ed 100644 --- a/test/foundry/unit/GlobalParams.t.sol +++ b/test/foundry/unit/GlobalParams.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "forge-std/Test.sol"; @@ -50,4 +50,4 @@ contract GlobalParams_UnitTest is Test { vm.expectRevert(); globalParams.updateTokenAddress(address(0xBEEF)); } -} \ No newline at end of file +} diff --git a/test/foundry/unit/TestUSD.t.sol b/test/foundry/unit/TestUSD.t.sol index cd1a2480..1eb7679c 100644 --- a/test/foundry/unit/TestUSD.t.sol +++ b/test/foundry/unit/TestUSD.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "forge-std/Test.sol"; @@ -26,4 +26,4 @@ contract TestUSD_UnitTest is Test { token.transfer(recipient, 200 * 1e18); assertEq(token.balanceOf(recipient), 200 * 1e18); } -} \ No newline at end of file +} diff --git a/test/foundry/unit/TreasuryFactory.t.sol b/test/foundry/unit/TreasuryFactory.t.sol index 41187800..3d5aee9d 100644 --- a/test/foundry/unit/TreasuryFactory.t.sol +++ b/test/foundry/unit/TreasuryFactory.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "forge-std/Test.sol"; diff --git a/test/foundry/utils/Constants.sol b/test/foundry/utils/Constants.sol index bf7e111e..f25eb6f0 100644 --- a/test/foundry/utils/Constants.sol +++ b/test/foundry/utils/Constants.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; abstract contract Constants { diff --git a/test/foundry/utils/Defaults.sol b/test/foundry/utils/Defaults.sol index 17815d82..bcb2fac4 100644 --- a/test/foundry/utils/Defaults.sol +++ b/test/foundry/utils/Defaults.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Constants} from "./Constants.sol"; diff --git a/test/foundry/utils/Types.sol b/test/foundry/utils/Types.sol index df4b5ffc..1331e769 100644 --- a/test/foundry/utils/Types.sol +++ b/test/foundry/utils/Types.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; struct Users { From 317463fe2e30b7fc746119362318ecadd689ad75 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 15 May 2025 06:37:15 +0600 Subject: [PATCH 16/41] Move TestUSD inside mocks --- script/DeployAllAndSetup.s.sol | 2 +- script/DeployTestUSD.s.sol | 2 +- test/foundry/Base.t.sol | 2 +- test/foundry/unit/CampaignInfoFactory.t.sol | 2 +- test/foundry/unit/GlobalParams.t.sol | 2 +- test/foundry/unit/TestUSD.t.sol | 2 +- test/foundry/unit/TreasuryFactory.t.sol | 2 +- {src => test/mocks}/TestUSD.sol | 0 8 files changed, 7 insertions(+), 7 deletions(-) rename {src => test/mocks}/TestUSD.sol (100%) diff --git a/script/DeployAllAndSetup.s.sol b/script/DeployAllAndSetup.s.sol index 0465b2ce..533be1ec 100644 --- a/script/DeployAllAndSetup.s.sol +++ b/script/DeployAllAndSetup.s.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; import {Script} from "forge-std/Script.sol"; import {console2} from "forge-std/console2.sol"; -import {TestUSD} from "src/TestUSD.sol"; +import {TestUSD} from "../test/mocks/TestUSD.sol"; import {GlobalParams} from "src/GlobalParams.sol"; import {CampaignInfoFactory} from "src/CampaignInfoFactory.sol"; import {CampaignInfo} from "src/CampaignInfo.sol"; diff --git a/script/DeployTestUSD.s.sol b/script/DeployTestUSD.s.sol index 5c0d7d2c..2aa21204 100644 --- a/script/DeployTestUSD.s.sol +++ b/script/DeployTestUSD.s.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {TestUSD} from "../src/TestUSD.sol"; +import {TestUSD} from "../test/mocks/TestUSD.sol"; import {DeployBase} from "./lib/DeployBase.s.sol"; contract DeployTestUSD is DeployBase { diff --git a/test/foundry/Base.t.sol b/test/foundry/Base.t.sol index 7cc9e2da..67b6a86f 100644 --- a/test/foundry/Base.t.sol +++ b/test/foundry/Base.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import {Users} from "./utils/Types.sol"; import {Defaults} from "./utils/Defaults.sol"; -import {TestUSD} from "src/TestUSD.sol"; +import {TestUSD} from "../mocks/TestUSD.sol"; import {GlobalParams} from "src/GlobalParams.sol"; import {CampaignInfoFactory} from "src/CampaignInfoFactory.sol"; import {CampaignInfo} from "src/CampaignInfo.sol"; diff --git a/test/foundry/unit/CampaignInfoFactory.t.sol b/test/foundry/unit/CampaignInfoFactory.t.sol index c94c12c1..8e75c0f8 100644 --- a/test/foundry/unit/CampaignInfoFactory.t.sol +++ b/test/foundry/unit/CampaignInfoFactory.t.sol @@ -5,7 +5,7 @@ import "forge-std/Test.sol"; import {CampaignInfoFactory} from "src/CampaignInfoFactory.sol"; import {GlobalParams} from "src/GlobalParams.sol"; import {TreasuryFactory} from "src/TreasuryFactory.sol"; -import {TestUSD} from "src/TestUSD.sol"; +import {TestUSD} from "../../mocks/TestUSD.sol"; import {Defaults} from "../Base.t.sol"; import {ICampaignData} from "src/interfaces/ICampaignData.sol"; import {CampaignInfo} from "src/CampaignInfo.sol"; diff --git a/test/foundry/unit/GlobalParams.t.sol b/test/foundry/unit/GlobalParams.t.sol index 333407ed..d01093cf 100644 --- a/test/foundry/unit/GlobalParams.t.sol +++ b/test/foundry/unit/GlobalParams.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import {GlobalParams} from "src/GlobalParams.sol"; -import {TestUSD} from "src/TestUSD.sol"; +import {TestUSD} from "../../mocks/TestUSD.sol"; contract GlobalParams_UnitTest is Test { GlobalParams internal globalParams; diff --git a/test/foundry/unit/TestUSD.t.sol b/test/foundry/unit/TestUSD.t.sol index 1eb7679c..d351c45b 100644 --- a/test/foundry/unit/TestUSD.t.sol +++ b/test/foundry/unit/TestUSD.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; -import {TestUSD} from "src/TestUSD.sol"; +import {TestUSD} from "../../mocks/TestUSD.sol"; contract TestUSD_UnitTest is Test { TestUSD internal token; diff --git a/test/foundry/unit/TreasuryFactory.t.sol b/test/foundry/unit/TreasuryFactory.t.sol index 3d5aee9d..acd8bb46 100644 --- a/test/foundry/unit/TreasuryFactory.t.sol +++ b/test/foundry/unit/TreasuryFactory.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import {TreasuryFactory} from "src/TreasuryFactory.sol"; import {GlobalParams} from "src/GlobalParams.sol"; -import {TestUSD} from "src/TestUSD.sol"; +import {TestUSD} from "../../mocks/TestUSD.sol"; import {AdminAccessChecker} from "src/utils/AdminAccessChecker.sol"; contract TreasuryFactory_UpdatedUnitTest is Test { diff --git a/src/TestUSD.sol b/test/mocks/TestUSD.sol similarity index 100% rename from src/TestUSD.sol rename to test/mocks/TestUSD.sol From a84b65da752616178494222cba521a71c2e9f1a9 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 15 May 2025 06:38:16 +0600 Subject: [PATCH 17/41] Update readme --- README.md | 68 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 5522623e..bd87115c 100644 --- a/README.md +++ b/README.md @@ -6,16 +6,15 @@ CC Protocol is a decentralized crowdfunding protocol designed to help creators l ## Features -- Cross-listable campaign creation -- Multiple treasury models -- Secure fund management -- Customizable protocol parameters +* Cross-listable campaign creation +* Multiple treasury models +* Secure fund management +* Customizable protocol parameters ## Prerequisites -- [Foundry](https://book.getfoundry.sh/) -- Solidity ^0.8.20 -- Node.js (recommended) +* [Foundry](https://book.getfoundry.sh/) +* Solidity ^0.8.20 ## Installation @@ -40,23 +39,22 @@ cp .env.example .env 4. Configure your `.env` file with: -- Private key -- RPC URL -- (Optional) Contract addresses for reuse +* Private key +* RPC URL +* (Optional) Contract addresses for reuse ## Documentation Comprehensive documentation is available in the `docs/` folder: -- Technical specifications -- Contract interfaces -- Deployment guides -- Development setup instructions +* Technical specifications +* Contract interfaces +* Deployment guides +* Development setup instructions To view the documentation: ```bash -# Navigate to docs folder cd docs ``` @@ -104,37 +102,43 @@ forge script script/DeployAll.s.sol:DeployAll --rpc-url $RPC_URL --private-key $ ### Core Contracts -- `TestUSD`: Mock ERC20 token for testing -- `GlobalParams`: Protocol-wide parameter management -- `CampaignInfoFactory`: Campaign creation and management -- `TreasuryFactory`: Treasury contract deployment +* `GlobalParams`: Protocol-wide parameter management +* `CampaignInfoFactory`: Campaign creation and management +* `TreasuryFactory`: Treasury contract deployment ### Treasury Models -- `AllOrNothing`: Funds refunded if campaign goal not met +* `AllOrNothing`: Funds refunded if campaign goal not met + +### Notes on Mock Contracts + +* `TestUSD` is a mock ERC20 token used **only for testing and development purposes**. +* It is located in the `mocks/` directory and should **not be included in production deployments**. ## Deployment Workflow -1. Deploy `TestUSD` -2. Deploy `GlobalParams` -3. Deploy `TreasuryFactory` -4. Deploy `CampaignInfoFactory` +1. Deploy `GlobalParams` +2. Deploy `TreasuryFactory` +3. Deploy `CampaignInfoFactory` + +>For local testing or development, the `TestUSD` mock token needs to be deployed before interacting with contracts requiring an ERC20 token. ## Environment Variables Key environment variables in `.env`: -- `PRIVATE_KEY`: Deployment wallet private key -- `RPC_URL`: Network RPC endpoint -- `SIMULATE`: Toggle simulation mode -- Contract address variables for reuse +* `PRIVATE_KEY`: Deployment wallet private key +* `RPC_URL`: Network RPC endpoint +* `SIMULATE`: Toggle simulation mode +* Contract address variables for reuse ## Troubleshooting -- Ensure sufficient network gas tokens -- Verify RPC URL connectivity -- Check contract dependencies +* Ensure sufficient network gas tokens +* Verify RPC URL connectivity +* Check contract dependencies ## License -[SPDX-License-Identifier: MIT] +This project is licensed under the [MIT License](https://opensource.org/licenses/MIT). + From 90058a525876457fd9d7c2b4861581f0304692de Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 15 May 2025 06:55:22 +0600 Subject: [PATCH 18/41] Update GitHub Actions workflow to use actions/upload-artifact@v4 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 460619f1..0df2ad81 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,7 +47,7 @@ jobs: id: gas - name: Archive gas report - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: always() with: name: gas-report From ff717195eec1fdeb6b77241e26e4ecb0d790fe0e Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 15 May 2025 07:12:37 +0600 Subject: [PATCH 19/41] Update test.yml to install release version of foundry --- .github/workflows/test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0df2ad81..f7f32095 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,10 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: release + + - name: Install dependencies + run: forge install - name: Run Forge build run: | From 42bbfadb7bb668df96a48349b79a134ac5082414 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 15 May 2025 07:15:13 +0600 Subject: [PATCH 20/41] Update foundry version --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f7f32095..5369553b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: release + version: "1.1.0" - name: Install dependencies run: forge install From 65ce09692e4b9a48d8deef124d4176a097449df3 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 15 May 2025 07:25:12 +0600 Subject: [PATCH 21/41] Update to use the default version --- .github/workflows/test.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5369553b..e1a364c7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,14 +20,13 @@ jobs: name: Foundry project runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Check-out the repo + uses: actions/checkout@v3 with: submodules: recursive - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 - with: - version: "1.1.0" - name: Install dependencies run: forge install @@ -39,13 +38,11 @@ jobs: id: build - name: Run Forge tests - run: | - forge test -vvv + run: forge test -vvv id: test - name: Run gas report - run: | - forge test --gas-report > gas-report.txt + run: forge test --gas-report > gas-report.txt if: always() id: gas From 63d74fea971675d6f0a35e8ffe513ca3b41b8fa1 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 15 May 2025 07:40:46 +0600 Subject: [PATCH 22/41] Update test.yml to install dependencies --- .github/workflows/test.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e1a364c7..1721aee6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,12 +28,21 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 - - name: Install dependencies - run: forge install + - name: Debug Info + run: | + pwd + ls -la + cat foundry.toml + - name: Install dependencies + run: | + # Install OpenZeppelin contracts version 4.8.0 + forge install OpenZeppelin/openzeppelin-contracts@v4.8.0 --no-commit + ls -la lib/ + - name: Run Forge build run: | - forge --version + forge remappings forge build --sizes id: build From a0a168e1c1972bd5f1af73402bc50e13cb47191d Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 15 May 2025 09:02:17 +0600 Subject: [PATCH 23/41] Update OpenZeppelin version in test.yml --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1721aee6..0af678be 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,8 +36,8 @@ jobs: - name: Install dependencies run: | - # Install OpenZeppelin contracts version 4.8.0 - forge install OpenZeppelin/openzeppelin-contracts@v4.8.0 --no-commit + # Install OpenZeppelin contracts version 5.3.0 + forge install OpenZeppelin/openzeppelin-contracts@v5.3.0 ls -la lib/ - name: Run Forge build @@ -60,4 +60,4 @@ jobs: if: always() with: name: gas-report - path: gas-report.txt \ No newline at end of file + path: gas-report.txt From 3e7b98ea670b36752aa82a498f510b56d66906d0 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Tue, 20 May 2025 17:44:00 +0600 Subject: [PATCH 24/41] Update file name `DeployAllAndSetup.s.sol` to `DeployAllAndSetupAllOrNothing.s.sol` --- ...sol => DeployAllAndSetupAllOrNothing.s.sol} | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) rename script/{DeployAllAndSetup.s.sol => DeployAllAndSetupAllOrNothing.s.sol} (96%) diff --git a/script/DeployAllAndSetup.s.sol b/script/DeployAllAndSetupAllOrNothing.s.sol similarity index 96% rename from script/DeployAllAndSetup.s.sol rename to script/DeployAllAndSetupAllOrNothing.s.sol index 533be1ec..dd170d00 100644 --- a/script/DeployAllAndSetup.s.sol +++ b/script/DeployAllAndSetupAllOrNothing.s.sol @@ -13,7 +13,7 @@ import {AllOrNothing} from "src/treasuries/AllOrNothing.sol"; /** * @notice Script to deploy and setup all needed contracts for the protocol */ -contract DeployAllAndSetup is Script { +contract DeployAllAndSetupAllOrNothing is Script { // Customizable values (set through environment variables) bytes32 platformHash; uint256 protocolFeePercent; @@ -24,7 +24,7 @@ contract DeployAllAndSetup is Script { // Contract addresses address testUSD; address globalParams; - address campaignInfo; + address campaignInfoImplementation; address treasuryFactory; address campaignInfoFactory; address allOrNothingImplementation; @@ -79,7 +79,7 @@ contract DeployAllAndSetup is Script { backer2 = vm.envOr("BACKER2_ADDRESS", address(0)); // Check for existing contract addresses - testUSD = vm.envOr("TEST_USD_ADDRESS", address(0)); + testUSD = vm.envOr("TOKEN_ADDRESS", address(0)); globalParams = vm.envOr("GLOBAL_PARAMS_ADDRESS", address(0)); treasuryFactory = vm.envOr("TREASURY_FACTORY_ADDRESS", address(0)); campaignInfoFactory = vm.envOr( @@ -134,8 +134,8 @@ contract DeployAllAndSetup is Script { // Deploy CampaignInfo implementation if needed for new deployments if (campaignInfoFactory == address(0)) { - campaignInfo = address(new CampaignInfo(address(this))); - console2.log("CampaignInfo deployed at:", campaignInfo); + campaignInfoImplementation = address(new CampaignInfo(address(this))); + console2.log("CampaignInfo implementation deployed at:", campaignInfoImplementation); } // Deploy or reuse TreasuryFactory @@ -154,7 +154,7 @@ contract DeployAllAndSetup is Script { campaignInfoFactory = address( new CampaignInfoFactory( GlobalParams(globalParams), - campaignInfo + campaignInfoImplementation ) ); CampaignInfoFactory(campaignInfoFactory)._initialize( @@ -362,10 +362,10 @@ contract DeployAllAndSetup is Script { // Output summary console2.log("\n--- Deployment & Setup Summary ---"); console2.log("Platform Name Hash:", vm.toString(platformHash)); - console2.log("TEST_USD_ADDRESS:", testUSD); + console2.log("TOKEN_ADDRESS:", testUSD); console2.log("GLOBAL_PARAMS_ADDRESS:", globalParams); - if (campaignInfo != address(0)) { - console2.log("CAMPAIGN_INFO_ADDRESS:", campaignInfo); + if (campaignInfoImplementation != address(0)) { + console2.log("CAMPAIGN_INFO_IMPLEMENTATION_ADDRESS:", campaignInfoImplementation); } console2.log("TREASURY_FACTORY_ADDRESS:", treasuryFactory); console2.log("CAMPAIGN_INFO_FACTORY_ADDRESS:", campaignInfoFactory); From 8e3b6d7572c28dcd7df7ad7c14c81561dd43ed7c Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 22 May 2025 18:11:02 +0600 Subject: [PATCH 25/41] Update `TestUSD` to `TestToken` --- script/DeployAll.s.sol | 16 ++--- script/DeployAllAndSetupAllOrNothing.s.sol | 65 ++++++++++++------- script/DeployGlobalParams.s.sol | 4 +- script/DeployTestToken.s.sol | 23 +++++++ script/DeployTestUSD.s.sol | 21 ------ test/foundry/Base.t.sol | 14 ++-- .../AllOrNothing/AllOrNothing.t.sol | 4 +- .../AllOrNothing/AllOrNothingFunction.t.sol | 18 ++--- test/foundry/unit/CampaignInfoFactory.t.sol | 8 +-- test/foundry/unit/GlobalParams.t.sol | 9 +-- .../unit/{TestUSD.t.sol => TestToken.t.sol} | 9 +-- test/foundry/unit/TreasuryFactory.t.sol | 11 ++-- test/mocks/TestToken.sol | 25 +++++++ test/mocks/TestUSD.sol | 22 ------- 14 files changed, 137 insertions(+), 112 deletions(-) create mode 100644 script/DeployTestToken.s.sol delete mode 100644 script/DeployTestUSD.s.sol rename test/foundry/unit/{TestUSD.t.sol => TestToken.t.sol} (73%) create mode 100644 test/mocks/TestToken.sol delete mode 100644 test/mocks/TestUSD.sol diff --git a/script/DeployAll.s.sol b/script/DeployAll.s.sol index bce481fd..f7936213 100644 --- a/script/DeployAll.s.sol +++ b/script/DeployAll.s.sol @@ -4,19 +4,19 @@ pragma solidity ^0.8.20; import {Script} from "forge-std/Script.sol"; import {console2} from "forge-std/console2.sol"; import {DeployGlobalParams} from "./DeployGlobalParams.s.sol"; -import {DeployTestUSD} from "./DeployTestUSD.s.sol"; +import {DeployTestToken} from "./DeployTestToken.s.sol"; import {DeployCampaignInfoFactory} from "./DeployCampaignInfoFactory.s.sol"; import {DeployTreasuryFactory} from "./DeployTreasuryFactory.s.sol"; contract DeployAll is Script { - function deployTestUSD() internal returns (address) { - DeployTestUSD script = new DeployTestUSD(); + function deployTestToken() internal returns (address) { + DeployTestToken script = new DeployTestToken(); return script.deploy(); } - function deployGlobalParams(address testUSD) internal returns (address) { + function deployGlobalParams(address testToken) internal returns (address) { DeployGlobalParams script = new DeployGlobalParams(); - return script.deployWithToken(testUSD); + return script.deployWithToken(testToken); } function deployTreasuryFactory( @@ -42,8 +42,8 @@ contract DeployAll is Script { vm.startBroadcast(deployerKey); } - address testUSD = deployTestUSD(); - address globalParams = deployGlobalParams(testUSD); + address testToken = deployTestToken(); + address globalParams = deployGlobalParams(testToken); address treasuryFactory = deployTreasuryFactory(globalParams); address campaignFactory = deployCampaignFactory( globalParams, @@ -54,7 +54,7 @@ contract DeployAll is Script { vm.stopBroadcast(); } - console2.log("TEST_USD_ADDRESS", testUSD); + console2.log("TOKEN_ADDRESS", testToken); console2.log("GLOBAL_PARAMS_ADDRESS", globalParams); console2.log("TREASURY_FACTORY_ADDRESS", treasuryFactory); console2.log("CAMPAIGN_INFO_FACTORY_ADDRESS", campaignFactory); diff --git a/script/DeployAllAndSetupAllOrNothing.s.sol b/script/DeployAllAndSetupAllOrNothing.s.sol index dd170d00..d0dc456c 100644 --- a/script/DeployAllAndSetupAllOrNothing.s.sol +++ b/script/DeployAllAndSetupAllOrNothing.s.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; import {Script} from "forge-std/Script.sol"; import {console2} from "forge-std/console2.sol"; -import {TestUSD} from "../test/mocks/TestUSD.sol"; +import {TestToken} from "../test/mocks/TestToken.sol"; import {GlobalParams} from "src/GlobalParams.sol"; import {CampaignInfoFactory} from "src/CampaignInfoFactory.sol"; import {CampaignInfo} from "src/CampaignInfo.sol"; @@ -22,7 +22,7 @@ contract DeployAllAndSetupAllOrNothing is Script { bool simulate; // Contract addresses - address testUSD; + address testToken; address globalParams; address campaignInfoImplementation; address treasuryFactory; @@ -36,6 +36,10 @@ contract DeployAllAndSetupAllOrNothing is Script { address backer1; address backer2; + // Token details + // string tokenName; + // string tokenSymbol; + // Flags to track what was completed bool platformEnlisted = false; bool implementationRegistered = false; @@ -43,7 +47,7 @@ contract DeployAllAndSetupAllOrNothing is Script { bool adminRightsTransferred = false; // Flags for contract deployment or reuse - bool testUsdDeployed = false; + bool testTokenDeployed = false; bool globalParamsDeployed = false; bool treasuryFactoryDeployed = false; bool campaignInfoFactoryDeployed = false; @@ -56,6 +60,7 @@ contract DeployAllAndSetupAllOrNothing is Script { "PLATFORM_NAME", string("MiniFunder") ); + platformHash = keccak256(abi.encodePacked(platformName)); protocolFeePercent = vm.envOr("PROTOCOL_FEE_PERCENT", uint256(100)); // Default 1% platformFeePercent = vm.envOr("PLATFORM_FEE_PERCENT", uint256(400)); // Default 4% @@ -79,7 +84,7 @@ contract DeployAllAndSetupAllOrNothing is Script { backer2 = vm.envOr("BACKER2_ADDRESS", address(0)); // Check for existing contract addresses - testUSD = vm.envOr("TOKEN_ADDRESS", address(0)); + testToken = vm.envOr("TOKEN_ADDRESS", address(0)); globalParams = vm.envOr("GLOBAL_PARAMS_ADDRESS", address(0)); treasuryFactory = vm.envOr("TREASURY_FACTORY_ADDRESS", address(0)); campaignInfoFactory = vm.envOr( @@ -104,13 +109,17 @@ contract DeployAllAndSetupAllOrNothing is Script { function deployContracts() internal { console2.log("Setting up contracts..."); - // Deploy or reuse TestUSD - if (testUSD == address(0)) { - testUSD = address(new TestUSD()); - testUsdDeployed = true; - console2.log("TestUSD deployed at:", testUSD); + // Deploy or reuse TestToken + + string memory tokenName = vm.envOr("TOKEN_NAME", string("TestToken")); + string memory tokenSymbol = vm.envOr("TOKEN_SYMBOL", string("TST")); + + if (testToken == address(0)) { + testToken = address(new TestToken(tokenName, tokenSymbol)); + testTokenDeployed = true; + console2.log("TestToken deployed at:", testToken); } else { - console2.log("Reusing TestUSD at:", testUSD); + console2.log("Reusing TestToken at:", testToken); } // Deploy or reuse GlobalParams @@ -118,7 +127,7 @@ contract DeployAllAndSetupAllOrNothing is Script { globalParams = address( new GlobalParams( deployerAddress, // Initially deployer is protocol admin - testUSD, + testToken, protocolFeePercent ) ); @@ -128,14 +137,19 @@ contract DeployAllAndSetupAllOrNothing is Script { console2.log("Reusing GlobalParams at:", globalParams); } - // We need at least TestUSD and GlobalParams to continue - require(testUSD != address(0), "TestUSD address is required"); + // We need at least TestToken and GlobalParams to continue + require(testToken != address(0), "TestToken address is required"); require(globalParams != address(0), "GlobalParams address is required"); // Deploy CampaignInfo implementation if needed for new deployments if (campaignInfoFactory == address(0)) { - campaignInfoImplementation = address(new CampaignInfo(address(this))); - console2.log("CampaignInfo implementation deployed at:", campaignInfoImplementation); + campaignInfoImplementation = address( + new CampaignInfo(address(this)) + ); + console2.log( + "CampaignInfo implementation deployed at:", + campaignInfoImplementation + ); } // Deploy or reuse TreasuryFactory @@ -277,17 +291,17 @@ contract DeployAllAndSetupAllOrNothing is Script { } function mintTokens() internal { - // Only mint tokens if we deployed TestUSD - if (!testUsdDeployed) { - console2.log("Skipping mintTokens - using existing TestUSD"); + // Only mint tokens if we deployed TestToken + if (!testTokenDeployed) { + console2.log("Skipping mintTokens - using existing TestToken"); return; } if (backer1 != address(0) && backer2 != address(0)) { console2.log("Minting tokens to test backers"); - TestUSD(testUSD).mint(backer1, tokenMintAmount); + TestToken(testToken).mint(backer1, tokenMintAmount); if (backer1 != backer2) { - TestUSD(testUSD).mint(backer2, tokenMintAmount); + TestToken(testToken).mint(backer2, tokenMintAmount); } console2.log("Tokens minted successfully"); } @@ -362,10 +376,13 @@ contract DeployAllAndSetupAllOrNothing is Script { // Output summary console2.log("\n--- Deployment & Setup Summary ---"); console2.log("Platform Name Hash:", vm.toString(platformHash)); - console2.log("TOKEN_ADDRESS:", testUSD); + console2.log("TOKEN_ADDRESS:", testToken); console2.log("GLOBAL_PARAMS_ADDRESS:", globalParams); if (campaignInfoImplementation != address(0)) { - console2.log("CAMPAIGN_INFO_IMPLEMENTATION_ADDRESS:", campaignInfoImplementation); + console2.log( + "CAMPAIGN_INFO_IMPLEMENTATION_ADDRESS:", + campaignInfoImplementation + ); } console2.log("TREASURY_FACTORY_ADDRESS:", treasuryFactory); console2.log("CAMPAIGN_INFO_FACTORY_ADDRESS:", campaignInfoFactory); @@ -385,8 +402,8 @@ contract DeployAllAndSetupAllOrNothing is Script { console2.log("\nDeployment status:"); console2.log( - "- TestUSD:", - testUsdDeployed ? "Newly deployed" : "Reused existing" + "- TestToken:", + testTokenDeployed ? "Newly deployed" : "Reused existing" ); console2.log( "- GlobalParams:", diff --git a/script/DeployGlobalParams.s.sol b/script/DeployGlobalParams.s.sol index 1ed2abed..185d3856 100644 --- a/script/DeployGlobalParams.s.sol +++ b/script/DeployGlobalParams.s.sol @@ -16,8 +16,8 @@ contract DeployGlobalParams is DeployBase { function _deploy() internal returns (address) { address deployer = vm.addr(vm.envUint("PRIVATE_KEY")); - address token = vm.envOr("TEST_USD_ADDRESS", address(0)); - require(token != address(0), "TestUSD address must be set"); + address token = vm.envOr("TOKEN_ADDRESS", address(0)); + require(token != address(0), "TestToken address must be set"); return address(new GlobalParams(deployer, token, 200)); } diff --git a/script/DeployTestToken.s.sol b/script/DeployTestToken.s.sol new file mode 100644 index 00000000..93d6d072 --- /dev/null +++ b/script/DeployTestToken.s.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {TestToken} from "../test/mocks/TestToken.sol"; +import {DeployBase} from "./lib/DeployBase.s.sol"; + +contract DeployTestToken is DeployBase { + function deploy() public returns (address) { + return deployOrUse("TOKEN_ADDRESS", _deploy); + } + + function _deploy() internal returns (address) { + string memory tokenName = vm.envOr("TOKEN_NAME", string("TestToken")); + string memory tokenSymbol = vm.envOr("TOKEN_SYMBOL", string("TST")); + return address(new TestToken(tokenName, tokenSymbol)); + } + + function run() external { + vm.startBroadcast(vm.envUint("PRIVATE_KEY")); + deploy(); + vm.stopBroadcast(); + } +} diff --git a/script/DeployTestUSD.s.sol b/script/DeployTestUSD.s.sol deleted file mode 100644 index 2aa21204..00000000 --- a/script/DeployTestUSD.s.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import {TestUSD} from "../test/mocks/TestUSD.sol"; -import {DeployBase} from "./lib/DeployBase.s.sol"; - -contract DeployTestUSD is DeployBase { - function deploy() public returns (address) { - return deployOrUse("TEST_USD_ADDRESS", _deploy); - } - - function _deploy() internal returns (address) { - return address(new TestUSD()); - } - - function run() external { - vm.startBroadcast(vm.envUint("PRIVATE_KEY")); - deploy(); - vm.stopBroadcast(); - } -} diff --git a/test/foundry/Base.t.sol b/test/foundry/Base.t.sol index 67b6a86f..ad771340 100644 --- a/test/foundry/Base.t.sol +++ b/test/foundry/Base.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import {Users} from "./utils/Types.sol"; import {Defaults} from "./utils/Defaults.sol"; -import {TestUSD} from "../mocks/TestUSD.sol"; +import {TestToken} from "../mocks/TestToken.sol"; import {GlobalParams} from "src/GlobalParams.sol"; import {CampaignInfoFactory} from "src/CampaignInfoFactory.sol"; import {CampaignInfo} from "src/CampaignInfo.sol"; @@ -17,7 +17,7 @@ abstract contract Base_Test is Test, Defaults { Users internal users; //Test Contracts - TestUSD internal testUSD; + TestToken internal testToken; GlobalParams internal globalParams; CampaignInfoFactory internal campaignInfoFactory; TreasuryFactory internal treasuryFactory; @@ -40,10 +40,10 @@ abstract contract Base_Test is Test, Defaults { vm.startPrank(users.contractOwner); // Deploy the base test contracts. - testUSD = new TestUSD(); + testToken = new TestToken(tokenName, tokenSymbol); globalParams = new GlobalParams( users.protocolAdminAddress, - address(testUSD), + address(testToken), PROTOCOL_FEE_PERCENT ); @@ -63,13 +63,13 @@ abstract contract Base_Test is Test, Defaults { allOrNothingImplementation = new AllOrNothing(); //Mint token to the backer - testUSD.mint(users.backer1Address, TOKEN_MINT_AMOUNT); - testUSD.mint(users.backer2Address, TOKEN_MINT_AMOUNT); + testToken.mint(users.backer1Address, TOKEN_MINT_AMOUNT); + testToken.mint(users.backer2Address, TOKEN_MINT_AMOUNT); vm.stopPrank(); // Label the base test contracts. - vm.label({account: address(testUSD), newLabel: "TestUSD"}); + vm.label({account: address(testToken), newLabel: "TestToken"}); vm.label({ account: address(globalParams), newLabel: "Global Parameter" diff --git a/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol b/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol index 29f5379c..70819256 100644 --- a/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol +++ b/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol @@ -174,7 +174,7 @@ abstract contract AllOrNothing_Integration_Shared_Test is vm.startPrank(caller); vm.recordLogs(); - testUSD.approve(allOrNothingAddress, pledgeAmount + shippingFee); + testToken.approve(allOrNothingAddress, pledgeAmount + shippingFee); vm.warp(launchTime); bytes32[] memory reward = new bytes32[](1); @@ -216,7 +216,7 @@ abstract contract AllOrNothing_Integration_Shared_Test is vm.startPrank(caller); vm.recordLogs(); - testUSD.approve(allOrNothingAddress, pledgeAmount); + testToken.approve(allOrNothingAddress, pledgeAmount); vm.warp(launchTime); AllOrNothing(allOrNothingAddress).pledgeWithoutAReward( diff --git a/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol b/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol index a11b4428..640a2559 100644 --- a/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol +++ b/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol @@ -63,7 +63,7 @@ contract AllOrNothingFunction_Integration_Shared_Test is bytes32[] memory rewards ) = pledgeForAReward( users.backer1Address, - address(testUSD), + address(testToken), address(allOrNothing), PLEDGE_AMOUNT, SHIPPING_FEE, @@ -71,8 +71,8 @@ contract AllOrNothingFunction_Integration_Shared_Test is REWARD_NAME_1_HASH ); - uint256 backerBalance = testUSD.balanceOf(users.backer1Address); - uint256 treasuryBalance = testUSD.balanceOf(address(allOrNothing)); + uint256 backerBalance = testToken.balanceOf(users.backer1Address); + uint256 treasuryBalance = testToken.balanceOf(address(allOrNothing)); uint256 backerNftBalance = allOrNothing.balanceOf(users.backer1Address); address nftOwnerAddress = allOrNothing.ownerOf(pledgeForARewardTokenId); @@ -91,7 +91,7 @@ contract AllOrNothingFunction_Integration_Shared_Test is (, uint256 rewardTokenId, ) = pledgeForAReward( users.backer1Address, - address(testUSD), + address(testToken), address(allOrNothing), PLEDGE_AMOUNT, SHIPPING_FEE, @@ -101,7 +101,7 @@ contract AllOrNothingFunction_Integration_Shared_Test is (, uint256 tokenId) = pledgeWithoutAReward( users.backer1Address, - address(testUSD), + address(testToken), address(allOrNothing), PLEDGE_AMOUNT, LAUNCH_TIME @@ -129,7 +129,7 @@ contract AllOrNothingFunction_Integration_Shared_Test is pledgeForAReward( users.backer1Address, - address(testUSD), + address(testToken), address(allOrNothing), PLEDGE_AMOUNT, SHIPPING_FEE, @@ -138,7 +138,7 @@ contract AllOrNothingFunction_Integration_Shared_Test is ); pledgeWithoutAReward( users.backer2Address, - address(testUSD), + address(testToken), address(allOrNothing), GOAL_AMOUNT, LAUNCH_TIME @@ -179,7 +179,7 @@ contract AllOrNothingFunction_Integration_Shared_Test is pledgeForAReward( users.backer1Address, - address(testUSD), + address(testToken), address(allOrNothing), PLEDGE_AMOUNT, SHIPPING_FEE, @@ -188,7 +188,7 @@ contract AllOrNothingFunction_Integration_Shared_Test is ); pledgeWithoutAReward( users.backer2Address, - address(testUSD), + address(testToken), address(allOrNothing), GOAL_AMOUNT, LAUNCH_TIME diff --git a/test/foundry/unit/CampaignInfoFactory.t.sol b/test/foundry/unit/CampaignInfoFactory.t.sol index 8e75c0f8..803a83bb 100644 --- a/test/foundry/unit/CampaignInfoFactory.t.sol +++ b/test/foundry/unit/CampaignInfoFactory.t.sol @@ -5,7 +5,7 @@ import "forge-std/Test.sol"; import {CampaignInfoFactory} from "src/CampaignInfoFactory.sol"; import {GlobalParams} from "src/GlobalParams.sol"; import {TreasuryFactory} from "src/TreasuryFactory.sol"; -import {TestUSD} from "../../mocks/TestUSD.sol"; +import {TestToken} from "../../mocks/TestToken.sol"; import {Defaults} from "../Base.t.sol"; import {ICampaignData} from "src/interfaces/ICampaignData.sol"; import {CampaignInfo} from "src/CampaignInfo.sol"; @@ -14,16 +14,16 @@ contract CampaignInfoFactory_UnitTest is Test, Defaults { CampaignInfoFactory internal factory; TreasuryFactory internal treasuryFactory; GlobalParams internal globalParams; - TestUSD internal testUSD; + TestToken internal testToken; CampaignInfo internal campaignInfoImplementation; address internal admin = address(0xA11CE); function setUp() public { - testUSD = new TestUSD(); + testToken = new TestToken(tokenName, tokenSymbol); globalParams = new GlobalParams( admin, - address(testUSD), + address(testToken), PROTOCOL_FEE_PERCENT ); campaignInfoImplementation = new CampaignInfo(address(this)); diff --git a/test/foundry/unit/GlobalParams.t.sol b/test/foundry/unit/GlobalParams.t.sol index d01093cf..05c82ffa 100644 --- a/test/foundry/unit/GlobalParams.t.sol +++ b/test/foundry/unit/GlobalParams.t.sol @@ -3,17 +3,18 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import {GlobalParams} from "src/GlobalParams.sol"; -import {TestUSD} from "../../mocks/TestUSD.sol"; +import {Defaults} from "../Base.t.sol"; +import {TestToken} from "../../mocks/TestToken.sol"; -contract GlobalParams_UnitTest is Test { +contract GlobalParams_UnitTest is Test, Defaults{ GlobalParams internal globalParams; - TestUSD internal token; + TestToken internal token; address internal admin = address(0xA11CE); uint256 internal protocolFee = 300; // 3% function setUp() public { - token = new TestUSD(); + token = new TestToken(tokenName, tokenSymbol); globalParams = new GlobalParams(admin, address(token), protocolFee); } diff --git a/test/foundry/unit/TestUSD.t.sol b/test/foundry/unit/TestToken.t.sol similarity index 73% rename from test/foundry/unit/TestUSD.t.sol rename to test/foundry/unit/TestToken.t.sol index d351c45b..0ba3c4ed 100644 --- a/test/foundry/unit/TestUSD.t.sol +++ b/test/foundry/unit/TestToken.t.sol @@ -2,16 +2,17 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; -import {TestUSD} from "../../mocks/TestUSD.sol"; +import {TestToken} from "../../mocks/TestToken.sol"; +import {Defaults} from "../Base.t.sol"; -contract TestUSD_UnitTest is Test { - TestUSD internal token; +contract TestToken_UnitTest is Test, Defaults { + TestToken internal token; address internal user = address(0x1234); uint256 internal mintAmount = 1_000 * 1e18; function setUp() public { - token = new TestUSD(); + token = new TestToken(tokenName, tokenSymbol); } function testMintIncreasesBalance() public { diff --git a/test/foundry/unit/TreasuryFactory.t.sol b/test/foundry/unit/TreasuryFactory.t.sol index acd8bb46..3a7a6785 100644 --- a/test/foundry/unit/TreasuryFactory.t.sol +++ b/test/foundry/unit/TreasuryFactory.t.sol @@ -4,13 +4,14 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import {TreasuryFactory} from "src/TreasuryFactory.sol"; import {GlobalParams} from "src/GlobalParams.sol"; -import {TestUSD} from "../../mocks/TestUSD.sol"; +import {TestToken} from "../../mocks/TestToken.sol"; +import {Defaults} from "../Base.t.sol"; import {AdminAccessChecker} from "src/utils/AdminAccessChecker.sol"; -contract TreasuryFactory_UpdatedUnitTest is Test { +contract TreasuryFactory_UpdatedUnitTest is Test, Defaults { TreasuryFactory internal factory; GlobalParams internal globalParams; - TestUSD internal testUSD; + TestToken internal testToken; address internal protocolAdmin = address(0xA11CE); address internal platformAdmin = address(0xBEEF); @@ -23,8 +24,8 @@ contract TreasuryFactory_UpdatedUnitTest is Test { uint256 internal platformFee = 300; // 3% function setUp() public { - testUSD = new TestUSD(); - globalParams = new GlobalParams(protocolAdmin, address(testUSD), 300); + testToken = new TestToken(tokenName, tokenSymbol); + globalParams = new GlobalParams(protocolAdmin, address(testToken), 300); factory = new TreasuryFactory(globalParams); // Label addresses for clarity diff --git a/test/mocks/TestToken.sol b/test/mocks/TestToken.sol new file mode 100644 index 00000000..19414ef1 --- /dev/null +++ b/test/mocks/TestToken.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {ERC20} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +import {Ownable} from "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; + +/** + * @title TestToken + * @notice A test token `tUSD` which is used in the tests. + */ +contract TestToken is ERC20, Ownable { + constructor( + string memory _name, + string memory _symbol + ) ERC20(_name, _symbol) Ownable(msg.sender) {} + + /** + * @notice Mints testToken token. + * @param to The token receivers address. + * @param amount The amount of tokens to mint. + */ + function mint(address to, uint256 amount) public onlyOwner { + _mint(to, amount); + } +} diff --git a/test/mocks/TestUSD.sol b/test/mocks/TestUSD.sol deleted file mode 100644 index 71753eda..00000000 --- a/test/mocks/TestUSD.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; - -/** - * @title TestUSD - * @notice A test token `tUSD` which is used in the tests. - */ -contract TestUSD is ERC20, Ownable { - constructor() ERC20("testUSD", "tUSD") Ownable(msg.sender) {} - - /** - * @notice Mints testUSD token. - * @param to The token receivers address. - * @param amount The amount of tokens to mint. - */ - function mint(address to, uint256 amount) public onlyOwner { - _mint(to, amount); - } -} From 4bbd918b3846a1796a9f7194e16f608ce6371c14 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 22 May 2025 18:11:15 +0600 Subject: [PATCH 26/41] Add defaults for TestToken --- test/foundry/utils/Defaults.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/foundry/utils/Defaults.sol b/test/foundry/utils/Defaults.sol index bcb2fac4..c77b2ea5 100644 --- a/test/foundry/utils/Defaults.sol +++ b/test/foundry/utils/Defaults.sol @@ -30,6 +30,10 @@ contract Defaults is Constants, ICampaignData, IReward { uint256 public immutable LAUNCH_TIME; uint256 public immutable DEADLINE; + //Token details + string tokenName = "TestToken"; + string tokenSymbol = "TST"; + //Variables CampaignData public CAMPAIGN_DATA; AllOrNothing.Reward public REWARD1; From 561b8e60baf0d254e288c0a0de194d64d50fbdfe Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 22 May 2025 18:11:50 +0600 Subject: [PATCH 27/41] Update env.example --- env.example | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/env.example b/env.example index c57b4c9d..c646394e 100644 --- a/env.example +++ b/env.example @@ -3,6 +3,7 @@ # ------------------------- PRIVATE_KEY= RPC_URL= +CHAIN_ID= # ------------------------- # Contract Addresses @@ -10,7 +11,7 @@ RPC_URL= # Optionally set this to reuse already-deployed contracts. # If any are left blank, they will be freshly deployed. -TEST_USD_ADDRESS= +TOKEN_ADDRESS= GLOBAL_PARAMS_ADDRESS= TREASURY_FACTORY_ADDRESS= CAMPAIGN_INFO_FACTORY_ADDRESS= @@ -29,11 +30,13 @@ PLATFORM_ADMIN_ADDRESS= PLATFORM_FEE_PERCENT= # ------------------------- -# TEST_USD Setups +# TOKEN Setups # ------------------------- -# Only required if TEST_USD needs to be pre-minted. +# Only required if TOKEN needs to be pre-minted. TOKEN_MINT_AMOUNT= +TOKEN_NAME="" +TOKEN_SYMBOL="" BACKER1_ADDRESS= BACKER2_ADDRESS= From cfd145bc19d4f5e440d13a42e266611ed6c2c79e Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 22 May 2025 18:12:00 +0600 Subject: [PATCH 28/41] Add Code of Conduct --- CODE_OF_CONDUCT.md | 133 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..58d55b4c --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,133 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[INSERT CONTACT METHOD]. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations \ No newline at end of file From cc290d0d8788ce15559f326a0a4b94c8bcf86163 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 22 May 2025 18:12:21 +0600 Subject: [PATCH 29/41] Add Contribution Guidelines --- CONTRIBUTING.md | 197 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..be7c9644 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,197 @@ +# Contributing to CC Protocol + +Thank you for your interest in contributing to the Creative Crowdfunding Protocol! This document provides detailed guidelines to help you contribute effectively. + +## Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [Getting Started](#getting-started) + - [Issues](#issues) + - [Development Environment](#development-environment) +- [Development Workflow](#development-workflow) + - [Branching Strategy](#branching-strategy) + - [Making Changes](#making-changes) + - [Testing](#testing) + - [Documentation](#documentation) +- [Smart Contract Development Guidelines](#smart-contract-development-guidelines) + - [Security Best Practices](#security-best-practices) + - [Gas Optimization](#gas-optimization) + - [Code Style](#code-style) +- [Pull Request Process](#pull-request-process) + - [PR Requirements](#pr-requirements) + - [Review Process](#review-process) +- [Community](#community) + +## Code of Conduct + +Please read our [Code of Conduct](./CODE_OF_CONDUCT.md) to understand the behavior we expect from all contributors. + +## Getting Started + +### Issues + +#### Create a New Issue + +If you want to add or modify the content of this project: + +1. [Search if an issue already exists](https://github.com/ccprotocol/ccprotocol-contracts/issues) +2. If a related issue doesn't exist, create a new issue using the appropriate template +3. Discuss the proposed changes with the community before starting work +4. Wait for issue assignment or approval before submitting a PR + +#### Solve an Issue + +Scan through our [existing issues](https://github.com/ccprotocol/ccprotocol-contracts/issues) to find one that interests you. You can use labels to filter issues: + +- `good first issue`: Suitable for newcomers +- `bug`: Issues with the existing code +- `enhancement`: New features or improvements +- `documentation`: Documentation improvements +- `help wanted`: Issues where help is particularly needed + +### Development Environment + +1. Fork the repository +2. Clone your fork: + ```bash + git clone https://github.com/YOUR_USERNAME/ccprotocol-contracts.git + cd ccprotocol-contracts + ``` +3. Add the original repository as upstream: + ```bash + git remote add upstream https://github.com/ccprotocol/ccprotocol-contracts.git + ``` +4. Install development dependencies: + ```bash + forge install + ``` +5. Copy and configure environment variables: + ```bash + cp .env.example .env + # Edit .env with your settings + ``` + +## Development Workflow + +### Branching Strategy + +- `main`: Production-ready code +- `develop`: Integration branch for features +- Feature branches: Named as `feature/your-feature-name` +- Bug fix branches: Named as `fix/bug-name` + +Always create your working branch from `develop`: + +```bash +git checkout develop +git pull upstream develop +git checkout -b feature/your-feature-name +``` + +### Making Changes + +1. Ensure your changes address a specific issue +2. Make commits with clear, descriptive messages +3. Keep changes focused and atomic +4. Rebase your branch regularly to incorporate upstream changes: + ```bash + git fetch upstream + git rebase upstream/develop + ``` + +### Testing + +All code changes must include appropriate tests: + +1. Write unit tests for new functionality +2. Run the test suite to ensure all tests pass: + ```bash + forge test + ``` +3. For more detailed test output: + ```bash + forge test -vvv + ``` +4. Run gas reports to ensure efficiency: + ```bash + forge test --gas-report + ``` + +### Documentation + +1. Update or add NatSpec comments for all public functions: + ```solidity + /** + * @notice Brief explanation of the function + * @param paramName Description of the parameter + * @return Description of the return value + */ + function exampleFunction(uint256 paramName) public returns (bool) { + // Function implementation + } + ``` +2. Update relevant documentation in the `docs/` directory +3. Include a summary of documentation changes in your PR + +## Smart Contract Development Guidelines + +### Security Best Practices + +1. Follow established security patterns +2. Use OpenZeppelin contracts where appropriate +3. Be aware of common vulnerabilities (reentrancy, frontrunning, etc.) +4. Avoid complex control flows that are difficult to audit +5. Consider formal verification for critical functions + +### Gas Optimization + +1. Be mindful of storage vs. memory usage +2. Batch operations when possible +3. Use appropriate data types (uint256 is often most gas-efficient) +4. Consider gas costs in loops and data structures +5. Include gas reports in PRs for significant changes + +### Code Style + +1. Follow Solidity style guides +2. Use meaningful variable and function names +3. Format your code using the prettier +4. Keep functions small and focused +5. Use appropriate visibility modifiers (public, external, internal, private) + +## Pull Request Process + +1. Update the README or documentation if needed +2. Ensure all CI checks pass +3. Create a pull request to the `develop` branch +4. Fill in the PR template with all required information +5. Request review from relevant team members + +### PR Requirements + +- PR title should be descriptive and reference the issue (e.g., "Fix #123: Add timestamp validation") +- All tests must pass +- Code must be properly formatted +- New code should be covered by tests +- Changes should be well-documented +- Commit history should be clean and logical + +### Review Process + +1. At least one core contributor must review and approve the changes +2. Address all review comments promptly +3. CI checks must pass +4. Changes may require revision based on feedback +5. Once approved, a maintainer will merge the PR + +## Community + +- **GitHub Issues**: For bugs and feature requests +- **Discord**: For quick questions and community discussions +- **Pull Requests**: For code review discussions + +Join our community on [Discord](https://discord.gg/4tR9rWc3QE). + +## License + +By contributing to CC Protocol, you agree that your contributions will be licensed under the project's [MIT License](./LICENSE). From cea10accf07b15e1e5afca586901e8f39a20730c Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 22 May 2025 18:13:03 +0600 Subject: [PATCH 30/41] Update foundry.toml --- foundry.toml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/foundry.toml b/foundry.toml index 3c29c44e..1ee5c201 100644 --- a/foundry.toml +++ b/foundry.toml @@ -11,6 +11,10 @@ remappings = [ "@openzeppelin/=lib/openzeppelin-contracts/" ] - [rpc_endpoints] -alfajores = "${ALFAJORES_RPC_URL}" +mainnet = "https://forno.celo.org/" +alfajores = "https://alfajores-forno.celo-testnet.org/" + +[etherscan] +mainnet = { key = "${ETHERSCAN_API_KEY}", url = "https://api.celoscan.io/api" } +alfajores = { key = "${ETHERSCAN_API_KEY}", url = "https://api-alfajores.celoscan.io/api" } From 9cce955ad8a36f2f44efdc803ca48eaa001d5f36 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 22 May 2025 18:13:29 +0600 Subject: [PATCH 31/41] Update Readme.md --- README.md | 99 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index bd87115c..68de14d6 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,15 @@ CC Protocol is a decentralized crowdfunding protocol designed to help creators l ## Features -* Cross-listable campaign creation -* Multiple treasury models -* Secure fund management -* Customizable protocol parameters +- Cross-listable campaign creation +- Multiple treasury models +- Secure fund management +- Customizable protocol parameters ## Prerequisites -* [Foundry](https://book.getfoundry.sh/) -* Solidity ^0.8.20 +- [Foundry](https://book.getfoundry.sh/) +- Solidity ^0.8.20 ## Installation @@ -37,20 +37,16 @@ forge install cp .env.example .env ``` -4. Configure your `.env` file with: - -* Private key -* RPC URL -* (Optional) Contract addresses for reuse +4. Configure your `.env` file following the template in `.env.example` ## Documentation Comprehensive documentation is available in the `docs/` folder: -* Technical specifications -* Contract interfaces -* Deployment guides -* Development setup instructions +- Technical specifications +- Contract interfaces +- Deployment guides +- Development setup instructions To view the documentation: @@ -91,29 +87,29 @@ anvil forge script script/DeployAll.s.sol:DeployAll --rpc-url http://localhost:8545 --private-key $PRIVATE_KEY --broadcast ``` -#### Testnet Deployment +#### Network Deployment ```bash -# Deploy to testnet -forge script script/DeployAll.s.sol:DeployAll --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast -vvvv +# Deploy to any configured network +forge script script/DeployAll.s.sol:DeployAll --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast ``` ## Contract Architecture ### Core Contracts -* `GlobalParams`: Protocol-wide parameter management -* `CampaignInfoFactory`: Campaign creation and management -* `TreasuryFactory`: Treasury contract deployment +- `GlobalParams`: Protocol-wide parameter management +- `CampaignInfoFactory`: Campaign creation and management +- `TreasuryFactory`: Treasury contract deployment ### Treasury Models -* `AllOrNothing`: Funds refunded if campaign goal not met +- `AllOrNothing`: Funds refunded if campaign goal not met ### Notes on Mock Contracts -* `TestUSD` is a mock ERC20 token used **only for testing and development purposes**. -* It is located in the `mocks/` directory and should **not be included in production deployments**. +- `TestToken` is a mock ERC20 token used **only for testing and development purposes**. +- It is located in the `mocks/` directory and should **not be included in production deployments**. ## Deployment Workflow @@ -121,24 +117,55 @@ forge script script/DeployAll.s.sol:DeployAll --rpc-url $RPC_URL --private-key $ 2. Deploy `TreasuryFactory` 3. Deploy `CampaignInfoFactory` ->For local testing or development, the `TestUSD` mock token needs to be deployed before interacting with contracts requiring an ERC20 token. +> For local testing or development, the `TestToken` mock token needs to be deployed before interacting with contracts requiring an ERC20 token. ## Environment Variables -Key environment variables in `.env`: +Key environment variables to configure in `.env`: -* `PRIVATE_KEY`: Deployment wallet private key -* `RPC_URL`: Network RPC endpoint -* `SIMULATE`: Toggle simulation mode -* Contract address variables for reuse +- `PRIVATE_KEY`: Deployment wallet private key +- `RPC_URL`: Network RPC endpoint (can be configured for any network) +- `SIMULATE`: Toggle simulation mode +- Contract address variables for reuse -## Troubleshooting +For a complete list of variables, refer to `.env.example`. -* Ensure sufficient network gas tokens -* Verify RPC URL connectivity -* Check contract dependencies +## Security -## License +### Audits + +Security audit reports can be found in the [`audits/`](./audits/) folder. We regularly conduct security audits to ensure the safety and reliability of the protocol. + +## Contributing + +We welcome all contributions to the Creative Crowdfunding Protocol. If you're interested in helping, here's how you can contribute: + +- **Report bugs** by opening issues +- **Suggest enhancements** or new features +- **Submit pull requests** to improve the codebase +- **Improve documentation** to make the project more accessible + +Before contributing, please read our detailed [Contributing Guidelines](./CONTRIBUTING.md) for comprehensive information on: +- Development workflow +- Coding standards +- Testing requirements +- Pull request process +- Smart contract security considerations -This project is licensed under the [MIT License](https://opensource.org/licenses/MIT). +### Community + +Join our community on [Discord](https://discord.gg/4tR9rWc3QE) for questions and discussions. + +Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectful. + +## Contributors + + + + + +Made with [contrib.rocks](https://contrib.rocks). + +## License +This project is licensed under the [MIT License](https://opensource.org/licenses/MIT). \ No newline at end of file From c76f696f69858fd78a1a6777c6b5e4daa8c047bd Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 22 May 2025 18:15:33 +0600 Subject: [PATCH 32/41] Add audit report --- ...-Audit-Report-CreativeCrowdfunding_v1.0.pdf | Bin 0 -> 369348 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 audits/PeckShield-Audit-Report-CreativeCrowdfunding_v1.0.pdf diff --git a/audits/PeckShield-Audit-Report-CreativeCrowdfunding_v1.0.pdf b/audits/PeckShield-Audit-Report-CreativeCrowdfunding_v1.0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d301a934bfcee05c8df0f1671c46e8373ad0a80c GIT binary patch literal 369348 zcmeFZ2|UzY`#Ah%Y+17xGO{EjNwS0?JINkV6v@71$!@4nvV>6f>`RPf$&w*^Wy!u~ z-^q++470so_p?90=lA@U|NDOa_viE8hck2L%$ak}b*}xo&WwOMLD&PP7UNv=TS$-0Zy__^wJ`;`>vfmC$f>@wW5ilhAOv?`@}MXY2mJj#f#D z*2~+|?!GIn-$ab@ZT(5*lOYF)Q^gWBChiy|KPQ@gqZces#7v|7v}}c|Q}1~s@)LvY z<7lXpN}@jgbY8yp@O$WdTv#^Ov%!j~hjFhAv8$2NjB2u_vnTM6gUo3~P8&aqtQDHj zg6h5){CXn$nV7TO>&WhJWDKMwj@U2_rj6mqC35sVf|$7QLhFv?!Y!&h+;hy%-gQeJ zBX%<5J#@uwj>;#P7QCPuOc6yAqK!M3wP9tIKf;?`^K{QVb)t-tzg|Z!AU8)#^0@TGfl1Ei}648M>E!*_@_G^et+8{WB9!Oo*SuEFXm2+f8LJqMvMkI0ZccmG`fp2B{g_f`0k#+_Zl83 zooPxLpt0M%pW<}&B1NCDBQ+;KDd6$jCozv`=~$1lEBx$|;_-}9dtI#uQxaumek6mn^&2=m1GI;H4P!YM)@)umMt`HIiF#{0J(ZP)wucC->^jt@Y3 zzASr%Rzl0p(cZzEPgasv;<}@^mw}z9s=KR)yPKUG*hwp)>h9w1Y3y;|7MxDa?y;k- zoss5sa6-NNUe0{7SHUHX{>C3t|9$@0nhx`MdWl|HWg9%^?CrPa33gsGKwiX5sMg>L z8Sv-g;EHeks;s3m|0M5q8>P0$3%VUA7EUA4d)4s?P1$h0%IgM|9`5na`@}W73q(3dch^d?Pcs&l13k{6h5|3D!({WPw_2W1yS5+93Ti6QHdIlBCu?wk+Gor|6ye#`;qj7fpBB=}Ai6@TR}9eO)grx%|7!B@uA3zj6~b|#I@ zx?*~Ch=xF4S73vvnxyg>xuEFCXYC~yU}LOf1x5k?GU0GZM*p&dFD3){)?3V|Bz=iJ@5Pfl}#isNlE>8)yP)bWO*sy z$q0sydk)Xr?(sE|p8j$wz1-|k5jlKj1!?Yh!4w-R*X_i`@i!k@=OLzi#E4Y+&LpRum6-rc09b@1#i>17+Ay| zC#O^S?RcLd5`Xv2G`h7F4N`d=?+mEJZjn0Tcfd~i>qrp4hz7LXo z?q3UgJA1dB#@jk@99QYfBIG-3j{3uv##X;&5RU`<>}MCe_WVx-55o7wM=hYRJcXHM}wc)Aid{d&VmKk zjLV{m+*Q=)r0eBU6;-um&LjJ$*#f^GjJK(#D{e2cuA=2&J}<3Df7Z;n5MMpNSUN@_ z=~|G?LSNV(C#-izfZ3Uyd!_mXJe|5?{EQs@MU2YWa~E+To|}=}wpE_!DYpBHs%knp zwX#x!*k4bsUF!Szql>=XNkr~yOc#=!G~dmQ@veQIyg#{Ry0l!Rww=|sb6L@3`}>_B zMjw~g^O61dbc%O!CsrmL5PmlfH84Kh^$!F@DulP5y)FOBy510w;Aev^4-S zP>*YYe*kF?P*(SIdmT3U8NJoGIY#pn5F0cXsc{cf9dZ_raA%AH@T#nx) z&67XVR#mk&Fw)o1zM=lx)a2gxJv>~FCvkQ2_5{rmKJ(iaeAH6_9Y7DT0P+CmeOoUN z6$67C$20uvf*JX32f(2C@mvqJ562b4eY2{lbl&pHdtdn1pZRMq-2*!>TMz^qu*dd+ zm#r(A&Xi~D+e9Jjl`Hk&87L9jh_+_wKy8+F{a`K?WU3<{g4iIFOJ z7^lGYNt-{l&mXt#|J0T}ZreKCe*lgFPZqfFr#*lz063wg#wT-0PF&@;SN|_QxVrd& zaQ;?~@kMXvW@-#Rp9Cuph+j2;50C*a0djyipyF-k2f_;gs_q{Cp1+xvD&Wc5@f};0 zKA_8Vflu4b_TmM;%a>B-s3o?$rzxBDl0{}Sz0DwgQtfVuwbw(b%fF2$qrVOSls`$N-E#myod5uY zcoGShLn0A!!Sz9$HM@|S0cIMA3l$%Pj2|FpCWA1Ok=g(#xDF-RZ{;rwlaWIxD5iq-HwHUA^F%VF{FXauf*Xkj<{ zffAIm@qBWEmV@)uX)d92!skUquSj2&k(HBIRa4i{)Y8^5HZi?r27+(48lcDK>?wl zK8A~o+!w46W(vx)l2j}zhSc{TvGQLIqhY%q|L#M}2>~f16uXV*4_XevD|15VW6*ws z?7s)tlm8WDe+BGsa7_ZL0QqkPLQW2$gg_vaRFq($qMsPn)d_5b=AKuG<6 z;No{ehY-?_KXCE8!NtHIxcJ@RV(<@K{BCeD^an0}H@F!70~fy=T#WpIi{A|{M*qOY z?*ASH7k~H{zaL!u;a~iIaPhzL zFXRo#)K9a$Wdo{t7xcS|yfR;#CwKn3GV5jdwC9@Ap1EU!q2bEUjJm*7D*33(=d;P9 z{;2;aXTbD7N^QJKryumi8G2M4iBf0S-h0n_U3(l>wMsin%Qy_d1)R~H6vm}5sWc-rMTi4kh_B_!L?O!wZj<#-O z4Vm>2g|RraX4|sbr{RfS5!g~j#ZD;iTd3qwVk$1Ww)OqDlZhGGSzf#ESK5OR3}Qx& zGs&GBjMWQF^nL+S7aK|@%>gOgA^T;;N)6|>edL7K9OJ9+R3%5xUXlQ%q6aJMm&A7J z*D=dS)>S|CgxWf{6?z}oViTA)43aespZq**q26Q1e1e`>Q@5(VH8UIHABV1G7j{vU zX8$<~Q+I>ASVL5NnnpE-%FQUK2w&l=H@NrnYYA0NXZ+s`UHPohRf}eiHG%<)W-I5| zc*2g%7cK09LVl6NM0n(#fm>=GPavGDnG$S-kY?u;RWFbce?Xgl;p&c{!% zo!%91!NByGMuPLSH^EtRxXcK5<8#EX>1Mlxb7n>~U3{^fBgk}167W{XuIa5T{$o_n zAYK!JwVA!+=WAR)kj|6*F;nYuu(<#L=Q^B%hgVq4ty^}l2R9kdHwoo^U^Cv;Lo^fL zsG%yi%_#K)60Y7r!FBMbQSMuH=*};fJEZBx6jWV#sV0Zo^5Glr11({9M#n?QNWhaw zyu#4!v*=&(!SD3>I^VLSeIh#$WsiVQ$^LSl_hLNJ*?&{pOK6NBaB<=N8UORzpK7NF zXS?zdk|@pg?MNu|7RPRj65q$+{^)p$uiqs{mvB?w3Lbt470WTqFTSut5+HggKa{Vx z({rT{@$PxJX@KXAx_DjFp#84q4dWA19ipf6_Z|ebK&v++PXW- zBa=*<$Yma;w$X1PR|utzlym(khrV;4JsWK%$@zj8T|}TaQV*dW$f}jL88-jqk(3iT zV|}mqs}IxM8}r=yW;4eTmEBl6$@X%4-DJh_!(RXSOw%WB%n8L8e~hBX2>fWXwmu51 zio!Ot6Y93>2KUtmB%sMmSb8Te7U^RkzPOXQ6Bpp#E;AF43}Q%n7{Bk^o9xa1>Ntwbu*d$ zyl}&MKZR!-cEcBR}aiPht-JVHy4g^pG=cA6eQz?uJm4fKfyL?4VqL zk@DQ~K4S1PzLqIGPW)6}gOEG2?oh+_&1k#+#AsULuCMT^Gg4VzsS!7;($Yp=B?OE* ze_ZuPKZ)(qVSShLY}JvAPx|}%j2}^YkZak;y%EmUQQXA2AS*W0=={2A`|jQCTjfS1 z;9WTv4tn=le4loIy8YOQ!i?B#sOBA?(_62C#cZx$XAwKMAQa)8Xgd`?`H|Z_7+yHd zpsC-GIXdyGv~Sxbvl^-X3)!chj>;YxxDViIS@r~Gbi zoV_u?{K!6Wsw+!A?y<6D_kC**tZzpX5Blyii^7O~x?rP$d$ir|q7|*)t6I<()Dy^L zmyD7+J_!i*DeA$2dMLf$V0#Ef6LAFf7~zw9cjcV!?Hjj+8!kSs#nW(MU0Pe~jc%Iz z-_G(0MN@s2&3}HUi&$(E4;8xRb2J?4WgQ8lhtKBBumoKas6y{Qvl6MiBX%>oW>oQT ziaNP-ENmaq9~S|wv2H=U*yhNvFJoXbO$@Uy4zG!y9FVbHLe9>pSZ6K=Nk)I!kd@(G zB|s$Rzn=+I*XjGPPhd}S_FZmE@DFPZRb{GI`Nj0eOf@|=V6;cHcR?KT+iWfBG!be-RfVyDSxD`;A4!-Xq&bFf6Lf*Vo-4PWs#PA5_aW z9soozarN5h%613SM2@Y$R}NmrPK5iE)!`4zl`}!F0v2%JWfjFnyLWDA$XDj81RX(T z+JcOqeG>`1qt@f-ZT zOA&T&W3N$0C+LN!I?MlRnAffOJi32k|3vrK#+}nTD@A0LC9rAW*0u6WG=jm(&{yP0 zlV(3XI(W6|XeEs6yMp`ssoaRxym~pskj3Ec1=s}U7S-q+Av7*TbD}&97S)#T1%CJA z{vINs(Qu)U13LkSwR7c-wk2FYjD1xeNYg?W=VHe9Xfn=82RDUycFA1rbGr1ezHYDH zi{GUcRZ^?5MR}B|9%6P)Z`swhcPuWPMalN_q+sR_Q52 zbvD4L=&WbpfJqs#OerEPN8nCx=|SAWUAe70O~nUs{Ug$PDCFrcR{Kti+jZ3JBR}`y z`JQIhzG$a8#E1Pi#u+Ju+wY5yqK5zcycoYdI90CIQc_r^FRW_1ar(?z?dX9Y+B%c0 z=Vv_Sz*~5!kq)cM06kz$lgWbp^lH|`*6P)kvx{mG~X4xkD#VEO145jVCikepg zPCnA10j*w%@kmT>e~47K`y3PJWWkI1`Pi-(B!Kte9hLs8fXGgvQ!5cId=H!UBh=34 z-}EFqv$4z5Dp3|*yjiO8odCP|ebr{Iq)N#9cFwDlj?T}w|FC}kYwHI_`uBlO$O3c{ z(&;PD8L`y}E%^H5j$hb=U0NQQcxL5U-u7=LD}&O9RfAVblU>{PE|7iMZ{9;x!d%a} zW6ilZzlYqFzd?_J1=JDY*@);!l|6QXK=WxId4D@O@#S(7fI5d1z%I1Y2W_mdujxBn zNtxz6tPxE%P9J>x4PbJzV?Uy}n-qVzE&8+Td`^_=f52xFa=5U6$W#nos{gLwibkNB zL`m?%p7ap!@VE6WKLW#jlhrSHd%D13Vp8|r;F*ok1@EbvrZ9U zW5^qR^GOh`CugA0_v%A4^^-splVR)vf74qmHBQp+V4)^2h06wR=NG_&bQoGTGE93+ z|M;t45w7GA1_tLvXcOsvY97sJC3!OZOX;U2CZ#hR(F;T>F7?*-2R05HYC*Da zsMJZZBQipC$SG{YoJ`B4J0o_4t!k*SvA*71^)Q@2<0+qzA9cBAS%~BOo#LVV(|Y-a zA)2eiGbUwR_==ZH&Q=qTmAW;)*$xzxTqOZP0jZy@V}wgJH$O~z@tn(l%{Kp7XbVjzJCMt^dd9>E)a(6R8 zOL?z6hPYPlYfb_zLXu*PgCyEKWIkKeU27r%#&_+GZS-B_&?uvT?K-L zg5ergxL0E(i*0unkBykLd#ZCbd3n}DC5u|JbE?gAQ?iT4te*IF=7TBXnR-^6MAWN% zO#NeB$HGguV!w%A+Fe*mc(e)_c6#WAB(=B-+B)9Nt>Bpru*V;nEl%lo2FRacciWly z1v8k7rFJd(w4Fc#E+qX5wA?H-{5^_H}oM_e&ya$=J;dsx7~XlnJQ_dcM15bomr-cI@n) zz^8fS)z*cTn-$)(+iB7$mIv7IMlw(((upEmlNDG6sHMs=2c2fUl4*@Cx7_+RGOCArVcZMlWx_I_qGFj8(N#2TS-Qza$;=M3?#!% zXUWDMBZhW=Dn1kGh+v&bDqkdi3+D9N!Ka0Znxs^>2S#CZKi4;P_Cb&L1dqsqT&Z$r z94FM8r(U{Pt((N)B?A3YP9<=I1kj@Q7e@yrTcOF%a-N3un@sBG>xk_*VN}MV$OkwM8Q#tip=2{urergb)Msmc(>p6Uc5wR4=kw%FB2s#nH5gBa zDlLaX)isyf3H$ifT^r&N(VI+&9h$~@FuI%1q7kwIiM#1Qwr3pFMnr)FSaGep+0=%5 zzcq5d>u)plhMrN^7*zXg?zOFweCe|JBV`st!waa7l#DXGPwU!s!L^Uq|KHS(c(%|^ zioJt8mUn{og;orJwz^Ef(T~r;4rD_nEK@B2l^I<_SZ3aAI+HPY7GGOlUs`n_0~r(m zRpj5*cQ`dU+(K+2Xc3~bPZSk3{h-G0S${XgJcq615N$$*a&mBL(A^(!N$tOMoy$q9 z3s&b&!AAi;Y}4O}e{FufDb*tn29tVDgZzJEFlY?@s+k~{P5s000{WV(8AUWovB>}A z)e|dmLkoxf6jjCocHZ=be1nze$s7u{RlDSlj831VPYhFL%K5*WZikTmefsJz0u!f3 z0xG<-j^vydBo8$E%_gjC-e1U+?H49;4lY9vz8C55vZFmHBovsVNB610&|gqbnFfN=?o zRt?tDo;t44$1R0dv_a!ib2HmuQkM-|^s+s!j}M1jAB;|Xi8~$At=fF6h6J#N@Q=Ho z)fT0b-hVx{_M?95p==jUwV1DB?&Q{~6=+EclJ>;!95**sBu08_@ErHr!7RYe!_qiQXt?H*c@e~HsLjsr)LXjEK3I4o} z1Qbq@fX$>bXPh5#xW+@g(VDe-pfuerlT#sm-@%+%jYiAmWiwSG=bDht&?Axh6$0@o zsEt=iK*SN@J$$ubBkSOZiKvN)aR7&PZtddCvkr^vXZ|#7y}cICMu+)W_0~Ra{$bT! z|I-QMk&7dX&^EL7?D;2N%FsY~>sO=;I5Srk;cyUsNEL_mH`@v)0qO$ABmgPzP6GHw zTi6V!e}bm=4q}py7^P820z$lJh$^{6UQ^tC_z$fi60qHy22!vzN}Y}D;1d|eP6`=Q zULkVaEP!oAq{1;@Q;58`aW=l#q@ws40yij-7e%qWQ2?B7<*(UHNso3G@9pq*=W+bj1a(#}fZES+9%vOnlC7*@1yMJA16L3^roRZ0E;RU4^4=R=gnwyOhh3m8g&dt#*%S>2ShaM!+L z!YZo(%5cYA#VwiF;Wp)vXV>QPb+4G0p}=-e$SX?$O>zMrD_9>nk`6xmqK6-=I$v() z^6)^bH8U-|aVjJS>643ls*s6YO9g`eiMT04%tFTDD8m!*2is9KSq$(wYHQ~AM|w4d z7({Jwn&YQbzcxF1*K~h5hV&?cA!3OH5b1<=iGvfCp&{Sy{bDUJiabh-qf- z;X80Yy6!}2>)tYOQugC+25{1khTvjlND{!6ON2Vlx*rLp#t|7@NdR^jE?;Fpy=Mx7 zT#b?;u=Hq>04h*U;hoAX;Vq6tuIVQ!FotUH!8V~JT zx?a<(buJyxFgg{lEA@57#Q|7M_GDvR3{!@V3va%~8CVd9LrxDjy5?bT9kd3xz4gJI zn!uPZIlsLw)@A%v=yAd9`@pMaMf^=Ab$32_T(6*}z#Qx$CdB=)MB@80;{3Hdd&(7Ktb;A*^K) z{@UkZJJj^Tc-p6Zn)}*OB~910Pv38itzMcz;q)oIp>#g<@UdHyBp}9Y5wSH_2X~rz z(fq-Sfb{w12_II)moEI0pAUuQUem{lN4B;$Y-Q0`YiZu+&2>E&lAq)>2jYAr=)x;k z@PLwqvt>py;POO|THYzH)Ts|io^3m@3;^ytQ(3!pIyYp=NhLHE86y(twPPOZuf#Mak@8SPO^aN`bEq(0*}|;zT-AW_@N9PqKBhyXN{*P zuJ~EER~$VY)psF~TT2$35$VKnk_|Z$5qNXo3Ty1n$L2n-wB96qV~Qd*H0jRZOYSiZ z4_`(sH(s$AvFo49~|d29pm z#M=Eck(-ZD?Y58M*KV+$nU0SAu8cWTy2bT(7Tn)kb5VfE`xdqaZ^JCB*XycX{Gm$X z=!0YRa1U#{aMyZnJ4Qhz(5`IN*q`&!xp=t8hc3ehbjzxcT)Vsa6e#C7P>5xRbXZ1Z zow9lYTc<7|0Xx!gMQfCS$b1~88k^~Ir%1knp=t|wse5lBwq-|b{&iypr-M!4K5Ri5 zI%VFjK%~bM1yDS@fqYf-cnG94CA8+^$WO8;*mQ#59iZ) z5J%XX0VkN`Z0?&t%oc8)dGy`_FF3q1{Gk8V^tRfF%q=UU>C+sn#6+IJ+BaF;UNMET z^Gz=iEi+jD=MlQlC|^ffO@VLuX9bccK6IISbpj1MwxwKz`G0goQ#YA)Yn7#L7JT{| zzkVLFV*Na;x^Qy?mDV=kCo?Y*>rJ4uh`N%r<#wmEMEgK{0cmLNh;t9=+Trg~y6ERZ zbsAWggkYa|iXDRBJ*jjuYQf!ec65}=Rn1#P*D%7C5-Uz0U6MY0Bi(b4KDY*s!yZF5 zet^F^vl$QSTd!7YtmI3)BhywLP9RhpTQ^q@TNmKOj-n$8b?@PQn$U6YqT#PFx)uCyBP4LrzrP~{+4aRt3n^I6MZ9u*J~qAR zJ*&-20@keAJypbq_7Qb(SCHYNo_@KY`3<9sx+zNnZd0?P#@Bk_1|Cp+lmqe?r~o#J z5@^v|y=X(?4ha~zcQxufqC$!1AKj6-;)%j-sQUJi;i||ru?Tgi)d|Mxd9j(zX{ugb zTw>gGbN+O2m%$kI6xp^_H_CFhsT8e*-oBWrtH|-~o79wslKo@uXoDw==Jam12VNW2 zMOM@(nTSTtyw1E;E|;qwntfeQh2o5~y9M`c^o29UcHIQgED`L13i8WYvvEV8Bw8_MuPHDe|WM^GHIrGpj%L^BCN56$X=x)fz~;t z@Xh)2)j4FnU8=+qT~`0-y0Wt3E|{RzCHy#~#ZQC?J#<$a{>(JGij_)Kv7CWp4wmxc z+T+;qT-bNBZOIE({q~mT{*H5PXtIqr<8PQA8^Fi+P}4e^d>=3NPs>rq-2r*ix*C36 z=8@nBf44>!$xilN>UP+8;M_{vt%RMgkQ}EKaZK73n(|I!fJTTWZ=S2W#^PxI67PBa z385GZ#Vbm>awyY|{YySPWj{bmJv^>m>{qn9r*AN*1dl$>_ic`%_2)kLyI({KCkKi9oKFA5Z>#gsPvp(khbE7%5b{r3DUN&_{RmSk zPBv>b!I)+bH7FAAj=t^F`&n7YBjl{t;I{c_W1_N%#!=!PrXB>dK92 zb;`U+4G|WW?Ob%;r^5&kk{LFWvrab&nEwiONzguP_cu z>@kCK;`Kh zID@r?M=V4WV%-TmUb5H~-tsCb;)xN~Fx+=o22ToKe(&9LtG5el*2P(%IZSIx)bA?J;7Yf#<#o*|~fiYyG^7@xq=d4(ZS0sDg%bsqb;Q{;XTs%v`!VZ_R(= zBI9gyOw5PO$TGh(A(8Nwi`t-LIe=pGKRhFSBes)+1+zV~pUqUlO{DpZRud6h2&Ps- z-36_mT>YK*uBt?ucJvQ^jRCyj+_x0rWqP+9z;<+{Z;+iJe$S`rpdbACZ8wmPuXvEgxXt2jH#gFvpq0Bh(C$ z;TPns+5J9{wc4ZF98+1ES zHA@ABFAK1#Y)W2tM7Zu^>>eacoMac|w^30jVeTK@&TJ#DX7hvLSF%A=Hcb-y&AEf; zK;{Y?v=P=3P!r@v0d zTe64Go0;_ckbmbSaD@~?cY2B-SZ(y{O8xmVE61BFf!_**hu)^AE|->|rDGO$d;qYJNbkA%WLAjhbQH#X+131RcZhfS@Bc;vlFLuVW`=)A!szK3x_zW{X;Mtigj zGI`g3l5%8ViwsKzh>|e395YNAHjfN9vEK{dejc}rc(t*CoXk%m0ZubfH=bSM+V2y{ znvFK=dVS3NWCU6ey{zy>X0$4?VGVvHzHtzXWCXo{sN{IzFrwhyFx=?S1yoR)PnERbUt<;iYxz{t?JBl$NhyTS@b8TDoI9 zwHWrVMv(xVbcky|=#u1?0dTD>lzO-~_7R%xQnP${I@!LMO&!SPHkJoAG@RO`Hw zf5(UWBp^@3y4vL5$tyC_zrQ04*_UWZJVX{WDwX!U{t@>&Wm+t&!|J@TVV@*R@E!PG5>YD( zw8d(aPX5gn%V&l_-&pca_x1Z^(=-c*O5N3ef)^$4im)Q%IrFke{6#`w zmXV+EmsI;_3UbbK(~Ru3Rh24SMYzs0y1YxV+QP-cHDc8-bjlg7p69rH$LAgyUi6-% z^>^uw`UKC!hJdW`H#)TGEHz(e9`UW|YRMao2y63{-1d+wdUoTQX{t!EWTDNok)NJd z+}L-r0&aKPx;4>TRmYQ1Snu97hG+{kGY z)AKstKrc=p1;rWGcnyX7lIr_RLDEUwn;9A-1fU7D zKq06DDPQVik0J^CL?1#7yhSl5LSmeH?#Y)=5S?3nrCOVo`|Nnn2`?X-eIIZH=vuZY zPQofVzu=i(uW9$;RHm2@!LX0B!!qjWZtS{m}M&k>qpN^z_x7Gj+I6XKMlvyEoK^J<)FM>w;+rDA3 zH9g(8BnT&X>E|~1(^6tFpv|7LkZz0fH2|4@13|o|44v+e*GJ65@~?Ru;7hUUP?kog z%D1_r((JY!>V#f6OiEe;FD?Ov_qP^-%a9ZO%%UaNJ^Wi10 ztI=*B$uql)r;7+epiCZew^lvmQfS|UfpUtL$dR^S*8Xv@BNf!x5-{w(43Sg6edg$l zG!oBc1xK#~#5Me%$I2ky;bY)*P*i=$MR@-jsPSe8z&K#st%wYC%KYb!ch2q-(feN# zbfQ{uxAr{DAtXQ?46Y~3$bJGD6^C_&PISU{ZXLTXPvt;YKZ67?~h-R*Arp*PVA#gv@aaecj ziEUz3!DkW>CIW8fIO%{Pl!M$_;yi<8$-=vZ!afG!jCoDer~Hq+Qi+#Iz}#oJGxA9E z&$DrtiNlDrCveuc+eX&Vs^*XQL~q2ninN@GekF;I0pPatbM%=8y^j(*RVHCpGcj5N zqE9-r5#QXg=Y*r1uHj8luoof1cssP~_H&nQ3Cf5>hJnd&6$jWrfid~n?zfGIH{Lg5 z#rA38`>wxe2n+yR1c|y8e0}5qQ;(*&wRyYDo4|WoR)DcWOY8K;L8L$wz7_EUi50!y zw-vbnJ6b6K0~K2bbMCx$`NSR8{+Ph!yI8RKt6r9- z%-|nmpZY(>Ev2*t^ezyW7USdaK9qi@0Q37o?9=dp#v!gFpAiv#^R zSH(f!Kgazt47|Az_uC^f6OIk`eF=(#3EOtJI%I=4_c=>-*B`S9|AGs1;GpOYpHy%u6u!=p^xU231w9$T6e* zYMt{I`NV{M2Ge*H9ye`(pR9MCZ+eSnm`Z*45?=ZR@;RyTBjx?pLoI7ZMU6*bYN}TP zcZ&Fx^X8}&UKrIj@U?wD&w*?wtDK>)s?$6$yH#&|SY0mC z2Vw$&mU;)7Q%avDhc8N9l-;K~PN_vcZ4{sDgZSC%p(3BXw;jCVdXBxey5^aUY>s|? zi6W)*ZDB8E(VN;{z=jqCXgUx*WyNiPdx}jP}v;EW`sXK-AmvmP&8ypnkoQT1eL^`v1 zzp*&1$wY`*taPy^apD#s63sH)~IUa4b10mayROyV)=yNcvxNvK=VZ&T`S(g45H$U~ff3YT> zBWtdo1f)8b!e=|ahQeGN5Ma(88w_hj9Gy$8CDOYTg9Hm>gs-NqBe9Z|*-VpMVrWJ9 zY&DeO#UYW~sX5SzL-QzVq8~n63FfV~-1UF(V|`28j>5llwDfGHQAl-th&Zb)OBvyD z9)huWwO61noW|8f1pzes_lnO$u!V$=XVNg)*!*2LFbE!JKuv_4o9TaQEipQnRU@a0 z(+@Hp8wcM>F@`>Wvlv3LfI_@kJ@(xpN7q4a7ps6VDG4xc6pyW-tMpNbNhdtWn@=Rh zn~~HCULm;$J>`}f`Xw>)Q(=c6q;WC=&zptoAmB}-AJ(sbg1MF_b$D`={>yzN)w&Wl zn*P9oeZT$LfI7vws|gdT+^@yY3qE+%sk4ln+qM2!OQ8KJ1X_=Q@MG%{F=V#LgjaIL z9H*@<+mKi$cM{MEGJ0fBNbk&^m|qGBAlm{Da|;MT8d@iC`QkZrF%EUY606s+cfB zPLL|vzS-G__hqU2eID(=lM!8d{!ev0q9|}E+YXQ?NaWo&StNsgD{NMis4P-8B(rpGF86@Xv z$!m%aeKhJ#PrYHCDM%?4_z4!K^*9Y)x_)WR!sq>gudl56z1o*O@tp@< zn~ED7anvE-4c3yuq*ZkZ_$>}TI*a$k-0bT?-5;MFFjv5~s{Q?u%=b~gF?Ww{Zyfk2 zUdW9=zgcl&9&8v88`0N2bPLMJbCBeG2>LCZ2u7G6(KbmD4 z=QJC-I*lc+d9Mn#24{{ZEsGFF6MvO!8iapXcm9;MfNX(=*LXT08NK7SPOyf$+A@Dx zJn+w(L{8y110hz>`M8PPdHWai$wzlks~jt5L;6l9xCAz4$KjUPM%zYuq&9sU!XqnR zPWMFrYT|a~_$e7#m#k)%GWb1- z=!>D4ecbM4QM<*B@=|-#5v0zrxsjDTZehDe$@cVcbjhl;bbVsFEk%BMbF{KfuxdbR zaYe30mS;rOjz|Jz56WqIIla1vI!ry?1Et2>u0xvr> z5zptO>h>^CN|{HlHj?+REX9N#hOSPUpHzBSeq-ayicVT_c+zG~VCE>3-!~D{7=@r) z^>-Z+Sp6~UDjC#lRKuOl$bDyVxK7Q8%Q;St+V~3}v}Ea{FVj%RXN3g&m#2Fpx(Yct z<_|RYC`BvM*|L9Sz5|_qj$`Xf>R$es$dFM@@|lh;wqIZv{2ADL>2DYBbFUo7+W%^3 zk%8Y-u4clg6}DyJIQO9hmSMccT|yUfTAu)zVQO*rt@;Xx-(c+9TNOgJsNQ1!mH4Du z8!7Adn|UvIa@hKQeTfY~U4p47pRNKImpfHTW&ETut_ZQYfnj=b9{E5&oLrigG2CV4 z%=jyokV0v^t(uHhY4qX(J0X_X`ctUi1q|dM!!PNV-c}b3V8~98$$%73#`?-m9vV=UBKQaPq;Lr}L zhqC^{Ci4OFQPTiz@D~GPnNOg8fGq&z;2}qNS@Z@?q?sAz>Yec=*Y%)jyK%@w%FKz= zrq{4pX}OczQ_#LeD{sjqMf+y@nk!&I%EZQPlKB}O(9S;QtB-9X{hg*`YHvd~pF!cb zcdm2`f4g<2hIgqe7YmX)T*=@BEtnosQ~H#hIhl! z@+_c$QKgkV_Id-Sc`m5t?^D|+nF~7;V3~Kx?Tn?DvQmpv%ro)9r$)>sz~;_2L9`9< zedvDV(gT__^T%&RMhZrdn%77;Sc@!J6imh*B%)Gm0!@unKibNPC!KsX^&bBYnusFY zA?!$~^Me%RK9X(#gMh^!93s%EAkM+y=u-cE^|1-`5C{D{Y6yZrzpeX^Giw{Ix z5qjxWd15?>ouquu9lSK?xu1VeU?~gTHcoqQLYepTvwvz5^sV+B(OZ?4;{T@OD@|r} zdsv&pEMu{NA$W3TV|@z5#Np1Cu^(Y8o7Sh(4yOc&IMzOn~jsbBQEQp{ELT|Az#>%vSYRb26Lrgz?w7A`eGw zMEP$VdE0B(E3<9yp`9es$q;S&Cq*B>Jqfe|t@uSMRIl(C<}d=a%9n$=+KywYXwy~P zDQ7`|?)Cs=^(jcYPcRZoDX+XzHR&yytMks^6MD?FU_2Rv>Mwy)hw~4jNq9@*9tEoW zftGZ~@{L!A;gC%yf~3DXSV67j3xG2sHm~ixh=MV-0xJMUQ{db%BwP4tQ6bF|`*4eo zXqsb5&RTJiObWRk98eqmLG1@*4P5==>L8vOHatcbamCT&0f3Ag2adVesA2Wkyt)FZ zIZP63`San?h5k?SGPL}Jd)r#~@=~WB759%W?jC}sWqP?UgUp3Bu^rMSZwHbfGD|5X1H2tqN~q?I^z5p*jvf+ee^lDZ7~oZ zy+se*WDeF{wzXD#wf7A-O?lW8c`%Aj!dDZMd-u3Gj71_@4Ez@dlX$9?`VQ^7Rphc0cvf}2I7|BU-MgN=8l3wj5@4{S zx?t-Czz{<9NaT1%8uX1Nk8V$G%+vOm0>9_U?L6IbosC?X_%oq1T#vm5lfpzkSid+A z%LSvl4xX65b)Z~HF%^J{Mn|dTkF86G_dn8l^-(F=Vp=F6?`d08PJZi|AGFg4_a7Qh zot{lQ5h3+j>aF4VughlLEa)~Qo%fx!5akQeWU#t9*F`6jVkT71F=+syc5FUCbr}pm zKHXzH0b;6nzVC!X^T(-&uSq0o9Rcd_AZSTF`_f4?G^(*rc=JZMN&-A zZ*Qulz9pfa33w#+;`yD2j^TrmLeh1g-SgXXT*pno0fnEwka;cGZ>Y7ri}#JBbg z#X`fho+K>!lP$WAm%5~2wG+;Ff#1{gr?+CrX__%L_PZci@;$@V7DwGqVNB5%IAM0N zQ^@Dp;=P-flFD-Cy*%e;m^O9d#?o-QhlBsY;!MmB0PojaR7rz@Po+GU*fB&Jxeh%5d}t?Ni-r`0V$ z4W&Q6Wj5+lBPT36dio_SGwF{XUWaNVj(esq5}h9U!KL{x?9?P)0k22ZZIprEN3+rF3~`L>1?t$HRr8!Fn(f?-p$s(Uq_d&L#MD ze6u@MTpZjAr%Ka8_My5H&kzj;Wrz+z#tV;hwl4AQZVnQIreh?56Ri_ZIsS~S@VQD1 zQT2F1nZ}YvmOKB2kGajege>K*B?tz3pNY1fChsloFfzrAo@=GU@Pe89Rhu@@v}uzW zMG*3ioydM)*mvmz{~b>qNr7g9dm&8B;cEy7V~t(uV*a-TjxtOboeQiFFS-{9DM`)x zK)4pxgDl!aRa%KInkbZ1mZy$8I2>DN7y22zU97>u`o)V+V8WsC<()~+1N5C3yAr2G}U@iE>sjb0D{u`6Op#v)3GwICQ`aIov(;}e`+pV zz}AgQF=o-bEGBwdYFPu(1Bm$BFX^IWsxX$SbG&{@Z}8i`o!Cv9HaZSL(y9c55b=b3 zrbdfGKG`ZMoH%_Q8HXqC{QoL#cZ0qE)CcBWMk&yk{&62#7#s~eQGHKA6=5#vd z4)IS4zmUI3UDD1l&Dd6e$wiIt_v~)u30)|Dhb+YCiqw?jZ=?swY>gdot#VpNx65@o zZre7Es4)A&c0A?k+v%-mm!0Y|RBZh;zxOI@3p*?Mi-cs6yUu7#67oJa~d5X@+INU!)0+`g}AlINei#N-)U6oEg5>Zz1 zV+Rt{$mlX<`Q_XV8Q*)2la;KR53}8Z%~u3W_toz?3U{;(>MUx(JH17JeCcfAty0YhDFvyyi|Ikgoe>o9T&1!vNHbgC&_mE+L0hW_ zC($Kct{g)>+DiLHSCcBXEZIG}zC2NUp?Z5_Z1238EAzw`TNS?)AFJ^?WH_?6xi}Wk zYes>0fsv=1laEwiF7NsHtFF~O1g^>#H1@q=IJ|A^M<55sv{m%o;}*Go^=dXgkmLyC z;&<5-^|wA7hGp|fX2oJx?PEjaV&bS;2VTg94e?mgF*J&$PdEqI&)$N>B@oh(u zjL9OdCV(OM_MEqj+J4LpdxS*VNM(I#`8|~JczU=7MGTw z>D6atHJV=+AJjSLQF!d|$S3gBkoYXzMnqF+W+1O-;@{L{4J-}nz5!_$gzJ)gZx%2C)K0!`A~=dV;%bDqF|&Xq{|<)-u@ zu{wg|J)1fR8Z2L1ltvt@digS(MRqyd0_H4{(Z9V((_oH?!blg5CRQWl_+A8F;g{;s zK6Q!a%#kS3jys1J%kiI$kQpvvOLjPKI^EE;O47!q-hKJ#^K79E=KjvsB)SpD7I>1> z-yB7E$=7yv6Oj5~Br^~;mn@ttk*c+0vr4Md5(D_f+>ee&*Qd4?$c zV6Uw%Rd;;(a#Qc##JhxNSJHOQtVSYB=6Yw7W@W}ITDChPpJyl@QR)fLMl6~UyKjdZ znc#oFmzlPvm@ELC;{^5<;Q=dr=`}f!t%X!x05m9GaUhMN$vh84FvU;AZS$;TFa)%82^Q3aBUm2bC(5oB2(7#$%$VJ5le;Fn0|_X zjFh!mmUz-&okM*O-1WMd?R|vV0W^&=Hlfc*eGhegBy24cz6D<_ugJYLfTP?5 z0k=AUIL1Kg$cfPD%dU5GxjZW*lm`OGK41FL1K3{y8;Bi#IdBs;3_~DL!@3|xk!^(Y z(0IaqK8k6@^K5CTeAD#MIryr!*@ChI!4PoAQ$y%2A%LuqjPN>%u3L%MeI-it7PPN^ zoDNaXoGF(6@v~ifSrD3&w+ZI_*#k{Wy8VUOoBf4d<$YsgqtTh?ik#2FgaKrv19=<1 zeGyneg$1)erv)nOMvhwbo8qO}@k> zC8&BY)iSLOm#8Lq(=j6jSPT?NM;s=o^3lIdnW+L+dOTOCJvetuYU71NsvhH{U!g*yjb-|YA5jV|GMin|S? z^TzT_uu$l{7MHFjOkPv@zp86LtRFU?!hx|j3@|^ar2Y@*xeihk#BtDbBI;0{w71G5 zc=ezyE0U9HSqG#EA<;nQI2H(Eug{eLp%>Dl-u+h?0};m4#zg7_nZVE&;a|`nkR?&} z>ivOeU*W@fKYV>J_ul8!bmJFmJuV)nd@#YB)oqPN$pQV%d})T%A$#A(^&p%<$wlql z`J%Y9ONFDw9~4MEEw9#RRBIkRb=Zct8!z&?yo))d`^W9NzsQN-fn_dW@3;38`pLR_%KXimUIrR9i3$eYuix2f8k;6lG_=DcrYvby4WeSam1G8#$qUR}b~K^WBAEnfn39u!s6$ zeDh6Y6XL~=J8sIlU!wQpNzV41Y_{hT!tbla#wlS(Kj`z_Wkj)MBnhAApS2jokJj0bZt-TDA*gf9{2=~Tf(pDQw z$a}lAUs&l|C3G5`a?6WSv9dgps=0LK`H<1*&C2Bj7W&t1cSi5FDUV0L(H}GjL`l;C z@Z6D3MpDJVG)R^g#*wZUUVs0KY}oAUPK`GtBB$=9$+8~MaCIafm z1f*65WFmv-4Fb$GBAOnrfe5P+>IsQfj$(kagve8V< z^b+Bjjqvi=kCK`fh-V2mfEA@a2<>_Er^>Y6@Mqr?wi8U+i8g`&NNxN`vy5$EtvCU5 zRLzL5wWgh1Oyi5BqYACuj=BvLk6s-((h~Ljz=w0t#q@**5x-Rpgy`v}CuZxbCMFu3 zbQ-Y^(;Uo;`C$0y}pM|&2$bQcqRUe+k_GI6po&%-GJWN zss$_d*WyYw>{?G|+-*2Nz~sd(r3E_0FK-|LZyJG*9a}@GI{$^;UUvKo(|5w3z}rx# z7v&nUd~F0D19wZ04aHtmLN|*MHd18%CAfzHIlxkH0_U_Rr$paqaJXSjYa)5ptbZE( zJUIz0B7u!c93JCc$!MRbh+4_kSUwhy8Aq6~!57gW3$2$%PPYfjfU=gIW@d^$`d;8I z@W8F7;50T@#Lh{eR<^IEfppYv3RppQ%K}C8A|JB~ce* z+;fHCa2kv`26{vww-s@bXbS6RV0-m%g6YG~K1ETYz6W?u1UOVg{EYcQNf@NFQlGe; zXP@d`Vi|7v3p33dszot5MZ9?{mfXo2E&JCmbxAqWx-R+A0mVB71U1-HXv}@q*qq3r zcr*JS7|L;ht`}jRCmB|?4U$o&haJ@azREapGgHWI1|3|5WabuImfgRKlomt$yG@yoP#F5 zZ4MCj%b1^sdg+g-kzS|O9jPhS4r)Wpaon^_qs$O=550Ysa2Q&;GXQPW1(03;C8$aR z6eZlGw z>@*zK(~AysoCA*&Kwcq{Q0olc9C)%UX#R{m`9Tnfh1d@@V1D6vMRcUS%>_iW286NS z>dt1ehW13U)OY2=AR{zMtBRW`F#EkA1NGe(#<+2Ql7POlmjI%)@i@!wMw-lT13}oj zUm^(Ld_HP8&!a!wasW+0{#S{||M;8ZKXvWPt^>_kRTHO9#`j|c{oV~mC-;8h#M_nL zv%)xUqoxo}?k4D}x>KL+ujzo@#K-Mz+mEO}jf-ZMQ5~{0qvTV4bUv`jWgp5WsiKxM zxceVQoJv^bTPvdXPrXqnQgZq9L6_B$Z{O&}-SNL6!@xgmS#Qg$nQ zTg}gs~;o_dTw*$x?XLDp7uk!{s4U!Iko4pDi?)EtW`Us$_iw2Gil%=x-_(+vzFq8r($=G&#`VTw7LG+pIn2Xd&F)lSL%THfr!JQi5PyaE3b^o}psV-rOt?jwbN$ZrRGDk4SX^d9$ZA*QmAkOA&l}w0!h}ZFo8}sr=JN8EN6u0|I@u(6 zOSiVhmR2O}ET~*^&-fE|OZ3km%T79K(|w}A#Cc*=x*x?Vbnh@+;~6_7M>udPcYrBQ zHPbh?(f?xErpkhQ+40d(J(#$O+@s5Lz6s~eBelbVPNt@sNWaV~FWSLHmq_jtvm+02Kd2+>KJBtUYCcLZ}zV))#6%C(9kNn=DcLWcjDT?H%31RNsv3Dm`Hz}(r|o! zVp(P5={?pI`USov;PS3N`37p~fFGJNhZ>G!+Hf1%wa0<=lRlMwLeHm6Bao87k2O|O&a7sH?V;LcNk*uP+_S`p^c)3{`rxdv(G(y$R%F^N0{tUD1fcWc9+KNRCe^1M~cX_Bf zX-=57|0`Z4wrxcd&g1lQi)TF#o$^_K%ZkNl{0+PvKl)U z!G6sK`AZp3-~IvE@?pT1xAsG`o$k9SyoNyk69XsPIqOay;lw%EG}C-_=?#h*2of{G z117Jk;LY443A%-+u3P0wl-`F4!A&(mvN~4e*~+(+O^QEh8ePZV%M-zWJPdYN`@Tb6 zdfco#aR>FB`D3mqke%u;DEpHU>EIFVHC_0`JV$y(4V2&A0du7WYV8LDJP6leqU5)& z0*DI;I&U#`1TzqjBjoe?fsAe#ZuPeFeK5)Tw|xixl@Vrv%KTbC67)UtG7J9FM8=3s z==M6gvaOkyS`XZ_V+_YPIHGMYzni5U;}X?_4ism3*ETP)sPP+!6ajK`gF9bSQ?n&m_N`#&>%d{%@Z7gi zlOkUyt#F5OwqTFtsk!8maqJ7sKKj)Gb%fslacL(x^|UelqvGL&8;a+qLWRjOk=)wn01So$?mZ&Ls&w)V7Vd39Z+H}7ac_3D)~)=ir$VMjk9s}0XR z(xzzA6qw!Wf{ZK-w+rD2T}nLsk7We2yKc6)?*z=?A$6AJnG_Ut;iJ+C!t?L(Q?y9L zEbk7;i1siTA7%f-oZ-*On)nf&-v`N;;)fP~KGqLZI9_McOnkVL>g%R_5ap;(9!I zMum2PdQ`ul$ND8$qm5UMkk%~!<#}``5W#*j7~@tK{f5~H5E(|itV%%x((VpkeehY`1F7f!=uKB}3{Ga%C5@LS-)ow=ewU31i$m(|g%06FDybEd zKmWo^Vr)TX$HzPEJ&)!qWACq%@WYy339stg6wm-gODQFUO}u>O71SB-pb^Irc*j$Q z>l<`0e=eg&&g29$4^+5>LG_BuCyN;`>I53(e!E@%gV25G6o-kHSrMdmG54=_Ej=KW z{)P2PL37Rc5-C{z!@Uk-ef>A*`^D}))$kD$Y#`j`huFW zi~B*o*2p~^`bW25A>50&cgGWXRi-T;merX&-eTeo-Ez=h=e zbznWc`d+mka%*BAL*`Ex^|ZyLHKvJhxFda=Z2KKK?j?qxZo(ijGpG>S!mj5p=o&hC zswA3pv)D^Uc%zp@?l#yQd2aBMWOyX@>x_VJ40^gi0PX$wXAIRA_xvS5)YPFiO)NkgG^J7J4xBEcCc8>0u zx>9$RI`D_Nk+$-&d4X6WxMs6y6oXhZuXO^+{1+pT%%8%`{L={qK0nLc*9+Lq%}E?h zKoX?G=ZTBcp<+SW>-bh2ReUC+98rQPdSta)N9LUx-{5=}AB~ZA+l>12OU&2sLr(NY zivSM`U4iZgQuT_-RocOYv7JYicrpA9YQ2~I?04*uQMuFEM*RF; zCC8DbZktB?$$CoF8?UKvy%$oczA>+415XMTc%Q;$qe*Z84a;mbY-j#=`R;%B1d=Hx zA)~#KtbWDKjR7}r40x_Q?rK+7Iv{Zae%DwC`5U&$S~+BzQ_jMs8rUFCZuFSpaWoBk zZ-ELcg|ZdCO*-q9N}Kw;4EnQBj&u(cnhcU_96E%XJbTKRQt@;9MLKKkvXlD6)4esf zCH%kM?)rk!r*lyIB^%U?XeyR+vZ2t4()h$Lh125hX#XHG4f!btSh894r)=`x<-BZ9DS0pU)?>{kN>GfQvM_r_`p12N5r9EGoW;RxB_C z27a0}ea#n-?p>3aF{(HgbtB5=A0WalsMmVSwP`HYBlbLTc+ti@m80;qOabf95xOL! zR(%g5^7lFHBsyZe^ZBH;)kstRo<|F?hnO*GJD6>`L<_BV0OxE8M1WVJQ13GT2X4%x0@~#>v?a&Lpn=WE1*z0H8RBYcu$T5cbq5O zqb0vtkFkIFEm?4r^LZVK?rIZtWygf~!->3aKR578UfFNlDe)vb{x<88R=;h5J+{|v zH-11mMF(ZoI0ERGK!o-V~*y?K=e_?)i39)a? z+=phETd(>VVPMf*ljW*d@*=C^$u7Uq<7=nfsGEHyl&a@|m5N1*YY6lK&|3X`0yOGA z?M4e@ydFP>W>ps*^a<7IC91^^ntN+fE4wc^{*Ru1%HxoW_VQN*5 z25uxX3U6izb7G@CgXDR+V7#tNMD2c9@cufTE%m|!HsGvzN#1DJyQm`EWr~N&izxQwKXcu1F;KOQuo4-auo&B$?0Q5lE6X zoQguxqM@0M8JI%%Lfiav zMr3q1hs*>7cgZ-~Q@VPP8qj~gH0HwS+2u?_@hJWz%S)P_S{#Ls*I>r8!`r>jS<|MY zk5G*{*1%x0J6>iKsa{Krr*KJ%;>aug+llDxF_MMt;0p3S_SjGsuR?OQxwhox6MgE? z;YorL=t2F~y3*LF`))!`lvd2v@p{lQmvI_Q9RcKYEN~jk221qL!w|yV#Jov2atU)^ z_j^SB>NC!~NA^DbS2o#kH(Q1(I6tGMc_lI9B?|*^TlHcS&oFI@H}W$H&o)o^ z3C9&3f{t%<&Jo75(8WTS?%ynljdk!MXEHHtBEgpBzy-DCcfLkoS+o5SLt?#_a2ie9u$Y2840CLVH=+p zItSw}bB+glEr5~wqAOf{y*}F^=P-1nCp!z2@~u)&qLxE4#JUTScgIA2KYc$Rze1Y& zah%J`nZKj_R=Ka*XZ9?R9+;lTjus&*C#ED|4U&24NpuOST+>e1Q}05#@4t`Ly*3zl z{M>Z1XMy#4oSoKig67h9?r#-sT7NF1Uj~Tr%WfU?6hdVArTAM=S$9zFpR16BJ`Sxv(VJF>ZT+bTC zsLy4b2NA>Eslu;94|Nt3x6|H!LZ;;WzHDEA`(^wBD`2FLVNM;#HY-nFSdxJP&uN{1 zQKhXnzF0_Z`rzHg&hPE3SIk@?Ky;X`KSS1a3WIcOgH%p%~ZlI(@pM#RDKcsXP4YjO1`tVVg!U^>C2aw0WS`B|bc?4uMXSM$c_muEgsqZiOiXw@# z;S~~TG23PfT+`n%5w(b37$3%`F zf=OS+-^t4FpJ|>TAi{ E6*Ce({kww|SH*6+Q8#hya0!K0cWD&m^sT=Ao8)GIL z+-#+x01r_Ss1G2qCng}m)CxvER|!o)Z|w$SyzE9ETSP_+h{;%tjae)oR1;{}UGApP z@+`LFFKh+L47tZf`%JZO1_=JXDJ(T{9&jFpNn|{omkmK`Qdijd1=H67C0Np(MGB(ujtpER{bm;n z4t;oTY{#AphRNvyv8fexAg+bvH{9Ua@4&s95+>e|F zfi}f8`EB5V_q^$`Y@nbb<`Iv+5X-Es0(erhnx`{~^EXRQN9tFnVm3Tfupi#L&x2c7 zZ8SzT@2tf~yDCQ_C|mOWe|&DL^$D4i4fFDKYD8z&)=abGRNGU91a=bb9>91Ve(Kv_ z4W+)(p7F3)7>%Suwh$4}J>B6j$bmpII;(Dvq$pFJglkiJ1N;BNe4H=9XVGp^+uRhu zqa~_S%|IHf5B)*kG-kPxxT4sDGk_|`^kBOU5ZrGp*VAHO73(8~6l$8}mDq zd4V|jc2`>n%0M^v6-*6*xb&s)VNe{62Qk`puqyI!G=6XNEH5SpH3RZ?LtZRJt2o~O z!eUwp&T)pFsVB1m*5`lNkPrEvc5--EQK+0Ydfs%9_hjdlEqv$L@WlqE)|X7bPrNF! zQweR?ntFcTwJKS;k_fhI^RajccO@Z)I40a# z$Ru9^oGI_uJE4$;%^ErI=7R2xgkN@dzUc~o7GKc`aA(MLk<(^3ePx<0F7FY&!qJC% zllo`FJ|6lt_K}e%V|4N!I`i>nl(eVvBsh+Jnl>Xtim>R)`ewBn;W{_Vr$njQ0JvdXV|BwKIwpGpj zH^o}UuJO}lmb=2C3dQ=aXDCpenN#9tYxe4(c7C{(Zr2shu|(O-kiP>8c*;X`V=La^ZYbY0v>r4`A;XJ5qUq*EqAk-b=Mg4!psN%N}%-jwI5-&Go##Suc<;#3>+!6 z-cpm^a0u&AQxrYPi|8RlxIuMeyPndGmQTF~L^TcH(3Jfpz}H?4Ry*~-U<%escvL6% z1olO0HRQN}*fBW%iCJ4S<+(zYpXxYo#(4T+Ja!+*ITC?2-(IJ?W(fd`+&x|a%<5_G-a znJ(_Rt@wbZ@<1ZQCq#q4eu2Xt^i9C`f!He13b+X}Vf!e7Egyh$2x<@}Z)`$7S!K%h zJ`*vQ4R%OD0oaQD9ck=W_bB~BrEcW!wKAEYy!CqgZ0x(e#-2tzEW3nL!-6WnudWZQ z0!L>Fs0VGjdiFQJF1m~xfi3`GU9tszrKCuh@?m@AGEjg2G@`5LeStB&bEMJLrTi|1BJ{*BrxNsV(d0j~ z*7BV_hBd_VdpJKwq6T6R2O4_YyP(U$Y$$IhaQhYlj-_Ol8h;tx80cx1|6V|7i`MAS zH6Q9Qf&sS?P}iOqOu(+muQe}ukz~6l0aT$00!$jdY$Wm9wfGj-PEseaatYq{D70Hj zBs|DS@kV0s1;~h$37>XnawearxlzGJDL^r!a~$6#$Y2NaF3bLG*K!GYzlq*6WN}vO ziq`A<(+qVFG|n7m8k?1nURaR^V>khr+8ttLwu`cp6~pO96E7GKA9$HYY>Ey{4)Mk~ zmdCPwl=PNJ2%ElhYiAlYI!4-ohlPeyp^sBcLMcevRM0;xz^DV2L&F^AD41u+0f>Y& z0;67b0jhUa=TVfLn5opJDJF9P`M%qBE(gb@no6-lgy#(4{ci3y6bL*8YFD1%;WYnV z&`@A=mxKI4KPiGifHp(idEjv^Fr5L!l?k7Rm3GT7`Eb{hK>lA~A}j8wv+N&AQP|87P|%Wwm1 zx_A}r>GK?XvkNXVd(tv8^X8ng9T9cx^U3vZYaI`)Bx38XDGefITBkz-P~E+O6R5W% zd23>z+;43xgm9=79fszrl_ynb@E4N?-ms??3E5~x-=4nRU5c$5+)2FoaZX7+40Mcn zN_+IueJF9#R(vnV%^FpolP7?s<6W~4;-XoWAeZ^b=c>+VN6E)0&dFNATVU!Tb^e*G zxzD4Hn#Xz6Bi?8lg0Z>=x`gk506E0Sw%(m~!b(+#H*a9m$8kZk-q>h76E%Nx{|rF^ ztfH6Mh~m8oLEbSS0@uqR=tkYH#03d-tMXxYga;O{`6yJNmE} z-HsJbird!+iJ{BkOU;w$UwM;-;G0&%DwIW9-F_fU5WY;Xl|Lsjf z98lSG_bM4B;hE}gFLYN0{b&lMA?1b#P2O*3;}YM=T+-5dd0&K`dvXJzUGm2n znD6@GTYGGn!D2~cn2E2d!nck@lha^j=rkk`a{N7l6~j%xLgs6Lj?ATPq~Rj)f^8Gy zq1LDxD5=5V4ivmedd{CjLthNLTzep{uRW91ci2H%-K!q(qX zqoLt6h}>4?3~XQsIZa|V}#RXDo-F2zAz5FiY>wEQ2XQw zN`|LciH~Ktn7vL&6Ure?N-qvT*t^H+zNcr z+PmQ6B_sb=JRhB|Xf&TWQg^3yb4V*_eYd!eCC(|oS=*;4jZhYQ2jadZcVP!d`GY6$SV5^tSHasE6w?3!dH>Zqwet2K+SG^ zMU2TrqPOzF(@E4w{DU3SAnxmZr+Xw$9=`bChI(5vrpw}}ELt*zLi$KwLV z`v+KFzMs>QnF0Gbp~rL3taW?+&=Vai56gt~Z_DOh3V-vi4tK%OSKXFX>-ZJbLmV(v z4-kt`Rmnd(h@z4MPU$QD?yDkLnvqK4PShlT$MWdW0eA*x1O$NdG6}nwpD}pA2sEXIiyMkJkz~m)h>dUVjAQ-V0QuSTnG<>E!O2i(Oi3Z44Vac(Oepm^ zlLUTZWWGNY>;6a9N(PzWPanqAx%EEwHK5`Du~bb$wmDki@pkW5fw|FWqhce)~*YX!HD(S8{q9;Y#->SA>>f zVSW*-4T1~oRppo0c^>Ez^U_0$EBFx&TTf6Ma*=^3VMCGIGV`V?{>}8R>Ax@@CCza% zmM=1LWtQ-g&@!E$BLXiHC-ao;n7ZH+L08-V*Jk7FB5tn-)JX`Nc~qg7O*6W)q@d`X z5H*qwqtkil@+U)DG>wRY>~c5#De45yq>o<38{$Qau@^TtKl;b(m0mj@#NkRzE|#Q? z#W>&DQjZGPf6_sFLAk=n1B7*?=;tNj;Bj+CDm)Y3Sl z@6NyP7o)q_$IthC*CO`*R`U(wTH{2F^wv${#xl2ohe$u8?-)tg`RI=mO<{*wO4;JH~EO_onDT*on`Akp|KKW(rvF`Pzrlr;oD@k~&HrKVt)uGb zwtP|C-GW1q;O-tQxO;GScimWUhXBC|8VK(05Fog_1qkjAn^)iIKKJ$QbMEQBqes7Y zMvpIlgiTRZyVj~TW&P%yzj@h10bi4L`L2@^J+%CzUrK?8|2PeSY>fAz;*Uoyy?I7X zAz^zh%{Dm(0W-@~Ykd_=DXLTl_?_n?pc7Z`OJ(Nv11LNIB1yZQ&X(6VI#n!OISCIX zlm?|5N?5~=fDHchG%kNS*i2O7h zG{G-^73_4%=*+XZ8Jp0PKlwqmuzt}`MS2XD4KcP13r)D*&uvWy@)lM7m{`K91+a#oPj7#jq((tJ0QGp`_jIO! zKHS3VIFHwu{WV?TzU2__ip7}pfoWGqRNVnTy8|^q8_2-v!SO?PDFM(~oCf?trsleX z)Kl~-q~EUhVBDuvc#15*S>8efEHb5+ZqqJH5p1+CwKRdGXUa=?b}4KOYL`j7J^dYf)gHXHa7O zq`C)#-2CacZl!>h+8Bh<^#FwM-{2ExWcL9|c=sG1&olJ=Q*1qWG?{3X_t;#K2iob5 z>KmOC^=qztft5dd5{ z+4gP(C>uxnL&OfcuC;f8!2pivr8(L8&KeImnz-wp!VoN9wLwS=eJ%hd_ALhXw5ERm z(tt-h{5i7hkHK4tQBHNTP!7+&6iCoF-!8eWE?g4;7`s3L7$I`ofyYm;9=_{YrVz;b z%-2+U#w6+w2ixpcfe``amQ?;o00iK2lkoHq#BUyR5q60~qi7^6%>;XWU*PFoZJ29lc3r zl*pF8+n?xqfAVmdOvR@O=Bvs9mfHvjzw5Wp`NqprC!j)XAEhABV1bOFRZw3Fm<=>} zv(@!<=MPY+O#$OnyB`3yvkPH>qqKGhusa$~3jwDt7=U{4I=OlvxjQ+|cl)zbr~&h| z^RpRuLJD{R)-PYbxIEs4V_XeoJAw2+zwoIc>=!|R*mKYK43}xZVd!X}jg?$5Mf|-h z%Lz7cfB0~bvy%y+O{3wArch}Q5IF&?YYzd)D)$jzkPmRY97OJ;`es3!ak&k!-?s&j z&(I7$sAKJct(;uEmM8fDJ_D^A%y=807$gX=4$wjA>9+FNj~jH#0Jx@%c*eG+;E)lO#wDD80G_gcU8~rCj7U z*;ml!J`e~8h!qjvJZZiY**5%Y2BaNYmQ-moJmvu)rSMBwC+dC4CeQIjp&#!>J@>h7 zYFg{(fgcT7dVS!}?o>4=39#c7=I}v31hp2SiB~oMr5K?9EJS%JJLSL(WH`Q~sEhaDi%^JSoQwI3^Ei50-E;I=s2%Lb>Y6dJ6 zT7of=jdLHPfHC&Z6aW`%1uSCzsFm6hFgNFee^Nz5f4MT8*Mu*^CryET{;Cb?VePUT z!#hM3>+7r0S^fBulvnD^Ao?vaDeR66X_$N&hm+wKOM9DPyID^g#j}f@};IU2k*lBcH^c zB`?B136mTWhQ)rjP4ndTRFSi+)izsc=pA(?irKtT82~A};|+{^TmhLNJAn5^()VPP z`%uhZ^6~ z>GNZst2?0%0&ArJvjMaH7k=(9hZ}cu@jxoy!Yy(&$Rjr7sUGs#AJo^}1(0*U^J#jy zF$Hv4{l7oZ@DhAXwpL&SK7jy{UV?h~L~QG0x}F)B43UR>YG}@(&U2?*?p}gLY`Xhd z`ba#X!RhZoD#8p;w2S;FMLl=GaMZx~EVtjuuH?DSo-WVK6Q>5$Qb$z zaON-Vp?ADP2O_n&OhA{XX{sdQH(u$!K)p5YEz2><6Q7?e5His^KkGN3JBMp3IPmxw zI=!m5w%Cr*A2zths-3loNA9lxQsouC&Lh6dgNe_3)I^VZ+ngyri#JE8(>W^KuZ(EH zmhc9?@-&;_YjHI|fE|mfbW8T~Z4-z9<$hW|8^*C&*Kc=8P!Y?5`4aDVy1(4Qa&Nk^ ztamAl@0CV&i<10o`=kdQWeqR%8~PpqCc}hYfd7A||G||Cn*@rrvIf<%oX}YMqyF4L zewL}_hB=$jgMj>XbFvTxp6=#5QyhTsdw8O;@)-&fu>jh+5niBXwR(Ijy!TXSXl=~) zkV84|E~j9>rSFbD4hT@uY|H{D&~+f%aEbx)`i=3 z(Ypfp^*~|imrvJ1wtYZ_N1q}3eej6AfO75h=Xb$dgmeWKE-MB+kduMlD0u+DeiCW^ z%?6+pq8T7Tma5NH?wV~E^0#+%v_(mtV66LKDk;5$#lR0kTO z{h8*tNrowjvBQ#oC|f{Gs?f+kPxDN>5iN544oK*wpB1?u0J)?KUuXJv0YO@KXrSvskL5d zGl76QQ2Hms78jhDz}klrFUA3cs70O`42eOL$SOcpG|)-`XoJL{^lyJRT&qfaa|h7! z;CN$#oIz(m>2t5rzdJ{f47J^L(&}Tp$n_4eMHoDKs=uTFZ~sBi6Hmc%%JOmvAgj#& z@G6mC%o^O;k}6UXFr?u5h%r}5vk&p6nIj%d0h{L@e_eH^b=>$0aWyP*mI%i2Pu&1} z)4W`Y^ahFqJ0AOTYYZl2yvH}r!tq#Z(pS(5j!7n{y+uGBf1o}L)6 zTVYaq*CXF3MLrvl(23aM)jjYDqK61Toq7-IJ@!l15Cul{2lSuq7zLCS%1;6yf6y6_Jw^yVnCNv3 zi=~PKqfJG+CT9z;Mbdm5j;G4?5!q7pV+RC;2Y9j`_pZN;tG6qmFX`wN!k^`SroG@W z_YUwA^ zXX*khPFpbN23?01_|fp9>eLpDW7y;PNV87%*E0+L<_K_Y+K8hDfP#iNC)b;Ye zjAG#q_(qhwb9`W9gf!C!aKqJ-J$;D3x2y`>0b5svfzFl80hzLbzIVD@nFE~xnwwCC z;K#7x(*bC(tNHBSvMUgX-zo@l0RDzA3z$RnB?k;+3cXbl2H$lnl(r8p4ipvu{-%Ty zFt851>#7q&Al-_pYC2>4nQU_c&5KM)AHL_2t1+lZlB%|%A%zYGN@lUGTKc@el{kxb zukByDQ2f0_?LUtF2VFQJiksF%WZmHc&52JTZM%g9{RnFBv$rbdZK{tN`I6>MyFG>; zn|7$R13q*{SPk;>md%umK>i}$YjfgVPNAny$tk_8vnxww53QanaGR@o%ni+m%k?d^ z!M1t~MYngg7<>~Z8Wx*YO1V+BqpoE5@r4OZeR$>U zEqt(-5E{dk%1$a@4#AF9p_r&z&qx+K5S73XG+MasLUI;j96~Cqpt()c1(#fOy>Tj% zFTth9TC#hE_~HiI-;J231(HL^|84FIaffZjJUAt?u>AkrM$f3X|P4^a5M21-yoci%S_KXO~l&x`+9hUrj!oz|pjFDe6&U5}o2@rCj0(l2PwI5!oL?{3D$HQZ)PZC~v2^EId zzt0@BztGhWEso!sKCsLp6HumCd+QsK(!@8o6IT#F;~3Rd&(d2J+~_N4T3Prpv{ato z4|=R4jf4&BxkpN22>Hw~L74re_SxQf>&Xz(kE%AlTNt;xN!N;^&Y5~DhV;sQg@Cd& z#+@qME?8KgxuvVgBzAw^(c(ogzPXbVye5Lx4q_UQ-_#JsoLqhI{p!CQT7$M{d^yn8 zN-hY(v)%eqn7Xam(vmPLSXdv|U&lfET@Fh|XqY0V6l-kcSdqxlM-^ zwMCf*hZM=I+dX!oZyjtOiMbkVuO5L(fd~TNiW(wYgVE0`%060WxQX%3N&OsZV>|8t zmE@DG|7;2|qblf{k*H-KfXSbfwaeGm7;qzwilm}`P)-H#;^eLVpJemT(CV6Gf9auG2V2(ljbEK3@KG9v>zu(F`Pj}@IyXm5HOvLrdg$Y=7YBy_u0RyQezx1->ktLP!70! zibsy*1)*n5dfBPF`D-3E#P{?L-6N3i3lbZlU>=M6%xXL$0t96fWXobZLk4gmZ%o(c8@;Jd)d3WQ1Y^Kvh4EIX)Y(J0YHp+`w4E-&7q`l5Wf5KeF8#zR{Qk^K3g1 z^qae{5gr-DKeXAd_q(Yl*>6^XWaBy`1#)=^-c<%i(H67*D@G1EI^R-ZTD7lFe^cqI zdGs*v?!nmy!niuxXtz!2tgHpV5W-()<-t;m#y-RVCcUNOlI6nxxRZE&T_N)d(OXAN zKo;xVWUrK0P@`leBqI|4Fz~()MN;wEt!&MfZkVGGmMxyQWX5MdE?cQcHpRnHSvgsu zsK&6v9Sn2M5(%cdFP`Y>#Hh1fQ+%lo`8pU9_W6ZUeosmevKuy{9gPlu z&pc4opdh9Yk!QlGGAbAwjEMu?5)WYpp|NuY&PH`}J#w|e%;T9_UwAUE6LD;~gs!&R4Dii6|rDfj*08ud(r z8JVraH|uHlvVs^~B!+~O8llWKfTN;!K=M`+NA2InBL4jRzsF|&?R-GL{^R}?|Lfe+ zA2fpMKr>>qQSO;fB4Hel3;nrdAWN-T$%)u!WGmtM{$X#k!Vff*RHLMm&NO#{&_B;(Ipo(W`fTyJ+WoVS;=HhDB(E)M#@6~9+$!zPZ+B8#FjFa?3;ZH+ zJ{xV&jXZ|L@RS~%DBr@*cYWv-0*@zpB^F+Qf)h>Vx;I?yAkgdOo+nc)}NfP-Lv&$0i3&E5d0URtSYbQ0-Oql zzd98n_nLOuB7^`BI0Lt0ZmhHPBa#4)VNgbuCiPQ;-hu!>5&CqSVR#q1p9WB>tJ#Tm z?p~m8!$W0sNf{}#vNzIqnzx_xQfn)>rPW*Y=GpYZj1=qKKELJ5`Hbx7Q@K}N2vujG z8}v6pbd{&0bL?Bc^OEjdWK>FNGW*%nUZST5h%1^zDMell)F~<4OJbQpoNDzoeupc| zx$^}SjUn~Dqcgvy)f&uX5f?9W%+tQw&GETi)>{-EY;pnYXT zE#?)P?@m7FsJfGkX%+xU&B7aN;h1!x4QwB3Wq#9GtGlzqgTlA5Nx_SF!%I-~HEN%~ z_uoVHfByb=%T=KMbzac_5gqKmnuouN93;YzA=#ijLp4p>LF-~T$+fS;f!cwh$NV?& z=O>1AejYD5$Itf2_i24d)wVUv`>IeydhyH`r;U$%{xgxglgQ?WPx91BhE^ z$OFGtBzV>hM=EZ8wIlIO-all;x8RBM{W8{wI09KtEDa4BlDg;P=HVHT)+JEi79U;a z6RZ)-g62n*Ae;)yNg+f!K**iA_Z(Y}Ar*d(8J6y9@e{=HnmHYW+J={6i!mzjLf`u651l%L0cAwyznBQ-Hk39N)_{p9K51?-6vybUwveNhU&$B;jTXbsaGSYJ z)0YjujTiig)`iq=53Y0$VpR0u=P?n0zRcOdeK5Sx-9nG*#I@O5(EiX?ogKe)rV=3Y z{x{K6E#$15NZ)S}|4lGoL2Oi!?pns#ELd$P7tNW#^!D13Ua9iLTW+S{&|4D6V{L_Z z4EK>g!{#72eMJ|EA#2_@fNLshpDSl0)-+#PsT2b&l|_j>R574 zto%v7=mDPxm?$!ZN8#Vln8o>cZJ-c%6BEZ=`nXqp16cPqmgM>ki5!#l7w~rE&O=$A zh68@3nJXf_cb>fVJQhA1GpKuF0S`8T1yfgsL~xjvNBf?ddWsXKCOpvTFFmC3K?o1I zEzsoPKI@NMIq~*zxkbH=^Qom2Q8?S2l3QX`qCwrz7gfVvb+NcKH-40J4iigW;=z{s zzIJN6@e(odaQEWk=O2Qsx2n*!C5?^Ef+(Y?A>R*y&ahW=l+?yNB7_aBGZBBOMPApa5dre1$a*J03Ye|Oa?`44eRk{E9llK2;{Qd(fg#Rsf=&uG4qELv= zN^lZ}u`OaB!sDjWw11s=x?RasIKD!+Xe@igc*i+0SLL_=5M?7n`7%9^qywrty)2Wg zKt+r*4y9(+w=sP#i!To%7v-CH73b^LH`y>mXXqR*i%irl4#CRo9{YhWA{~bTE{Hh@ z0v){YaV5!&V)kNQUz}9;dQSc4W7P#xSEV?XQ~y!@}G;(6P7m z*HO!z_^3q0n|BOMjhW;dI0TTN_j~%JJGjXbl}x;=tnZm-7BFs(0o9<4n&1nLc>!q*4c`gi8m z4@E`+@8U-ZY&~mA9Byxw5)fIxX@&eK+df(S)on}~0{0`NLdwwY$VS_-<{ozQY8W`LZ$J2NOcFW)>11>;+9Sk{G~d<-dj`Fg4jr-SaC zz*_L~dDGcoSJIcO?pR+I8I?Xh5%jThXw2A499jyO(TuLrbGKyJlYz>HedRsXevz!O zN>Dd0HSSKX{2%mqD1W}~fBd%pqxpHAdwKp3-uk~?0e^n}KSLq^)wzNGk76@_zNf!$ z=KmY!1^V?rfj$2>eD8mC4gF8N{yz;d{`o%s+vNlL{{nydpSTwPnZ^YDe+fYRGd=tN zv}b|-$4q_y?Q;1)Z9e}i~Q`o-}~paf9o6n!!oWv?e+hsdg0Ig#ow;a|G#AR z&;7+e)4TXjrZD`eum0Qh)t~!|eR6>#oWu|noMgx z)r==0M6PECQO9A+yUgZE*z8${vXxk(SO}f94~G@aQ-2=%b0+>=6aT-70{rU|lDUJK ztDB3tvHc&P98GMH_}Ix=$^ZBuD2T)&Z|-2}W<}1%&CN;vmw!ksAFS=%%w5P?KG+$% znM;_PI+~dy2@50r>rK3tJ2G?~m!)xrHXd*&Z(!@q+3!Y$xiY!eEao&aK9tMalj%8O zl?T$Ldpw=o#SFm-e2RqkRzbM;@B_P!Pgo9`s!43dQz+tWYvvF8oui^6_?&c}ZXvtc zQauK(TD<0e9!^({)OoP2p6*@3vin?5jQO*W4JG#I(;Av8SZS~Hu&Stcq}VF?O}6mb4^jb=-XRFkH?9x&mQC5N0qphyE|nEpjEVS zWs1`iL!8k*PTbZaVS+zy|cC76*HzeJ1U}>gSSE?U#~hC_Gd$ zgQ`pO7B+ocoz`^*X}X};d3{(ed$tBVy8IfnMtC&MMO9rM#N~;K(Pk4pvFYlqq=Gpi z{_6cb_my&iyK&nut|77Y4VfBIr-b>GKVJPMZ>9}}v)+>wEz0VIC1btE+|HwNb?}#G zvG{^q9Ifl$s`*^ns4Y!G29v9_f@MUdsV9h4Et^d7l+(&cuRSUyj}DSQW-^RCT?9lH1?DVg6I^^c|Z;?il(Hb zWGAiWaN$RR4f#436?8|{=Ep6bsyJbJx%yddW~1@mJ!1pfp_J^-FyKDp$ZjksP)FVb zI&AVEve2~dtkX=eNa8Sf6{z35$-(^nCaPV+G-(1#TLRhIRFt6c_@14j0*2srR-1G6 zHV*cg5Wgg4_wLUOP11Y9tV|-xz9ptr5X#kKT^--FqTNa@&%3M*EG9 zP=#BQb(($sR|*#iY3}*Z5L5XG5R;F4lUeuwzJR%rC88ib3M{kVJIu3uhmPXrg}Zy!aze?MvVL29lB{{6ZMUF zielL*kPkgGe2W~9!{bt5Aq==859(1*SILs<$o)3biA^TTVQ2hzU}&C|4IigeBlX*5 z*UV6tkBV;8#;?yAMsR99jXUm|@e89%4Ls3perG8ez)|O_Ejv7%;_YK6nxPtAJCXCwGHN|5 zks$1AHNCWw#E6q5}l1J3LEqz*~m0kau~g9#y%%Z$|ll%`v~i zAZk`-@3>vwyojfc7lSu>q7l~x=FO3Ud*X7p&BaVVC{@*Aa#pJ1^kBC!{Mnr z$mY8lm-)F(j#(WVuLO@^sJPmDjRnK|JBYmEs?m%%ng_u^(fTZIIHU1~NdLZX?r4;( zpPiF=PR8dutR<_-H5AM&HSks+NJw{~CO2;rHNz%{*mhQzh1ST|I`trhws+DPMqVZY z$YMX`?HW1Aqxfb$0sSJLq*?yfp0TlU{;fgd<6-+3dq(~r8?+N`ImaDtjLs)5jNg*N z5nFQTd+I#aP>y6r3hf<*zRFY|G3g_9ggzE_b&9KAVz1-3>5{*P8vV*7`y966*GCXV z0Yw(Yi-?)_R%Gh zl!u*o1^Akcda<_mmhlgVL!6L;DNTJF(M$JtSD^#F+kj{c@7rF7N_WHuhx8gZQD)+KdF$U;OUa~&$$@Wd` zY5j?;dyDOlY_jm0@RES{KNxIiF}zdUt?m#kq!0|`jqyK&-Jg_8*;g#Nkq(YbJu){p z`GWfrjf63tGY?6#R5|nypRIFMnIFoFuJI=>t^}(-F~a4rL~}DGe^ng|vRWeQlZuQ} zR7A}mMXA=~ke*ES-(&C7P_dNEZZecdxYWgh(xnMq=`6#l`@j{Rh|~V?z~?!Ny%SY| z-OqA3YzF7iKkB(z#k1^5h-jUXR25a8zrD>|$*hrvQ#2Cz%6jRbzLK^E`I5zs<&%Pm0|R5?5x!{uzAVyEzVRl4zs|Q{F+`Jv1yW)mfGC{!iZ(*{bv60i6$J6a#@U= z5j^wh3gW)GkG8%raGcK|{7o7T)_Kya!>JFkU|;n(Qqu;Y%DYy3sMDA16z$#0 zKh(_otjE2+&Wl9_^Sv9yo?sMR<^T^nJmv8OXjEskU>*D#dyh87Kz~h?%XSqD>)_pu z4|fR|AYS+y$d;JuZW^|g++QHr@FUp2ryKbGRyVM-0~+H$>+I_2I<7Wi1>99(Ouixb zJ+du{wOf+RTM`z1%c+2J{q`V4bNdu&&Zen#@j?{z{ADZQqjd#WZM8GTP@&hC6&_-j z!Jo)mWLFaSz7(+?e!dq?o|ryO_qM2AP>E$fe6O9-1Jc)OjTn)dtu-)cu#Lh*G~8);tI}dto&eB&i>A40w36z*JA?8U{vS1`DDz-&vyh=p3}|q z2oM=A1XT2FP!Ln;b?<4n$52*Sr72c}$4)-ondgfgyo#$yQJwtKU*l>U{j?b{wXfe& z?tC!^m?Q=wpJ-ZC6NuIGRwgnx|CR)qU!Fv#)xdUG+DHXr7>HC+J;Q#79@45EbmCPl~9r9 zQ=E^r&tk_svgiD@ULvv=LH*9LtwH`zmGrh(m=ER(A%mf-=@usbO-1>;Cu%DPOjc<# z5{*s7b$;RuD7NWS=sI&Di3g+8#}HBMid6uw17 zWxQjc4fwp`UxfLLl8uR)SlkJ29NqJUz%Z+_*eqAt9?wrB0Vc?}~wOoyAM!m*gpCdA`k?;luWuTr}J` zzu`rkFM&1+>$4>Gj^|3%LhC?c>W`BcyIDuK&K0O73L?CIaFkOnHtDhT13@`lTC_CV zD~}s$Vt2E{Q0O9bMC0VPXbIpK-p z%c7dNqLxFVyp742L~gceJlAC$p|4D8F4}fH9)Y(9c;}6jv^b3wa5}M1y+fPnlVsb& z>3PgDgv)%F?q97F$>RnyGjLIZ?{*1)GJLr{<0;xzNoZ>Jvap(zaoE4+kkUlhvlP0A zac7d~QDKb!JY+_0_R~Hzj3|uGlL*GHmN;0*wEJmoI@AXP@+0+gCXtOuFG;r_zL~HA z97;$+hq74n0gl0H3^hhgFs)|IIbplmUWxFUaN7%&Trel*P?KTOJImF8okdj6twR)? zoek{vE=CGcm1;Pq{p|+*OI%KVLMd#L*lv36(cioy9Hj6RTQq%w+WeZrtx*x!A_Ws- z`-Jfd8sInn*p`=r&5K)QYz4Q4Zu5P_d{N@{8U#&)14Q~K)>Mwy!B9=uj@v;xQZ@Y& zsk2qJor7{>y^2IVDd?3s6Z%4`MFG>QRs2}Wwvhs`rkQ(@i%wcYITgX!jHZXX%uJ(PERt5#mS zDTd;2*;qHl+Qj+$5m?rit*<%*msWZ8I~x5Uh%q{OQ4%_g@@vw1P@6==U72nAuD)@S zuC+cL7nR7T!03G#p8!wFInUd|4!SddTkBZs;J{hB6j$C*02DD zMpmhO{SiR?3%1biFH>1(xog+Q%EtV?ijFhJ5FPjU#>U%Uy7 zAU+v+`L{?<{{SgLZExxe_1j}%z>f*RRUk%B24rQ;r^)k2dI_dLhDs>0;&ngxY>iF4 zB{NPWrr1acGpZRA?lWUMq2F(QwCr*L{RFJZE;OQnGKihu4UxGK}(QDftl)*itVy-n> zlO5LO71x{UkYTg32l%x;g%;1q`F2REaFT@GY{#H|;RwzoErI-`gyRto7`9v9D0W1z zRH#Ut!d`l6-)EYY!+pfMtH36sBct?cl67RaRZEIXM2YcKD>zJQsDT14iljg}nhRS@ z6;Vdj5R_y)9Kqb%+sFW{jHXSI_dva;cZzto+RY%fVF??bZVG|?Hm9=8rL6o{UZcFN zBi5icK}=#QB^iNlD7m?5*o2XfjyOoP|?j6HP=Z(faUCeAp{>to0BV zVsu!B^*^Fju`r)zQFluUb1#nLm^F=)W0h5qhh1{Z5Tp2-*HHY3B<%Z`4etc0-W$@! zqC7R4$YOHtW)5xUstn1ML(cU~8AJuit>5HWRaH4}-gJ-#xwuO|k&8>QH;5;0g7h`clDHNkWO-0CMa{@cptW+4K0Jf!D3fCGPc!G_8`M*0<8b-{UZs8=fWrH7FUB451s z-#7HM=(kk4e)?C7B+29&i)>a)~X%tRi}d9JdeRgxUxBucx%q$5Bu;VY1aw z%iCU&Ro1AB8e3!12Yd%uCahlzj{lC^!@>1;+#XI|p8u@dQ=y~dy2AU1+ha7>IjMme z6RmY?Ub{4`Cu5JcFfN`1pAk%*N;kc=_5E()YypBcvX!E$WIMvBVCpx~S{?!~K(2nl ztE@weQy%Tu1B)Jzp9>q1J~B;vPl~blg4kvDPNKiiznD>xvtpMqxlA1 zdkde+Pgv~3^m$YhesQooid3>xuG0qgFi%K0`4dS9n(BQJ{YsrI<0OPG9DWv_S;olR zW$+qsamD3DWNj`etvg!GYqL{tI0oX5tZ}3TX1#MT0RbYOT#dyKcJewz=)8B>T;@hgcXw-} z<>it~Ea60&oaN3S3_YshP5Cif#L3&IFf2Q6?pCrdMa`bkxbTdm|f+kQu`9#e&=g%jCDf5hWx>j z!h$fWzP5@--u%9I$_cD4{0la3M0AI>N`|AGu=Tn4JGURyz-b)a`9{XFK(8^MnoC@< z@3Bwaq2M-m5laO93_oPx3eR0#>p^tUe#Q5F@r9=NI+Y@Li9`7(WjwgqqH8}nr_H{8 zxM9EdPR-s(F}2KPJvtHZHErwr)m)UZrlGW2ie?4Q@ogR0;R#el2JoMyu6Uo5`|mhi z2%Eq~TzvH|YO$_4{akb;9(wf;HWUWO*x2~OIqB>JwNyx7Q4)i!gcH+XrYnCvsvC@O z_9jKp;l+C!$;%1peku1YR|r*X!ad2fB4_G$Qk6@RO+vmare=FU@6RjzGBB*;LaVCi zBa23`WwtfkNlpb%FvDiydfYjpvlKY_8*E7D7)zrpN6p#0R!%!L>7$TU+m3o{)-Dm1CLkzIdRBDG=_@Y z<&FHt>muSJ&N$J5WnB>!-uZQUz_CFNfxxn{xT}Nh@P4gm5Uwkq`A+tiv_6|I+BNP- zoZ)Zjnu%g-&B@#xGM*e)g*skMoTF zCYdl7m-$8IuFhpL7S4M@Io=zYx? zj0lkA74eEWyGupbl8_-zjzYu{>ugbn&m8qEZu0%%w5~q3eZgW!qY+vxf(23#_@>?~ z(WpU*IirK;A+(IX!2EOcl@R_~K?m=vMmd}=Wd7HFYgi)Xp1pVbVMv8Oo@4fE`Bh>} zH)}lJ))6D_8uN-Gc>C|pey*ZsE(^U%%7LlI4g7rop25-6am;%!KJ5G>LiBpIb+}os zSl{ktn$~T*D!PCc*R^Wbmu&~bYUmuL7QaMmIPSV+9#M?YT=zQ)j$w6Td%Z0AEj?n& zDu^FB5>~5vEY|#-ZL|IFoSUyj%?!(&9}0961kO7giAPOJ^=N(Lc8E=#lIuwVn z%I{+cIs4^)TMZ^v9PcSTtJaipy4y$uE83-e-S2Q30Omvm)jE2`T!>QsSsj}`u*vcI ze0KWTSc1k_*|)aNu_qE(F~sgM1{RmCr(hYP{n`44Ldg#`YlXOEe9l-iG$!;4gGWVF zj8ZFDlb^o$idI?Sao;pZ7g2iH7eE&TED^>pE$hv9xX~<+591HX7h}5Zk4uDeXppXI z{>I!HcuTKbIoBnZ5N@^kBYG0#g_CrO!Et_I6?=V)k&WPh+Cv>cp0iwP)xiAw7Ks>5>;T=YpHJz=MzEv5tkE`ZtqjXulv`EOEdCDP|KU9W zt|fk3mS{^GnD`+ja(}g1e5zFj$FUNhGB+!^f$W`b0DkO3mc+>8TWi5oBCEs&%7HH; z<<=@HoZy72H=j33v^QMRTab}hmZ)%j;Xhoja*H1o*pJRA-1S1n6Y3*;`sipMc7hks zlgsJ<)1>A0#W3CrLzWk_{OX`x;82YIL%P|%nvZXa&&82z!;xdzopGk5O{gIhXf6cEM9YH+z!H%WX21jmvWWcHp7mCAb)ch>kmU4D?l;wrsB7JLfCd{VzQ(eXaAsCb&m zdQF&9Cq1pwvCdlXzFAaB!QNhdOZfVcr=yR4zjSnDMGC%=OqsFy2yTamx{a7NhCA)y zqim)^Jr2yt`x!i4n6pdWoevc{zmB>+$t|5f?iPJk{AfjkX(J_|>UA5)$Ii(BB=IJXu7E&kw=&@sx~Wyi|L^#LoPP%zXXoPM`_KA; z9hv&BnLn_?&R!Tw`87&@AuFVxed*wjJMpT^RIdduW*!@0gqqVMv4FzPwLgBSSFFa+0JhqGtQ(PT3;N?U(4sT)RWP?-B4GhmF2M9i!7Mr%bx-_H_z76@*0dK@BNtCS36; zUnPd=qFYQP5E|=z3_~!>bP7Y^#1B#sp80817juY>_U8FgP4t2tG5V|!^7UL!6{W()nhhwZbhGw@0gW-GQZW2-PA(VsoENtYT z0RiOV2KiKxxbak`Fear^m;Bb`E?!h6xb4#e^ehW&K?^JHSAwP2XqUB^B!d{typeQ2 zTccHHLv_kViYuC|bxAntO53#0g&nzNGS`L3CLAg)(5SNsLU%;An6P2i zcwM|FUR}ZpapL;U2N8xyk#e#baR1T5-8F5)bE+|V!B9_rye#~CPIq+u$PO$jo*dP> zcF>(H&iWFTxYw6=>W9)Trr!&Ezf?5t($lSUG%(XeO~^DAK2TcJFwJmRjUdiTV++|% zDywd3i-$?vyWO5s&R|4gyNBm}D)ZXd zB(^1@rmCPKO<5e@92NF*|Sk;e6&$KUOa3gyXYq$yC(sYJzP8D)yde{M>T zr{Yr}w!kx<7~zBpk%;v_mHi}5d-EXP^fS1smt6o7*E%{JiO|_DL76&2CM1|&*94&~ z>^O%WLrsE%v^E`z;#eQne27>2*S(PRB*rv_s0(sW@7MRhZDYPU2$I9`;eVQ*4QZ!K zw)b72Hh2KlY3%1~={UCuj<$ZcgJPRzkH@FzD3b1#$BNXg-=jwvR8e@3R?n#Y?ui#E zTJs0mcv(4ODld_sY=RRke;l=W!WT81pG#Pj1Q3=Ef*7NZ4t)w=9;49O8(cLSd0*!( z+`ok0_R>)qV#g#ldjCkl5+^{bt%hTF3kwo7G?_GqeTEH;BuHd@-zl9zVVfb0l~V4U zr!7FNT+)MsSBi-t>Ga-G4#kIwYD+T&UxJII)jcP_~!L%jf$Xiv~gFNQRs}|>RVLs)CAa1i@_n` zKc1Oik7uF^<(O+DGf-?hbKxhIah7Z`px_FXJHmkbTw&N!zyxAeBVFd^z_s3MTb2vj zKg9{^J|FxJr*o1jv4FI0&xM_gz^z4o>xJTs^m%eD4ZocbhcOzMKAy4lu<+=4nT45y z-wWm6*XKMfmpbAFF>dSFvuRbTJ$yFv-qPXm&SCU9bpz9aH<^V0LkgxK^kOo~i8uSn z!n!t^Y4c7kE{3(_Y#TY8WCPV_4C+x!4=ltBGXbTC^HGV;EpE?7dM_3mvp>g37rTE3!FfD=B9col27);$v<2ib z_}Xh?qF&p#JDTW-FmU^$BY~i<;WnK%*(3YRwD^Ln+g@X#wReG~&^L6RvC5=L;DwcU zES@^AZ8q5@TSDs9-nZ_4BYW`&-WaZgH6P|7h_OV+l)1Y7B1Joup}p9UDbcvP!NTuV ze^so|-VfVC*`~px5GK9l0C_Go!(qXl+eP+t??f@oXg~;lAEjBjWp+)ZdFW*9QW`PK zw%BH_c^XLs(q%g`Mhc(3JeK2%3mC@xI~mY;tr9;*~o~Vt3@mHcN!_uFcE; ze;9km7)_(CYqxB7*|u%l?6U2rY}>YN+qP|6T~?P)@0^p9FL`(Jy~+J^{hV2A++&Vw zPBurDgaLmr5nJ-vG)x;{4I@G?liIP(J^MQ%)zs%*Y7FYdZVQCL`*)Gmoz#AG49$(7 z5lX-6jo7{=1GtXcaap)~$d+49eIo$gu_z4%IUy_L_gPvQEke(>njTx6sTM`dmF>H6 zANffoz{lTVTJnn5Y+eyNO4Bl2m~*;`41!5!kksFyMq}!=@dVp3x>|?Mr#7K@AZ>4O z;2ALo%QCwR4m+9X)i(o-VzInu?;VAt%Q6}pX=xa$!MYli-_UFOT6n~Fgg+L;GGz=F z8|7+9ae`Tuk6GI=zUB@M%;`o2XYy0O3WV{+Cw{8?{o#=eda$||@{rU>-a!s&G{2V_ zZmXwJR1wK32hZ>|i?FJ@DzuAz+%)w!4p7s>+Kc<`Wk``{?;H_TxWk)F!E0o87&Rit zu&eFpP}a(aU8n2LlbS$J9l_R}7lljCC!s{1z;{3tB&$&n?HN|FP394O-oNY1N3_j+ zlJfYH9W|R{rZ(rB{AYD9%~8wt&m(cwYb$$WXNDe3{BO_gd?K#KOBp{619 zShdN2HPZo9u7(_vEHdKEFjf~?Xx(vL8;W?Ni?L^@IrG<&kKgcX0crT0Ghn)Hn-`)o}M9gpM_H9HP0@R zpAPG6m7f2v81t8-OPcveoD`z^u-4Z}7K)5K!vcSrSm1^K<) zNd#xa_IM$tUF02;;7}PCT&qWs#@yKuHj>T?Gayl~YI)#raN2^s{2ZRsLF?}Par>cl z%s;#F%GK)wEHPk6OQhD4KL}o3-Y9u6Y()vse{(X8@Xlxi%Kcqi?~{Zp&$SES*t=Wt z>*#3r#2aL;$1z##+VF6Qj}RQu!=@@wzAb&?f9s3e>ZGO@*!lFlzl3miYH#e95upq0 zC;qsjx|7!US!ogm!y;Z@h%)+I-Syhvb})vnvXRG30IvuqCfCZ`>g-Y7^lRS^roM}6 z#p>+F^h}?ew#U)38;eD^V^F(vThZmm)WVb%U^OGG@20YB!FeaNW2r63k@SWeEa!Q6 z7?|g#XE$BB_HyWm5WeZ#K^8TJS$gd#`2CmEvgHLJxt&LG2@ZP6$||NINP@~+5efytV*2zTZkZsLcxda zAT%pNhTW~BC-6BE|8Y6X3g<>Dvv16z9=Y^k#W_FDt%6(sw^4x&6wfbRr6m+dPp%M3IJb+f%$ntMtl^xSaKR8>+H}v7RB0N3zS#opw zpC5D9{W6sd{`V)Oq{TbhB4B|WQKALEfJNHd2Z+JX$P?0la8*ZipSxnm6-NUK$vL5d z;`xOobs!VVWcs?h#qQeQ8f#2Y$7P&rSZ_og2$76v4YRq&ys*L3$BB=xVjKu+k3g=! zf`mH-u}TyAaCqihV##wls;2p3+Klzt;#-%dGvOdI6vyJR&Lq~0a=w8-ClW?$R1~vV zc>v8&*4z~+8Ou|G4%%nnR~(aWOBvi0B%<1v|J-C%`iw zN@wk|Ds6w??b`w?F;TGj3?F_Pc|e59zl`o+X^xaO2_4E;xhM5ZPQ{is9BTIbwFXw4 zjsn---n8*xt#w*UQl@lOQm6=i=dhHesrAy5W<&Gs!;yoY5HM1FW&S8Sy=VlWGBMmi zTe=l>s#VkhvpS<6M67_$K~#pE0Rb0_X{_i#75mT;nz@`&jFoKDgIM8&cT|S)kWVdm zMgLUklaCDslL1^DQ#S~`8F!4T^DM9CSD{zUa#LOA{rERT7D9%cRo#zwi&SH@@){+~ zC*odBzRy>?>o?e1L?Rdo!z56gaZYTz)8G8sSa^1L!iJrC`S>SkZp9&Jcbm+8ufvAk zoeh%T^2xfGf$e$vD}yL@;+wxv+uKuQz1}ma1JUs6ZON) zb3j9y#y42D3ZsIwwDiY|!k1`NCgBi!cX2lk2!DSe_hJRju{*diZ+9S2g4gaDPKg5?4S!E z$buSHk_tNXu1PzFL=~o)6vKs8FslY_f05lK6oFhzi%B{~ZxbDHH+#N2I)&7PXOHNY&L)=yp#6dCN@2a#Li7UpXXwt`M(Iz}dt?s&d_t6EZM}tJ; z>88u9P6!bwwNE?e`4X&$Ni!P8i^{Kn`xBlyJbQ4zeqluA-fPk!fZRiw>6j9xK*ZO0lazh$vC zGX~2!M%HsWC(b|GB`THofE#{EGyVDf5vpT8dE-Khp(_uUgm>IT-_{_w9SbQDS=)ZO zZTXw#56=BXw;}y+k-1CjHHhjx?%;G0$kv4k@(E*b?*Q4&T`Z0RoIkm9xV~YwC~l+T z&$79=$azhXz1L%F(M~94ms*e8_LqGH(;g7&AuP?(qx)4!`po^`QI62}m0UleirrFpgE z5V-8VXb%W0OiS)Gv{TAV6j2j05s>=4cb3HW0-H-Z6*Xasjd#%EKa*C&1YxtGM z9MG!>nC!a{o5g*9_5HW%G^a+O=dUkSe&86gbckWXI()if1hXKOKxG)F07A3nfn`Zal(jC zW6zk8#ilhkvvh;Xeij!qde3iMd;WT5_J3r%SmWRBZj1@oYoMOLia&X}uWc!iIr&!G z`*ysWjwK&h4x_Lx+L!zsP3_losqIgunO)ox*zJA~2f$r>Hr(=7;~tFEjs=r|o-$wX zn#`_^oP9TpFKr3n`}V%y0d;S57|kW{I`SzfygVb$P56H|6@@@C59^iug6c+};l_F+JL2-iSSDmv0iC{0_PX5Zh$1qDFLeQ(eTC_v|xt%8#{6 zHd84HDtlGs7EfBI`uGlZzP^F!`BBynYb7_?`$o|5x9PvcV0sQ3Mn7Qev@Tz*tC%y1 zIaK&;93NBNd{W)CB*%VtFmx+|=zN|x-xXg4p;iNp9q9_h<|qc+A&r)u`tNR|3E8{? z4Nn>eTa32@C3hfWY+J6*CZsYDl+}%NNYt%3Yd~WR_LeKnS~YL+>-cm{skFcAv^#)J zLGh^rnr7Uj%2uE0#+yBIp`3{YAw-M}Zhz>2(f`&mtoK4;?yKq$gV2+xLwHjMe)Q5N zrI8W_BAF#%NE*P1U?NodqQPh$k0$1v`b({Wg2*wEgmXG~fQ5vqMNqOTmeZ(CxY#eh z_Cvr^wnqn5%oq|?Cn<0NIiYAe6$-9^icb^cG3y4EK@Ea6Xdpe zWTJ*x&Q;X{KZ1}n@{3gk4p-YhSjAL<*`=9HvEuBEV)i&I5NB%Cjq}6zY5F#paF)xE$tVc1ftzR)^_a|Uab66Wy8HwS*HvpqfC2N zpRz=YE-WR1xp~=!BCaw;I?sZ1PDPtTS5K8{z?pQQrh$?Onq8zmkQnZx?k_W+_!k2L z1qsIT*xN#ob6cC0V%~{}qUk&X;OLKU*s2Y8jtqH@Z2Z(OQUr4zpP|%}QNoJTx5870 zO$y1Vmhd9R44a=ow77(rdMU+rlbaCeUdcc(vwQ=Mo5Rov9SdkrzIWjS@i{>jm})pWXfe6B9cl-iW`9&XyusOs@3C|a5WxhnU`y>IR>f0t0wiEgoS!V8~w5t zqcc?|vsN3l*3ki3yBO+mtw+JLF~OsCMZ~Dt(6&|B!Dpx(PD$McFQ`4FZ%LUAVS@E-3;}jsKvWFi_GHnDv3+@2(?5Z(^b+;~IT^1r;S+ zLxS{pJwBrx5dmYt zWfnpfT}OXx18kn*1*lydJ<_bg*ewC&VBewVf zJJ38p%IGi<(S{xDkzs}DFh0N4%bgkMX;FPpWMH^Sn$>t7eudnh2DkGSm86r+C&M&@ zVi)~%$4qFbivbujizQ#>JqqUr5dM+{^B~*G1%ub4x6b5LiD~$wJGI65{-A(fwT0F{ zS4l`ZxNggve4vy(VqvRLSp}6duus8{gu<70I$szmYo72omA%ZL;MoqKx z?e$89Lb-v9o1^2`$-g-DrGJg@-x2oK#zR1-_x3`Vw42z0;gps<>e(iiWq%4P$5Xgh zJUI~kYX)U7I$=tAkS9KbN>1{G7mKs8d9RBpGqWcox1G~GrwPeg4bm#$U@+bg`oBLw z_6#MzsmtkVJ(@&c`x=rmLEj7~6BpPk99`LX$lsFW+@`R*u@>VvF}w{wXPnp%(q}AjJh1k z>6=zk<;JO6#PoplX=Ea$A^l>M)w%bMlg83|5{5)hHXi0bdEW2!f&fX_mvr-N*!rwwzB zcylPsACfKT6(UAGB3V6Pra@B6uuHC;VIWIOC%WX-oS=rF)D)`7j2TO#PF|W&TBGbgUkFiBCXdUPRGyd1N^+TMdzVM6jQAl>Bm|4l zQWI_b`u9V}Ko_2>IEHuYH721f2xen8RRx#9MDi*OV1oX>dBr7H+9n+pNzWu`swl_) z1f4KiS-R%~pR24_i?b;=MMNl7|Yy4Gu;H{gU4uMNQ)HJ#AvDYbg8b!#6G4S&@ zVLw{yFf9~wAWN3P)0#hW@cq7t&gb#u2)>!g{$U{b(Pe@&&N$q~S!sXki(I|+QZn!Q zBIdo2+#GNDyNv)a=aZfkQG(I%rO@yVn+Auj@;{~U|Cvx#^#GU>GAI~XsW{uhFvt@! zF*5!K+jDesCgfyf`u{2Qf8fslNA>;Rp}rZde+gD`6yLMDa|s$XtZAQior;ta$*N70 zB9xOI8(cm`Qd&b15LzVJ>aXVyHmH$hu}P-%a_PnW^NaVt>HH9lq*RFs$>ZG0nZkso zlm~TVw!|ScI8rjoN{PRV6Ukx-ZXh=k*dti=yx_daCM=lujp1q;-I-?-q1y*h+;bQy zKSdkSttWw3T^5ni9SEBubefM@JqQ7zyzblzz`VNo{xS?y!{M)}LWgu>SCG3(&d|%K zNu<>&#RWhe(Lc`28}`93 z8t~EQQ65oQOVkEME&8>}XOdhs;4hcpI1fCUE#ozKkabE-P7F#_6%mh>64k&{sP9-1 zLKRUiA9C|JnURD05n8bPQ|9ArN&;S*l|jLsS2gaGQ2v?#qb6UWS=?EJ;-CrIgnI{Q zP8dS3R-0T9k%EQLGim4n8ApSLp2J;N8u*&$tAgL>7=sU<(=*nL7LQjh0FyU-!bCSO z*X+3;)e|4zr>;QN-R+(S1d6=v3mI=TVj4OTc(9X?jUyU77H5E<8==v>$;_w5fNE#< zV*sG4-azoJ@lX#0K~d9Vqxv&LehbSsxa?6j)CSs%jUXVjMM6vtQ#Y*OC!@$6!^U&I zC4z*VC*gH_h-}0+9$j`9UdQXj)JZ&&*M)2r+4o{~b5mt?X3~zyDW!NJhGTeq2$yR= zd`($x%ntzPtg5NRR9%#EdHT#+@_(DU>mDynlv0_ooqTk6)RM0>cXn=w+Nv*yjTrIb zp*3~ydMR%sOerbJM?P5Hv#R^hTmrbVVlK1flJS=OjyaxKkF>#ZEW$iks7v32XCFo! zH*Exs_%|$cR@ibE9r>}?-W}L7|IAgIZhU@Tp7H&y?W7)6O?GC?oRJt&^HBCJXK%PM z$om~7=D^ic;C5mG?Xx!W19XMDUh8PqCXn;3_|s%nOSDGrnqzRr2$YU@!qsDKxEuEL z_ZjA!G0(`3pDQOe6H$%Nn27!Uw%VIHYi*@Y@U3p48Hk{}_!1P4ZYnkY<*Mq0mVv{1 z*+t{(q_7}q#3+L$?rQ>0!*CS-^hyy|^~AkXhqqIkd$CSbV|Lbw7I}j# zN6A%{6+`y(bcT?pFXJpZC${!MDAWZTJ@gR^3KDC(L~C_Fgt5W%!H1tp+`cOADc8ee z)<;Sot{*6h9SW4D@u*X4mMf&$?ZZ?v;L2;33=T*$I4nvisvu;3W;}GmgO3`+$&917 z;MyP^@3as7==1uG&Xi(#dFm74A@!BeOM4}$+fHaA>iTv=%GDodxDz%NMDG(nL&PHX z86RE9Oil?*R1U5Cjy}Mqz1s$J!cFX5rqwUXy03*8(8I%Xu%~WJX~}B$%`Rc1+1wx& zUA2KP$QN2=EKRpIW?1=hif$%NOdRUPfKmxoOmt8%S`Pkz8vb(83p#DcU0`bcg)op= z;rBVGkR1`UL`>M0JazGO2+d4-p5G&gzb<~t+Fn4aK@n7e#C>((%{psos?R9~x<+eh z`h2|=H*;TqAXm8w8FUTRX#>tJJPTX#C{J3nF2{AaSbXFf3>HBgR@Y$ia)g-nV;Xb+ zl!Rs8jJ7cW*CG2QADYdCf2v5kkBk3riL;+gI+PYqe$+szZv4}iZoCOW7h$Q(>+O_b zHe*$%=?SCqFed+yVdCZ`BVVTbPIbLYW80ikVCNjuD@LXUmDk>=&ik|B@%o{RFI(`+ zJfBWQ0PNOEd8d+F(S`U{Of8NNN2p!&&icIyoJr`S}K?@YV9l1wkl8Htu1m<)yg6c72H#*kS2{c98*Jmik(!b~iIvq#jU0 zE$FyXMKW-&{asAtW%ihKJfH-j^w!rHVj@RQw0QeA%i$Nu;zt#nK#LE495GQR(|cY% zWSCp@%brTmn_`Qsc7qTV3(f`~RY{zc0=I*TRc<0Y><-cpiTM_KDAU&c`L8T+9(Knm zd}M)nX{{J9V~$KyNIk0((T%c+V0HiydgXu#N9EA6Ung2F%?CfR>fI{>Z?JZuLT;b>(o%8s z;UAF6%+CAcec5Sw8nvdm8m^gJL-aA!&xvT&oZL1JCr(--5E>ou_503sU!_U!PE%EJ z^L_8$fhJYw)7!fz?|R3HAq;hrBCb3*NXFJk0Utb6eCSDZV5L+2dCP+7mZ40G)he=Y z)g9F{-0?R_nT)I3>e>-!=E4aphB4_|>$Zmn^zQnZX|N0T_c0b|U31E;7?5cC&OeaA zhWdGyd9duwmxE+m3Iss+%Pj}&dMJoxYiaSjF>V1&vN_W71J3|cQEO?M{ z!1POquf*1~#^l>7O{8j+I1RKBELftl!&*@Wddd&#Lm`-cfy8uB)0h{C)ltR^_)7U|&>A3!_}2iOOY~=Nl79 zSN((3PAZI$P=%lxJxARRJ||&6TIK{qj22nK?SkOHC<-8F+d!YS8D7K`ySqQ2ersM$ zfccRqHmByhFSThkb+V`6UE_#AXg5+O1F;nw;Fi)r_fm;gXczi*Mh$Bp);X)L9K4g{ zMjl9ONy~j^2{OmI5CO;S49I=DABvhDp*Fprnl91oOy^2tO2|otOM#9NQo`NKn5|w- zEHkvcuNcZMT?Hp*g*aT@!b9FHC>mf$Q02F`%f0nn^1zeRdo|s1C+R9WZl>ghX1z`mHDqO$$%s}a>@e8v$*Or!a?gaNPnTbz^ac#H z`gCdiLyM|7%4s!d;`g!J90!x1PW%L%QFRNwog%j3pI~eRZ1TvZ)hv9_x;G1L|I#yjP6tj7!eSi1txhR<8us91MtGp5&Uo%2 zteT>4ZGxYE3>cxo>_>4~%1V*QR+QHcGhV&w@@(IZMR<@m2ApqL;YldDbD$uKxB>WE zSL?1TJ`Te>5!qUvNCh4$JqtZLLLjKzd|$MejFj>J?J1?5u$1l9$U4|HYAt!v47h>D z=U}aTG`n;4KNxT}0jKQi|Gu8~iK(#V!6JZ*p zQkOFc9L49c_dA}UB=JsQ+$7wR!+F2L{Bvq41C!@bF;ik6bYsR~YE;8n%*1eIH!UQJ zfc!MB8v^@&gJLTy6N>KLn!62J!c`ihnxJy~8LPU7gX5%=MNM7_n5j*#{hY1_Zf2DW z{<`%%wAUs#9H?QIQ-D?MLr_UL?G3%*q?FmW;@Sh_<*TXotM z+5V^#GHUV`6W)7J=Jyy%r%pT@-^l&4H}gCG$$) znm3o8oIs{6*D~yLXYfITURmghaL;V(`=p8{2u3#`?)zN@EA}@a&{u#bQQs1gpW;5| zqiQ1xtytfW&&xpK{teEH<>TfWKm88}62=t9$Ahm*y&9x(<@qVxYnke&~ zF}}K^rz#nUCg%7e?K@?ktOX|Kl z^J(73-6CRk$Rb1++g*x7G)@ALxU6)-EEzBy2*OOPT%0MV1vZdZfE?LCX3;8Mw=S0~5diYLp-$w>{+c zYchZ*K9{cMd2|IGY}955;C3lu?zqK%r*=IbG-!bgBbxZn?c86CDeE!bOl`%iCWAy`z;Ozw)&{K(2Y4)G zo47*7aH-)J4KcY=p%6G?yf2y0i^zmaNf{}vW0qx`*Kz<%Mb0tk?6R5nY}y%d!>7W2 zg@koK!B|apq)mIZwIP8>wD!8(L)$1{LzNlR(#aE+oaQp?e_M7xG~V~#@Ttr13X#l! zubpMVIB1cny&dVtkQBk8%Kg#OqIKk$AB%Trw1y1(HCX=?4F)wNZ2Wz03D&in+2BA* z(6FvzR<4JDvv|dgzKN12VpHf4wh#5&jM0YM6<3w>6oX=x!+kdq1OIkF1#@qDd%x&I z1c7!8gavb@`0&o9o zIj;SO1&*#{W|YVG)f$P=m2SitQ+_x+4j?YTN_CfYAFuj)-h%f>n2Uc476>$>gtxOe0KS?r9q1vb zY}%Xk^-`U@U{!|ZzR|bzMTS!(s1cl6n|->io7?Tin1{Pu4EI=T%PmAM(D4X34u;%y zx%AQVxwdHSC)B3*TeL?oI9QqF`cZ#brr?WWjuY8Cya+~t+WT}D&0^Pj zNgxKq_nb*8_=$_!U$}yhHk_8T+%Wz_y?c%km|5$qnqYQ~7`5tEGsEnpw4n$J99B3R zX%vJYcM{R(U+bq56S@;8f{G8%=aTsw$d|7rX0M2sm&-LgVVEXWbR&Tpy4A zRDA7bjU6j0nl_u5_iT{bj!{Z&Vx`R$rzOr7tj|HEt4N=L*x5Vxid-v|%jIZtZT^(p zZ!6s^Xa9=MnN?SiVmgx%`n3@Ht@fG9#ez{XPvmG#mOROWYtfG#FfH0rTYs46uwS zW}y!~s;DLk%!)*~F<<>8dHDbsS{53IKSJs1?hPe1qkAJiw`>qy5Jw>+h$X+E%+=p1 z0&?H%w-_k`T#DY71*j?m^{u8%WU+U34fsFG-^=GTZT^OaeA$cwFwj2&>4^0Y{od$8 z@az#AFHY1E+f6^*)?r9)!vN#}U*fmbP!b!;7j-X8WPR|*o7B6|;(_HmH-{-EC^>qS=Lza%VJHwxw%rZK4kXDq(McFCDAUa8?<13>Y z{}h@LOFB+`H(`py^#n>{VB9WLQQ*qIzfK7RYN<@aB&Lb>=>nz=f{OM7p`ZGu&3wT+ z;@FxJ5D}>)oG*gTyC7yuVt9ZxTM)PT8GVr129YMc ztZ$OI3NN3Ky!JP3u04{*e^j(zD(Cg$^LYZG~WL*(FSoR+=6=7tet_#9cgJm zj5k+XGU4FLHV17-{L&lMwZ0{EdC~7KF}NDjDZ_~|wW=jucTK2^TcG`E`F2~e+o3zc zN~AkD2rwb(I(4u?rt^%AX?6!5F%uzBh7$#2c1IgAK>}VX5~Cz1!GxSc9vfc5)dtIW z4`c)kfc?erqVUc%eJnVuw<(-*`E5apSrlEnd-SYot^R@M*4lqNX zwZ7F>cWQ^a|mfAN`FTy`HEOsj7KO@~(adS&uRrrn>X!99P;M^$6p}^vZ zZ0jj5|F5r~_}G9*8A1FnC`^L3TlvNu{X_yKm87eXYjBJ*{#DBn;A^*)6~`MDZ>&aN zrhl8P^A+&SIk$MgldqxH)_TkL;$ph^I=&*-a}m3U(nre9kiUf@kAKeIdR=wi8q5y5 zGrHOBZ`ag-cmY8SLZ&yy@d)fUJMsXwM~d6@Wiid+5@;_&i0F+YA~4mqG2ZmX{(Hn* zqNb~~#rgq7z;lb(5l$dik8o@eghRmQTT`GrSX|~!UX&ktW4BrNq8NwYYOAh`dyV)}Av)YN)w3np)YdgYb7 z&b75+8EAcdcs1yzuIbdymRVoT4ib%fW7KpN6=A?C8t*=bOKuap7u5BV*`pr5ipBD?a}Zt?*hwkn)xmSHi42t7@>jUn~wq*=k#7D>f#9 z$S+YGr&f37wy>aK)}}V|kE6>ljg(9F*@sYGJRy=uDfV@Cz05}b++}#mgk|Kc1r7!5 z`a@>{uNe=~jxV5sq^>I4(wnD;v1II^$Dkg3H6LY6oS%Dir$Ss4$Cgr}y|xFxrfDmU z{~{v(+t6TU7RLYm95w7M$F26~9sPj}epCi;O1J ziV{k%CD$JxM1WvqG3}H*1@0CnK7rQ{_a9l<;tr+Uk>qYB5*5<)0b#1wc{L^TTP~BkD_3YL;RT zr+rmlE`a8%7ria4XO>=_*Hbg+)BE8uwp>spj`VzZZ!yh|W!=RM#_d6q^Dp8Wg?Sw~ zD`*F+;li_Av4t?DdO|`r;Fm5#A>w`4%^7iCo^R*({qYLh{Az8={5X^h<#UwJn`jYu z^ADy6ISArTxf*Fokk}JGrG15E0R@o!BpK7HJBWeO3>Gr_E4r_?bhM)iuDcV8Pr4@c z(U0Mp#l-wOv-M*4IC>f2H?qEImhFNK#IIRBYn*@LV|m+FwkTtjRLM|(5TeLXbJPSy zKlSla^{&0P$pbV>8`*vh$fH{_>sl@a{jADLo1LJd@NNt+zGVds_hg|*+%2ho#j2m0 zb|Qy13#H<3pD!GZ1+QpXC8pZtB(UxBY^Fdcja~QxZiMm(7qH$d&R8jwD^={To(-Pz zHjahokVG-0IgDL4==*jug#oY{ICT5*WGhOJDMjGO4(VVijc{mukA&Ydchk(_DBB*@ zH?XGi_l1Ed-ZRNYOPZD&S;I>1FaOoTsk&#*mp>9u>Pbgqh40RB#cC6)^; z($DkUa<~LFk;XE=_(X5;P>jFTT^XLSeMxs@S{Dh=an;3T3P!dkLh>(zPg={3QVU|| ztAin>WZ;m~V&`J?45Fg~S?iXJs`SnlE{SM9-S{g|sutAXxI@oUH(4t06AvP7cWD)} z{$;z%%nU$y0KO28dhnzWtA9acdWS5eTrO>CxK4S#qfg(4jPdb%HAQ<;?DK!j3 zoEIn6JjqHd{#swh$nHWj6I<Ndn0}(OB|&@t$zPuxi+aE`i0PeuhclS_+4-3}L}fMHzCZNg z#MUVY;c53Cw#6X;G;p;2g1*H`jwj|G=Cm{3c7E-0+6||=Xq6ML1tJ*-*Xfgkm7^_d z$^_TA<;M9GI0S!6R+4d}5zq?${Y_8zAa<1_%7`VH`mT!(K|*B5h!R-ikq(?0HSQ;` znZ1(Y*2DeX4L=jWhjhM0M;(0Oxr4HBqh!H{1WCS8X^wv10ofh!UtHGh%j1nPfvcoa-g;coq32 z)B228hQ8-d`O|yuH@vVie1_5$3Z(p06($tB0)8?faq^+D&WeqLNBZ9Hh-xGTOsy{wGB)J!yk+fDAqV&_6Je$yyGVx^Kn7pZ1l_7kYEj?&rH+Azm zW~uEUp${?aR`JAVA(x_n$2Wt0mH%kVwP%Naz}eYsx^AaQJhuPH8*NWZ z8Z~E!Ljr0Jntg(u?}7Q+=t7Kk!%lJ6Rn?^%9pSFgdO;dDPAT>pVS@NEu4vS}daHSl+CsXWwZ zSeYros{a|0{#T6^uQL<4TuWn@z$ZUEA}Lv*!U!l}L)?wmeY7UIakplfx@=4Fw3pWg zMW;XtN>zi2F`~A?9tGt2H(awuz7!NIbim%EyEbeUm^SCF?XuiD0=hNQr<34RVH>7> zn2GIPZrUoMmwkr&tu2B#^5U*nR*`=2pz;8IMaCq42RLZDG{yn;v~5|`!~)pSD@k2j zCh0bx9BFXHOCA*ao9lkBH|(GuZ>lhLdK#`DUsx{&!zf)>83vO2=l){#Zn zd(0(LALE1gabPfMz{p(Bszu=UfSmr=MR%eMoIfA$dbQ#BI?O0f0mnD8~Rqx z;qGx@&bk;^o-f%T{`*8@b7+5=4K4K{g5>LYWnjS)YR8|RWxK2Mp4be8oLE5$8R|rL zrW^5F%&BL(G>o9mm($$~yuHN>>$E}%{QV-STeNFoP%DamN}QmP2>2l4k{SGOh>_p>T^o-YW^UEyi6TBd0JRL zUxk1sUJXG<_xFRfHf5EtU{ghv&OW&M3bkyVB4Cu9JOp&&TmspQekdfZ=qAoQ3j9Ww zs-j`C00ZD!VTlLtc1xx*@*Vp&QfGD}gy$m@gv0+rhG1H5zthcGmTQUejz!TVB= zsxAa=th7=F!HBpbK`*wHpV8N#^b?_9e_yA<6`FTYp-l@p8T3h=tGGIRK)V#C87@-6 z^TI~uPen%q#x6EpKO7t~VEkzKd(OIwpC&|UY}l3&j`?zolB@>)Z+I;Rgi(FgE3gJ_ zjGqIPB!*gwZc()J`468$rl->SH}eO_B4iK7lry^mw76CQzaG6G^<0#vA=U5>GZ)Sr9T!E{U+N5KAYP0MCgwMOq@zuU!G^R!i!Fe0EidGJS@dn$8ak!Uqaxm&_qi>{=F0r&H-r~ESm~29WcM3UI1``(#pk! zIZ1nL_FZ%zSk*Au49QAuSPGYbONQyzcq4|$^-s$wf~D35_uNt4ucSGf^QApS%0c?v ze`z7Ns6h*mxgz&wd%*b~v#<51xZOk1QWN2K>y(0-&Nx@R5!L69@r{E6-Vih>9QRm| z6aoU_E=DN+)t}XznYyuKT##%ypD;Opy=Iv*vp9)j;A5snfy6c(0FdQxP zzoJj#>sg~v=L6YWYZ zmO5chvNS7tOBT0YFSDA2SSEqAuEE47rH#g-J)Vel1{c7 zJ$TGQvlYa~rdFnc1p%Fd^_09Kwnd@DWfM%gLcT5G=axmXA@lDWbB_W-hyLuS-X(@) z+J2nCVfE;)3MBRQ^@i#3aA8DnR%~=AuP2A9A7eEn&ZR$BL1Sc?X1!6*Ha>P*}JaFFDUsL;HC^+bi6`{rOD;XqX7xJyfYB}} z!g;IikTvR+GJ|r}q)A9nHd7{0)Gv4BMqw;iG zo!PMHDC-mw>TNCd;D20uSE#e&zuBnapXSCT3L~MPM8M`_hNThgNSDP1o4kO5kD2p@ ze4)l*+nlvH%JDLj*|zH=>S}Dm(iHqZjJ;!wC{eer+qP}n z_G+xQZQHhO+qP}nwr$(pckOd-Zcehl+_Ni{N+p%5%pbEd^p0n!TxtW}eC1lxEE_b)pmK8Tj1joEfvKxm<^}QDs1S!joLuk_|M|;tBG6QW$Q(I zsT6o{6UHe#Ep>X9VS-O(HmJ!{Y!UKM28gAlw!z|^Imd)Yxt0>uv2lcruIz1b3j?4( zIs3c*2+SJa9?_?9`=CK!20{n-uL_|6^$RlF{UqQ zr9}C<7Jaf?1@zqv@9{qKSBvr`@mXC{@>lx{x9BdTR{&XE*U>Qa4=L$zY&dW_#U&^< zriVRU^}_ESX&mu=tVWgBuxIs3gj5VP{gfkAz_~Td9UnxGC>|&^TQ^l-Rga=3qBas6 z0pi87RyeUEoeH2lX34h5ko1Fx^y1S*aU;%4rfk zaHb1g9dvl1#&O4{8&RQ9N9_7}kQD@BF5Wlhm@7h^H!XnXs9y)A~viIvP9p*8LL^YwMx;6HpqXMbZp7a4#x;4udfQQ4*6e z7xD4`z4T^s;?n5CQLVO{o?MRkAU5NlIJTKeuGr_^PVM|QrpApYgG9Uz1GlYV&ENBX z;ooLlKLJf{?o0w&yZkFpjhv^zee>BmVadoRzxTpT^vi8_A*a$GEsl%tF zW~ytokv1nXnq=i4Dz@MAFFaTg2PbYSwDDbwVjeQ+N!^HJ?%&Yq+m=Srd%U%YnD9O= z)%`-Dat&_{T)>Z=#>V;>FwPS=cnbFg!Ab-`(@4_b=Xl8F3kBU^xONX615U0MDZqCF zYS={?ucyqU9(KS6GGq%_3FuNzS)tlgVG1P>HpJR{eha;#dM&>cCPNauAWB>>VP;fW zcT6tjByk<=t@!E||8$?iA*RsiF>NKHZs4;xn+DIv6cw2|_7*(d)@i*s1?~i#)|f`> zZvDU^*!aTVu)LPP?&Wayefj2RbPFeU3cZmB`3k?W4*UweLFs3_+Zg`FS+DCJTF>p- zqGc=Akt}KoZ8~=C(_qm!(p*kA5`795BrIS-n%=Wb%z?0mNJSGW8ZJ~ZrkHt+&1?QG z+4GpR35oVjgm(5mUFy%aZAcWE8Siefx|e2S;<5yfcrm*E3ohS9e^}p3+W3NHa*)k= z?3?=~H+RNA^3o}WYqsoDqp`frE~rnS^T#+h9IHkePwue~f48*3fj^ z{9i(|y_udlX2d9Lz&h@9b@FOO*R7@I?#UHSP`*{7yL5A=$^A156PctEX`H(3Q)p_txQ?*0H-3h=n-1^m@#Lo-9B>vBaYgXy#K4fX+^7bwM-URQv6ymZuslyY^EE5y)Hjkd2K2lON z`ZIe2c)TWyvMpPkpMnYqQF8N8{nwk-n@kMTDU)8_k=fG5l0cp&Tt2!>`a&&qdQR^Y ziAYt6;XO>V5lE<>@(b-dohGWaJMOAr^A8tRc~)!m zUtCZbMr!NBgF7fA7A>=G8CYpjQ+=OGnO<`KjfUxD);w<2zc?=#D@}oEDup?Vf+%l0 z^h)5TS)en)9FT$l4G8n!A;6nt=^0mDk(>*AyTU+gM&tekAP=DHh$cSTsUrsbKn5!s z3zGqn`C-%CHtsuo_t5crUN-qWY1ZB_w>C|ktja;R`EXcnMFaX1<`D-#fEK78Cxl5_ z@W96Pbat^V!yz3NgnOyav0U!s!x2oe79Gh@F4a#=a&u=obH;x*cqSB;65XEV`;B^W z`H;ISMS&`4ds)p2dCS$fDif?*x7Xa=O1cK0wr{GYA%Um+7WaHtO79)->j1rO+(W^j z_~vl3u9pM*2MGIAFJSQ_zWWxegcmuh7{mdl$YCJb0}_6d!XCya;eE>9(mz$yfTj&m zdShtQIZrg5mqGw?Tt19GUa!HpprtkK6bsvrpUml{4>AdAIFB zTpPaei+*;_`(c#h_dGKWjSVBBv{TdF*TI8;5Aen)E;$jTkUW*a704Z^L5~VpPT0afO1%pIltDhIGIjGlPE{Ckk(Mr?OD%P8 zdTb5{b$!gPqi=;pQyM5H5sGC5oMYx5@JtjNZXMfh0|^WP~-3aaa3&?jDnycFR8d>TsbINvI=+>2tND0=POIJ_~scc#nX>|8gAI z4;lp#SV}JqhDaegtV^#kxf(E#qo~Z>>n1J)=52S~i~)xQI|}r!E$vY8)3aq_70-do zA!Lb);LiMq8Px$RtfgjK<@*YBp<%u1^ z(~HR12C=&NtZ_0skriB5@C`27yw}EZP=EkKDH%$xB^M@FmCoWYo0{H88Dq-=hRQN{AkNR4_ zq4LkyiNrPcbNlIZxowCx3J6OMZ&5l*m#Xb7pG^7j#b%X87X^ghEaV~-ZLQsVsIU&O zS_P2d1mGoaAb0*o`M8|hVn{w_&pKE5t34c~WTQUDl_m*l4!jtZ*~UiZ%hWrH^uIBT z*D**t^!W}p0kpTIa<6{^L&{FDs`J}t?7Yu;h@@~+_+@qIvP=45y#auj@DwufB++?if(TxDfY#`KAr_QfM<=p6m6~|S#0<2{%THh$2fOHt5I1Wl?#%9 zK#BZK2IH(~f&|+D2PP3vsOc``yQrp-4wJve?EGl1-($9RP&`cJ*kRs&&n?7W@oAcpvz1ePy-qXEfDUZMwg>G?IK7EmZy7L$lW0&1~J%476}1vXijjJLv3JfieB9*qy! zL#WoEOglA3G7aeX!>yJ}>T_!Z-&D(F1iw1t<;hvY$|&uW5kn$2L*Nr85_b;J$xFm5 z)$pn#MKRGp%Jc|eyC>=Zq6O%bYKaeYH?{ab!i$hX{wdIN6T|!sTIAa>pp3#Rkf#yJ8{r_ zk)CTFX7Dq}o>M2!RHTp4g65DR0%HREa8DLfG?D>NBcDw|?en3#6a}|g>!z&uqKg%K z^`0eA@k6b_xm15=LWSqtO?#iKRm}+}jIHJcud?9O&9;8RgSfPNHMN@xK{Tbu0srGH zz6hS2j#!=8`<*1=bCzT0+DFsSa2z0p{%-2xtSZz zbSgaDV{V=64rlpeDg2|?DTD9XLtd{=o3-BNWZ<8xn_aLRt!PpBpHcy{)t;`^ASzY9h*lYWT}RxpOUkUOR! zFGbJ0_9T6MPa_?}clfU@eS=?ogFQEXhrL&UGq)NvIUkED;k$1y=HP|D8$g0ZnQs+~ zKRd0pul_y{Q%-|e2m4Ng9_Jx^2{vknyZR|mm60)$4Ivy|l|KbehHyohPm_zVg%<3% zLH>e@!35(-?_2au-H33!)g|#IAOTDnNXX=&z3B(s4SPJ#To3pdUL86|E}Vn2C^GDg zCxY|Tk-hr|vt0gft9Sj#r9A0!gQ1;Y_z{4$Z2ut;VEYf+Q0D)tP5iIp|K4Rg{I3eJ zDe}fsQXC>3kM@CDMTWXT-GLF|NCuXnj$;ikY(u> z);OqrW9YKes8vr8;!A^24<}R*XyyK*`7epT+hG7EOoCJy@Y%<@i2o=^7F90Bbc`pJ z#K6uLgH(-#IE1LW@}Q@{*FJqfEx>mFzaf1lOyf#=PMu*qS=`TEpR!G z76`kado*m7X+X=`RDi(brETs~Ypfy-Ai4jSKU*uWVSH0R8T<_|B4iN?LcgRx|)$eQA2Y45@gqqe&(b2zyQu9e731Y?N<_> zIeZ{HGPRqVJFk8{gd&h6(4~&yz8{RK5;dgOvxO^&%I9s7U>Wmz0dpxtDM*dytpb)R zZidI=;G^yzr&5*~`lHa(?&-mj^o9M}`iR$!Vkcz4ZZx%$9GAo(Zk#>$<@|G`$y=^J zt!gu&iw^k%wIR_X7FV_LvRJB0Kb(UN11Uhcs&861#93|846U-bKgl}3;}(odD%p2p z_wg)(T|fYV8585U@5}&N5u1elpV{guxhdpAwzM9=nZ5eE90Q> zzt;ejmYn{etREU8%@wQ0649&KfLThF=kB7-sLO01DNAqKrU0eO@D$*RR9=m{V{(YJ z6~V&K4P^*usEh)^b!A~_sPhFxEC01(cb)8mxp2+ zWrt zCjd%F^+k|S^oz$_v?j;O?yXpMWL_^;YYm#Ri&VYi=vn>X<`u#QAwAQWt^WzsmJTDW6xc%H3q?P}elziR8_dRN`hNU!tOf442_ z0k*8&cEx6%FZ1{KrRF1;L$jtO*4^?Ll3Pk|$s?7`9 zDoiFHP=OY`S40vs>@f|`1nxH~J^ z2LrC#bWOr{3M*IrgTB|JwpH9YD69MfJA!+*|B)XD7fRW)3wlE#s$5}Jeut4>DnV@Sb18anI(mP5 z71*gpCO@I6$)KWQz6Svj^hEdU-ZRZM{6Xl8Rp^>PR_@sw1Q7$=Vwu#c-29h4tr|^p z^~ONi6mms4g)ZyVS^DuwP$p0T=-B2QcPRubYu@EgD}JkTPu3Q?BA;G1QTT$f&T*zk zu)D_mCJk-*IWAGWqVY$)RO90`9GQ)znTVdjy9AdCqfECT*!olEFa^gqau zJk=B-KL%mSoPh~ zMq>5T-($05A=}jH@2$;3G?c8y=*(#vg)qhwx*0Dd;l2&*&7g7u=g~r1hK=aK^pkU^ zeU7)J=e`@ub)gR#9~kIbiH*8cAU#mUy`Y31m#2ckS_-Ew(a}rV4V=TBPl12EmG+xQ znh6Wa>lqi*7U1F%*5%^4pdk)E#lV29Qd)1LRyiq+Uf9tI_)v&~Y-S_l@WBXs)ZNBt ze|f!Jh&m{Vi~PGFN45zAqXx5qVP@I#QV`1^P@Zgrn;!sg_j#?FEX%}L9vTM~n^{v7 zY3}oYPD3SPjw?SvlUVYKWH41u)OHNi_1d2TLq}nwTxHmK*;@&*A`k1^rrk-D2d$MI zxfR}WIc}&wwN~k34RBK!LPn|Kl0c|{viykhWDVG>%&~nA^;1llm=*z#N{Sm9j7ou9 zL7@H_9bm=hc6E$QG5bGA(Am+fu+YtXbK#%hT;iT%3wS|ZCQNriqV+i8Fg)T!=}Srs zrRlT?ded&FW2>a^y~t${Z6aZYZ2v4)5eQnL1Zpdjf(MO*2KI2Y-1DGQ*1~xOBa#)x z-8q=c4i&UzEoZDTQroJvi096`VNKUVQ=coDjeP91{+z53ce^}`NweK?GS0@nmLdHsPSI!F zr657*rB54{uuD7moAj#j*6^k|L4a}*>=1r0SWej@o!VGVF<`e97>Bzh*{zp`V&fzS z;)kQX9Hx5=y=#T(@^0mShn?$m5Z!hxpBO)rETDlv{TpsLjqDSaauU5L++>o~^yCX( zYLCo@Vad7EQ&16JCgsMjTLpsr}1E zH6L#)6k~8e*6Q0hhaKR=_F-wkQ$SX_M*{ky_{H}sR6B|5xSnnVZ5xDbXU_8heV%ds zEhuP+*gOxY`29xOM+T7aFnJeH=~K+^Iy=xZ1xxXMVwEv|Jh&|g9)s&;SS`lI@*c7Mip>d5+fJIL&{v<@^lF3T?zi>-H} zPKHVOtK?_Vekn#ODo$o^qzRKX!(FSO?E4(wwUz zuPdTA0nx7rKDexV0k-@c-gGSf#rHOSPTe2+kT<>!#V(WpJB*hb7c1x|I1Tk0jSP7c znrFDKj-i*|q=WnT-B%%WGnUBtAePt~+RJJFTs9=RybB(W485(q2bSRocXx|!6>E59 zeA*;X6^&g=7g~p9(`2Fue4kO$D38Vl2 zLk+QW{C}t+Mvi|qlK){4G_AgCi_QM8K~A@S^o3B%frD>sfFiEM87prX)gEp-J04sZ z6-ifnJZ_c$rnlEtCE}1H#??OgfM<>S$VU<`lzA7Xyo$3ZP8j&JFeD<>B2VFtCO@r} zQw)j6a*oKKrA(ZHQtd?tl8k9mMbJ>VGx#dk z#8(uED`hg7DlJ)P}||5X26{ zQ$f{xA+JfSVr0I?0%N6lI7NLR7+P(54nz<(gj50~n^Agpi1&E@b6Nmu;0z)2fLeiS zF8Km>3|jnC{h-WB;OJ3WxKY*#Db6BmSmpuQfu~}YbbY=FpNPD3N10HamLotEoqKw8 zcC2oY{nko#00%fqpe;uJpUo_Rt7gGqHq6y0KqHpxpfHO=!C?K-0U@N|k|BF~gl)Bf z#clYVeFzK;0)T~pRR~~ppwz%^e=+)C17fQ%(s852m{e2|h@o4O_wr48zQe%Gq#6qg z)n5%crr$V%PxC$BYkk4n;vj{CHaC*L8^JIF5|pHGeqdelN1 zf`8d=KaWjN%{ITzwSS+Aa$hIoLSxijyL6uS&nTQm@rF9ZW9qBx+9okNJl|tif7R() z>P&t0#qo8%Th!@gQoK2amH6;NZ-yVVZ}Z+Wj}z^>{m_5A)jH^GQ<%@%E>bIhkgoK2 zr>Z=Ay0mny(IzMT`9o@SQ+>0hebsuQOCfPH7)=XR(`f2hC8lKvU1%=?GGs^2`%|+Ej@xAYXk2qPm=dQ zBP1Zq=i|CpE{eujwUCSM(5)h$-ECDbES|PZcd}h?G+5r+DZ5_3w!Pju=lTPB#N
;;a`_R77nu6ShZTh(6%Us@PhR#{ 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�HnVU$Nm&`Qm~>48sxOyNq*zD2P)wthBWd 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 literal 0 HcmV?d00001 From 847ebcd6fb4734f4eb0051e781196a22b559aac9 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Thu, 22 May 2025 19:48:36 +0600 Subject: [PATCH 33/41] Update .env structure --- env.example | 65 +++++++++++++++++++++++++++++++++++----------------- foundry.toml | 4 ---- 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/env.example b/env.example index c646394e..9265a035 100644 --- a/env.example +++ b/env.example @@ -1,48 +1,71 @@ -# ------------------------- -# Deploy Config -# ------------------------- +# ========================= +# Deploy Configuration +# ========================= + +# Wallet and RPC PRIVATE_KEY= RPC_URL= + +# Optional: Separate RPC URLs for multiple chains +ALFAJORES_RPC_URL= +CELO_RPC_URL= + +# Chain IDs CHAIN_ID= +ALFAJORES_CHAIN_ID= +CELO_CHAIN_ID= + -# ------------------------- +# ========================= # Contract Addresses -# ------------------------- -# Optionally set this to reuse already-deployed contracts. -# If any are left blank, they will be freshly deployed. +# ========================= +# Optional: Reuse already-deployed contracts TOKEN_ADDRESS= GLOBAL_PARAMS_ADDRESS= TREASURY_FACTORY_ADDRESS= CAMPAIGN_INFO_FACTORY_ADDRESS= -# ------------------------- -# Protocol Params -# ------------------------- + +# ========================= +# Protocol Parameters +# ========================= + PROTOCOL_ADMIN_ADDRESS= PROTOCOL_FEE_PERCENT= -# ------------------------- -# Platform Params -# ------------------------- + +# ========================= +# Platform Parameters +# ========================= + PLATFORM_NAME= PLATFORM_ADMIN_ADDRESS= PLATFORM_FEE_PERCENT= -# ------------------------- -# TOKEN Setups -# ------------------------- -# Only required if TOKEN needs to be pre-minted. +# ========================= +# Token Setup +# ========================= + +# Only required if TOKEN needs to be pre-minted TOKEN_MINT_AMOUNT= TOKEN_NAME="" TOKEN_SYMBOL="" BACKER1_ADDRESS= BACKER2_ADDRESS= -# ------------------------- + +# ========================= # Simulation -# ------------------------- -# Can be true or false only. +# ========================= + +# Set to "true" or "false" only +SIMULATE= + + +# ========================= +# Verification +# ========================= -SIMULATE= \ No newline at end of file +ETHERSCAN_API_KEY= diff --git a/foundry.toml b/foundry.toml index 1ee5c201..95ee243f 100644 --- a/foundry.toml +++ b/foundry.toml @@ -14,7 +14,3 @@ remappings = [ [rpc_endpoints] mainnet = "https://forno.celo.org/" alfajores = "https://alfajores-forno.celo-testnet.org/" - -[etherscan] -mainnet = { key = "${ETHERSCAN_API_KEY}", url = "https://api.celoscan.io/api" } -alfajores = { key = "${ETHERSCAN_API_KEY}", url = "https://api-alfajores.celoscan.io/api" } From ab5811e7385a169f7e8c3aaed2c554c7f3c2911d Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 23 May 2025 01:04:29 +0600 Subject: [PATCH 34/41] Remove unused `CampaignInfoOwnershipTransferred` --- src/CampaignInfo.sol | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/CampaignInfo.sol b/src/CampaignInfo.sol index ac16d1d7..9dc4e9af 100644 --- a/src/CampaignInfo.sol +++ b/src/CampaignInfo.sol @@ -82,16 +82,6 @@ contract CampaignInfo is address indexed platformTreasury ); - /** - * @dev Emitted when ownership of the contract is transferred. - * @param previousOwner The address of the previous owner. - * @param newOwner The address of the new owner. - */ - event CampaignInfoOwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - /** * @dev Emitted when an invalid platform update is attempted. * @param platformHash The bytes32 identifier of the platform. From 1f6791765b7aef9c88d345bd795339548b0d20e6 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 23 May 2025 01:07:43 +0600 Subject: [PATCH 35/41] Use >= `_revertIfCurrentTimeIsNotLess` and <= in `_revertIfCurrentTimeIsNotGreater` instead of >,< to improve checks --- src/utils/TimestampChecker.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/TimestampChecker.sol b/src/utils/TimestampChecker.sol index 21bb25e0..7ae687f7 100644 --- a/src/utils/TimestampChecker.sol +++ b/src/utils/TimestampChecker.sol @@ -63,7 +63,7 @@ abstract contract TimestampChecker { uint256 inputTime ) internal view virtual { uint256 currentTime = block.timestamp; - if (currentTime > inputTime) { + if (currentTime >= inputTime) { revert CurrentTimeIsGreater(inputTime, currentTime); } } @@ -76,7 +76,7 @@ abstract contract TimestampChecker { uint256 inputTime ) internal view virtual { uint256 currentTime = block.timestamp; - if (currentTime < inputTime) { + if (currentTime <= inputTime) { revert CurrentTimeIsLess(inputTime, currentTime); } } From b6945e2b533f7d9aacb156ae915f6d1bb6b199de Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 6 Jun 2025 16:56:23 +0600 Subject: [PATCH 36/41] Add helper functions - Add `removeReward` - Add `pauseTreasury` - Add `unpauseTreasury` - Add `cancelTreasury` - Receive `warpTime` in params to better simulate the timing constraints --- .../AllOrNothing/AllOrNothing.t.sol | 205 ++++++++++++++++-- 1 file changed, 185 insertions(+), 20 deletions(-) diff --git a/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol b/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol index 70819256..2b12aebb 100644 --- a/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol +++ b/test/foundry/integration/AllOrNothing/AllOrNothing.t.sol @@ -10,19 +10,35 @@ import {CampaignInfo} from "src/CampaignInfo.sol"; import {IReward} from "src/interfaces/IReward.sol"; import {LogDecoder} from "../../utils/LogDecoder.sol"; -/// @notice Common testing logic needed by all AllOrNothing integration tests. +/** + * @title AllOrNothing Integration Test Shared Contract + * @notice Common testing logic needed by all AllOrNothing integration tests. + * @dev Abstract contract that provides shared setup and helper functions for AllOrNothing treasury testing. + * Handles platform enrollment, treasury implementation registration, campaign creation, and treasury deployment. + * Also provides utility functions for pledging, refunding, fee disbursement, and withdrawals. + */ abstract contract AllOrNothing_Integration_Shared_Test is IReward, LogDecoder, Base_Test { + /// @dev Address of the created campaign contract address campaignAddress; + + /// @dev Address of the deployed treasury contract address treasuryAddress; + + /// @dev Instance of the AllOrNothing treasury contract AllOrNothing internal allOrNothing; + /// @dev Token ID for pledges that include rewards uint256 pledgeForARewardTokenId; - /// @dev Initial dependent functions setup included for AllOrNothing Integration Tests. + /** + * @notice Initial setup for AllOrNothing integration tests + * @dev Performs the complete setup sequence: platform enrollment, treasury registration, + * campaign creation, and treasury deployment. Called by inheriting test contracts. + */ function setUp() public virtual override { super.setUp(); console.log("setUp: enlistPlatform"); @@ -31,9 +47,11 @@ abstract contract AllOrNothing_Integration_Shared_Test is enlistPlatform(PLATFORM_1_HASH); console.log("enlisted platform"); + //Register Treasury Implementation registerTreasuryImplementation(PLATFORM_1_HASH); console.log("registered treasury"); + //Approve Treasury Implementation approveTreasuryImplementation(PLATFORM_1_HASH); console.log("approved treasury"); @@ -47,8 +65,9 @@ abstract contract AllOrNothing_Integration_Shared_Test is } /** - * @notice Implements enlistPlatform helper function. - * @param platformHash The platform bytes. + * @notice Enlists a platform in the protocol + * @dev Called by protocol admin to register a new platform with specified fee structure + * @param platformHash The unique identifier hash for the platform */ function enlistPlatform(bytes32 platformHash) internal { vm.startPrank(users.protocolAdminAddress); @@ -60,6 +79,11 @@ abstract contract AllOrNothing_Integration_Shared_Test is vm.stopPrank(); } + /** + * @notice Registers a treasury implementation for a platform + * @dev Called by platform admin to register AllOrNothing treasury implementation + * @param platformHash The platform identifier to register the treasury for + */ function registerTreasuryImplementation(bytes32 platformHash) internal { vm.startPrank(users.platform1AdminAddress); treasuryFactory.registerTreasuryImplementation( @@ -70,6 +94,11 @@ abstract contract AllOrNothing_Integration_Shared_Test is vm.stopPrank(); } + /** + * @notice Approves a registered treasury implementation + * @dev Called by protocol admin to approve a platform's treasury implementation + * @param platformHash The platform identifier whose treasury implementation to approve + */ function approveTreasuryImplementation(bytes32 platformHash) internal { vm.startPrank(users.protocolAdminAddress); treasuryFactory.approveTreasuryImplementation(platformHash, 0); @@ -77,8 +106,9 @@ abstract contract AllOrNothing_Integration_Shared_Test is } /** - * @notice Implements createCampaign helper function. It creates new campaign info contract - * @param platformHash The platform bytes. + * @notice Creates a new campaign for testing + * @dev Creates a campaign info contract and extracts the campaign address from emitted events + * @param platformHash The platform identifier to create the campaign on */ function createCampaign(bytes32 platformHash) internal { bytes32 identifierHash = keccak256(abi.encodePacked(platformHash)); @@ -114,7 +144,9 @@ abstract contract AllOrNothing_Integration_Shared_Test is } /** - * @notice Implements deploy helper function. It deploys treasury contract. + * @notice Deploys a treasury contract for the created campaign + * @dev Deploys AllOrNothing treasury and extracts the treasury address from emitted events + * @param platformHash The platform identifier to deploy the treasury for */ function deploy(bytes32 platformHash) internal { vm.startPrank(users.platform1AdminAddress); @@ -141,6 +173,14 @@ abstract contract AllOrNothing_Integration_Shared_Test is allOrNothing = AllOrNothing(treasuryAddress); } + /** + * @notice Adds rewards to a treasury contract + * @dev Helper function to add reward tiers to an AllOrNothing treasury + * @param caller The address that will call the addRewards function + * @param treasury The treasury contract address + * @param rewardNames Array of reward names/identifiers + * @param rewards Array of reward structs containing reward details + */ function addRewards( address caller, address treasury, @@ -153,15 +193,24 @@ abstract contract AllOrNothing_Integration_Shared_Test is } /** - * @notice Implements pledgeForAReward helper function. + * @notice Simulates pledging for a specific reward + * @dev Creates a pledge with reward selection and captures the receipt event + * @param caller The address making the pledge + * @param warpTime The block timestamp to warp to + * @param allOrNothingAddress The treasury contract address + * @param pledgeAmount The amount to pledge (automatically calculated from reward) + * @param shippingFee The shipping fee for the reward + * @param rewardName The identifier of the reward being pledged for + * @return logs The transaction logs + * @return tokenId The NFT token ID representing the pledge + * @return rewards Array of reward names associated with the pledge */ function pledgeForAReward( address caller, - address token, + uint256 warpTime, address allOrNothingAddress, uint256 pledgeAmount, uint256 shippingFee, - uint256 launchTime, bytes32 rewardName ) internal @@ -172,10 +221,10 @@ abstract contract AllOrNothing_Integration_Shared_Test is ) { vm.startPrank(caller); + vm.warp(warpTime); vm.recordLogs(); testToken.approve(allOrNothingAddress, pledgeAmount + shippingFee); - vm.warp(launchTime); bytes32[] memory reward = new bytes32[](1); reward[0] = rewardName; @@ -194,7 +243,6 @@ abstract contract AllOrNothing_Integration_Shared_Test is allOrNothingAddress ); - // (, tokenId, rewards) = abi.decode(data, (uint256, uint256, bytes32[])); (, , tokenId, rewards) = abi.decode( data, (uint256, uint256, uint256, bytes32[]) @@ -204,20 +252,26 @@ abstract contract AllOrNothing_Integration_Shared_Test is } /** - * @notice Implements pledgeWithoutAReward helper function. + * @notice Simulates pledging without selecting a reward + * @dev Creates a pledge without reward selection and captures the receipt event + * @param caller The address making the pledge + * @param warpTime The block timestamp to warp to + * @param allOrNothingAddress The treasury contract address + * @param pledgeAmount The amount to pledge + * @return logs The transaction logs + * @return tokenId The NFT token ID representing the pledge */ function pledgeWithoutAReward( address caller, - address token, + uint256 warpTime, address allOrNothingAddress, - uint256 pledgeAmount, - uint256 launchTime + uint256 pledgeAmount ) internal returns (Vm.Log[] memory logs, uint256 tokenId) { vm.startPrank(caller); + vm.warp(warpTime); vm.recordLogs(); testToken.approve(allOrNothingAddress, pledgeAmount); - vm.warp(launchTime); AllOrNothing(allOrNothingAddress).pledgeWithoutAReward( caller, @@ -241,10 +295,20 @@ abstract contract AllOrNothing_Integration_Shared_Test is } /** - * @notice Implements claimRefund helper function. + * @notice Simulates claiming a refund for a failed campaign + * @dev Claims refund for a pledge token and captures the refund event + * @param caller The address claiming the refund + * @param warpTime The block timestamp to warp to + * @param allOrNothingAddress The treasury contract address + * @param tokenId The pledge token ID to refund + * @return logs The transaction logs + * @return refundedTokenId The token ID that was refunded + * @return refundAmount The amount refunded + * @return claimer The address that claimed the refund */ function claimRefund( address caller, + uint256 warpTime, address allOrNothingAddress, uint256 tokenId ) @@ -257,6 +321,7 @@ abstract contract AllOrNothing_Integration_Shared_Test is ) { vm.startPrank(caller); + vm.warp(warpTime); vm.recordLogs(); AllOrNothing(allOrNothingAddress).claimRefund(tokenId); @@ -278,7 +343,13 @@ abstract contract AllOrNothing_Integration_Shared_Test is } /** - * @notice Implements disburseFees helper function. + * @notice Simulates fee disbursement for a successful campaign + * @dev Disburses protocol and platform fees and captures the disbursement event + * @param allOrNothingAddress The treasury contract address + * @param warpTime The block timestamp to warp to + * @return logs The transaction logs + * @return protocolShare The amount allocated to protocol fees + * @return platformShare The amount allocated to platform fees */ function disburseFees( address allOrNothingAddress, @@ -308,7 +379,13 @@ abstract contract AllOrNothing_Integration_Shared_Test is } /** - * @notice Implements withdraw helper function. + * @notice Simulates withdrawal of funds from a successful campaign + * @dev Withdraws remaining funds to campaign creator and captures the withdrawal event + * @param allOrNothingAddress The treasury contract address + * @param warpTime The block timestamp to warp to + * @return logs The transaction logs + * @return to The address that received the withdrawal + * @return amount The amount withdrawn */ function withdraw( address allOrNothingAddress, @@ -336,4 +413,92 @@ abstract contract AllOrNothing_Integration_Shared_Test is return (logs, to, amount); } + + /** + * @notice Removes a reward from a treasury contract + * @dev Helper function to remove a reward from an AllOrNothing treasury + * @param caller The address that will call the removeReward function + * @param treasury The treasury contract address + * @param rewardName The name of the reward to remove + * @return logs The transaction logs + */ + function removeReward( + address caller, + address treasury, + bytes32 rewardName + ) internal returns (Vm.Log[] memory logs) { + vm.startPrank(caller); + vm.recordLogs(); + + AllOrNothing(treasury).removeReward(rewardName); + + logs = vm.getRecordedLogs(); + vm.stopPrank(); + } + + /** + * @notice Pauses a treasury contract + * @dev Helper function to pause an AllOrNothing treasury + * @param caller The address that will call the pauseTreasury function + * @param treasury The treasury contract address + * @param reason The reason for pausing + * @return logs The transaction logs + */ + function pauseTreasury( + address caller, + address treasury, + bytes32 reason + ) internal returns (Vm.Log[] memory logs) { + vm.startPrank(caller); + vm.recordLogs(); + + AllOrNothing(treasury).pauseTreasury(reason); + + logs = vm.getRecordedLogs(); + vm.stopPrank(); + } + + /** + * @notice Unpauses a treasury contract + * @dev Helper function to unpause an AllOrNothing treasury + * @param caller The address that will call the unpauseTreasury function + * @param treasury The treasury contract address + * @param reason The reason for unpausing + * @return logs The transaction logs + */ + function unpauseTreasury( + address caller, + address treasury, + bytes32 reason + ) internal returns (Vm.Log[] memory logs) { + vm.startPrank(caller); + vm.recordLogs(); + + AllOrNothing(treasury).unpauseTreasury(reason); + + logs = vm.getRecordedLogs(); + vm.stopPrank(); + } + + /** + * @notice Cancels a treasury contract + * @dev Helper function to cancel an AllOrNothing treasury + * @param caller The address that will call the cancelTreasury function + * @param treasury The treasury contract address + * @param reason The reason for cancellation + * @return logs The transaction logs + */ + function cancelTreasury( + address caller, + address treasury, + bytes32 reason + ) internal returns (Vm.Log[] memory logs) { + vm.startPrank(caller); + vm.recordLogs(); + + AllOrNothing(treasury).cancelTreasury(reason); + + logs = vm.getRecordedLogs(); + vm.stopPrank(); + } } From 98bd8fe99fd3dc302bf14defd07f8a1bb26cce06 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 6 Jun 2025 17:32:40 +0600 Subject: [PATCH 37/41] Update git source --- docs/book.toml | 2 +- .../CampaignInfo.sol/contract.CampaignInfo.md | 17 +---------------- .../contract.CampaignInfoFactory.md | 2 +- .../GlobalParams.sol/contract.GlobalParams.md | 2 +- .../contract.TreasuryFactory.md | 2 +- .../interface.ICampaignData.md | 2 +- .../interface.ICampaignInfo.md | 2 +- .../interface.ICampaignInfoFactory.md | 2 +- .../interface.ICampaignTreasury.md | 10 +++++----- .../interface.IGlobalParams.md | 2 +- .../src/interfaces/IItem.sol/interface.IItem.md | 2 +- .../interfaces/IReward.sol/interface.IReward.md | 2 +- .../interface.ITreasuryFactory.md | 2 +- .../AllOrNothing.sol/contract.AllOrNothing.md | 2 +- .../abstract.AdminAccessChecker.md | 2 +- .../BaseTreasury.sol/abstract.BaseTreasury.md | 10 +++++----- .../abstract.CampaignAccessChecker.md | 2 +- .../src/utils/Counters.sol/library.Counters.md | 2 +- .../FiatEnabled.sol/abstract.FiatEnabled.md | 2 +- .../ItemRegistry.sol/contract.ItemRegistry.md | 2 +- .../abstract.PausableCancellable.md | 2 +- .../abstract.TimestampChecker.md | 2 +- 22 files changed, 30 insertions(+), 45 deletions(-) diff --git a/docs/book.toml b/docs/book.toml index b93f4313..d8a41741 100644 --- a/docs/book.toml +++ b/docs/book.toml @@ -7,7 +7,7 @@ no-section-label = true additional-js = ["solidity.min.js"] additional-css = ["book.css"] mathjax-support = true -git-repository-url = "https://github.com/ccprotocol/reference-client-sc" +git-repository-url = "https://github.com/ccprotocol/ccprotocol-contracts" [output.html.fold] enable = true diff --git a/docs/src/src/CampaignInfo.sol/contract.CampaignInfo.md b/docs/src/src/CampaignInfo.sol/contract.CampaignInfo.md index 7d1b5dd3..3543572d 100644 --- a/docs/src/src/CampaignInfo.sol/contract.CampaignInfo.md +++ b/docs/src/src/CampaignInfo.sol/contract.CampaignInfo.md @@ -1,5 +1,5 @@ # CampaignInfo -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/CampaignInfo.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/CampaignInfo.sol) **Inherits:** [ICampaignData](/src/interfaces/ICampaignData.sol/interface.ICampaignData.md), [ICampaignInfo](/src/interfaces/ICampaignInfo.sol/interface.ICampaignInfo.md), Ownable, [PausableCancellable](/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md), [TimestampChecker](/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md), [AdminAccessChecker](/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md), Initializable @@ -569,21 +569,6 @@ event CampaignInfoPlatformInfoUpdated(bytes32 indexed platformHash, address inde |`platformHash`|`bytes32`|The bytes32 identifier of the platform.| |`platformTreasury`|`address`|The address of the platform's treasury.| -### CampaignInfoOwnershipTransferred -*Emitted when ownership of the contract is transferred.* - - -```solidity -event CampaignInfoOwnershipTransferred(address indexed previousOwner, address indexed newOwner); -``` - -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`previousOwner`|`address`|The address of the previous owner.| -|`newOwner`|`address`|The address of the new owner.| - ## Errors ### CampaignInfoInvalidPlatformUpdate *Emitted when an invalid platform update is attempted.* diff --git a/docs/src/src/CampaignInfoFactory.sol/contract.CampaignInfoFactory.md b/docs/src/src/CampaignInfoFactory.sol/contract.CampaignInfoFactory.md index ecf45080..17439f11 100644 --- a/docs/src/src/CampaignInfoFactory.sol/contract.CampaignInfoFactory.md +++ b/docs/src/src/CampaignInfoFactory.sol/contract.CampaignInfoFactory.md @@ -1,5 +1,5 @@ # CampaignInfoFactory -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/CampaignInfoFactory.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/CampaignInfoFactory.sol) **Inherits:** Initializable, [ICampaignInfoFactory](/src/interfaces/ICampaignInfoFactory.sol/interface.ICampaignInfoFactory.md), Ownable diff --git a/docs/src/src/GlobalParams.sol/contract.GlobalParams.md b/docs/src/src/GlobalParams.sol/contract.GlobalParams.md index 2cf9e304..c48beca0 100644 --- a/docs/src/src/GlobalParams.sol/contract.GlobalParams.md +++ b/docs/src/src/GlobalParams.sol/contract.GlobalParams.md @@ -1,5 +1,5 @@ # GlobalParams -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/GlobalParams.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/GlobalParams.sol) **Inherits:** [IGlobalParams](/src/interfaces/IGlobalParams.sol/interface.IGlobalParams.md), Ownable diff --git a/docs/src/src/TreasuryFactory.sol/contract.TreasuryFactory.md b/docs/src/src/TreasuryFactory.sol/contract.TreasuryFactory.md index 7d26317c..17455ce4 100644 --- a/docs/src/src/TreasuryFactory.sol/contract.TreasuryFactory.md +++ b/docs/src/src/TreasuryFactory.sol/contract.TreasuryFactory.md @@ -1,5 +1,5 @@ # TreasuryFactory -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/TreasuryFactory.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/TreasuryFactory.sol) **Inherits:** [ITreasuryFactory](/src/interfaces/ITreasuryFactory.sol/interface.ITreasuryFactory.md), [AdminAccessChecker](/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md) diff --git a/docs/src/src/interfaces/ICampaignData.sol/interface.ICampaignData.md b/docs/src/src/interfaces/ICampaignData.sol/interface.ICampaignData.md index 00944837..c159c65d 100644 --- a/docs/src/src/interfaces/ICampaignData.sol/interface.ICampaignData.md +++ b/docs/src/src/interfaces/ICampaignData.sol/interface.ICampaignData.md @@ -1,5 +1,5 @@ # ICampaignData -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/ICampaignData.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/interfaces/ICampaignData.sol) An interface for managing campaign data in a CCP. diff --git a/docs/src/src/interfaces/ICampaignInfo.sol/interface.ICampaignInfo.md b/docs/src/src/interfaces/ICampaignInfo.sol/interface.ICampaignInfo.md index af5a884a..09b0d8e5 100644 --- a/docs/src/src/interfaces/ICampaignInfo.sol/interface.ICampaignInfo.md +++ b/docs/src/src/interfaces/ICampaignInfo.sol/interface.ICampaignInfo.md @@ -1,5 +1,5 @@ # ICampaignInfo -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/ICampaignInfo.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/interfaces/ICampaignInfo.sol) An interface for managing campaign information in a crowdfunding system. diff --git a/docs/src/src/interfaces/ICampaignInfoFactory.sol/interface.ICampaignInfoFactory.md b/docs/src/src/interfaces/ICampaignInfoFactory.sol/interface.ICampaignInfoFactory.md index e28f1138..b82c3002 100644 --- a/docs/src/src/interfaces/ICampaignInfoFactory.sol/interface.ICampaignInfoFactory.md +++ b/docs/src/src/interfaces/ICampaignInfoFactory.sol/interface.ICampaignInfoFactory.md @@ -1,5 +1,5 @@ # ICampaignInfoFactory -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/ICampaignInfoFactory.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/interfaces/ICampaignInfoFactory.sol) **Inherits:** [ICampaignData](/src/interfaces/ICampaignData.sol/interface.ICampaignData.md) diff --git a/docs/src/src/interfaces/ICampaignTreasury.sol/interface.ICampaignTreasury.md b/docs/src/src/interfaces/ICampaignTreasury.sol/interface.ICampaignTreasury.md index bcede9cd..bfa758f0 100644 --- a/docs/src/src/interfaces/ICampaignTreasury.sol/interface.ICampaignTreasury.md +++ b/docs/src/src/interfaces/ICampaignTreasury.sol/interface.ICampaignTreasury.md @@ -1,5 +1,5 @@ # ICampaignTreasury -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/ICampaignTreasury.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/interfaces/ICampaignTreasury.sol) An interface for managing campaign treasury contracts. @@ -38,13 +38,13 @@ function claimRefund(uint256 tokenId) external; |`tokenId`|`uint256`|The unique identifier of the refundable token.| -### getplatformHash +### getPlatformHash Retrieves the platform identifier associated with the treasury. ```solidity -function getplatformHash() external view returns (bytes32); +function getPlatformHash() external view returns (bytes32); ``` **Returns** @@ -53,13 +53,13 @@ function getplatformHash() external view returns (bytes32); |``|`bytes32`|The platform identifier as a bytes32 value.| -### getplatformFeePercent +### getPlatformFeePercent Retrieves the platform fee percentage for the treasury. ```solidity -function getplatformFeePercent() external view returns (uint256); +function getPlatformFeePercent() external view returns (uint256); ``` **Returns** diff --git a/docs/src/src/interfaces/IGlobalParams.sol/interface.IGlobalParams.md b/docs/src/src/interfaces/IGlobalParams.sol/interface.IGlobalParams.md index c23e2700..447c2b9a 100644 --- a/docs/src/src/interfaces/IGlobalParams.sol/interface.IGlobalParams.md +++ b/docs/src/src/interfaces/IGlobalParams.sol/interface.IGlobalParams.md @@ -1,5 +1,5 @@ # IGlobalParams -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/IGlobalParams.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/interfaces/IGlobalParams.sol) An interface for accessing and managing global parameters of the protocol. diff --git a/docs/src/src/interfaces/IItem.sol/interface.IItem.md b/docs/src/src/interfaces/IItem.sol/interface.IItem.md index 41b6afc0..1371e884 100644 --- a/docs/src/src/interfaces/IItem.sol/interface.IItem.md +++ b/docs/src/src/interfaces/IItem.sol/interface.IItem.md @@ -1,5 +1,5 @@ # IItem -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/IItem.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/interfaces/IItem.sol) An interface for managing items and their attributes. diff --git a/docs/src/src/interfaces/IReward.sol/interface.IReward.md b/docs/src/src/interfaces/IReward.sol/interface.IReward.md index bfbd0aa2..bd0fdf23 100644 --- a/docs/src/src/interfaces/IReward.sol/interface.IReward.md +++ b/docs/src/src/interfaces/IReward.sol/interface.IReward.md @@ -1,5 +1,5 @@ # IReward -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/IReward.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/interfaces/IReward.sol) An interface for managing rewards in a campaign. diff --git a/docs/src/src/interfaces/ITreasuryFactory.sol/interface.ITreasuryFactory.md b/docs/src/src/interfaces/ITreasuryFactory.sol/interface.ITreasuryFactory.md index 07b47fcf..5acfbf2b 100644 --- a/docs/src/src/interfaces/ITreasuryFactory.sol/interface.ITreasuryFactory.md +++ b/docs/src/src/interfaces/ITreasuryFactory.sol/interface.ITreasuryFactory.md @@ -1,5 +1,5 @@ # ITreasuryFactory -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/interfaces/ITreasuryFactory.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/interfaces/ITreasuryFactory.sol) *Interface for the TreasuryFactory contract, which registers, approves, and deploys treasury clones.* diff --git a/docs/src/src/treasuries/AllOrNothing.sol/contract.AllOrNothing.md b/docs/src/src/treasuries/AllOrNothing.sol/contract.AllOrNothing.md index 21e280ad..5d719fbc 100644 --- a/docs/src/src/treasuries/AllOrNothing.sol/contract.AllOrNothing.md +++ b/docs/src/src/treasuries/AllOrNothing.sol/contract.AllOrNothing.md @@ -1,5 +1,5 @@ # AllOrNothing -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/treasuries/AllOrNothing.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/treasuries/AllOrNothing.sol) **Inherits:** [IReward](/src/interfaces/IReward.sol/interface.IReward.md), [BaseTreasury](/src/utils/BaseTreasury.sol/abstract.BaseTreasury.md), [TimestampChecker](/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md), ERC721Burnable diff --git a/docs/src/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md b/docs/src/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md index ea05746a..b8065c6a 100644 --- a/docs/src/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md +++ b/docs/src/src/utils/AdminAccessChecker.sol/abstract.AdminAccessChecker.md @@ -1,5 +1,5 @@ # AdminAccessChecker -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/AdminAccessChecker.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/utils/AdminAccessChecker.sol) *This abstract contract provides access control mechanisms to restrict the execution of specific functions to authorized protocol administrators and platform administrators.* diff --git a/docs/src/src/utils/BaseTreasury.sol/abstract.BaseTreasury.md b/docs/src/src/utils/BaseTreasury.sol/abstract.BaseTreasury.md index de7920fe..1b437429 100644 --- a/docs/src/src/utils/BaseTreasury.sol/abstract.BaseTreasury.md +++ b/docs/src/src/utils/BaseTreasury.sol/abstract.BaseTreasury.md @@ -1,5 +1,5 @@ # BaseTreasury -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/BaseTreasury.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/utils/BaseTreasury.sol) **Inherits:** Initializable, [ICampaignTreasury](/src/interfaces/ICampaignTreasury.sol/interface.ICampaignTreasury.md), [CampaignAccessChecker](/src/utils/CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md), [PausableCancellable](/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md) @@ -85,13 +85,13 @@ modifier whenCampaignNotPaused(); modifier whenCampaignNotCancelled(); ``` -### getplatformHash +### getPlatformHash Retrieves the platform identifier associated with the treasury. ```solidity -function getplatformHash() external view override returns (bytes32); +function getPlatformHash() external view override returns (bytes32); ``` **Returns** @@ -100,13 +100,13 @@ function getplatformHash() external view override returns (bytes32); |``|`bytes32`|The platform identifier as a bytes32 value.| -### getplatformFeePercent +### getPlatformFeePercent Retrieves the platform fee percentage for the treasury. ```solidity -function getplatformFeePercent() external view override returns (uint256); +function getPlatformFeePercent() external view override returns (uint256); ``` **Returns** diff --git a/docs/src/src/utils/CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md b/docs/src/src/utils/CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md index 05a8e870..153e499e 100644 --- a/docs/src/src/utils/CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md +++ b/docs/src/src/utils/CampaignAccessChecker.sol/abstract.CampaignAccessChecker.md @@ -1,5 +1,5 @@ # CampaignAccessChecker -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/CampaignAccessChecker.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/utils/CampaignAccessChecker.sol) *This abstract contract provides access control mechanisms to restrict the execution of specific functions to authorized protocol administrators, platform administrators, and campaign owners.* diff --git a/docs/src/src/utils/Counters.sol/library.Counters.md b/docs/src/src/utils/Counters.sol/library.Counters.md index 2c667abe..45805f48 100644 --- a/docs/src/src/utils/Counters.sol/library.Counters.md +++ b/docs/src/src/utils/Counters.sol/library.Counters.md @@ -1,5 +1,5 @@ # Counters -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/Counters.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/utils/Counters.sol) ## Functions diff --git a/docs/src/src/utils/FiatEnabled.sol/abstract.FiatEnabled.md b/docs/src/src/utils/FiatEnabled.sol/abstract.FiatEnabled.md index 8a148bda..ee5c2c9d 100644 --- a/docs/src/src/utils/FiatEnabled.sol/abstract.FiatEnabled.md +++ b/docs/src/src/utils/FiatEnabled.sol/abstract.FiatEnabled.md @@ -1,5 +1,5 @@ # FiatEnabled -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/FiatEnabled.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/utils/FiatEnabled.sol) A contract that provides functionality for tracking and managing fiat transactions. This contract allows tracking the amount of fiat raised, individual fiat transactions, and the state of fiat fee disbursement. diff --git a/docs/src/src/utils/ItemRegistry.sol/contract.ItemRegistry.md b/docs/src/src/utils/ItemRegistry.sol/contract.ItemRegistry.md index 217effc5..2e4d08a6 100644 --- a/docs/src/src/utils/ItemRegistry.sol/contract.ItemRegistry.md +++ b/docs/src/src/utils/ItemRegistry.sol/contract.ItemRegistry.md @@ -1,5 +1,5 @@ # ItemRegistry -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/ItemRegistry.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/utils/ItemRegistry.sol) **Inherits:** [IItem](/src/interfaces/IItem.sol/interface.IItem.md), Context diff --git a/docs/src/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md b/docs/src/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md index fda365d5..cd083e89 100644 --- a/docs/src/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md +++ b/docs/src/src/utils/PausableCancellable.sol/abstract.PausableCancellable.md @@ -1,5 +1,5 @@ # PausableCancellable -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/PausableCancellable.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/utils/PausableCancellable.sol) Abstract contract providing pause and cancel state management with events and modifiers diff --git a/docs/src/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md b/docs/src/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md index 0931066c..ae8c27a2 100644 --- a/docs/src/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md +++ b/docs/src/src/utils/TimestampChecker.sol/abstract.TimestampChecker.md @@ -1,5 +1,5 @@ # TimestampChecker -[Git Source](https://github.com/ccprotocol/reference-client-sc/blob/32b7b1617200d0c6f3248845ef972180411f1f65/src/utils/TimestampChecker.sol) +[Git Source](https://github.com/ccprotocol/ccprotocol-contracts/blob/b6945e2b533f7d9aacb156ae915f6d1bb6b199de/src/utils/TimestampChecker.sol) A contract that provides timestamp-related checks for contract functions. From a71b944f9d2b2604281f9158b676ba8933f8d3cc Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 6 Jun 2025 17:33:57 +0600 Subject: [PATCH 38/41] Update function name - `getplatformHash` to `getPlatformHash` - `getplatformFeePercent` to `getPlatformFeePercent` --- src/interfaces/ICampaignTreasury.sol | 4 ++-- src/utils/BaseTreasury.sol | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/interfaces/ICampaignTreasury.sol b/src/interfaces/ICampaignTreasury.sol index 5bac65ee..2b6c2b67 100644 --- a/src/interfaces/ICampaignTreasury.sol +++ b/src/interfaces/ICampaignTreasury.sol @@ -26,13 +26,13 @@ interface ICampaignTreasury { * @notice Retrieves the platform identifier associated with the treasury. * @return The platform identifier as a bytes32 value. */ - function getplatformHash() external view returns (bytes32); + function getPlatformHash() external view returns (bytes32); /** * @notice Retrieves the platform fee percentage for the treasury. * @return The platform fee percentage as a uint256 value. */ - function getplatformFeePercent() external view returns (uint256); + function getPlatformFeePercent() external view returns (uint256); /** * @notice Retrieves the total raised amount in the treasury. diff --git a/src/utils/BaseTreasury.sol b/src/utils/BaseTreasury.sol index f41f1572..78abe289 100644 --- a/src/utils/BaseTreasury.sol +++ b/src/utils/BaseTreasury.sol @@ -98,14 +98,14 @@ abstract contract BaseTreasury is /** * @inheritdoc ICampaignTreasury */ - function getplatformHash() external view override returns (bytes32) { + function getPlatformHash() external view override returns (bytes32) { return PLATFORM_HASH; } /** * @inheritdoc ICampaignTreasury */ - function getplatformFeePercent() external view override returns (uint256) { + function getPlatformFeePercent() external view override returns (uint256) { return PLATFORM_FEE_PERCENT; } From e9dd49d3316393d53f6893a87665a4c0283e63f2 Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 6 Jun 2025 17:34:23 +0600 Subject: [PATCH 39/41] Add contribution and licensing info --- docs/src/README.md | 75 ++++++++++++++++++++++++++++++++------------- docs/src/SUMMARY.md | 1 - 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/docs/src/README.md b/docs/src/README.md index 5522623e..68de14d6 100644 --- a/docs/src/README.md +++ b/docs/src/README.md @@ -15,7 +15,6 @@ CC Protocol is a decentralized crowdfunding protocol designed to help creators l - [Foundry](https://book.getfoundry.sh/) - Solidity ^0.8.20 -- Node.js (recommended) ## Installation @@ -38,11 +37,7 @@ forge install cp .env.example .env ``` -4. Configure your `.env` file with: - -- Private key -- RPC URL -- (Optional) Contract addresses for reuse +4. Configure your `.env` file following the template in `.env.example` ## Documentation @@ -56,7 +51,6 @@ Comprehensive documentation is available in the `docs/` folder: To view the documentation: ```bash -# Navigate to docs folder cd docs ``` @@ -93,18 +87,17 @@ anvil forge script script/DeployAll.s.sol:DeployAll --rpc-url http://localhost:8545 --private-key $PRIVATE_KEY --broadcast ``` -#### Testnet Deployment +#### Network Deployment ```bash -# Deploy to testnet -forge script script/DeployAll.s.sol:DeployAll --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast -vvvv +# Deploy to any configured network +forge script script/DeployAll.s.sol:DeployAll --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast ``` ## Contract Architecture ### Core Contracts -- `TestUSD`: Mock ERC20 token for testing - `GlobalParams`: Protocol-wide parameter management - `CampaignInfoFactory`: Campaign creation and management - `TreasuryFactory`: Treasury contract deployment @@ -113,28 +106,66 @@ forge script script/DeployAll.s.sol:DeployAll --rpc-url $RPC_URL --private-key $ - `AllOrNothing`: Funds refunded if campaign goal not met +### Notes on Mock Contracts + +- `TestToken` is a mock ERC20 token used **only for testing and development purposes**. +- It is located in the `mocks/` directory and should **not be included in production deployments**. + ## Deployment Workflow -1. Deploy `TestUSD` -2. Deploy `GlobalParams` -3. Deploy `TreasuryFactory` -4. Deploy `CampaignInfoFactory` +1. Deploy `GlobalParams` +2. Deploy `TreasuryFactory` +3. Deploy `CampaignInfoFactory` + +> For local testing or development, the `TestToken` mock token needs to be deployed before interacting with contracts requiring an ERC20 token. ## Environment Variables -Key environment variables in `.env`: +Key environment variables to configure in `.env`: - `PRIVATE_KEY`: Deployment wallet private key -- `RPC_URL`: Network RPC endpoint +- `RPC_URL`: Network RPC endpoint (can be configured for any network) - `SIMULATE`: Toggle simulation mode - Contract address variables for reuse -## Troubleshooting +For a complete list of variables, refer to `.env.example`. + +## Security + +### Audits + +Security audit reports can be found in the [`audits/`](./audits/) folder. We regularly conduct security audits to ensure the safety and reliability of the protocol. + +## Contributing + +We welcome all contributions to the Creative Crowdfunding Protocol. If you're interested in helping, here's how you can contribute: + +- **Report bugs** by opening issues +- **Suggest enhancements** or new features +- **Submit pull requests** to improve the codebase +- **Improve documentation** to make the project more accessible + +Before contributing, please read our detailed [Contributing Guidelines](./CONTRIBUTING.md) for comprehensive information on: +- Development workflow +- Coding standards +- Testing requirements +- Pull request process +- Smart contract security considerations + +### Community + +Join our community on [Discord](https://discord.gg/4tR9rWc3QE) for questions and discussions. + +Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectful. + +## Contributors + + + + -- Ensure sufficient network gas tokens -- Verify RPC URL connectivity -- Check contract dependencies +Made with [contrib.rocks](https://contrib.rocks). ## License -[SPDX-License-Identifier: MIT] +This project is licensed under the [MIT License](https://opensource.org/licenses/MIT). \ No newline at end of file diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index d2c85d09..aafa9997 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -24,5 +24,4 @@ - [CampaignInfo](src/CampaignInfo.sol/contract.CampaignInfo.md) - [CampaignInfoFactory](src/CampaignInfoFactory.sol/contract.CampaignInfoFactory.md) - [GlobalParams](src/GlobalParams.sol/contract.GlobalParams.md) - - [TestUSD](src/TestUSD.sol/contract.TestUSD.md) - [TreasuryFactory](src/TreasuryFactory.sol/contract.TreasuryFactory.md) From c0aca4e89671b0658b023693afccc9e6592b1d3f Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 6 Jun 2025 17:34:44 +0600 Subject: [PATCH 40/41] Remove TestUSD link --- docs/src/src/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/src/src/README.md b/docs/src/src/README.md index 7423e1d4..7592aab6 100644 --- a/docs/src/src/README.md +++ b/docs/src/src/README.md @@ -7,5 +7,4 @@ - [CampaignInfo](CampaignInfo.sol/contract.CampaignInfo.md) - [CampaignInfoFactory](CampaignInfoFactory.sol/contract.CampaignInfoFactory.md) - [GlobalParams](GlobalParams.sol/contract.GlobalParams.md) -- [TestUSD](TestUSD.sol/contract.TestUSD.md) - [TreasuryFactory](TreasuryFactory.sol/contract.TreasuryFactory.md) From 1b198e0d9a5b708c934b3bbd9983de470ef85a0e Mon Sep 17 00:00:00 2001 From: rayedsikder Date: Fri, 6 Jun 2025 17:38:25 +0600 Subject: [PATCH 41/41] Add test cases - `test_removeReward` - `test_getReward` - `test_getRaisedAmount` - `test_pauseTreasury` - `test_unpauseTreasury` - `test_cancelTreasury` - `test_cancelTreasuryByCampaignOwner` - `test_name` - `test_symbol` - `test_getPlatformHash` - `test_getPlatformFeePercent` --- .../AllOrNothing/AllOrNothingFunction.t.sol | 487 ++++++++++++++++-- 1 file changed, 453 insertions(+), 34 deletions(-) diff --git a/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol b/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol index 640a2559..fef07b0d 100644 --- a/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol +++ b/test/foundry/integration/AllOrNothing/AllOrNothingFunction.t.sol @@ -10,9 +10,22 @@ import {Constants} from "../../utils/Constants.sol"; import {Users} from "../../utils/Types.sol"; import {IReward} from "src/interfaces/IReward.sol"; +/** + * @title AllOrNothing Function Integration Test Contract + * @notice Comprehensive integration tests for AllOrNothing treasury contract functionality + * @dev Inherits from AllOrNothing_Integration_Shared_Test to access common setup and utilities. + * Tests cover the full lifecycle of campaign operations including reward setup, pledging, + * refund claims, fee disbursement, and fund withdrawal scenarios. + */ contract AllOrNothingFunction_Integration_Shared_Test is AllOrNothing_Integration_Shared_Test { + /** + * @notice Tests the addRewards functionality + * @dev Verifies that rewards can be properly added to the treasury contract and that + * all reward properties are stored correctly including values, tiers, items, and quantities. + * Tests multiple rewards with different configurations to ensure proper storage and retrieval. + */ function test_addRewards() external { addRewards( users.creator1Address, @@ -49,6 +62,289 @@ contract AllOrNothingFunction_Integration_Shared_Test is assertEq(REWARDS[2].itemId.length, resultReward3.itemId.length); } + /** + * @notice Tests the removeReward functionality + * @dev Verifies that rewards can be properly removed from the treasury contract and that + * the reward is no longer accessible after removal. Ensures the RewardRemoved event + * is emitted correctly and attempts to access removed rewards result in reverts. + */ + function test_removeReward() external { + addRewards( + users.creator1Address, + address(allOrNothing), + REWARD_NAMES, + REWARDS + ); + + // Verify reward exists before removal + Reward memory existingReward = allOrNothing.getReward(REWARD_NAMES[0]); + assertEq(existingReward.rewardValue, REWARDS[0].rewardValue); + + // Remove the reward using helper function + Vm.Log[] memory logs = removeReward( + users.creator1Address, + address(allOrNothing), + REWARD_NAMES[0] + ); + + // For indexed parameters, we need to check topics + (bytes32[] memory topics, ) = decodeTopicsAndData( + logs, + "RewardRemoved(bytes32)", + address(allOrNothing) + ); + assertEq(topics[1], REWARD_NAMES[0], "Removed reward name should match"); + + // Verify reward no longer exists (should revert) + vm.expectRevert(); + allOrNothing.getReward(REWARD_NAMES[0]); + } + + /** + * @notice Tests the getReward functionality + * @dev Verifies that reward details can be properly retrieved from the treasury contract. + * Tests retrieval of all reward properties including values, tier flags, item arrays, + * and validates that non-existent rewards cause appropriate reverts. + */ + function test_getReward() external { + addRewards( + users.creator1Address, + address(allOrNothing), + REWARD_NAMES, + REWARDS + ); + + // Test getting each reward + for (uint i = 0; i < REWARD_NAMES.length; i++) { + Reward memory retrievedReward = allOrNothing.getReward(REWARD_NAMES[i]); + + assertEq(retrievedReward.rewardValue, REWARDS[i].rewardValue, "Reward value mismatch"); + assertEq(retrievedReward.isRewardTier, REWARDS[i].isRewardTier, "Reward tier flag mismatch"); + assertEq(retrievedReward.itemId.length, REWARDS[i].itemId.length, "Item ID array length mismatch"); + assertEq(retrievedReward.itemValue.length, REWARDS[i].itemValue.length, "Item value array length mismatch"); + assertEq(retrievedReward.itemQuantity.length, REWARDS[i].itemQuantity.length, "Item quantity array length mismatch"); + + // Check array contents + for (uint j = 0; j < retrievedReward.itemId.length; j++) { + assertEq(retrievedReward.itemId[j], REWARDS[i].itemId[j], "Item ID mismatch"); + assertEq(retrievedReward.itemValue[j], REWARDS[i].itemValue[j], "Item value mismatch"); + assertEq(retrievedReward.itemQuantity[j], REWARDS[i].itemQuantity[j], "Item quantity mismatch"); + } + } + + // Test getting non-existent reward (should revert) + vm.expectRevert(); + allOrNothing.getReward(keccak256("NonExistentReward")); + } + + /** + * @notice Tests the getRaisedAmount functionality + * @dev Verifies that the total raised amount is correctly tracked and returned. + * Tests progression from zero to multiple pledges to ensure accurate accumulation. + * Note that raised amount only tracks pledge amounts, not shipping fees. + */ + function test_getRaisedAmount() external { + addRewards( + users.creator1Address, + address(allOrNothing), + REWARD_NAMES, + REWARDS + ); + + // Initially should be zero + uint256 initialRaised = allOrNothing.getRaisedAmount(); + assertEq(initialRaised, 0, "Initial raised amount should be zero"); + + // Make a pledge and check raised amount + pledgeForAReward( + users.backer1Address, + LAUNCH_TIME, + address(allOrNothing), + PLEDGE_AMOUNT, + SHIPPING_FEE, + REWARD_NAME_1_HASH + ); + + uint256 raisedAfterFirstPledge = allOrNothing.getRaisedAmount(); + assertEq(raisedAfterFirstPledge, PLEDGE_AMOUNT, "Raised amount should equal first pledge amount"); + + // Make another pledge and check raised amount + pledgeWithoutAReward( + users.backer2Address, + LAUNCH_TIME, + address(allOrNothing), + GOAL_AMOUNT + ); + + uint256 finalRaised = allOrNothing.getRaisedAmount(); + assertEq(finalRaised, PLEDGE_AMOUNT + GOAL_AMOUNT, "Raised amount should equal sum of all pledges"); + } + + /** + * @notice Tests the pauseTreasury functionality + * @dev Verifies that the treasury can be paused by platform admin and that the paused + * state is correctly set. Validates that the Paused event is emitted from the + * correct contract when the pause operation is executed. + */ + function test_pauseTreasury() external { + bytes32 pauseReason = keccak256("Test pause"); + + assertFalse(allOrNothing.paused(), "Treasury should not be paused initially"); + + Vm.Log[] memory logs = pauseTreasury( + users.platform1AdminAddress, + address(allOrNothing), + pauseReason + ); + + assertTrue(allOrNothing.paused(), "Treasury should be paused"); + + // Use LogDecoder to find and verify the Paused event + Vm.Log memory pausedLog = findLogByTopic( + logs, + keccak256("Paused(address,bytes32)") + ); + + assertEq(pausedLog.emitter, address(allOrNothing), "Event should be emitted by allOrNothing contract"); + } + + /** + * @notice Tests the unpauseTreasury functionality + * @dev Verifies that the treasury can be unpaused by platform admin after being paused. + * Ensures proper state transition from paused to unpaused and validates that the + * Unpaused event is correctly emitted from the treasury contract. + */ + function test_unpauseTreasury() external { + bytes32 pauseReason = keccak256("Test pause"); + bytes32 unpauseReason = keccak256("Test unpause"); + + pauseTreasury(users.platform1AdminAddress, address(allOrNothing), pauseReason); + assertTrue(allOrNothing.paused(), "Treasury should be paused"); + + Vm.Log[] memory logs = unpauseTreasury( + users.platform1AdminAddress, + address(allOrNothing), + unpauseReason + ); + + assertFalse(allOrNothing.paused(), "Treasury should not be paused"); + + // Use LogDecoder to find and verify the Unpaused event + Vm.Log memory unpausedLog = findLogByTopic( + logs, + keccak256("Unpaused(address,bytes32)") + ); + + assertEq(unpausedLog.emitter, address(allOrNothing), "Event should be emitted by allOrNothing contract"); + } + + /** + * @notice Tests the cancelTreasury functionality by platform admin + * @dev Verifies that the treasury can be cancelled by platform admin and that the cancelled + * state is permanently set. Validates that the Cancelled event is emitted correctly + * and that cancellation is an irreversible operation. + */ + function test_cancelTreasury() external { + bytes32 cancelReason = keccak256("Test cancellation"); + + assertFalse(allOrNothing.cancelled(), "Treasury should not be cancelled initially"); + + Vm.Log[] memory logs = cancelTreasury( + users.platform1AdminAddress, + address(allOrNothing), + cancelReason + ); + + assertTrue(allOrNothing.cancelled(), "Treasury should be cancelled"); + + // Use LogDecoder to find and verify the Cancelled event + Vm.Log memory cancelledLog = findLogByTopic( + logs, + keccak256("Cancelled(address,bytes32)") + ); + + assertEq(cancelledLog.emitter, address(allOrNothing), "Event should be emitted by allOrNothing contract"); + } + + /** + * @notice Tests cancelTreasury functionality by campaign owner + * @dev Verifies that the campaign owner can also cancel the treasury, demonstrating + * the dual authorization model where both platform admin and campaign owner + * have cancellation privileges. Validates proper event emission and state change. + */ + function test_cancelTreasuryByCampaignOwner() external { + bytes32 cancelReason = keccak256("Owner cancellation"); + + assertFalse(allOrNothing.cancelled(), "Treasury should not be cancelled initially"); + + // Cancel the treasury as campaign owner using helper function + Vm.Log[] memory logs = cancelTreasury( + users.creator1Address, + address(allOrNothing), + cancelReason + ); + + // Verify treasury is cancelled + assertTrue(allOrNothing.cancelled(), "Treasury should be cancelled by owner"); + + // Use LogDecoder to find and verify the Cancelled event + Vm.Log memory cancelledLog = findLogByTopic( + logs, + keccak256("Cancelled(address,bytes32)") + ); + + assertEq(cancelledLog.emitter, address(allOrNothing), "Event should be emitted by allOrNothing contract"); + } + + /** + * @notice Tests the name functionality + * @dev Verifies that the contract name is correctly returned and matches the value + * that was set during contract initialization. Tests the ERC721 metadata extension. + */ + function test_name() external { + string memory contractName = allOrNothing.name(); + assertEq(contractName, NAME, "Contract name should match initialized name"); + } + + /** + * @notice Tests the symbol functionality + * @dev Verifies that the contract symbol is correctly returned and matches the value + * that was set during contract initialization. Tests the ERC721 metadata extension. + */ + function test_symbol() external { + string memory contractSymbol = allOrNothing.symbol(); + assertEq(contractSymbol, SYMBOL, "Contract symbol should match initialized symbol"); + } + + /** + * @notice Tests the getPlatformHash functionality + * @dev Verifies that the platform hash is correctly returned and matches the value + * that was set during contract initialization. This hash identifies which platform + * the treasury belongs to. + */ + function test_getPlatformHash() external { + bytes32 platformHash = allOrNothing.getPlatformHash(); + assertEq(platformHash, PLATFORM_1_HASH, "Platform hash should match initialized value"); + } + + /** + * @notice Tests the getPlatformFeePercent functionality + * @dev Verifies that the platform fee percentage is correctly returned and matches + * the value that was set during contract initialization. This percentage determines + * the platform's share of successful campaign funds. + */ + function test_getPlatformFeePercent() external { + uint256 platformFeePercent = allOrNothing.getPlatformFeePercent(); + assertEq(platformFeePercent, PLATFORM_FEE_PERCENT, "Platform fee percent should match initialized value"); + } + + /** + * @notice Tests the pledgeForAReward functionality + * @dev Verifies that users can pledge for specific rewards, including proper token transfers, + * NFT minting, and balance updates. Confirms that the backer receives an NFT representing + * their pledge and that funds (pledge amount + shipping fee) are correctly transferred + * to the treasury. Tests the complete reward-based pledging workflow. + */ function test_pledgeForAReward() external { addRewards( users.creator1Address, @@ -63,24 +359,98 @@ contract AllOrNothingFunction_Integration_Shared_Test is bytes32[] memory rewards ) = pledgeForAReward( users.backer1Address, - address(testToken), + LAUNCH_TIME, address(allOrNothing), PLEDGE_AMOUNT, SHIPPING_FEE, - LAUNCH_TIME, REWARD_NAME_1_HASH ); - uint256 backerBalance = testToken.balanceOf(users.backer1Address); uint256 treasuryBalance = testToken.balanceOf(address(allOrNothing)); uint256 backerNftBalance = allOrNothing.balanceOf(users.backer1Address); - address nftOwnerAddress = allOrNothing.ownerOf(pledgeForARewardTokenId); + address nftOwnerAddress = allOrNothing.ownerOf(tokenId); + + // Verify Receipt event was emitted with correct data + Vm.Log memory receiptLog = findLogByTopic( + logs, + keccak256("Receipt(address,bytes32,uint256,uint256,uint256,bytes32[])") + ); + assertEq(receiptLog.emitter, address(allOrNothing), "Receipt event should be emitted by allOrNothing contract"); + + // Verify state changes + assertEq(users.backer1Address, nftOwnerAddress, "Backer should own the NFT"); + assertEq(PLEDGE_AMOUNT + SHIPPING_FEE, treasuryBalance, "Treasury should contain pledge amount + shipping fee"); + assertEq(1, backerNftBalance, "Backer should have exactly 1 NFT"); + assertEq(rewards[0], REWARD_NAME_1_HASH, "Reward name should match"); + } + + /** + * @notice Tests the pledgeWithoutAReward functionality + * @dev Verifies that users can make pledges without selecting rewards, including proper + * token transfers, NFT minting, and balance updates. Confirms that the backer receives + * an NFT representing their pledge and that only the pledge amount is transferred + * (no shipping fees since no rewards are selected). Tests the basic pledging workflow. + */ + function test_pledgeWithoutAReward() external { + // Get initial balances + uint256 initialBackerBalance = testToken.balanceOf(users.backer1Address); + uint256 initialTreasuryBalance = testToken.balanceOf(address(allOrNothing)); + uint256 initialBackerNftBalance = allOrNothing.balanceOf(users.backer1Address); + + // Make a pledge without reward + (, uint256 tokenId) = pledgeWithoutAReward( + users.backer1Address, + LAUNCH_TIME, + address(allOrNothing), + PLEDGE_AMOUNT + ); + + // Get final balances + uint256 finalBackerBalance = testToken.balanceOf(users.backer1Address); + uint256 finalTreasuryBalance = testToken.balanceOf(address(allOrNothing)); + uint256 finalBackerNftBalance = allOrNothing.balanceOf(users.backer1Address); + address nftOwnerAddress = allOrNothing.ownerOf(tokenId); + + // Verify token transfers + assertEq( + initialBackerBalance - finalBackerBalance, + PLEDGE_AMOUNT, + "Incorrect amount deducted from backer" + ); + assertEq( + finalTreasuryBalance - initialTreasuryBalance, + PLEDGE_AMOUNT, + "Incorrect amount transferred to treasury" + ); + + // Verify NFT minting + assertEq( + finalBackerNftBalance - initialBackerNftBalance, + 1, + "Backer should receive exactly one NFT" + ); + assertEq( + nftOwnerAddress, + users.backer1Address, + "Backer should own the minted NFT" + ); - assertEq(users.backer1Address, nftOwnerAddress); - assertEq(PLEDGE_AMOUNT + SHIPPING_FEE, treasuryBalance); - assertEq(1, backerNftBalance); + // Verify treasury balance matches expected amount (no shipping fees) + assertEq( + finalTreasuryBalance, + PLEDGE_AMOUNT, + "Treasury should only contain the pledge amount" + ); } + /** + * @notice Tests the claimRefund functionality for both reward and non-reward pledges + * @dev Verifies that backers can claim refunds when campaigns fail to meet their goals. + * Tests both reward pledges (with shipping fees) and non-reward pledges, ensuring + * proper refund amounts and that the correct addresses receive refunds for both types. + * Validates that refunds include shipping fees for reward pledges and that NFTs are + * burned upon successful refund claims. + */ function test_claimRefund() external { addRewards( users.creator1Address, @@ -89,36 +459,68 @@ contract AllOrNothingFunction_Integration_Shared_Test is REWARDS ); + // Create a pledge with reward (, uint256 rewardTokenId, ) = pledgeForAReward( users.backer1Address, - address(testToken), + LAUNCH_TIME, address(allOrNothing), PLEDGE_AMOUNT, SHIPPING_FEE, - LAUNCH_TIME, REWARD_NAME_1_HASH ); - (, uint256 tokenId) = pledgeWithoutAReward( + // Create a pledge without reward + (, uint256 nonRewardTokenId) = pledgeWithoutAReward( users.backer1Address, - address(testToken), + LAUNCH_TIME, address(allOrNothing), - PLEDGE_AMOUNT, - LAUNCH_TIME + PLEDGE_AMOUNT ); + // Test refund for pledge without reward + ( + , + uint256 refundedNonRewardTokenId, + uint256 nonRewardRefundAmount, + address nonRewardClaimer + ) = claimRefund( + users.backer1Address, + LAUNCH_TIME + 1, + address(allOrNothing), + nonRewardTokenId + ); + + // Verify non-reward refund + assertEq(refundedNonRewardTokenId, nonRewardTokenId, "Incorrect non-reward token ID refunded"); + assertEq(nonRewardRefundAmount, PLEDGE_AMOUNT, "Incorrect non-reward refund amount"); + assertEq(nonRewardClaimer, users.backer1Address, "Incorrect non-reward claimer address"); + + // Test refund for pledge with reward ( - Vm.Log[] memory refundLogs, - uint256 refundedTokenId, - uint256 refundAmount, - address claimer - ) = claimRefund(users.backer1Address, address(allOrNothing), tokenId); + , + uint256 refundedRewardTokenId, + uint256 rewardRefundAmount, + address rewardClaimer + ) = claimRefund( + users.backer1Address, + LAUNCH_TIME + 1, + address(allOrNothing), + rewardTokenId + ); - assertEq(refundedTokenId, tokenId); - assertEq(refundAmount, PLEDGE_AMOUNT); - assertEq(claimer, users.backer1Address); + // Verify reward refund (should include pledge amount + shipping fee) + assertEq(refundedRewardTokenId, rewardTokenId, "Incorrect reward token ID refunded"); + assertEq(rewardRefundAmount, PLEDGE_AMOUNT + SHIPPING_FEE, "Incorrect reward refund amount"); + assertEq(rewardClaimer, users.backer1Address, "Incorrect reward claimer address"); } + /** + * @notice Tests the disburseFees functionality + * @dev Verifies that protocol and platform fees are correctly calculated and distributed + * when a campaign succeeds. Tests the fee calculation logic and ensures proper + * allocation between protocol and platform shares. Only executes after campaign + * deadline and when success conditions are met. + */ function test_disburseFees() external { addRewards( users.creator1Address, @@ -129,19 +531,17 @@ contract AllOrNothingFunction_Integration_Shared_Test is pledgeForAReward( users.backer1Address, - address(testToken), + LAUNCH_TIME, address(allOrNothing), PLEDGE_AMOUNT, SHIPPING_FEE, - LAUNCH_TIME, REWARD_NAME_1_HASH ); pledgeWithoutAReward( users.backer2Address, - address(testToken), + LAUNCH_TIME, address(allOrNothing), - GOAL_AMOUNT, - LAUNCH_TIME + GOAL_AMOUNT ); uint256 totalPledged = GOAL_AMOUNT + PLEDGE_AMOUNT; @@ -150,13 +550,20 @@ contract AllOrNothingFunction_Integration_Shared_Test is Vm.Log[] memory logs, uint256 protocolShare, uint256 platformShare - ) = disburseFees(address(allOrNothing), DEADLINE); + ) = disburseFees(address(allOrNothing), DEADLINE + 1); uint256 expectedProtocolShare = (totalPledged * PROTOCOL_FEE_PERCENT) / PERCENT_DIVIDER; uint256 expectedPlatformShare = (totalPledged * PLATFORM_FEE_PERCENT) / PERCENT_DIVIDER; + // Verify FeesDisbursed event was emitted + Vm.Log memory feesLog = findLogByTopic( + logs, + keccak256("FeesDisbursed(uint256,uint256)") + ); + assertEq(feesLog.emitter, address(allOrNothing), "FeesDisbursed event should be emitted by allOrNothing contract"); + assertEq( protocolShare, expectedProtocolShare, @@ -169,6 +576,13 @@ contract AllOrNothingFunction_Integration_Shared_Test is ); } + /** + * @notice Tests the withdraw functionality + * @dev Verifies that campaign creators can withdraw remaining funds after successful + * campaigns and fee disbursement. Tests proper calculation of withdrawal amounts + * after deducting protocol and platform fees, and confirms funds go to the correct + * recipient (campaign owner). Includes shipping fees in the final withdrawal amount. + */ function test_withdraw() external { addRewards( users.creator1Address, @@ -179,23 +593,21 @@ contract AllOrNothingFunction_Integration_Shared_Test is pledgeForAReward( users.backer1Address, - address(testToken), + LAUNCH_TIME, address(allOrNothing), PLEDGE_AMOUNT, SHIPPING_FEE, - LAUNCH_TIME, REWARD_NAME_1_HASH ); pledgeWithoutAReward( users.backer2Address, - address(testToken), + LAUNCH_TIME, address(allOrNothing), - GOAL_AMOUNT, - LAUNCH_TIME + GOAL_AMOUNT ); uint256 totalPledged = GOAL_AMOUNT + PLEDGE_AMOUNT; - disburseFees(address(allOrNothing), DEADLINE); + disburseFees(address(allOrNothing), DEADLINE + 1); (Vm.Log[] memory logs, address to, uint256 amount) = withdraw( address(allOrNothing), @@ -211,6 +623,13 @@ contract AllOrNothingFunction_Integration_Shared_Test is protocolShare - platformShare; + // Verify WithdrawalSuccessful event was emitted + Vm.Log memory withdrawalLog = findLogByTopic( + logs, + keccak256("WithdrawalSuccessful(address,uint256)") + ); + assertEq(withdrawalLog.emitter, address(allOrNothing), "WithdrawalSuccessful event should be emitted by allOrNothing contract"); + assertEq( to, users.creator1Address, @@ -218,4 +637,4 @@ contract AllOrNothingFunction_Integration_Shared_Test is ); assertEq(amount, expectedAmount, "Incorrect withdrawal amount"); } -} +} \ No newline at end of file