@bananapus/core-v6 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +112 -0
- package/SKILLS.md +151 -0
- package/docs/book.css +13 -0
- package/docs/book.toml +12 -0
- package/docs/solidity.min.js +74 -0
- package/docs/src/README.md +703 -0
- package/docs/src/SUMMARY.md +94 -0
- package/docs/src/src/JBChainlinkV3PriceFeed.sol/contract.JBChainlinkV3PriceFeed.md +83 -0
- package/docs/src/src/JBChainlinkV3SequencerPriceFeed.sol/contract.JBChainlinkV3SequencerPriceFeed.md +88 -0
- package/docs/src/src/JBController.sol/contract.JBController.md +1121 -0
- package/docs/src/src/JBDeadline.sol/contract.JBDeadline.md +84 -0
- package/docs/src/src/JBDirectory.sol/contract.JBDirectory.md +294 -0
- package/docs/src/src/JBERC20.sol/contract.JBERC20.md +190 -0
- package/docs/src/src/JBFeelessAddresses.sol/contract.JBFeelessAddresses.md +80 -0
- package/docs/src/src/JBFundAccessLimits.sol/contract.JBFundAccessLimits.md +253 -0
- package/docs/src/src/JBMultiTerminal.sol/contract.JBMultiTerminal.md +1472 -0
- package/docs/src/src/JBPermissions.sol/contract.JBPermissions.md +199 -0
- package/docs/src/src/JBPrices.sol/contract.JBPrices.md +154 -0
- package/docs/src/src/JBProjects.sol/contract.JBProjects.md +131 -0
- package/docs/src/src/JBRulesets.sol/contract.JBRulesets.md +677 -0
- package/docs/src/src/JBSplits.sol/contract.JBSplits.md +237 -0
- package/docs/src/src/JBTerminalStore.sol/contract.JBTerminalStore.md +591 -0
- package/docs/src/src/JBTokens.sol/contract.JBTokens.md +353 -0
- package/docs/src/src/README.md +25 -0
- package/docs/src/src/abstract/JBControlled.sol/abstract.JBControlled.md +64 -0
- package/docs/src/src/abstract/JBPermissioned.sol/abstract.JBPermissioned.md +84 -0
- package/docs/src/src/abstract/README.md +5 -0
- package/docs/src/src/enums/JBApprovalStatus.sol/enum.JBApprovalStatus.md +17 -0
- package/docs/src/src/enums/README.md +4 -0
- package/docs/src/src/interfaces/IJBCashOutHook.sol/interface.IJBCashOutHook.md +29 -0
- package/docs/src/src/interfaces/IJBCashOutTerminal.sol/interface.IJBCashOutTerminal.md +57 -0
- package/docs/src/src/interfaces/IJBControlled.sol/interface.IJBControlled.md +12 -0
- package/docs/src/src/interfaces/IJBController.sol/interface.IJBController.md +334 -0
- package/docs/src/src/interfaces/IJBDirectory.sol/interface.IJBDirectory.md +108 -0
- package/docs/src/src/interfaces/IJBDirectoryAccessControl.sol/interface.IJBDirectoryAccessControl.md +19 -0
- package/docs/src/src/interfaces/IJBFeeTerminal.sol/interface.IJBFeeTerminal.md +91 -0
- package/docs/src/src/interfaces/IJBFeelessAddresses.sol/interface.IJBFeelessAddresses.md +26 -0
- package/docs/src/src/interfaces/IJBFundAccessLimits.sol/interface.IJBFundAccessLimits.md +88 -0
- package/docs/src/src/interfaces/IJBMigratable.sol/interface.IJBMigratable.md +29 -0
- package/docs/src/src/interfaces/IJBMultiTerminal.sol/interface.IJBMultiTerminal.md +50 -0
- package/docs/src/src/interfaces/IJBPayHook.sol/interface.IJBPayHook.md +28 -0
- package/docs/src/src/interfaces/IJBPayoutTerminal.sol/interface.IJBPayoutTerminal.md +105 -0
- package/docs/src/src/interfaces/IJBPermissioned.sol/interface.IJBPermissioned.md +12 -0
- package/docs/src/src/interfaces/IJBPermissions.sol/interface.IJBPermissions.md +74 -0
- package/docs/src/src/interfaces/IJBPermitTerminal.sol/interface.IJBPermitTerminal.md +15 -0
- package/docs/src/src/interfaces/IJBPriceFeed.sol/interface.IJBPriceFeed.md +12 -0
- package/docs/src/src/interfaces/IJBPrices.sol/interface.IJBPrices.md +74 -0
- package/docs/src/src/interfaces/IJBProjectUriRegistry.sol/interface.IJBProjectUriRegistry.md +19 -0
- package/docs/src/src/interfaces/IJBProjects.sol/interface.IJBProjects.md +49 -0
- package/docs/src/src/interfaces/IJBRulesetApprovalHook.sol/interface.IJBRulesetApprovalHook.md +35 -0
- package/docs/src/src/interfaces/IJBRulesetDataHook.sol/interface.IJBRulesetDataHook.md +97 -0
- package/docs/src/src/interfaces/IJBRulesets.sol/interface.IJBRulesets.md +165 -0
- package/docs/src/src/interfaces/IJBSplitHook.sol/interface.IJBSplitHook.md +31 -0
- package/docs/src/src/interfaces/IJBSplits.sol/interface.IJBSplits.md +35 -0
- package/docs/src/src/interfaces/IJBTerminal.sol/interface.IJBTerminal.md +141 -0
- package/docs/src/src/interfaces/IJBTerminalStore.sol/interface.IJBTerminalStore.md +198 -0
- package/docs/src/src/interfaces/IJBToken.sol/interface.IJBToken.md +54 -0
- package/docs/src/src/interfaces/IJBTokenUriResolver.sol/interface.IJBTokenUriResolver.md +12 -0
- package/docs/src/src/interfaces/IJBTokens.sol/interface.IJBTokens.md +151 -0
- package/docs/src/src/interfaces/README.md +33 -0
- package/docs/src/src/libraries/JBCashOuts.sol/library.JBCashOuts.md +40 -0
- package/docs/src/src/libraries/JBConstants.sol/library.JBConstants.md +52 -0
- package/docs/src/src/libraries/JBCurrencyIds.sol/library.JBCurrencyIds.md +19 -0
- package/docs/src/src/libraries/JBFees.sol/library.JBFees.md +52 -0
- package/docs/src/src/libraries/JBFixedPointNumber.sol/library.JBFixedPointNumber.md +12 -0
- package/docs/src/src/libraries/JBMetadataResolver.sol/library.JBMetadataResolver.md +242 -0
- package/docs/src/src/libraries/JBRulesetMetadataResolver.sol/library.JBRulesetMetadataResolver.md +180 -0
- package/docs/src/src/libraries/JBSplitGroupIds.sol/library.JBSplitGroupIds.md +14 -0
- package/docs/src/src/libraries/JBSurplus.sol/library.JBSurplus.md +44 -0
- package/docs/src/src/libraries/README.md +12 -0
- package/docs/src/src/periphery/JBDeadline1Day.sol/contract.JBDeadline1Day.md +15 -0
- package/docs/src/src/periphery/JBDeadline3Days.sol/contract.JBDeadline3Days.md +15 -0
- package/docs/src/src/periphery/JBDeadline3Hours.sol/contract.JBDeadline3Hours.md +15 -0
- package/docs/src/src/periphery/JBDeadline7Days.sol/contract.JBDeadline7Days.md +15 -0
- package/docs/src/src/periphery/JBMatchingPriceFeed.sol/contract.JBMatchingPriceFeed.md +22 -0
- package/docs/src/src/periphery/README.md +8 -0
- package/docs/src/src/structs/JBAccountingContext.sol/struct.JBAccountingContext.md +20 -0
- package/docs/src/src/structs/JBAfterCashOutRecordedContext.sol/struct.JBAfterCashOutRecordedContext.md +43 -0
- package/docs/src/src/structs/JBAfterPayRecordedContext.sol/struct.JBAfterPayRecordedContext.md +42 -0
- package/docs/src/src/structs/JBBeforeCashOutRecordedContext.sol/struct.JBBeforeCashOutRecordedContext.md +45 -0
- package/docs/src/src/structs/JBBeforePayRecordedContext.sol/struct.JBBeforePayRecordedContext.md +41 -0
- package/docs/src/src/structs/JBCashOutHookSpecification.sol/struct.JBCashOutHookSpecification.md +22 -0
- package/docs/src/src/structs/JBCurrencyAmount.sol/struct.JBCurrencyAmount.md +17 -0
- package/docs/src/src/structs/JBFee.sol/struct.JBFee.md +20 -0
- package/docs/src/src/structs/JBFundAccessLimitGroup.sol/struct.JBFundAccessLimitGroup.md +39 -0
- package/docs/src/src/structs/JBPayHookSpecification.sol/struct.JBPayHookSpecification.md +22 -0
- package/docs/src/src/structs/JBPermissionsData.sol/struct.JBPermissionsData.md +21 -0
- package/docs/src/src/structs/JBRuleset.sol/struct.JBRuleset.md +55 -0
- package/docs/src/src/structs/JBRulesetConfig.sol/struct.JBRulesetConfig.md +51 -0
- package/docs/src/src/structs/JBRulesetMetadata.sol/struct.JBRulesetMetadata.md +79 -0
- package/docs/src/src/structs/JBRulesetWeightCache.sol/struct.JBRulesetWeightCache.md +16 -0
- package/docs/src/src/structs/JBRulesetWithMetadata.sol/struct.JBRulesetWithMetadata.md +16 -0
- package/docs/src/src/structs/JBSingleAllowance.sol/struct.JBSingleAllowance.md +26 -0
- package/docs/src/src/structs/JBSplit.sol/struct.JBSplit.md +49 -0
- package/docs/src/src/structs/JBSplitGroup.sol/struct.JBSplitGroup.md +17 -0
- package/docs/src/src/structs/JBSplitHookContext.sol/struct.JBSplitHookContext.md +29 -0
- package/docs/src/src/structs/JBTerminalConfig.sol/struct.JBTerminalConfig.md +16 -0
- package/docs/src/src/structs/JBTokenAmount.sol/struct.JBTokenAmount.md +23 -0
- package/docs/src/src/structs/README.md +25 -0
- package/foundry.lock +11 -0
- package/foundry.toml +41 -0
- package/package.json +38 -0
- package/remappings.txt +1 -0
- package/script/Deploy.s.sol +111 -0
- package/script/DeployPeriphery.s.sol +287 -0
- package/script/helpers/CoreDeploymentLib.sol +121 -0
- package/slither-ci.config.json +10 -0
- package/sphinx.lock +507 -0
- package/src/JBChainlinkV3PriceFeed.sol +77 -0
- package/src/JBChainlinkV3SequencerPriceFeed.sol +75 -0
- package/src/JBController.sol +1186 -0
- package/src/JBDeadline.sol +73 -0
- package/src/JBDirectory.sol +343 -0
- package/src/JBERC20.sol +131 -0
- package/src/JBFeelessAddresses.sol +54 -0
- package/src/JBFundAccessLimits.sol +308 -0
- package/src/JBMultiTerminal.sol +2024 -0
- package/src/JBPermissions.sol +252 -0
- package/src/JBPrices.sol +227 -0
- package/src/JBProjects.sol +126 -0
- package/src/JBRulesets.sol +1093 -0
- package/src/JBSplits.sol +324 -0
- package/src/JBTerminalStore.sol +908 -0
- package/src/JBTokens.sol +376 -0
- package/src/abstract/JBControlled.sol +48 -0
- package/src/abstract/JBPermissioned.sol +77 -0
- package/src/enums/JBApprovalStatus.sol +12 -0
- package/src/interfaces/IJBCashOutHook.sol +15 -0
- package/src/interfaces/IJBCashOutTerminal.sol +51 -0
- package/src/interfaces/IJBControlled.sol +10 -0
- package/src/interfaces/IJBController.sol +280 -0
- package/src/interfaces/IJBDirectory.sol +69 -0
- package/src/interfaces/IJBDirectoryAccessControl.sol +15 -0
- package/src/interfaces/IJBFeeTerminal.sol +61 -0
- package/src/interfaces/IJBFeelessAddresses.sol +17 -0
- package/src/interfaces/IJBFundAccessLimits.sol +94 -0
- package/src/interfaces/IJBMigratable.sol +24 -0
- package/src/interfaces/IJBMultiTerminal.sol +36 -0
- package/src/interfaces/IJBPayHook.sol +14 -0
- package/src/interfaces/IJBPayoutTerminal.sol +92 -0
- package/src/interfaces/IJBPermissioned.sol +10 -0
- package/src/interfaces/IJBPermissions.sol +71 -0
- package/src/interfaces/IJBPermitTerminal.sol +14 -0
- package/src/interfaces/IJBPriceFeed.sol +10 -0
- package/src/interfaces/IJBPrices.sol +65 -0
- package/src/interfaces/IJBProjectUriRegistry.sol +15 -0
- package/src/interfaces/IJBProjects.sol +27 -0
- package/src/interfaces/IJBRulesetApprovalHook.sol +21 -0
- package/src/interfaces/IJBRulesetDataHook.sol +56 -0
- package/src/interfaces/IJBRulesets.sol +151 -0
- package/src/interfaces/IJBSplitHook.sol +16 -0
- package/src/interfaces/IJBSplits.sol +28 -0
- package/src/interfaces/IJBTerminal.sol +120 -0
- package/src/interfaces/IJBTerminalStore.sol +225 -0
- package/src/interfaces/IJBToken.sol +39 -0
- package/src/interfaces/IJBTokenUriResolver.sol +10 -0
- package/src/interfaces/IJBTokens.sol +113 -0
- package/src/libraries/JBCashOuts.sol +120 -0
- package/src/libraries/JBConstants.sol +14 -0
- package/src/libraries/JBCurrencyIds.sol +7 -0
- package/src/libraries/JBFees.sol +28 -0
- package/src/libraries/JBFixedPointNumber.sol +12 -0
- package/src/libraries/JBMetadataResolver.sol +306 -0
- package/src/libraries/JBRulesetMetadataResolver.sol +160 -0
- package/src/libraries/JBSplitGroupIds.sol +7 -0
- package/src/libraries/JBSurplus.sol +40 -0
- package/src/periphery/JBDeadline1Day.sol +8 -0
- package/src/periphery/JBDeadline3Days.sol +8 -0
- package/src/periphery/JBDeadline3Hours.sol +8 -0
- package/src/periphery/JBDeadline7Days.sol +8 -0
- package/src/periphery/JBMatchingPriceFeed.sol +13 -0
- package/src/structs/JBAccountingContext.sol +12 -0
- package/src/structs/JBAfterCashOutRecordedContext.sol +30 -0
- package/src/structs/JBAfterPayRecordedContext.sol +29 -0
- package/src/structs/JBBeforeCashOutRecordedContext.sol +31 -0
- package/src/structs/JBBeforePayRecordedContext.sol +28 -0
- package/src/structs/JBCashOutHookSpecification.sol +15 -0
- package/src/structs/JBCurrencyAmount.sol +10 -0
- package/src/structs/JBFee.sol +12 -0
- package/src/structs/JBFundAccessLimitGroup.sol +28 -0
- package/src/structs/JBPayHookSpecification.sol +15 -0
- package/src/structs/JBPermissionsData.sol +13 -0
- package/src/structs/JBRuleset.sol +42 -0
- package/src/structs/JBRulesetConfig.sol +43 -0
- package/src/structs/JBRulesetMetadata.sol +56 -0
- package/src/structs/JBRulesetWeightCache.sol +9 -0
- package/src/structs/JBRulesetWithMetadata.sol +12 -0
- package/src/structs/JBSingleAllowance.sol +16 -0
- package/src/structs/JBSplit.sol +37 -0
- package/src/structs/JBSplitGroup.sol +12 -0
- package/src/structs/JBSplitHookContext.sol +20 -0
- package/src/structs/JBTerminalConfig.sol +12 -0
- package/src/structs/JBTokenAmount.sol +14 -0
- package/test/AuditExploits.t.sol +2710 -0
- package/test/ComprehensiveInvariant.t.sol +298 -0
- package/test/EconomicSimulation.t.sol +340 -0
- package/test/EntryPointPermutations.t.sol +671 -0
- package/test/FlashLoanAttacks.t.sol +792 -0
- package/test/PermissionEscalation.t.sol +679 -0
- package/test/RulesetTransitions.t.sol +699 -0
- package/test/SplitLoopTests.t.sol +731 -0
- package/test/TestAccessToFunds.sol +2644 -0
- package/test/TestCashOut.sol +185 -0
- package/test/TestCashOutCountFor.sol +272 -0
- package/test/TestCashOutHooks.sol +317 -0
- package/test/TestCashOutTimingEdge.sol +229 -0
- package/test/TestDurationUnderflow.sol +220 -0
- package/test/TestFeeProcessingFailure.sol +208 -0
- package/test/TestFees.sol +604 -0
- package/test/TestInterfaceSupport.sol +62 -0
- package/test/TestJBERC20Inheritance.sol +91 -0
- package/test/TestLaunchProject.sol +176 -0
- package/test/TestMetaTx.sol +203 -0
- package/test/TestMetadataParserLib.sol +438 -0
- package/test/TestMigrationHeldFees.sol +249 -0
- package/test/TestMintTokensOf.sol +172 -0
- package/test/TestMultiTokenSurplus.sol +206 -0
- package/test/TestMultipleAccessLimits.sol +642 -0
- package/test/TestPayBurnRedeemFlow.sol +180 -0
- package/test/TestPayHooks.sol +190 -0
- package/test/TestPermissions.sol +305 -0
- package/test/TestPermissionsEdge.sol +286 -0
- package/test/TestPermit2Terminal.sol +339 -0
- package/test/TestRulesetQueueing.sol +1001 -0
- package/test/TestRulesetQueuingStress.sol +778 -0
- package/test/TestRulesetWeightCaching.sol +177 -0
- package/test/TestSplits.sol +369 -0
- package/test/TestTerminalMigration.sol +167 -0
- package/test/TestTokenFlow.sol +174 -0
- package/test/WeirdTokenTests.t.sol +764 -0
- package/test/formal/BondingCurveProperties.t.sol +411 -0
- package/test/formal/FeeProperties.t.sol +246 -0
- package/test/helpers/JBTest.sol +129 -0
- package/test/helpers/MetadataResolverHelper.sol +116 -0
- package/test/helpers/TestBaseWorkflow.sol +317 -0
- package/test/invariants/Phase3DeepInvariant.t.sol +404 -0
- package/test/invariants/RulesetsInvariant.t.sol +115 -0
- package/test/invariants/TerminalStoreInvariant.t.sol +220 -0
- package/test/invariants/TokensInvariant.t.sol +184 -0
- package/test/invariants/handlers/ComprehensiveHandler.sol +285 -0
- package/test/invariants/handlers/EconomicHandler.sol +347 -0
- package/test/invariants/handlers/Phase3Handler.sol +414 -0
- package/test/invariants/handlers/RulesetsHandler.sol +111 -0
- package/test/invariants/handlers/TerminalStoreHandler.sol +146 -0
- package/test/invariants/handlers/TokensHandler.sol +127 -0
- package/test/mock/ERC2771ForwarderMock.sol +37 -0
- package/test/mock/MockERC20.sol +18 -0
- package/test/mock/MockMaliciousBeneficiary.sol +67 -0
- package/test/mock/MockMaliciousSplitHook.sol +42 -0
- package/test/mock/MockPriceFeed.sol +20 -0
- package/test/trees/JBController/burnTokensOf.tree +9 -0
- package/test/trees/JBController/claimTokensFor.tree +5 -0
- package/test/trees/JBController/deployERC20For.tree +5 -0
- package/test/trees/JBController/getRulesetOf.tree +5 -0
- package/test/trees/JBController/launchProjectFor.tree +12 -0
- package/test/trees/JBController/launchRulesetsFor.tree +8 -0
- package/test/trees/JBController/migrateController.tree +12 -0
- package/test/trees/JBController/mintTokensOf.tree +12 -0
- package/test/trees/JBController/payReservedTokenToTerminal.tree +8 -0
- package/test/trees/JBController/receiveMigrationFrom.tree +4 -0
- package/test/trees/JBController/sendReservedTokensToSplitsOf.tree +12 -0
- package/test/trees/JBController/setMetadataOf.tree +5 -0
- package/test/trees/JBController/setSplitGroupsOf.tree +5 -0
- package/test/trees/JBController/setTokenFor.tree +5 -0
- package/test/trees/JBController/transferCreditsFrom.tree +8 -0
- package/test/trees/JBDirectory/primaryTerminalOf.tree +8 -0
- package/test/trees/JBDirectory/setControllerOf.tree +11 -0
- package/test/trees/JBDirectory/setPrimaryTerminalOf.tree +15 -0
- package/test/trees/JBDirectory/setTerminalsOf.tree +11 -0
- package/test/trees/JBERC20/initialize.tree +7 -0
- package/test/trees/JBERC20/name.tree +5 -0
- package/test/trees/JBERC20/nonces.tree +5 -0
- package/test/trees/JBERC20/symbol.tree +5 -0
- package/test/trees/JBFeelessAddresses/setFeelessAddress.tree +5 -0
- package/test/trees/JBFeelessAddresses/supportsInterface.tree +5 -0
- package/test/trees/JBFundAccessLimits/payoutLimitOf.tree +5 -0
- package/test/trees/JBFundAccessLimits/payoutLimitsOf.tree +8 -0
- package/test/trees/JBFundAccessLimits/setFundAccessLimitsFor.tree +18 -0
- package/test/trees/JBFundAccessLimits/surplusAllowanceOf.tree +5 -0
- package/test/trees/JBFundAccessLimits/surplusAllowancesOf.tree +8 -0
- package/test/trees/JBMetadataResolver/getDataFor.tree +8 -0
- package/test/trees/JBMultiTerminal/accountingContextsOf.tree +5 -0
- package/test/trees/JBMultiTerminal/addAccountingContextsFor.tree +10 -0
- package/test/trees/JBMultiTerminal/addToBalanceOf.tree +23 -0
- package/test/trees/JBMultiTerminal/cashOutTokensOf.tree +23 -0
- package/test/trees/JBMultiTerminal/executePayout.tree +32 -0
- package/test/trees/JBMultiTerminal/executeProcessFee.tree +14 -0
- package/test/trees/JBMultiTerminal/migrateBalanceOf.tree +12 -0
- package/test/trees/JBMultiTerminal/pay.tree +23 -0
- package/test/trees/JBMultiTerminal/processHeldFeesOf.tree +8 -0
- package/test/trees/JBMultiTerminal/sendPayoutsOf.tree +34 -0
- package/test/trees/JBMultiTerminal/useAllowanceOf.tree +16 -0
- package/test/trees/JBPermissions/hasPermission.tree +8 -0
- package/test/trees/JBPermissions/hasPermissions.tree +8 -0
- package/test/trees/JBPermissions/setPermissionsFor.tree +5 -0
- package/test/trees/JBPrices/addPriceFeedFor.tree +14 -0
- package/test/trees/JBPrices/pricePerUnitOf.tree +11 -0
- package/test/trees/JBProjects/createFor.tree +11 -0
- package/test/trees/JBProjects/setTokenUriResolver.tree +5 -0
- package/test/trees/JBProjects/supportsInterface.tree +9 -0
- package/test/trees/JBProjects/tokenURI.tree +5 -0
- package/test/trees/JBRulesets/currentApprovalStatusForLatestRulesetOf.tree +8 -0
- package/test/trees/JBRulesets/currentOf.tree +12 -0
- package/test/trees/JBRulesets/getRulesetOf.tree +5 -0
- package/test/trees/JBRulesets/latestQueuedRulesetOf.tree +10 -0
- package/test/trees/JBRulesets/rulesetsOf.tree +11 -0
- package/test/trees/JBRulesets/upcomingRulesetOf.tree +20 -0
- package/test/trees/JBRulesets/updateRulesetWeightCache.tree +5 -0
- package/test/trees/JBSplits/setSplitGroupsOf.tree +17 -0
- package/test/trees/JBSplits/splitsOf.tree +5 -0
- package/test/trees/JBTerminalStore/currentReclaimableSurplusOf.tree +16 -0
- package/test/trees/JBTerminalStore/currentSurplusOf.tree +25 -0
- package/test/trees/JBTerminalStore/currentTotalSurplusOf.tree +5 -0
- package/test/trees/JBTerminalStore/recordCashOutsFor.tree +16 -0
- package/test/trees/JBTerminalStore/recordPaymentFrom.tree +14 -0
- package/test/trees/JBTerminalStore/recordPayoutFor.tree +10 -0
- package/test/trees/JBTerminalStore/recordTerminalMigration.tree +5 -0
- package/test/trees/JBTerminalStore/recordUsedAllowanceOf.tree +10 -0
- package/test/trees/JBTokens/burnFrom.tree +10 -0
- package/test/trees/JBTokens/claimTokensFor.tree +10 -0
- package/test/trees/JBTokens/deployERC20For.tree +12 -0
- package/test/trees/JBTokens/mintFor.tree +10 -0
- package/test/trees/JBTokens/setTokenFor.tree +11 -0
- package/test/trees/JBTokens/totalBalanceOf.tree +5 -0
- package/test/trees/JBTokens/totalSupplyOf.tree +5 -0
- package/test/trees/JBTokens/transferCreditsFrom.tree +8 -0
- package/test/trees/mintTokensOf.tree +12 -0
- package/test/units/static/JBChainlinkV3PriceFeed/TestPriceFeed.sol +220 -0
- package/test/units/static/JBController/JBControllerSetup.sol +40 -0
- package/test/units/static/JBController/TestBurnTokensOf.sol +107 -0
- package/test/units/static/JBController/TestClaimTokensFor.sol +60 -0
- package/test/units/static/JBController/TestDeployErc20For.sol +80 -0
- package/test/units/static/JBController/TestLaunchProjectFor.sol +282 -0
- package/test/units/static/JBController/TestLaunchRulesetsFor.sol +322 -0
- package/test/units/static/JBController/TestMigrateController.sol +148 -0
- package/test/units/static/JBController/TestMintTokensOfUnits.sol +102 -0
- package/test/units/static/JBController/TestPayReservedTokenToTerminal.sol +71 -0
- package/test/units/static/JBController/TestReceiveMigrationFrom.sol +95 -0
- package/test/units/static/JBController/TestRulesetViews.sol +219 -0
- package/test/units/static/JBController/TestSendReservedTokensToSplitsOf.sol +595 -0
- package/test/units/static/JBController/TestSetSplitGroupsOf.sol +63 -0
- package/test/units/static/JBController/TestSetTokenFor.sol +227 -0
- package/test/units/static/JBController/TestSetUriOf.sol +53 -0
- package/test/units/static/JBController/TestTransferCreditsFrom.sol +159 -0
- package/test/units/static/JBDeadline/TestDeadlineFuzz.sol +194 -0
- package/test/units/static/JBDirectory/JBDirectorySetup.sol +22 -0
- package/test/units/static/JBDirectory/TestPrimaryTerminalOf.sol +122 -0
- package/test/units/static/JBDirectory/TestSetControllerOf.sol +173 -0
- package/test/units/static/JBDirectory/TestSetControllerOfMigrationOrder.sol +98 -0
- package/test/units/static/JBDirectory/TestSetPrimaryTerminalOf.sol +169 -0
- package/test/units/static/JBDirectory/TestSetTerminalsOf.sol +128 -0
- package/test/units/static/JBERC20/JBERC20Setup.sol +20 -0
- package/test/units/static/JBERC20/SigUtils.sol +34 -0
- package/test/units/static/JBERC20/TestInitialize.sol +54 -0
- package/test/units/static/JBERC20/TestName.sol +30 -0
- package/test/units/static/JBERC20/TestNonces.sol +59 -0
- package/test/units/static/JBERC20/TestSymbol.sol +31 -0
- package/test/units/static/JBFeelessAdresses/JBFeelessSetup.sol +20 -0
- package/test/units/static/JBFeelessAdresses/TestInterfaces.sol +29 -0
- package/test/units/static/JBFeelessAdresses/TestSetFeelessAddress.sol +35 -0
- package/test/units/static/JBFees/TestFeesFuzz.sol +78 -0
- package/test/units/static/JBFixedPointNumber/TestAdjustDecimals.sol +16 -0
- package/test/units/static/JBFixedPointNumber/TestAdjustDecimalsFuzz.sol +71 -0
- package/test/units/static/JBFundAccessLimits/JBFundAccessSetup.sol +21 -0
- package/test/units/static/JBFundAccessLimits/TestFundAccessLimitsEdge.sol +159 -0
- package/test/units/static/JBFundAccessLimits/TestPayoutLimitOf.sol +56 -0
- package/test/units/static/JBFundAccessLimits/TestPayoutLimitsOf.sol +94 -0
- package/test/units/static/JBFundAccessLimits/TestSetFundAccessLimitsFor.sol +182 -0
- package/test/units/static/JBFundAccessLimits/TestSurplusAllowanceOf.sol +61 -0
- package/test/units/static/JBFundAccessLimits/TestSurplusAllowancesOf.sol +96 -0
- package/test/units/static/JBMetadataResolver/TestGetDataFor.sol +89 -0
- package/test/units/static/JBMetadataResolver/TestMetadataResolverFuzz.sol +227 -0
- package/test/units/static/JBMetadataResolver/TestMetadataResolverM20M21.sol +245 -0
- package/test/units/static/JBMultiTerminal/JBMultiTerminalSetup.sol +39 -0
- package/test/units/static/JBMultiTerminal/TestAccountingContextsOf.sol +65 -0
- package/test/units/static/JBMultiTerminal/TestAddAccountingContextsFor.sol +313 -0
- package/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol +432 -0
- package/test/units/static/JBMultiTerminal/TestCashOutTokensOf.sol +478 -0
- package/test/units/static/JBMultiTerminal/TestExecutePayout.sol +577 -0
- package/test/units/static/JBMultiTerminal/TestExecuteProcessFee.sol +176 -0
- package/test/units/static/JBMultiTerminal/TestMigrateBalanceOf.sol +190 -0
- package/test/units/static/JBMultiTerminal/TestPay.sol +514 -0
- package/test/units/static/JBMultiTerminal/TestProcessHeldFeesOf.sol +29 -0
- package/test/units/static/JBMultiTerminal/TestSendPayoutsOf.sol +243 -0
- package/test/units/static/JBMultiTerminal/TestUseAllowanceOf.sol +310 -0
- package/test/units/static/JBPermissions/JBPermissionsSetup.sol +18 -0
- package/test/units/static/JBPermissions/TestHasPermission.sol +50 -0
- package/test/units/static/JBPermissions/TestHasPermissions.sol +93 -0
- package/test/units/static/JBPermissions/TestSetPermissionsFor.sol +62 -0
- package/test/units/static/JBPrices/JBPricesSetup.sol +26 -0
- package/test/units/static/JBPrices/TestAddPriceFeedFor.sol +102 -0
- package/test/units/static/JBPrices/TestPricePerUnitOf.sol +129 -0
- package/test/units/static/JBPrices/TestPrices.sol +262 -0
- package/test/units/static/JBProjects/JBProjectsSetup.sol +20 -0
- package/test/units/static/JBProjects/TestCreateFor.sol +69 -0
- package/test/units/static/JBProjects/TestInitialProject.sol +19 -0
- package/test/units/static/JBProjects/TestInterfaces.sol +27 -0
- package/test/units/static/JBProjects/TestSetResolver.sol +36 -0
- package/test/units/static/JBProjects/TestTokenUri.sol +38 -0
- package/test/units/static/JBRulesetMetadataResolver/TestSetCashOutTaxRateTo.sol +99 -0
- package/test/units/static/JBRulesets/JBRulesetsSetup.sol +21 -0
- package/test/units/static/JBRulesets/TestCurrentApprovalStatusForLatestRulesetOf.sol +257 -0
- package/test/units/static/JBRulesets/TestCurrentOf.sol +231 -0
- package/test/units/static/JBRulesets/TestGetRulesetOf.sol +94 -0
- package/test/units/static/JBRulesets/TestLatestQueuedRulesetOf.sol +252 -0
- package/test/units/static/JBRulesets/TestRulesets.sol +617 -0
- package/test/units/static/JBRulesets/TestRulesetsOf.sol +37 -0
- package/test/units/static/JBRulesets/TestUpcomingRulesetOf.sol +526 -0
- package/test/units/static/JBRulesets/TestUpdateRulesetWeightCache.sol +91 -0
- package/test/units/static/JBSplits/JBSplitsSetup.sol +23 -0
- package/test/units/static/JBSplits/TestSelfManagedSplitGroups.sol +502 -0
- package/test/units/static/JBSplits/TestSetSplitGroupsOf.sol +370 -0
- package/test/units/static/JBSplits/TestSplitsLockedEdge.sol +262 -0
- package/test/units/static/JBSplits/TestSplitsOf.sol +24 -0
- package/test/units/static/JBSplits/TestSplitsPacking.sol +33 -0
- package/test/units/static/JBSurplus/TestSurplusFuzz.sol +125 -0
- package/test/units/static/JBTerminalStore/JBTerminalStoreSetup.sol +23 -0
- package/test/units/static/JBTerminalStore/TestCurrentReclaimableSurplusOf.sol +434 -0
- package/test/units/static/JBTerminalStore/TestCurrentSurplusOf.sol +428 -0
- package/test/units/static/JBTerminalStore/TestCurrentTotalSurplusOf.sol +65 -0
- package/test/units/static/JBTerminalStore/TestRecordCashOutsFor.sol +479 -0
- package/test/units/static/JBTerminalStore/TestRecordPaymentFrom.sol +508 -0
- package/test/units/static/JBTerminalStore/TestRecordPayoutFor.sol +257 -0
- package/test/units/static/JBTerminalStore/TestRecordTerminalMigration.sol +131 -0
- package/test/units/static/JBTerminalStore/TestRecordUsedAllowanceOf.sol +390 -0
- package/test/units/static/JBTerminalStore/TestUint224Overflow.sol +187 -0
- package/test/units/static/JBTokens/JBTokensSetup.sol +23 -0
- package/test/units/static/JBTokens/TestBurnFrom.sol +104 -0
- package/test/units/static/JBTokens/TestClaimTokensFor.sol +107 -0
- package/test/units/static/JBTokens/TestDeployERC20ForUnits.sol +89 -0
- package/test/units/static/JBTokens/TestMintFor.sol +97 -0
- package/test/units/static/JBTokens/TestSetTokenFor.sol +95 -0
- package/test/units/static/JBTokens/TestTotalBalanceOf.sol +65 -0
- package/test/units/static/JBTokens/TestTotalSupplyOf.sol +56 -0
- package/test/units/static/JBTokens/TestTransferCreditsFrom.sol +54 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.23;
|
|
3
|
+
|
|
4
|
+
import /* {*} from */ "../../../helpers/TestBaseWorkflow.sol";
|
|
5
|
+
import {JBControllerSetup} from "./JBControllerSetup.sol";
|
|
6
|
+
|
|
7
|
+
contract TestLaunchProjectFor_Local is JBControllerSetup {
|
|
8
|
+
using JBRulesetMetadataResolver for JBRulesetMetadata;
|
|
9
|
+
|
|
10
|
+
address payable _splitsBeneficiary = payable(makeAddr("someone"));
|
|
11
|
+
string _metadata = "JUICAY_DATA";
|
|
12
|
+
string _memo = "JUICAY_MEMO";
|
|
13
|
+
|
|
14
|
+
function setUp() public {
|
|
15
|
+
super.controllerSetup();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
modifier whenCalledDefault() {
|
|
19
|
+
// we must mock calls to Projects, Directory, Rulesets, possibly Splits, and possibly a second call to directory
|
|
20
|
+
|
|
21
|
+
bytes memory projectsCall = abi.encodeCall(IJBProjects.createFor, (address(this)));
|
|
22
|
+
bytes memory projectsReturn = abi.encode(1);
|
|
23
|
+
mockExpect(address(projects), projectsCall, projectsReturn);
|
|
24
|
+
|
|
25
|
+
bytes memory setControllerCall =
|
|
26
|
+
abi.encodeCall(IJBDirectory.setControllerOf, (1, IERC165(address(_controller))));
|
|
27
|
+
bytes memory setControllerReturn = "";
|
|
28
|
+
mockExpect(address(directory), setControllerCall, setControllerReturn);
|
|
29
|
+
_;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function test_GivenMetadataIsProvided() external whenCalledDefault {
|
|
33
|
+
// it will set metadata
|
|
34
|
+
|
|
35
|
+
JBRulesetConfig[] memory _rulesets = new JBRulesetConfig[](0);
|
|
36
|
+
JBTerminalConfig[] memory _terminals = new JBTerminalConfig[](0);
|
|
37
|
+
|
|
38
|
+
vm.expectEmit();
|
|
39
|
+
emit IJBController.LaunchProject(0, 1, _metadata, "", address(this));
|
|
40
|
+
|
|
41
|
+
_controller.launchProjectFor(address(this), _metadata, _rulesets, _terminals, "");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function test_GivenRulesetHasInvalidReservedPercent() external whenCalledDefault {
|
|
45
|
+
// it will revert INVALID_RESERVED_PERCENT()
|
|
46
|
+
|
|
47
|
+
JBRulesetMetadata memory _rulesMetadata = JBRulesetMetadata({
|
|
48
|
+
reservedPercent: JBConstants.MAX_RESERVED_PERCENT + 1, // invalid
|
|
49
|
+
cashOutTaxRate: JBConstants.MAX_CASH_OUT_TAX_RATE / 2, //50%
|
|
50
|
+
baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
51
|
+
pausePay: false,
|
|
52
|
+
pauseCreditTransfers: false,
|
|
53
|
+
allowOwnerMinting: false,
|
|
54
|
+
allowSetCustomToken: false,
|
|
55
|
+
allowTerminalMigration: false,
|
|
56
|
+
allowSetTerminals: false,
|
|
57
|
+
ownerMustSendPayouts: false,
|
|
58
|
+
allowSetController: false,
|
|
59
|
+
allowAddAccountingContext: true,
|
|
60
|
+
allowAddPriceFeed: false,
|
|
61
|
+
holdFees: false,
|
|
62
|
+
useTotalSurplusForCashOuts: true,
|
|
63
|
+
useDataHookForPay: false,
|
|
64
|
+
useDataHookForCashOut: false,
|
|
65
|
+
dataHook: address(0),
|
|
66
|
+
metadata: 0
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
JBFundAccessLimitGroup[] memory _fundAccessLimitGroup = new JBFundAccessLimitGroup[](0);
|
|
70
|
+
JBTerminalConfig[] memory _terminals = new JBTerminalConfig[](0);
|
|
71
|
+
|
|
72
|
+
// Package up the ruleset configuration.
|
|
73
|
+
JBRulesetConfig[] memory _rulesetConfigurations = new JBRulesetConfig[](1);
|
|
74
|
+
_rulesetConfigurations[0].mustStartAtOrAfter = 0;
|
|
75
|
+
_rulesetConfigurations[0].duration = 0;
|
|
76
|
+
_rulesetConfigurations[0].weight = 1e18;
|
|
77
|
+
_rulesetConfigurations[0].weightCutPercent = 0;
|
|
78
|
+
_rulesetConfigurations[0].approvalHook = IJBRulesetApprovalHook(address(0));
|
|
79
|
+
_rulesetConfigurations[0].metadata = _rulesMetadata;
|
|
80
|
+
_rulesetConfigurations[0].splitGroups = new JBSplitGroup[](0);
|
|
81
|
+
_rulesetConfigurations[0].fundAccessLimitGroups = _fundAccessLimitGroup;
|
|
82
|
+
|
|
83
|
+
vm.expectRevert(
|
|
84
|
+
abi.encodeWithSelector(
|
|
85
|
+
JBController.JBController_InvalidReservedPercent.selector,
|
|
86
|
+
JBConstants.MAX_RESERVED_PERCENT + 1,
|
|
87
|
+
JBConstants.MAX_RESERVED_PERCENT
|
|
88
|
+
)
|
|
89
|
+
);
|
|
90
|
+
_controller.launchProjectFor(address(this), _metadata, _rulesetConfigurations, _terminals, _memo);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function test_GivenRulesetHasInvalidCashOutTaxRate() external whenCalledDefault {
|
|
94
|
+
// it will revert INVALID_CASH_OUT_RATE()
|
|
95
|
+
|
|
96
|
+
JBRulesetMetadata memory _rulesMetadata = JBRulesetMetadata({
|
|
97
|
+
reservedPercent: JBConstants.MAX_RESERVED_PERCENT / 2,
|
|
98
|
+
cashOutTaxRate: JBConstants.MAX_CASH_OUT_TAX_RATE + 1, // invalid
|
|
99
|
+
baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
100
|
+
pausePay: false,
|
|
101
|
+
pauseCreditTransfers: false,
|
|
102
|
+
allowOwnerMinting: false,
|
|
103
|
+
allowSetCustomToken: false,
|
|
104
|
+
allowTerminalMigration: false,
|
|
105
|
+
allowSetTerminals: false,
|
|
106
|
+
ownerMustSendPayouts: false,
|
|
107
|
+
allowSetController: false,
|
|
108
|
+
allowAddAccountingContext: true,
|
|
109
|
+
allowAddPriceFeed: false,
|
|
110
|
+
holdFees: false,
|
|
111
|
+
useTotalSurplusForCashOuts: true,
|
|
112
|
+
useDataHookForPay: false,
|
|
113
|
+
useDataHookForCashOut: false,
|
|
114
|
+
dataHook: address(0),
|
|
115
|
+
metadata: 0
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
JBFundAccessLimitGroup[] memory _fundAccessLimitGroup = new JBFundAccessLimitGroup[](0);
|
|
119
|
+
JBTerminalConfig[] memory _terminals = new JBTerminalConfig[](0);
|
|
120
|
+
|
|
121
|
+
// Package up the ruleset configuration.
|
|
122
|
+
JBRulesetConfig[] memory _rulesetConfigurations = new JBRulesetConfig[](1);
|
|
123
|
+
_rulesetConfigurations[0].mustStartAtOrAfter = 0;
|
|
124
|
+
_rulesetConfigurations[0].duration = 0;
|
|
125
|
+
_rulesetConfigurations[0].weight = 1e18;
|
|
126
|
+
_rulesetConfigurations[0].weightCutPercent = 0;
|
|
127
|
+
_rulesetConfigurations[0].approvalHook = IJBRulesetApprovalHook(address(0));
|
|
128
|
+
_rulesetConfigurations[0].metadata = _rulesMetadata;
|
|
129
|
+
_rulesetConfigurations[0].splitGroups = new JBSplitGroup[](0);
|
|
130
|
+
_rulesetConfigurations[0].fundAccessLimitGroups = _fundAccessLimitGroup;
|
|
131
|
+
|
|
132
|
+
vm.expectRevert(
|
|
133
|
+
abi.encodeWithSelector(
|
|
134
|
+
JBController.JBController_InvalidCashOutTaxRate.selector,
|
|
135
|
+
JBConstants.MAX_CASH_OUT_TAX_RATE + 1,
|
|
136
|
+
JBConstants.MAX_CASH_OUT_TAX_RATE
|
|
137
|
+
)
|
|
138
|
+
);
|
|
139
|
+
_controller.launchProjectFor(address(this), _metadata, _rulesetConfigurations, _terminals, _memo);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function test_GivenSplitsRulesetsAndFundAccessConstraintsAreConfigured() external whenCalledDefault {
|
|
143
|
+
// it will set split groups, ruleset, fundAccessConstraints
|
|
144
|
+
|
|
145
|
+
JBRulesetMetadata memory _rulesMetadata = JBRulesetMetadata({
|
|
146
|
+
reservedPercent: JBConstants.MAX_RESERVED_PERCENT / 2,
|
|
147
|
+
cashOutTaxRate: JBConstants.MAX_CASH_OUT_TAX_RATE / 2,
|
|
148
|
+
baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
149
|
+
pausePay: false,
|
|
150
|
+
pauseCreditTransfers: false,
|
|
151
|
+
allowOwnerMinting: false,
|
|
152
|
+
allowSetCustomToken: false,
|
|
153
|
+
allowTerminalMigration: false,
|
|
154
|
+
allowSetTerminals: false,
|
|
155
|
+
ownerMustSendPayouts: false,
|
|
156
|
+
allowSetController: false,
|
|
157
|
+
allowAddAccountingContext: true,
|
|
158
|
+
allowAddPriceFeed: false,
|
|
159
|
+
holdFees: false,
|
|
160
|
+
useTotalSurplusForCashOuts: true,
|
|
161
|
+
useDataHookForPay: false,
|
|
162
|
+
useDataHookForCashOut: false,
|
|
163
|
+
dataHook: address(0),
|
|
164
|
+
metadata: 0
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
uint256 _packed = _rulesMetadata.packRulesetMetadata();
|
|
168
|
+
|
|
169
|
+
JBFundAccessLimitGroup[] memory _fundAccessLimitGroup = new JBFundAccessLimitGroup[](0);
|
|
170
|
+
JBTerminalConfig[] memory _terminals = new JBTerminalConfig[](0);
|
|
171
|
+
|
|
172
|
+
// splits
|
|
173
|
+
JBSplitGroup[] memory _splitsGroup = new JBSplitGroup[](1);
|
|
174
|
+
JBSplit[] memory _splits = new JBSplit[](1);
|
|
175
|
+
|
|
176
|
+
_splits[0] = JBSplit({
|
|
177
|
+
preferAddToBalance: false,
|
|
178
|
+
percent: JBConstants.SPLITS_TOTAL_PERCENT,
|
|
179
|
+
projectId: 1,
|
|
180
|
+
beneficiary: _splitsBeneficiary,
|
|
181
|
+
lockedUntil: 0,
|
|
182
|
+
hook: IJBSplitHook(address(0))
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
_splitsGroup[0] = JBSplitGroup({groupId: uint32(uint160(JBConstants.NATIVE_TOKEN)), splits: _splits});
|
|
186
|
+
|
|
187
|
+
// Package up the ruleset configuration.
|
|
188
|
+
JBRulesetConfig[] memory _rulesetConfigurations = new JBRulesetConfig[](1);
|
|
189
|
+
_rulesetConfigurations[0].mustStartAtOrAfter = 0;
|
|
190
|
+
_rulesetConfigurations[0].duration = 0;
|
|
191
|
+
_rulesetConfigurations[0].weight = 1e18;
|
|
192
|
+
_rulesetConfigurations[0].weightCutPercent = 0;
|
|
193
|
+
_rulesetConfigurations[0].approvalHook = IJBRulesetApprovalHook(address(0));
|
|
194
|
+
_rulesetConfigurations[0].metadata = _rulesMetadata;
|
|
195
|
+
_rulesetConfigurations[0].splitGroups = _splitsGroup;
|
|
196
|
+
_rulesetConfigurations[0].fundAccessLimitGroups = _fundAccessLimitGroup;
|
|
197
|
+
|
|
198
|
+
// JBRulesets calldata
|
|
199
|
+
JBRuleset memory returnedRuleset = JBRuleset({
|
|
200
|
+
cycleNumber: uint48(block.timestamp),
|
|
201
|
+
id: uint48(block.timestamp),
|
|
202
|
+
basedOnId: 0,
|
|
203
|
+
start: uint48(block.timestamp),
|
|
204
|
+
duration: _rulesetConfigurations[0].duration,
|
|
205
|
+
weight: _rulesetConfigurations[0].weight,
|
|
206
|
+
weightCutPercent: _rulesetConfigurations[0].weightCutPercent,
|
|
207
|
+
approvalHook: _rulesetConfigurations[0].approvalHook,
|
|
208
|
+
metadata: _packed
|
|
209
|
+
});
|
|
210
|
+
bytes memory rulesetsCall = abi.encodeCall(
|
|
211
|
+
IJBRulesets.queueFor,
|
|
212
|
+
(
|
|
213
|
+
1,
|
|
214
|
+
_rulesetConfigurations[0].duration,
|
|
215
|
+
_rulesetConfigurations[0].weight,
|
|
216
|
+
_rulesetConfigurations[0].weightCutPercent,
|
|
217
|
+
_rulesetConfigurations[0].approvalHook,
|
|
218
|
+
_packed,
|
|
219
|
+
_rulesetConfigurations[0].mustStartAtOrAfter
|
|
220
|
+
)
|
|
221
|
+
);
|
|
222
|
+
bytes memory rulesetsReturned = abi.encode(returnedRuleset);
|
|
223
|
+
|
|
224
|
+
// JBRulesets call
|
|
225
|
+
mockExpect(address(rulesets), rulesetsCall, rulesetsReturned);
|
|
226
|
+
|
|
227
|
+
// JBSplits call
|
|
228
|
+
bytes memory splitsCall = abi.encodeCall(IJBSplits.setSplitGroupsOf, (1, block.timestamp, _splitsGroup));
|
|
229
|
+
bytes memory splitsReturned = "";
|
|
230
|
+
mockExpect(address(splits), splitsCall, splitsReturned);
|
|
231
|
+
|
|
232
|
+
// JBFundAccess call
|
|
233
|
+
bytes memory fundsCall =
|
|
234
|
+
abi.encodeCall(IJBFundAccessLimits.setFundAccessLimitsFor, (1, block.timestamp, _fundAccessLimitGroup));
|
|
235
|
+
bytes memory fundsReturned = "";
|
|
236
|
+
mockExpect(address(fundAccessLimits), fundsCall, fundsReturned);
|
|
237
|
+
|
|
238
|
+
_controller.launchProjectFor(address(this), _metadata, _rulesetConfigurations, _terminals, _memo);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function test_GivenTerminalsAreProvided() external whenCalledDefault {
|
|
242
|
+
// it will set terminals
|
|
243
|
+
IJBTerminal _terminal = IJBTerminal(makeAddr("terminal"));
|
|
244
|
+
address _token = makeAddr("token");
|
|
245
|
+
|
|
246
|
+
JBRulesetConfig[] memory _rulesets = new JBRulesetConfig[](0);
|
|
247
|
+
JBTerminalConfig[] memory _terminals = new JBTerminalConfig[](1);
|
|
248
|
+
JBAccountingContext[] memory _tokensToAccept = new JBAccountingContext[](1);
|
|
249
|
+
_tokensToAccept[0] = JBAccountingContext({
|
|
250
|
+
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
_terminals[0] = JBTerminalConfig({terminal: _terminal, accountingContextsToAccept: _tokensToAccept});
|
|
254
|
+
|
|
255
|
+
// mock call return data
|
|
256
|
+
JBAccountingContext memory _returnedContext =
|
|
257
|
+
JBAccountingContext({token: _token, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))});
|
|
258
|
+
|
|
259
|
+
// mock call to the terminal addAccountingContextsFor()
|
|
260
|
+
bytes memory addCall = abi.encodeCall(IJBTerminal.addAccountingContextsFor, (1, _tokensToAccept));
|
|
261
|
+
bytes memory addReturned = abi.encode(_returnedContext);
|
|
262
|
+
|
|
263
|
+
mockExpect(address(_terminal), addCall, addReturned);
|
|
264
|
+
|
|
265
|
+
vm.expectEmit();
|
|
266
|
+
emit IJBController.LaunchProject(0, 1, _metadata, _memo, address(this));
|
|
267
|
+
|
|
268
|
+
_controller.launchProjectFor(address(this), _metadata, _rulesets, _terminals, _memo);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function test_GivenMemoIsProvided() external whenCalledDefault {
|
|
272
|
+
// it will be included in the emit
|
|
273
|
+
|
|
274
|
+
JBRulesetConfig[] memory _rulesets = new JBRulesetConfig[](0);
|
|
275
|
+
JBTerminalConfig[] memory _terminals = new JBTerminalConfig[](0);
|
|
276
|
+
|
|
277
|
+
vm.expectEmit();
|
|
278
|
+
emit IJBController.LaunchProject(0, 1, _metadata, _memo, address(this));
|
|
279
|
+
|
|
280
|
+
_controller.launchProjectFor(address(this), _metadata, _rulesets, _terminals, _memo);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.23;
|
|
3
|
+
|
|
4
|
+
import /* {*} from */ "../../../helpers/TestBaseWorkflow.sol";
|
|
5
|
+
import {JBControllerSetup} from "./JBControllerSetup.sol";
|
|
6
|
+
|
|
7
|
+
contract TestLaunchRulesetsFor_Local is JBControllerSetup {
|
|
8
|
+
function setUp() public {
|
|
9
|
+
super.controllerSetup();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
modifier whenCallerHasPermission() {
|
|
13
|
+
// mock ownerOf call
|
|
14
|
+
bytes memory _ownerOfCall = abi.encodeCall(IERC721.ownerOf, (1));
|
|
15
|
+
bytes memory _ownerData = abi.encode(address(this));
|
|
16
|
+
|
|
17
|
+
mockExpect(address(projects), _ownerOfCall, _ownerData);
|
|
18
|
+
_;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
modifier whenCallerWithoutPermission() {
|
|
22
|
+
// mock ownerOf call
|
|
23
|
+
bytes memory _ownerOfCall = abi.encodeCall(IERC721.ownerOf, (1));
|
|
24
|
+
bytes memory _ownerData = abi.encode(address(1));
|
|
25
|
+
|
|
26
|
+
mockExpect(address(projects), _ownerOfCall, _ownerData);
|
|
27
|
+
|
|
28
|
+
// mock permission call
|
|
29
|
+
bytes memory _call = abi.encodeCall(
|
|
30
|
+
IJBPermissions.hasPermission, (address(this), address(1), 1, JBPermissionIds.LAUNCH_RULESETS, true, true)
|
|
31
|
+
);
|
|
32
|
+
mockExpect(address(permissions), _call, abi.encode(false));
|
|
33
|
+
_;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function genRuleset()
|
|
37
|
+
public
|
|
38
|
+
pure
|
|
39
|
+
returns (JBTerminalConfig[] memory _terminalConfig, JBRulesetConfig[] memory _rulesetConfig)
|
|
40
|
+
{
|
|
41
|
+
// it should set the controller, queue the rulesets, configure terminals, and emit LaunchRulesets
|
|
42
|
+
JBTerminalConfig[] memory _terminalConfigs = new JBTerminalConfig[](0);
|
|
43
|
+
JBRulesetConfig[] memory _rulesetConfigs = new JBRulesetConfig[](1);
|
|
44
|
+
|
|
45
|
+
JBRulesetMetadata memory _metadata = JBRulesetMetadata({
|
|
46
|
+
reservedPercent: JBConstants.MAX_RESERVED_PERCENT / 2, //50%
|
|
47
|
+
cashOutTaxRate: JBConstants.MAX_CASH_OUT_TAX_RATE / 2, //50%
|
|
48
|
+
baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
49
|
+
pausePay: false,
|
|
50
|
+
pauseCreditTransfers: false,
|
|
51
|
+
allowOwnerMinting: false,
|
|
52
|
+
allowSetCustomToken: false,
|
|
53
|
+
allowTerminalMigration: false,
|
|
54
|
+
allowSetTerminals: false,
|
|
55
|
+
ownerMustSendPayouts: false,
|
|
56
|
+
allowSetController: false,
|
|
57
|
+
allowAddAccountingContext: true,
|
|
58
|
+
allowAddPriceFeed: false,
|
|
59
|
+
holdFees: false,
|
|
60
|
+
useTotalSurplusForCashOuts: true,
|
|
61
|
+
useDataHookForPay: false,
|
|
62
|
+
useDataHookForCashOut: false,
|
|
63
|
+
dataHook: address(0),
|
|
64
|
+
metadata: 0
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Package up the limits for the given terminal.
|
|
68
|
+
JBFundAccessLimitGroup[] memory _fundAccessLimitGroup = new JBFundAccessLimitGroup[](1);
|
|
69
|
+
|
|
70
|
+
// Specify a payout limit.
|
|
71
|
+
JBCurrencyAmount[] memory _payoutLimits = new JBCurrencyAmount[](1);
|
|
72
|
+
_payoutLimits[0] = JBCurrencyAmount({amount: 0, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))});
|
|
73
|
+
|
|
74
|
+
// Specify a surplus allowance.
|
|
75
|
+
JBCurrencyAmount[] memory _surplusAllowances = new JBCurrencyAmount[](1);
|
|
76
|
+
_surplusAllowances[0] = JBCurrencyAmount({amount: 0, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))});
|
|
77
|
+
|
|
78
|
+
_fundAccessLimitGroup[0] = JBFundAccessLimitGroup({
|
|
79
|
+
terminal: address(0),
|
|
80
|
+
token: JBConstants.NATIVE_TOKEN,
|
|
81
|
+
payoutLimits: _payoutLimits,
|
|
82
|
+
surplusAllowances: _surplusAllowances
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Package up the ruleset configuration.
|
|
86
|
+
_rulesetConfigs[0].mustStartAtOrAfter = 0;
|
|
87
|
+
_rulesetConfigs[0].duration = 0;
|
|
88
|
+
_rulesetConfigs[0].weight = 0;
|
|
89
|
+
_rulesetConfigs[0].weightCutPercent = 0;
|
|
90
|
+
_rulesetConfigs[0].approvalHook = IJBRulesetApprovalHook(address(0));
|
|
91
|
+
_rulesetConfigs[0].metadata = _metadata;
|
|
92
|
+
_rulesetConfigs[0].splitGroups = new JBSplitGroup[](0);
|
|
93
|
+
_rulesetConfigs[0].fundAccessLimitGroups = _fundAccessLimitGroup;
|
|
94
|
+
|
|
95
|
+
return (_terminalConfigs, _rulesetConfigs);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function test_RevertWhen_RulesetLengthIsZero() external {
|
|
99
|
+
// it should revert
|
|
100
|
+
JBTerminalConfig[] memory _terminalConfigs = new JBTerminalConfig[](0);
|
|
101
|
+
JBRulesetConfig[] memory _rulesetConfigs = new JBRulesetConfig[](0);
|
|
102
|
+
|
|
103
|
+
vm.expectRevert(JBController.JBController_RulesetsArrayEmpty.selector);
|
|
104
|
+
|
|
105
|
+
_controller.launchRulesetsFor(1, _rulesetConfigs, _terminalConfigs, "");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function test_RevertWhen_CallerDoesNotHavePermission() external whenCallerWithoutPermission {
|
|
109
|
+
// it should revert
|
|
110
|
+
JBTerminalConfig[] memory _terminalConfigs = new JBTerminalConfig[](0);
|
|
111
|
+
JBRulesetConfig[] memory _rulesetConfigs = new JBRulesetConfig[](1);
|
|
112
|
+
|
|
113
|
+
vm.expectRevert(
|
|
114
|
+
abi.encodeWithSelector(
|
|
115
|
+
JBPermissioned.JBPermissioned_Unauthorized.selector,
|
|
116
|
+
address(1),
|
|
117
|
+
address(this),
|
|
118
|
+
1,
|
|
119
|
+
JBPermissionIds.LAUNCH_RULESETS
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
_controller.launchRulesetsFor(1, _rulesetConfigs, _terminalConfigs, "");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function test_Revert_GivenTheProjectAlreadyHasRulesets() external whenCallerHasPermission {
|
|
127
|
+
// it should revert
|
|
128
|
+
JBTerminalConfig[] memory _terminalConfigs = new JBTerminalConfig[](0);
|
|
129
|
+
JBRulesetConfig[] memory _rulesetConfigs = new JBRulesetConfig[](1);
|
|
130
|
+
|
|
131
|
+
bytes memory _latestRulesetIdOfCall = abi.encodeCall(IJBRulesets.latestRulesetIdOf, (1));
|
|
132
|
+
bytes memory _returnData = abi.encode(1);
|
|
133
|
+
|
|
134
|
+
mockExpect(address(rulesets), _latestRulesetIdOfCall, _returnData);
|
|
135
|
+
|
|
136
|
+
vm.expectRevert(abi.encodeWithSelector(JBController.JBController_RulesetsAlreadyLaunched.selector, 1));
|
|
137
|
+
|
|
138
|
+
_controller.launchRulesetsFor(1, _rulesetConfigs, _terminalConfigs, "");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function test_GivenTheProjectDoesNotYetHaveRulesets() external whenCallerHasPermission {
|
|
142
|
+
// setup: needed for the call chain
|
|
143
|
+
JBTerminalConfig[] memory _terminalConfigs;
|
|
144
|
+
JBRulesetConfig[] memory _rulesetConfigs;
|
|
145
|
+
uint48 _ts = uint48(block.timestamp);
|
|
146
|
+
uint256 _projectId = 1;
|
|
147
|
+
(_terminalConfigs, _rulesetConfigs) = genRuleset();
|
|
148
|
+
|
|
149
|
+
// inlined to avoid stack2deep
|
|
150
|
+
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.latestRulesetIdOf, (_projectId)), abi.encode(0));
|
|
151
|
+
mockExpect(
|
|
152
|
+
address(directory),
|
|
153
|
+
abi.encodeCall(IJBDirectory.setControllerOf, (_projectId, IERC165(address(_controller)))),
|
|
154
|
+
""
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// mock call to rulesets queueFor
|
|
158
|
+
// setup: return data
|
|
159
|
+
JBRuleset memory data = JBRuleset({
|
|
160
|
+
cycleNumber: 1,
|
|
161
|
+
id: _ts,
|
|
162
|
+
basedOnId: 0,
|
|
163
|
+
start: _ts,
|
|
164
|
+
duration: 0,
|
|
165
|
+
weight: 0,
|
|
166
|
+
weightCutPercent: 0,
|
|
167
|
+
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
168
|
+
metadata: 0
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Mock call to rulesets queueFor
|
|
172
|
+
bytes memory _queueForCall = abi.encodeCall(
|
|
173
|
+
IJBRulesets.queueFor,
|
|
174
|
+
(
|
|
175
|
+
_projectId,
|
|
176
|
+
0,
|
|
177
|
+
0,
|
|
178
|
+
0,
|
|
179
|
+
_rulesetConfigs[0].approvalHook,
|
|
180
|
+
JBRulesetMetadataResolver.packRulesetMetadata(_rulesetConfigs[0].metadata),
|
|
181
|
+
0
|
|
182
|
+
)
|
|
183
|
+
);
|
|
184
|
+
bytes memory _queueReturn = abi.encode(data);
|
|
185
|
+
mockExpect(address(rulesets), _queueForCall, _queueReturn);
|
|
186
|
+
|
|
187
|
+
// Mock call to splits setSplitGroupsOf
|
|
188
|
+
bytes memory _setSplitsCall =
|
|
189
|
+
abi.encodeCall(IJBSplits.setSplitGroupsOf, (_projectId, _ts, _rulesetConfigs[0].splitGroups));
|
|
190
|
+
bytes memory _splitsReturn = "";
|
|
191
|
+
mockExpect(address(splits), _setSplitsCall, _splitsReturn);
|
|
192
|
+
|
|
193
|
+
// Mock call to fundaccesslimits setFundAccessLimitsFor
|
|
194
|
+
bytes memory _fundAccessCall = abi.encodeCall(
|
|
195
|
+
IJBFundAccessLimits.setFundAccessLimitsFor, (_projectId, _ts, _rulesetConfigs[0].fundAccessLimitGroups)
|
|
196
|
+
);
|
|
197
|
+
bytes memory _accessReturn = "";
|
|
198
|
+
mockExpect(address(fundAccessLimits), _fundAccessCall, _accessReturn);
|
|
199
|
+
|
|
200
|
+
// event as expected
|
|
201
|
+
/* vm.expectEmit();
|
|
202
|
+
emit IJBController.LaunchRulesets(_ts, 1, "", address(this)); */
|
|
203
|
+
|
|
204
|
+
_controller.launchRulesetsFor(_projectId, _rulesetConfigs, _terminalConfigs, "");
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function test_GivenCallerOnlyHasLaunchPermission() external {
|
|
208
|
+
// it should revert
|
|
209
|
+
|
|
210
|
+
// mock ownerOf call
|
|
211
|
+
bytes memory _ownerOfCall = abi.encodeCall(IERC721.ownerOf, (1));
|
|
212
|
+
address _ownerData = address(1);
|
|
213
|
+
|
|
214
|
+
mockExpect(address(projects), _ownerOfCall, abi.encode(_ownerData));
|
|
215
|
+
|
|
216
|
+
// mock permission call - caller has LAUNCH_RULESETS
|
|
217
|
+
bytes memory _call = abi.encodeCall(
|
|
218
|
+
IJBPermissions.hasPermission, (address(this), address(1), 1, JBPermissionIds.LAUNCH_RULESETS, true, true)
|
|
219
|
+
);
|
|
220
|
+
mockExpect(address(permissions), _call, abi.encode(true));
|
|
221
|
+
|
|
222
|
+
// SET_TERMINALS - caller does NOT have this
|
|
223
|
+
bytes memory _call3 = abi.encodeCall(
|
|
224
|
+
IJBPermissions.hasPermission, (address(this), address(1), 1, JBPermissionIds.SET_TERMINALS, true, true)
|
|
225
|
+
);
|
|
226
|
+
mockExpect(address(permissions), _call3, abi.encode(false));
|
|
227
|
+
|
|
228
|
+
// it should revert
|
|
229
|
+
JBTerminalConfig[] memory _terminalConfigs = new JBTerminalConfig[](0);
|
|
230
|
+
JBRulesetConfig[] memory _rulesetConfigs = new JBRulesetConfig[](1);
|
|
231
|
+
|
|
232
|
+
vm.expectRevert(
|
|
233
|
+
abi.encodeWithSelector(
|
|
234
|
+
JBPermissioned.JBPermissioned_Unauthorized.selector,
|
|
235
|
+
_ownerData,
|
|
236
|
+
address(this),
|
|
237
|
+
1,
|
|
238
|
+
JBPermissionIds.SET_TERMINALS
|
|
239
|
+
)
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
_controller.launchRulesetsFor(1, _rulesetConfigs, _terminalConfigs, "");
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function test_GivenNonOwnerHasBothPermissions() external {
|
|
246
|
+
// it will launch rulesets
|
|
247
|
+
|
|
248
|
+
// mock ownerOf call
|
|
249
|
+
bytes memory _ownerOfCall = abi.encodeCall(IERC721.ownerOf, (1));
|
|
250
|
+
bytes memory _ownerData = abi.encode(address(1));
|
|
251
|
+
|
|
252
|
+
mockExpect(address(projects), _ownerOfCall, _ownerData);
|
|
253
|
+
|
|
254
|
+
// mock permission call - caller has LAUNCH_RULESETS
|
|
255
|
+
bytes memory _call = abi.encodeCall(
|
|
256
|
+
IJBPermissions.hasPermission, (address(this), address(1), 1, JBPermissionIds.LAUNCH_RULESETS, true, true)
|
|
257
|
+
);
|
|
258
|
+
mockExpect(address(permissions), _call, abi.encode(true));
|
|
259
|
+
|
|
260
|
+
// SET_TERMINALS
|
|
261
|
+
bytes memory _call3 = abi.encodeCall(
|
|
262
|
+
IJBPermissions.hasPermission, (address(this), address(1), 1, JBPermissionIds.SET_TERMINALS, true, true)
|
|
263
|
+
);
|
|
264
|
+
mockExpect(address(permissions), _call3, abi.encode(true));
|
|
265
|
+
|
|
266
|
+
// setup: needed for the call chain
|
|
267
|
+
JBTerminalConfig[] memory _terminalConfigs;
|
|
268
|
+
JBRulesetConfig[] memory _rulesetConfigs;
|
|
269
|
+
uint48 _ts = uint48(block.timestamp);
|
|
270
|
+
uint256 _projectId = 1;
|
|
271
|
+
(_terminalConfigs, _rulesetConfigs) = genRuleset();
|
|
272
|
+
|
|
273
|
+
// inlined to avoid stack2deep
|
|
274
|
+
mockExpect(address(rulesets), abi.encodeCall(IJBRulesets.latestRulesetIdOf, (_projectId)), abi.encode(0));
|
|
275
|
+
mockExpect(
|
|
276
|
+
address(directory),
|
|
277
|
+
abi.encodeCall(IJBDirectory.setControllerOf, (_projectId, IERC165(address(_controller)))),
|
|
278
|
+
""
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
// mock call to rulesets queueFor
|
|
282
|
+
// setup: return data
|
|
283
|
+
JBRuleset memory data = JBRuleset({
|
|
284
|
+
cycleNumber: 1,
|
|
285
|
+
id: _ts,
|
|
286
|
+
basedOnId: 0,
|
|
287
|
+
start: _ts,
|
|
288
|
+
duration: 0,
|
|
289
|
+
weight: 0,
|
|
290
|
+
weightCutPercent: 0,
|
|
291
|
+
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
292
|
+
metadata: 0
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// Mock call to rulesets queueFor
|
|
296
|
+
bytes memory _queueForCall = abi.encodeCall(
|
|
297
|
+
IJBRulesets.queueFor,
|
|
298
|
+
(_projectId, 0, 0, 0, _rulesetConfigs[0].approvalHook, 642_241_845_873_572_506_056_833, 0)
|
|
299
|
+
);
|
|
300
|
+
bytes memory _queueReturn = abi.encode(data);
|
|
301
|
+
mockExpect(address(rulesets), _queueForCall, _queueReturn);
|
|
302
|
+
|
|
303
|
+
// Mock call to splits setSplitGroupsOf
|
|
304
|
+
bytes memory _setSplitsCall =
|
|
305
|
+
abi.encodeCall(IJBSplits.setSplitGroupsOf, (_projectId, _ts, _rulesetConfigs[0].splitGroups));
|
|
306
|
+
bytes memory _splitsReturn = "";
|
|
307
|
+
mockExpect(address(splits), _setSplitsCall, _splitsReturn);
|
|
308
|
+
|
|
309
|
+
// Mock call to fundaccesslimits setFundAccessLimitsFor
|
|
310
|
+
bytes memory _fundAccessCall = abi.encodeCall(
|
|
311
|
+
IJBFundAccessLimits.setFundAccessLimitsFor, (_projectId, _ts, _rulesetConfigs[0].fundAccessLimitGroups)
|
|
312
|
+
);
|
|
313
|
+
bytes memory _accessReturn = "";
|
|
314
|
+
mockExpect(address(fundAccessLimits), _fundAccessCall, _accessReturn);
|
|
315
|
+
|
|
316
|
+
// event as expected
|
|
317
|
+
vm.expectEmit();
|
|
318
|
+
emit IJBController.LaunchRulesets(_ts, 1, "", address(this));
|
|
319
|
+
|
|
320
|
+
_controller.launchRulesetsFor(1, _rulesetConfigs, _terminalConfigs, "");
|
|
321
|
+
}
|
|
322
|
+
}
|