@bananapus/core-v6 0.0.37 → 0.0.39
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/foundry.lock +1 -7
- package/foundry.toml +1 -1
- package/package.json +19 -7
- package/src/JBChainlinkV3PriceFeed.sol +4 -1
- package/src/JBChainlinkV3SequencerPriceFeed.sol +4 -2
- package/src/JBController.sol +71 -44
- package/src/JBDeadline.sol +4 -4
- package/src/JBDirectory.sol +34 -32
- package/src/JBERC20.sol +5 -4
- package/src/JBFeelessAddresses.sol +6 -3
- package/src/JBFundAccessLimits.sol +25 -21
- package/src/JBMultiTerminal.sol +121 -84
- package/src/JBPermissions.sol +34 -37
- package/src/JBPrices.sol +23 -18
- package/src/JBProjects.sol +6 -3
- package/src/JBRulesets.sol +44 -41
- package/src/JBSplits.sol +18 -16
- package/src/JBTerminalStore.sol +32 -25
- package/src/JBTokens.sol +36 -26
- package/src/abstract/JBControlled.sol +3 -1
- package/src/abstract/JBPermissioned.sol +3 -1
- package/src/enums/JBApprovalStatus.sol +7 -1
- package/src/interfaces/IJBController.sol +7 -3
- package/src/interfaces/IJBDirectory.sol +3 -1
- package/src/interfaces/IJBMultiTerminal.sol +3 -2
- package/src/interfaces/IJBPermissions.sol +2 -1
- package/src/interfaces/IJBPrices.sol +3 -1
- package/src/interfaces/IJBRulesets.sol +2 -1
- package/src/interfaces/IJBSplits.sol +2 -1
- package/src/interfaces/IJBTerminal.sol +3 -1
- package/src/interfaces/IJBTerminalStore.sol +3 -1
- package/src/interfaces/IJBTokens.sol +2 -1
- package/src/libraries/JBCashOuts.sol +6 -1
- package/src/libraries/JBConstants.sol +12 -3
- package/src/libraries/JBCurrencyIds.sol +2 -0
- package/src/libraries/JBFees.sol +52 -10
- package/src/libraries/JBFixedPointNumber.sol +2 -0
- package/src/libraries/JBPayoutSplitGroupLib.sol +7 -4
- package/src/libraries/JBRulesetMetadataResolver.sol +4 -0
- package/src/libraries/JBSplitGroupIds.sol +2 -1
- package/src/libraries/JBSurplus.sol +3 -1
- package/src/periphery/JBMatchingPriceFeed.sol +3 -1
- package/src/structs/JBAccountingContext.sol +7 -4
- package/src/structs/JBFundAccessLimitGroup.sol +10 -17
- package/src/structs/JBRuleset.sol +18 -26
- package/src/structs/JBRulesetConfig.sol +13 -25
- package/src/structs/JBRulesetMetadata.sol +25 -32
- package/test/mock/MockMaliciousBeneficiary.sol +15 -15
- package/ADMINISTRATION.md +0 -103
- package/ARCHITECTURE.md +0 -133
- package/AUDIT_INSTRUCTIONS.md +0 -139
- package/RISKS.md +0 -215
- package/SKILLS.md +0 -55
- package/STYLE_GUIDE.md +0 -610
- package/USER_JOURNEYS.md +0 -215
- package/script/Deploy.s.sol +0 -124
- package/script/DeployPeriphery.s.sol +0 -354
- package/slither-ci.config.json +0 -10
- package/test/AuditFixes.t.sol +0 -808
- package/test/ComprehensiveInvariant.t.sol +0 -306
- package/test/CoreExploitTests.t.sol +0 -2741
- package/test/EconomicSimulation.t.sol +0 -348
- package/test/EntryPointPermutations.t.sol +0 -684
- package/test/FlashLoanAttacks.t.sol +0 -797
- package/test/PermissionEscalation.t.sol +0 -711
- package/test/PermissionsInvariant.t.sol +0 -403
- package/test/RulesetTransitions.t.sol +0 -713
- package/test/SplitLoopTests.t.sol +0 -752
- package/test/TestAccessToFunds.sol +0 -2683
- package/test/TestAuditResponseDesignProofs.sol +0 -434
- package/test/TestCashOut.sol +0 -198
- package/test/TestCashOutCountFor.sol +0 -271
- package/test/TestCashOutHooks.sol +0 -351
- package/test/TestCashOutTimingEdge.sol +0 -241
- package/test/TestDataHookFuzzing.sol +0 -524
- package/test/TestDurationUnderflow.sol +0 -233
- package/test/TestFeeFreeCashOutBypass.sol +0 -949
- package/test/TestFeeProcessingFailure.sol +0 -218
- package/test/TestFees.sol +0 -619
- package/test/TestForwardedTokenConsumption.sol +0 -425
- package/test/TestInterfaceSupport.sol +0 -81
- package/test/TestJBERC20Inheritance.sol +0 -103
- package/test/TestL2SequencerPriceFeed.sol +0 -292
- package/test/TestLaunchProject.sol +0 -188
- package/test/TestMetaTx.sol +0 -217
- package/test/TestMetadataOffsetOverflow.sol +0 -179
- package/test/TestMetadataParserLib.sol +0 -471
- package/test/TestMigrationHeldFees.sol +0 -255
- package/test/TestMintTokensOf.sol +0 -185
- package/test/TestMultiTerminalSurplus.sol +0 -348
- package/test/TestMultiTokenSurplus.sol +0 -202
- package/test/TestMultipleAccessLimits.sol +0 -664
- package/test/TestPayBurnRedeemFlow.sol +0 -195
- package/test/TestPayHooks.sol +0 -209
- package/test/TestPermissions.sol +0 -324
- package/test/TestPermissionsEdge.sol +0 -290
- package/test/TestPermit2DataHook.t.sol +0 -360
- package/test/TestPermit2Terminal.sol +0 -372
- package/test/TestRulesetQueueing.sol +0 -1025
- package/test/TestRulesetQueuingStress.sol +0 -806
- package/test/TestRulesetWeightCaching.sol +0 -178
- package/test/TestSplits.sol +0 -391
- package/test/TestTerminalMigration.sol +0 -274
- package/test/TestTerminalPreviewParity.sol +0 -208
- package/test/TestTokenFlow.sol +0 -191
- package/test/TestWeightCacheStaleAfterRejection.sol +0 -303
- package/test/WeirdTokenTests.t.sol +0 -817
- package/test/audit/CashOutReenterPay.t.sol +0 -501
- package/test/audit/CodexHeldFeeRounding.t.sol +0 -159
- package/test/audit/CodexMigrationFeeFailure.t.sol +0 -163
- package/test/audit/CrossTerminalSurplusSpoof.t.sol +0 -140
- package/test/audit/CycledSurplusAllowanceReset.t.sol +0 -184
- package/test/audit/FeeFreeSurplusLifecycle.t.sol +0 -399
- package/test/audit/FeeFreeSurplusStale.t.sol +0 -248
- package/test/audit/USDTVoidReturnCompat.t.sol +0 -525
- package/test/fork/TestChainlinkPriceFeedFork.sol +0 -254
- package/test/fork/TestSequencerPriceFeedFork.sol +0 -168
- package/test/fork/TestTerminalPreviewParityFork.sol +0 -108
- package/test/formal/BondingCurveProperties.t.sol +0 -420
- package/test/formal/FeeProperties.t.sol +0 -252
- package/test/invariants/Phase3DeepInvariant.t.sol +0 -412
- package/test/invariants/RulesetsInvariant.t.sol +0 -125
- package/test/invariants/TerminalStoreInvariant.t.sol +0 -227
- package/test/invariants/TokensInvariant.t.sol +0 -195
- package/test/invariants/handlers/ComprehensiveHandler.sol +0 -303
- package/test/invariants/handlers/EconomicHandler.sol +0 -377
- package/test/invariants/handlers/Phase3Handler.sol +0 -443
- package/test/invariants/handlers/RulesetsHandler.sol +0 -115
- package/test/invariants/handlers/TerminalStoreHandler.sol +0 -151
- package/test/invariants/handlers/TokensHandler.sol +0 -126
- package/test/regression/HoldFeesCashOutReserved.t.sol +0 -415
- package/test/regression/WeightCacheBoundary.t.sol +0 -291
- package/test/trees/JBController/burnTokensOf.tree +0 -9
- package/test/trees/JBController/claimTokensFor.tree +0 -5
- package/test/trees/JBController/deployERC20For.tree +0 -5
- package/test/trees/JBController/getRulesetOf.tree +0 -5
- package/test/trees/JBController/launchProjectFor.tree +0 -12
- package/test/trees/JBController/launchRulesetsFor.tree +0 -8
- package/test/trees/JBController/migrateController.tree +0 -12
- package/test/trees/JBController/mintTokensOf.tree +0 -12
- package/test/trees/JBController/payReservedTokenToTerminal.tree +0 -8
- package/test/trees/JBController/receiveMigrationFrom.tree +0 -4
- package/test/trees/JBController/sendReservedTokensToSplitsOf.tree +0 -12
- package/test/trees/JBController/setMetadataOf.tree +0 -5
- package/test/trees/JBController/setSplitGroupsOf.tree +0 -5
- package/test/trees/JBController/setTokenFor.tree +0 -5
- package/test/trees/JBController/transferCreditsFrom.tree +0 -8
- package/test/trees/JBDirectory/primaryTerminalOf.tree +0 -8
- package/test/trees/JBDirectory/setControllerOf.tree +0 -11
- package/test/trees/JBDirectory/setPrimaryTerminalOf.tree +0 -15
- package/test/trees/JBDirectory/setTerminalsOf.tree +0 -11
- package/test/trees/JBERC20/initialize.tree +0 -7
- package/test/trees/JBERC20/name.tree +0 -5
- package/test/trees/JBERC20/nonces.tree +0 -5
- package/test/trees/JBERC20/symbol.tree +0 -5
- package/test/trees/JBFeelessAddresses/setFeelessAddress.tree +0 -5
- package/test/trees/JBFeelessAddresses/supportsInterface.tree +0 -5
- package/test/trees/JBFundAccessLimits/payoutLimitOf.tree +0 -5
- package/test/trees/JBFundAccessLimits/payoutLimitsOf.tree +0 -8
- package/test/trees/JBFundAccessLimits/setFundAccessLimitsFor.tree +0 -18
- package/test/trees/JBFundAccessLimits/surplusAllowanceOf.tree +0 -5
- package/test/trees/JBFundAccessLimits/surplusAllowancesOf.tree +0 -8
- package/test/trees/JBMetadataResolver/getDataFor.tree +0 -8
- package/test/trees/JBMultiTerminal/accountingContextsOf.tree +0 -5
- package/test/trees/JBMultiTerminal/addAccountingContextsFor.tree +0 -10
- package/test/trees/JBMultiTerminal/addToBalanceOf.tree +0 -23
- package/test/trees/JBMultiTerminal/cashOutTokensOf.tree +0 -23
- package/test/trees/JBMultiTerminal/executePayout.tree +0 -32
- package/test/trees/JBMultiTerminal/executeProcessFee.tree +0 -14
- package/test/trees/JBMultiTerminal/migrateBalanceOf.tree +0 -12
- package/test/trees/JBMultiTerminal/pay.tree +0 -23
- package/test/trees/JBMultiTerminal/processHeldFeesOf.tree +0 -8
- package/test/trees/JBMultiTerminal/sendPayoutsOf.tree +0 -34
- package/test/trees/JBMultiTerminal/useAllowanceOf.tree +0 -16
- package/test/trees/JBPermissions/hasPermission.tree +0 -8
- package/test/trees/JBPermissions/hasPermissions.tree +0 -8
- package/test/trees/JBPermissions/setPermissionsFor.tree +0 -5
- package/test/trees/JBPrices/addPriceFeedFor.tree +0 -14
- package/test/trees/JBPrices/pricePerUnitOf.tree +0 -11
- package/test/trees/JBProjects/createFor.tree +0 -11
- package/test/trees/JBProjects/setTokenUriResolver.tree +0 -5
- package/test/trees/JBProjects/supportsInterface.tree +0 -9
- package/test/trees/JBProjects/tokenURI.tree +0 -5
- package/test/trees/JBRulesets/currentApprovalStatusForLatestRulesetOf.tree +0 -8
- package/test/trees/JBRulesets/currentOf.tree +0 -12
- package/test/trees/JBRulesets/getRulesetOf.tree +0 -5
- package/test/trees/JBRulesets/latestQueuedRulesetOf.tree +0 -10
- package/test/trees/JBRulesets/rulesetsOf.tree +0 -11
- package/test/trees/JBRulesets/upcomingRulesetOf.tree +0 -20
- package/test/trees/JBRulesets/updateRulesetWeightCache.tree +0 -5
- package/test/trees/JBSplits/setSplitGroupsOf.tree +0 -17
- package/test/trees/JBSplits/splitsOf.tree +0 -5
- package/test/trees/JBTerminalStore/currentReclaimableSurplusOf.tree +0 -16
- package/test/trees/JBTerminalStore/currentSurplusOf.tree +0 -25
- package/test/trees/JBTerminalStore/currentTotalSurplusOf.tree +0 -5
- package/test/trees/JBTerminalStore/recordCashOutsFor.tree +0 -16
- package/test/trees/JBTerminalStore/recordPaymentFrom.tree +0 -14
- package/test/trees/JBTerminalStore/recordPayoutFor.tree +0 -10
- package/test/trees/JBTerminalStore/recordTerminalMigration.tree +0 -5
- package/test/trees/JBTerminalStore/recordUsedAllowanceOf.tree +0 -10
- package/test/trees/JBTokens/burnFrom.tree +0 -10
- package/test/trees/JBTokens/claimTokensFor.tree +0 -10
- package/test/trees/JBTokens/deployERC20For.tree +0 -12
- package/test/trees/JBTokens/mintFor.tree +0 -10
- package/test/trees/JBTokens/setTokenFor.tree +0 -11
- package/test/trees/JBTokens/totalBalanceOf.tree +0 -5
- package/test/trees/JBTokens/totalSupplyOf.tree +0 -5
- package/test/trees/JBTokens/transferCreditsFrom.tree +0 -8
- package/test/trees/mintTokensOf.tree +0 -12
- package/test/units/static/JBChainlinkV3PriceFeed/TestPriceFeed.sol +0 -223
- package/test/units/static/JBController/JBControllerSetup.sol +0 -50
- package/test/units/static/JBController/TestBurnTokensOf.sol +0 -114
- package/test/units/static/JBController/TestClaimTokensFor.sol +0 -63
- package/test/units/static/JBController/TestDeployErc20For.sol +0 -86
- package/test/units/static/JBController/TestLaunchProjectFor.sol +0 -302
- package/test/units/static/JBController/TestLaunchRulesetsFor.sol +0 -342
- package/test/units/static/JBController/TestMigrateController.sol +0 -157
- package/test/units/static/JBController/TestMintTokensOfUnits.sol +0 -111
- package/test/units/static/JBController/TestOmnichainRulesetOperator.sol +0 -324
- package/test/units/static/JBController/TestPayReservedTokenToTerminal.sol +0 -74
- package/test/units/static/JBController/TestPreviewMintOf.sol +0 -117
- package/test/units/static/JBController/TestReceiveMigrationFrom.sol +0 -99
- package/test/units/static/JBController/TestRulesetViews.sol +0 -225
- package/test/units/static/JBController/TestSendReservedTokensToSplitsOf.sol +0 -615
- package/test/units/static/JBController/TestSetSplitGroupsOf.sol +0 -68
- package/test/units/static/JBController/TestSetTokenFor.sol +0 -239
- package/test/units/static/JBController/TestSetUriOf.sol +0 -57
- package/test/units/static/JBController/TestTransferCreditsFrom.sol +0 -169
- package/test/units/static/JBDeadline/TestDeadlineFuzz.sol +0 -211
- package/test/units/static/JBDirectory/JBDirectorySetup.sol +0 -26
- package/test/units/static/JBDirectory/TestPrimaryTerminalOf.sol +0 -126
- package/test/units/static/JBDirectory/TestSetControllerOf.sol +0 -183
- package/test/units/static/JBDirectory/TestSetControllerOfMigrationOrder.sol +0 -104
- package/test/units/static/JBDirectory/TestSetPrimaryTerminalOf.sol +0 -179
- package/test/units/static/JBDirectory/TestSetTerminalsOf.sol +0 -137
- package/test/units/static/JBERC20/JBERC20Setup.sol +0 -34
- package/test/units/static/JBERC20/SigUtils.sol +0 -36
- package/test/units/static/JBERC20/TestInitialize.sol +0 -60
- package/test/units/static/JBERC20/TestName.sol +0 -30
- package/test/units/static/JBERC20/TestNonces.sol +0 -62
- package/test/units/static/JBERC20/TestSymbol.sol +0 -31
- package/test/units/static/JBFeelessAdresses/JBFeelessSetup.sol +0 -22
- package/test/units/static/JBFeelessAdresses/TestInterfaces.sol +0 -30
- package/test/units/static/JBFeelessAdresses/TestSetFeelessAddress.sol +0 -35
- package/test/units/static/JBFees/TestFeesFuzz.sol +0 -79
- package/test/units/static/JBFixedPointNumber/TestAdjustDecimals.sol +0 -16
- package/test/units/static/JBFixedPointNumber/TestAdjustDecimalsFuzz.sol +0 -71
- package/test/units/static/JBFundAccessLimits/JBFundAccessSetup.sol +0 -24
- package/test/units/static/JBFundAccessLimits/TestFundAccessLimitsEdge.sol +0 -163
- package/test/units/static/JBFundAccessLimits/TestPayoutLimitOf.sol +0 -59
- package/test/units/static/JBFundAccessLimits/TestPayoutLimitsOf.sol +0 -101
- package/test/units/static/JBFundAccessLimits/TestSetFundAccessLimitsFor.sol +0 -189
- package/test/units/static/JBFundAccessLimits/TestSurplusAllowanceOf.sol +0 -64
- package/test/units/static/JBFundAccessLimits/TestSurplusAllowancesOf.sol +0 -102
- package/test/units/static/JBMetadataResolver/TestGetDataFor.sol +0 -90
- package/test/units/static/JBMetadataResolver/TestMetadataResolverEdgeCases.sol +0 -247
- package/test/units/static/JBMetadataResolver/TestMetadataResolverFuzz.sol +0 -229
- package/test/units/static/JBMultiTerminal/JBMultiTerminalSetup.sol +0 -50
- package/test/units/static/JBMultiTerminal/TestAccountingContextsOf.sol +0 -72
- package/test/units/static/JBMultiTerminal/TestAddAccountingContextsFor.sol +0 -289
- package/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol +0 -474
- package/test/units/static/JBMultiTerminal/TestCashOutTokensOf.sol +0 -624
- package/test/units/static/JBMultiTerminal/TestExecutePayout.sol +0 -578
- package/test/units/static/JBMultiTerminal/TestExecuteProcessFee.sol +0 -202
- package/test/units/static/JBMultiTerminal/TestMigrateBalanceOf.sol +0 -222
- package/test/units/static/JBMultiTerminal/TestPay.sol +0 -604
- package/test/units/static/JBMultiTerminal/TestPreviewCashOutFrom.sol +0 -117
- package/test/units/static/JBMultiTerminal/TestPreviewPayFor.sol +0 -114
- package/test/units/static/JBMultiTerminal/TestProcessHeldFeesOf.sol +0 -228
- package/test/units/static/JBMultiTerminal/TestSelfPayRevert.sol +0 -55
- package/test/units/static/JBMultiTerminal/TestSendPayoutsOf.sol +0 -257
- package/test/units/static/JBMultiTerminal/TestUseAllowanceOf.sol +0 -611
- package/test/units/static/JBPermissions/JBPermissionsSetup.sol +0 -20
- package/test/units/static/JBPermissions/TestHasPermission.sol +0 -50
- package/test/units/static/JBPermissions/TestHasPermissions.sol +0 -93
- package/test/units/static/JBPermissions/TestSetPermissionsFor.sol +0 -64
- package/test/units/static/JBPrices/JBPricesSetup.sol +0 -32
- package/test/units/static/JBPrices/TestAddPriceFeedFor.sol +0 -107
- package/test/units/static/JBPrices/TestPricePerUnitOf.sol +0 -132
- package/test/units/static/JBPrices/TestPrices.sol +0 -265
- package/test/units/static/JBProjects/JBProjectsSetup.sol +0 -22
- package/test/units/static/JBProjects/TestCreateFor.sol +0 -71
- package/test/units/static/JBProjects/TestInitialProject.sol +0 -21
- package/test/units/static/JBProjects/TestInterfaces.sol +0 -26
- package/test/units/static/JBProjects/TestSetResolver.sol +0 -37
- package/test/units/static/JBProjects/TestTokenUri.sol +0 -40
- package/test/units/static/JBRulesetMetadataResolver/TestSetCashOutTaxRateTo.sol +0 -108
- package/test/units/static/JBRulesets/JBRulesetsSetup.sol +0 -24
- package/test/units/static/JBRulesets/TestCurrentApprovalStatusForLatestRulesetOf.sol +0 -265
- package/test/units/static/JBRulesets/TestCurrentOf.sol +0 -242
- package/test/units/static/JBRulesets/TestGetRulesetOf.sol +0 -100
- package/test/units/static/JBRulesets/TestLatestQueuedRulesetOf.sol +0 -260
- package/test/units/static/JBRulesets/TestRulesets.sol +0 -632
- package/test/units/static/JBRulesets/TestRulesetsOf.sol +0 -37
- package/test/units/static/JBRulesets/TestUpcomingRulesetOf.sol +0 -522
- package/test/units/static/JBRulesets/TestUpdateRulesetWeightCache.sol +0 -96
- package/test/units/static/JBSplits/JBSplitsSetup.sol +0 -26
- package/test/units/static/JBSplits/TestSelfManagedSplitGroups.sol +0 -552
- package/test/units/static/JBSplits/TestSetSplitGroupsOf.sol +0 -377
- package/test/units/static/JBSplits/TestSplitsLockedEdge.sol +0 -267
- package/test/units/static/JBSplits/TestSplitsOf.sol +0 -24
- package/test/units/static/JBSplits/TestSplitsPacking.sol +0 -36
- package/test/units/static/JBSurplus/TestSurplusFuzz.sol +0 -160
- package/test/units/static/JBTerminalStore/JBTerminalStoreSetup.sol +0 -45
- package/test/units/static/JBTerminalStore/TestCurrentReclaimableSurplusOf.sol +0 -536
- package/test/units/static/JBTerminalStore/TestCurrentSurplusOf.sol +0 -463
- package/test/units/static/JBTerminalStore/TestCurrentTotalSurplusOf.sol +0 -135
- package/test/units/static/JBTerminalStore/TestPreviewCashOutFrom.sol +0 -476
- package/test/units/static/JBTerminalStore/TestPreviewPayFrom.sol +0 -494
- package/test/units/static/JBTerminalStore/TestRecordCashOutsFor.sol +0 -652
- package/test/units/static/JBTerminalStore/TestRecordPaymentFrom.sol +0 -744
- package/test/units/static/JBTerminalStore/TestRecordPayoutFor.sol +0 -289
- package/test/units/static/JBTerminalStore/TestRecordTerminalMigration.sol +0 -138
- package/test/units/static/JBTerminalStore/TestRecordUsedAllowanceOf.sol +0 -415
- package/test/units/static/JBTerminalStore/TestUint224Overflow.sol +0 -219
- package/test/units/static/JBTokens/JBTokensSetup.sol +0 -32
- package/test/units/static/JBTokens/TestBurnFrom.sol +0 -107
- package/test/units/static/JBTokens/TestClaimTokensFor.sol +0 -110
- package/test/units/static/JBTokens/TestDeployERC20ForUnits.sol +0 -92
- package/test/units/static/JBTokens/TestMintFor.sol +0 -100
- package/test/units/static/JBTokens/TestSetTokenFor.sol +0 -98
- package/test/units/static/JBTokens/TestTotalBalanceOf.sol +0 -65
- package/test/units/static/JBTokens/TestTotalSupplyOf.sol +0 -56
- package/test/units/static/JBTokens/TestTransferCreditsFrom.sol +0 -56
|
@@ -1,711 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.6;
|
|
3
|
-
|
|
4
|
-
import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
|
|
5
|
-
import {JBPermissions} from "../src/JBPermissions.sol";
|
|
6
|
-
import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
|
|
7
|
-
import {JBConstants} from "../src/libraries/JBConstants.sol";
|
|
8
|
-
import {JBRulesetMetadataResolver} from "../src/libraries/JBRulesetMetadataResolver.sol";
|
|
9
|
-
import {JBCurrencyAmount} from "../src/structs/JBCurrencyAmount.sol";
|
|
10
|
-
import {JBFundAccessLimitGroup} from "../src/structs/JBFundAccessLimitGroup.sol";
|
|
11
|
-
import {JBPermissionsData} from "../src/structs/JBPermissionsData.sol";
|
|
12
|
-
import {JBRuleset} from "../src/structs/JBRuleset.sol";
|
|
13
|
-
import {JBRulesetConfig} from "../src/structs/JBRulesetConfig.sol";
|
|
14
|
-
import {JBRulesetMetadata} from "../src/structs/JBRulesetMetadata.sol";
|
|
15
|
-
import {JBSplitGroup} from "../src/structs/JBSplitGroup.sol";
|
|
16
|
-
import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
|
|
17
|
-
import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
|
|
18
|
-
import {JBAccountingContext} from "../src/structs/JBAccountingContext.sol";
|
|
19
|
-
|
|
20
|
-
/// @notice Tests for permission system correctness: ROOT restrictions, wildcard, boundary IDs, escalation prevention.
|
|
21
|
-
contract PermissionEscalation_Local is TestBaseWorkflow {
|
|
22
|
-
using JBRulesetMetadataResolver for JBRuleset;
|
|
23
|
-
|
|
24
|
-
uint256 public projectId2;
|
|
25
|
-
uint256 public projectId3;
|
|
26
|
-
address public projectOwner;
|
|
27
|
-
address public alice;
|
|
28
|
-
address public bob;
|
|
29
|
-
address public charlie;
|
|
30
|
-
|
|
31
|
-
function setUp() public override {
|
|
32
|
-
super.setUp();
|
|
33
|
-
projectOwner = multisig();
|
|
34
|
-
alice = address(0xA11CE);
|
|
35
|
-
bob = address(0xB0B);
|
|
36
|
-
charlie = address(0xC4A7);
|
|
37
|
-
|
|
38
|
-
// Launch fee collector project (#1)
|
|
39
|
-
_launchFeeProject();
|
|
40
|
-
|
|
41
|
-
// Launch test project #2
|
|
42
|
-
projectId2 = _launchSimpleProject("project2");
|
|
43
|
-
|
|
44
|
-
// Launch test project #3
|
|
45
|
-
projectId3 = _launchSimpleProject("project3");
|
|
46
|
-
|
|
47
|
-
// Give Alice ROOT on project 2
|
|
48
|
-
uint8[] memory rootPerms = new uint8[](1);
|
|
49
|
-
rootPerms[0] = JBPermissionIds.ROOT;
|
|
50
|
-
vm.prank(projectOwner);
|
|
51
|
-
jbPermissions()
|
|
52
|
-
.setPermissionsFor(
|
|
53
|
-
projectOwner,
|
|
54
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
55
|
-
JBPermissionsData({operator: alice, projectId: uint64(projectId2), permissionIds: rootPerms})
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
60
|
-
// Helpers
|
|
61
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
62
|
-
|
|
63
|
-
function _launchFeeProject() internal {
|
|
64
|
-
JBRulesetConfig[] memory feeRulesetConfig = new JBRulesetConfig[](1);
|
|
65
|
-
feeRulesetConfig[0].mustStartAtOrAfter = 0;
|
|
66
|
-
feeRulesetConfig[0].duration = 0;
|
|
67
|
-
feeRulesetConfig[0].weight = 1000e18;
|
|
68
|
-
feeRulesetConfig[0].weightCutPercent = 0;
|
|
69
|
-
feeRulesetConfig[0].approvalHook = IJBRulesetApprovalHook(address(0));
|
|
70
|
-
feeRulesetConfig[0].metadata = JBRulesetMetadata({
|
|
71
|
-
reservedPercent: 0,
|
|
72
|
-
cashOutTaxRate: 0,
|
|
73
|
-
baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
74
|
-
pausePay: false,
|
|
75
|
-
pauseCreditTransfers: false,
|
|
76
|
-
allowOwnerMinting: false,
|
|
77
|
-
allowSetCustomToken: false,
|
|
78
|
-
allowTerminalMigration: false,
|
|
79
|
-
allowSetTerminals: false,
|
|
80
|
-
ownerMustSendPayouts: false,
|
|
81
|
-
allowSetController: false,
|
|
82
|
-
allowAddAccountingContext: true,
|
|
83
|
-
allowAddPriceFeed: false,
|
|
84
|
-
holdFees: false,
|
|
85
|
-
useTotalSurplusForCashOuts: false,
|
|
86
|
-
useDataHookForPay: false,
|
|
87
|
-
useDataHookForCashOut: false,
|
|
88
|
-
dataHook: address(0),
|
|
89
|
-
metadata: 0
|
|
90
|
-
});
|
|
91
|
-
feeRulesetConfig[0].splitGroups = new JBSplitGroup[](0);
|
|
92
|
-
feeRulesetConfig[0].fundAccessLimitGroups = new JBFundAccessLimitGroup[](0);
|
|
93
|
-
|
|
94
|
-
JBTerminalConfig[] memory terminalConfigurations = _defaultTerminalConfig();
|
|
95
|
-
|
|
96
|
-
jbController()
|
|
97
|
-
.launchProjectFor({
|
|
98
|
-
owner: address(420),
|
|
99
|
-
projectUri: "feeCollector",
|
|
100
|
-
rulesetConfigurations: feeRulesetConfig,
|
|
101
|
-
terminalConfigurations: terminalConfigurations,
|
|
102
|
-
memo: ""
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function _launchSimpleProject(string memory uri) internal returns (uint256) {
|
|
107
|
-
JBRulesetConfig[] memory rulesetConfig = new JBRulesetConfig[](1);
|
|
108
|
-
rulesetConfig[0].mustStartAtOrAfter = 0;
|
|
109
|
-
rulesetConfig[0].duration = 0;
|
|
110
|
-
rulesetConfig[0].weight = 1000e18;
|
|
111
|
-
rulesetConfig[0].weightCutPercent = 0;
|
|
112
|
-
rulesetConfig[0].approvalHook = IJBRulesetApprovalHook(address(0));
|
|
113
|
-
rulesetConfig[0].metadata = JBRulesetMetadata({
|
|
114
|
-
reservedPercent: 0,
|
|
115
|
-
cashOutTaxRate: 3000,
|
|
116
|
-
baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
117
|
-
pausePay: false,
|
|
118
|
-
pauseCreditTransfers: false,
|
|
119
|
-
allowOwnerMinting: true,
|
|
120
|
-
allowSetCustomToken: true,
|
|
121
|
-
allowTerminalMigration: false,
|
|
122
|
-
allowSetTerminals: false,
|
|
123
|
-
ownerMustSendPayouts: false,
|
|
124
|
-
allowSetController: false,
|
|
125
|
-
allowAddAccountingContext: true,
|
|
126
|
-
allowAddPriceFeed: false,
|
|
127
|
-
holdFees: false,
|
|
128
|
-
useTotalSurplusForCashOuts: false,
|
|
129
|
-
useDataHookForPay: false,
|
|
130
|
-
useDataHookForCashOut: false,
|
|
131
|
-
dataHook: address(0),
|
|
132
|
-
metadata: 0
|
|
133
|
-
});
|
|
134
|
-
rulesetConfig[0].splitGroups = new JBSplitGroup[](0);
|
|
135
|
-
rulesetConfig[0].fundAccessLimitGroups = new JBFundAccessLimitGroup[](0);
|
|
136
|
-
|
|
137
|
-
return jbController()
|
|
138
|
-
.launchProjectFor({
|
|
139
|
-
owner: projectOwner,
|
|
140
|
-
projectUri: uri,
|
|
141
|
-
rulesetConfigurations: rulesetConfig,
|
|
142
|
-
terminalConfigurations: _defaultTerminalConfig(),
|
|
143
|
-
memo: ""
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function _defaultTerminalConfig() internal view returns (JBTerminalConfig[] memory) {
|
|
148
|
-
JBTerminalConfig[] memory terminalConfigurations = new JBTerminalConfig[](1);
|
|
149
|
-
JBAccountingContext[] memory tokensToAccept = new JBAccountingContext[](1);
|
|
150
|
-
tokensToAccept[0] = JBAccountingContext({
|
|
151
|
-
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
152
|
-
});
|
|
153
|
-
terminalConfigurations[0] =
|
|
154
|
-
JBTerminalConfig({terminal: jbMultiTerminal(), accountingContextsToAccept: tokensToAccept});
|
|
155
|
-
return terminalConfigurations;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
159
|
-
// Test 1: ROOT cannot set wildcard permissions (projectId=0)
|
|
160
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
161
|
-
|
|
162
|
-
function test_rootOperator_cannotSetWildcardPermissions() public {
|
|
163
|
-
// Alice has ROOT on project 2. She tries to grant Bob permissions at projectId=0 (wildcard).
|
|
164
|
-
uint8[] memory perms = new uint8[](1);
|
|
165
|
-
perms[0] = JBPermissionIds.CASH_OUT_TOKENS;
|
|
166
|
-
|
|
167
|
-
vm.prank(alice);
|
|
168
|
-
vm.expectRevert(
|
|
169
|
-
abi.encodeWithSelector(
|
|
170
|
-
JBPermissions.JBPermissions_Unauthorized.selector, projectOwner, alice, 0, JBPermissionIds.ROOT
|
|
171
|
-
)
|
|
172
|
-
);
|
|
173
|
-
jbPermissions()
|
|
174
|
-
.setPermissionsFor(projectOwner, JBPermissionsData({operator: bob, projectId: 0, permissionIds: perms}));
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
178
|
-
// Test 2: ROOT cannot grant ROOT to a third party
|
|
179
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
180
|
-
|
|
181
|
-
function test_rootOperator_cannotGrantRoot() public {
|
|
182
|
-
// Alice has ROOT on project 2. She tries to grant ROOT to Bob.
|
|
183
|
-
uint8[] memory perms = new uint8[](1);
|
|
184
|
-
perms[0] = JBPermissionIds.ROOT;
|
|
185
|
-
|
|
186
|
-
vm.prank(alice);
|
|
187
|
-
vm.expectRevert(
|
|
188
|
-
abi.encodeWithSelector(
|
|
189
|
-
JBPermissions.JBPermissions_Unauthorized.selector,
|
|
190
|
-
projectOwner,
|
|
191
|
-
alice,
|
|
192
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
193
|
-
uint64(projectId2),
|
|
194
|
-
JBPermissionIds.ROOT
|
|
195
|
-
)
|
|
196
|
-
);
|
|
197
|
-
jbPermissions()
|
|
198
|
-
.setPermissionsFor(
|
|
199
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
200
|
-
projectOwner,
|
|
201
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
202
|
-
JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
207
|
-
// Test 3: ROOT CAN grant non-ROOT permissions (positive test)
|
|
208
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
209
|
-
|
|
210
|
-
function test_rootOperator_canGrantNonRootPermissions() public {
|
|
211
|
-
// Alice has ROOT on project 2. She grants Bob CASH_OUT_TOKENS.
|
|
212
|
-
uint8[] memory perms = new uint8[](1);
|
|
213
|
-
perms[0] = JBPermissionIds.CASH_OUT_TOKENS;
|
|
214
|
-
|
|
215
|
-
vm.prank(alice);
|
|
216
|
-
jbPermissions()
|
|
217
|
-
.setPermissionsFor(
|
|
218
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
219
|
-
projectOwner,
|
|
220
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
221
|
-
JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
|
|
222
|
-
);
|
|
223
|
-
|
|
224
|
-
// Verify Bob now has CASH_OUT_TOKENS
|
|
225
|
-
bool hasPerm = jbPermissions()
|
|
226
|
-
.hasPermission({
|
|
227
|
-
operator: bob,
|
|
228
|
-
account: projectOwner,
|
|
229
|
-
projectId: projectId2,
|
|
230
|
-
permissionId: JBPermissionIds.CASH_OUT_TOKENS,
|
|
231
|
-
includeRoot: false,
|
|
232
|
-
includeWildcardProjectId: false
|
|
233
|
-
});
|
|
234
|
-
assertTrue(hasPerm, "ROOT should be able to grant non-ROOT permissions");
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
238
|
-
// Test 4: Wildcard permission — applies cross-project
|
|
239
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
240
|
-
|
|
241
|
-
function test_wildcardPermission_crossProject() public {
|
|
242
|
-
// Owner grants Bob CASH_OUT_TOKENS at projectId=0 (wildcard)
|
|
243
|
-
uint8[] memory perms = new uint8[](1);
|
|
244
|
-
perms[0] = JBPermissionIds.CASH_OUT_TOKENS;
|
|
245
|
-
|
|
246
|
-
vm.prank(projectOwner);
|
|
247
|
-
jbPermissions()
|
|
248
|
-
.setPermissionsFor(projectOwner, JBPermissionsData({operator: bob, projectId: 0, permissionIds: perms}));
|
|
249
|
-
|
|
250
|
-
// Bob should have CASH_OUT_TOKENS for project 2 (via wildcard)
|
|
251
|
-
bool hasPermProject2 = jbPermissions()
|
|
252
|
-
.hasPermission({
|
|
253
|
-
operator: bob,
|
|
254
|
-
account: projectOwner,
|
|
255
|
-
projectId: projectId2,
|
|
256
|
-
permissionId: JBPermissionIds.CASH_OUT_TOKENS,
|
|
257
|
-
includeRoot: false,
|
|
258
|
-
includeWildcardProjectId: true
|
|
259
|
-
});
|
|
260
|
-
assertTrue(hasPermProject2, "Wildcard should apply to project 2");
|
|
261
|
-
|
|
262
|
-
// Bob should have CASH_OUT_TOKENS for project 3 (via wildcard)
|
|
263
|
-
bool hasPermProject3 = jbPermissions()
|
|
264
|
-
.hasPermission({
|
|
265
|
-
operator: bob,
|
|
266
|
-
account: projectOwner,
|
|
267
|
-
projectId: projectId3,
|
|
268
|
-
permissionId: JBPermissionIds.CASH_OUT_TOKENS,
|
|
269
|
-
includeRoot: false,
|
|
270
|
-
includeWildcardProjectId: true
|
|
271
|
-
});
|
|
272
|
-
assertTrue(hasPermProject3, "Wildcard should apply to project 3");
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
276
|
-
// Test 5: Permission revocation is immediate
|
|
277
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
278
|
-
|
|
279
|
-
function test_permissionRevocation_immediate() public {
|
|
280
|
-
// Grant Bob CASH_OUT_TOKENS on project 2
|
|
281
|
-
uint8[] memory perms = new uint8[](1);
|
|
282
|
-
perms[0] = JBPermissionIds.CASH_OUT_TOKENS;
|
|
283
|
-
|
|
284
|
-
vm.prank(projectOwner);
|
|
285
|
-
jbPermissions()
|
|
286
|
-
.setPermissionsFor(
|
|
287
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
288
|
-
projectOwner,
|
|
289
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
290
|
-
JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
|
|
291
|
-
);
|
|
292
|
-
|
|
293
|
-
// Verify Bob has it
|
|
294
|
-
assertTrue(
|
|
295
|
-
jbPermissions()
|
|
296
|
-
.hasPermission({
|
|
297
|
-
operator: bob,
|
|
298
|
-
account: projectOwner,
|
|
299
|
-
projectId: projectId2,
|
|
300
|
-
permissionId: JBPermissionIds.CASH_OUT_TOKENS,
|
|
301
|
-
includeRoot: false,
|
|
302
|
-
includeWildcardProjectId: false
|
|
303
|
-
}),
|
|
304
|
-
"Bob should have CASH_OUT_TOKENS"
|
|
305
|
-
);
|
|
306
|
-
|
|
307
|
-
// Revoke by setting empty permissions
|
|
308
|
-
uint8[] memory emptyPerms = new uint8[](0);
|
|
309
|
-
|
|
310
|
-
vm.prank(projectOwner);
|
|
311
|
-
jbPermissions()
|
|
312
|
-
.setPermissionsFor(
|
|
313
|
-
projectOwner,
|
|
314
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
315
|
-
JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: emptyPerms})
|
|
316
|
-
);
|
|
317
|
-
|
|
318
|
-
// Immediately verify Bob lost it
|
|
319
|
-
assertFalse(
|
|
320
|
-
jbPermissions()
|
|
321
|
-
.hasPermission({
|
|
322
|
-
operator: bob,
|
|
323
|
-
account: projectOwner,
|
|
324
|
-
projectId: projectId2,
|
|
325
|
-
permissionId: JBPermissionIds.CASH_OUT_TOKENS,
|
|
326
|
-
includeRoot: false,
|
|
327
|
-
includeWildcardProjectId: false
|
|
328
|
-
}),
|
|
329
|
-
"Revocation should be immediate"
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
334
|
-
// Test 6: Bit 255 (ROOT) works. Bit 256 reverts.
|
|
335
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
336
|
-
|
|
337
|
-
function test_permission_bit255_boundary() public {
|
|
338
|
-
// Permission 255 should work (max valid ID)
|
|
339
|
-
uint8[] memory perms = new uint8[](1);
|
|
340
|
-
perms[0] = 255;
|
|
341
|
-
|
|
342
|
-
vm.prank(projectOwner);
|
|
343
|
-
jbPermissions()
|
|
344
|
-
.setPermissionsFor(
|
|
345
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
346
|
-
projectOwner,
|
|
347
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
348
|
-
JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
|
|
349
|
-
);
|
|
350
|
-
|
|
351
|
-
bool hasPerm = jbPermissions()
|
|
352
|
-
.hasPermission({
|
|
353
|
-
operator: bob,
|
|
354
|
-
account: projectOwner,
|
|
355
|
-
projectId: projectId2,
|
|
356
|
-
permissionId: 255,
|
|
357
|
-
includeRoot: false,
|
|
358
|
-
includeWildcardProjectId: false
|
|
359
|
-
});
|
|
360
|
-
assertTrue(hasPerm, "Permission ID 255 should work");
|
|
361
|
-
|
|
362
|
-
// Permission 256 should revert (out of bounds)
|
|
363
|
-
vm.expectRevert(abi.encodeWithSelector(JBPermissions.JBPermissions_PermissionIdOutOfBounds.selector, 256));
|
|
364
|
-
jbPermissions()
|
|
365
|
-
.hasPermission({
|
|
366
|
-
operator: bob,
|
|
367
|
-
account: projectOwner,
|
|
368
|
-
projectId: projectId2,
|
|
369
|
-
permissionId: 256,
|
|
370
|
-
includeRoot: false,
|
|
371
|
-
includeWildcardProjectId: false
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
376
|
-
// Test 7: Permission ID 0 reverts
|
|
377
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
378
|
-
|
|
379
|
-
function test_permission_bit0_rejected() public {
|
|
380
|
-
// Permission 0 is invalid
|
|
381
|
-
uint8[] memory perms = new uint8[](1);
|
|
382
|
-
perms[0] = 0;
|
|
383
|
-
|
|
384
|
-
vm.prank(projectOwner);
|
|
385
|
-
vm.expectRevert(abi.encodeWithSelector(JBPermissions.JBPermissions_NoZeroPermission.selector));
|
|
386
|
-
jbPermissions()
|
|
387
|
-
.setPermissionsFor(
|
|
388
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
389
|
-
projectOwner,
|
|
390
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
391
|
-
JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
396
|
-
// Test 8: Bob can't cashOut Alice's tokens without permission
|
|
397
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
398
|
-
|
|
399
|
-
function test_permissionedOperation_cashOut_requiresPermission() public {
|
|
400
|
-
// Give Alice tokens by paying
|
|
401
|
-
vm.deal(alice, 10 ether);
|
|
402
|
-
vm.prank(alice);
|
|
403
|
-
uint256 tokens = jbMultiTerminal().pay{value: 10 ether}({
|
|
404
|
-
projectId: projectId2,
|
|
405
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
406
|
-
amount: 10 ether,
|
|
407
|
-
beneficiary: alice,
|
|
408
|
-
minReturnedTokens: 0,
|
|
409
|
-
memo: "",
|
|
410
|
-
metadata: new bytes(0)
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
// Bob tries to cash out Alice's tokens without permission
|
|
414
|
-
vm.prank(bob);
|
|
415
|
-
vm.expectRevert();
|
|
416
|
-
jbMultiTerminal()
|
|
417
|
-
.cashOutTokensOf({
|
|
418
|
-
holder: alice,
|
|
419
|
-
projectId: projectId2,
|
|
420
|
-
cashOutCount: tokens,
|
|
421
|
-
tokenToReclaim: JBConstants.NATIVE_TOKEN,
|
|
422
|
-
minTokensReclaimed: 0,
|
|
423
|
-
beneficiary: payable(bob),
|
|
424
|
-
metadata: new bytes(0)
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
429
|
-
// Test 9: ownerMustSendPayouts flag enforcement
|
|
430
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
431
|
-
|
|
432
|
-
function test_permissionedOperation_sendPayouts_ownerMustSend() public {
|
|
433
|
-
// Launch project with ownerMustSendPayouts = true
|
|
434
|
-
JBRulesetConfig[] memory rulesetConfig = new JBRulesetConfig[](1);
|
|
435
|
-
rulesetConfig[0].mustStartAtOrAfter = 0;
|
|
436
|
-
rulesetConfig[0].duration = 0;
|
|
437
|
-
rulesetConfig[0].weight = 1000e18;
|
|
438
|
-
rulesetConfig[0].weightCutPercent = 0;
|
|
439
|
-
rulesetConfig[0].approvalHook = IJBRulesetApprovalHook(address(0));
|
|
440
|
-
rulesetConfig[0].metadata = JBRulesetMetadata({
|
|
441
|
-
reservedPercent: 0,
|
|
442
|
-
cashOutTaxRate: 0,
|
|
443
|
-
baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
444
|
-
pausePay: false,
|
|
445
|
-
pauseCreditTransfers: false,
|
|
446
|
-
allowOwnerMinting: true,
|
|
447
|
-
allowSetCustomToken: true,
|
|
448
|
-
allowTerminalMigration: false,
|
|
449
|
-
allowSetTerminals: false,
|
|
450
|
-
ownerMustSendPayouts: true, // KEY
|
|
451
|
-
allowSetController: false,
|
|
452
|
-
allowAddAccountingContext: true,
|
|
453
|
-
allowAddPriceFeed: false,
|
|
454
|
-
holdFees: false,
|
|
455
|
-
useTotalSurplusForCashOuts: false,
|
|
456
|
-
useDataHookForPay: false,
|
|
457
|
-
useDataHookForCashOut: false,
|
|
458
|
-
dataHook: address(0),
|
|
459
|
-
metadata: 0
|
|
460
|
-
});
|
|
461
|
-
rulesetConfig[0].splitGroups = new JBSplitGroup[](0);
|
|
462
|
-
|
|
463
|
-
JBCurrencyAmount[] memory payoutLimits = new JBCurrencyAmount[](1);
|
|
464
|
-
payoutLimits[0] = JBCurrencyAmount({amount: 10 ether, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))});
|
|
465
|
-
JBFundAccessLimitGroup[] memory fundAccessLimitGroups = new JBFundAccessLimitGroup[](1);
|
|
466
|
-
fundAccessLimitGroups[0] = JBFundAccessLimitGroup({
|
|
467
|
-
terminal: address(jbMultiTerminal()),
|
|
468
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
469
|
-
payoutLimits: payoutLimits,
|
|
470
|
-
surplusAllowances: new JBCurrencyAmount[](0)
|
|
471
|
-
});
|
|
472
|
-
rulesetConfig[0].fundAccessLimitGroups = fundAccessLimitGroups;
|
|
473
|
-
|
|
474
|
-
uint256 pid = jbController()
|
|
475
|
-
.launchProjectFor({
|
|
476
|
-
owner: projectOwner,
|
|
477
|
-
projectUri: "ownerMustPayTest",
|
|
478
|
-
rulesetConfigurations: rulesetConfig,
|
|
479
|
-
terminalConfigurations: _defaultTerminalConfig(),
|
|
480
|
-
memo: ""
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
// Fund the project
|
|
484
|
-
vm.deal(address(0xBA1E), 20 ether);
|
|
485
|
-
vm.prank(address(0xBA1E));
|
|
486
|
-
jbMultiTerminal().pay{value: 20 ether}({
|
|
487
|
-
projectId: pid,
|
|
488
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
489
|
-
amount: 20 ether,
|
|
490
|
-
beneficiary: address(0xBA1E),
|
|
491
|
-
minReturnedTokens: 0,
|
|
492
|
-
memo: "",
|
|
493
|
-
metadata: new bytes(0)
|
|
494
|
-
});
|
|
495
|
-
|
|
496
|
-
// Grant Bob SEND_PAYOUTS permission
|
|
497
|
-
uint8[] memory perms = new uint8[](1);
|
|
498
|
-
perms[0] = JBPermissionIds.SEND_PAYOUTS;
|
|
499
|
-
vm.prank(projectOwner);
|
|
500
|
-
jbPermissions()
|
|
501
|
-
.setPermissionsFor(
|
|
502
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
503
|
-
projectOwner,
|
|
504
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
505
|
-
JBPermissionsData({operator: bob, projectId: uint64(pid), permissionIds: perms})
|
|
506
|
-
);
|
|
507
|
-
|
|
508
|
-
// Charlie (no permission) tries to send payouts — should fail because ownerMustSendPayouts
|
|
509
|
-
// requires SEND_PAYOUTS permission
|
|
510
|
-
vm.prank(charlie);
|
|
511
|
-
vm.expectRevert();
|
|
512
|
-
jbMultiTerminal()
|
|
513
|
-
.sendPayoutsOf({
|
|
514
|
-
projectId: pid,
|
|
515
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
516
|
-
amount: 5 ether,
|
|
517
|
-
currency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
518
|
-
minTokensPaidOut: 0
|
|
519
|
-
});
|
|
520
|
-
|
|
521
|
-
// Bob (with SEND_PAYOUTS permission) CAN send payouts
|
|
522
|
-
vm.prank(bob);
|
|
523
|
-
jbMultiTerminal()
|
|
524
|
-
.sendPayoutsOf({
|
|
525
|
-
projectId: pid,
|
|
526
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
527
|
-
amount: 5 ether,
|
|
528
|
-
currency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
529
|
-
minTokensPaidOut: 0
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
534
|
-
// Test 10: ROOT on project 2 has no power over project 3
|
|
535
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
536
|
-
|
|
537
|
-
function test_permission_rootOnProject_doesNotAffectOtherProject() public view {
|
|
538
|
-
// Alice has ROOT on project 2 (from setUp)
|
|
539
|
-
// Alice should NOT have any permissions on project 3
|
|
540
|
-
bool hasPermOnProject3 = jbPermissions()
|
|
541
|
-
.hasPermission({
|
|
542
|
-
operator: alice,
|
|
543
|
-
account: projectOwner,
|
|
544
|
-
projectId: projectId3,
|
|
545
|
-
permissionId: JBPermissionIds.ROOT,
|
|
546
|
-
includeRoot: true,
|
|
547
|
-
includeWildcardProjectId: false
|
|
548
|
-
});
|
|
549
|
-
assertFalse(hasPermOnProject3, "ROOT on project 2 must not grant power over project 3");
|
|
550
|
-
|
|
551
|
-
bool hasCashOutOnProject3 = jbPermissions()
|
|
552
|
-
.hasPermission({
|
|
553
|
-
operator: alice,
|
|
554
|
-
account: projectOwner,
|
|
555
|
-
projectId: projectId3,
|
|
556
|
-
permissionId: JBPermissionIds.CASH_OUT_TOKENS,
|
|
557
|
-
includeRoot: true,
|
|
558
|
-
includeWildcardProjectId: false
|
|
559
|
-
});
|
|
560
|
-
assertFalse(hasCashOutOnProject3, "ROOT on project 2 must not grant CASH_OUT on project 3");
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
564
|
-
// Test 11: Double set overwrites previous (not additive)
|
|
565
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
566
|
-
|
|
567
|
-
function test_permission_doubleSet_overwritesPrevious() public {
|
|
568
|
-
// Grant Bob CASH_OUT_TOKENS + BURN_TOKENS
|
|
569
|
-
uint8[] memory perms1 = new uint8[](2);
|
|
570
|
-
perms1[0] = JBPermissionIds.CASH_OUT_TOKENS;
|
|
571
|
-
perms1[1] = JBPermissionIds.BURN_TOKENS;
|
|
572
|
-
|
|
573
|
-
vm.prank(projectOwner);
|
|
574
|
-
jbPermissions()
|
|
575
|
-
.setPermissionsFor(
|
|
576
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
577
|
-
projectOwner,
|
|
578
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
579
|
-
JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms1})
|
|
580
|
-
);
|
|
581
|
-
|
|
582
|
-
assertTrue(
|
|
583
|
-
jbPermissions()
|
|
584
|
-
.hasPermission({
|
|
585
|
-
operator: bob,
|
|
586
|
-
account: projectOwner,
|
|
587
|
-
projectId: projectId2,
|
|
588
|
-
permissionId: JBPermissionIds.CASH_OUT_TOKENS,
|
|
589
|
-
includeRoot: false,
|
|
590
|
-
includeWildcardProjectId: false
|
|
591
|
-
}),
|
|
592
|
-
"Bob should have CASH_OUT_TOKENS"
|
|
593
|
-
);
|
|
594
|
-
assertTrue(
|
|
595
|
-
jbPermissions()
|
|
596
|
-
.hasPermission({
|
|
597
|
-
operator: bob,
|
|
598
|
-
account: projectOwner,
|
|
599
|
-
projectId: projectId2,
|
|
600
|
-
permissionId: JBPermissionIds.BURN_TOKENS,
|
|
601
|
-
includeRoot: false,
|
|
602
|
-
includeWildcardProjectId: false
|
|
603
|
-
}),
|
|
604
|
-
"Bob should have BURN_TOKENS"
|
|
605
|
-
);
|
|
606
|
-
|
|
607
|
-
// Now set ONLY MINT_TOKENS — should replace all previous
|
|
608
|
-
uint8[] memory perms2 = new uint8[](1);
|
|
609
|
-
perms2[0] = JBPermissionIds.MINT_TOKENS;
|
|
610
|
-
|
|
611
|
-
vm.prank(projectOwner);
|
|
612
|
-
jbPermissions()
|
|
613
|
-
.setPermissionsFor(
|
|
614
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
615
|
-
projectOwner,
|
|
616
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
617
|
-
JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms2})
|
|
618
|
-
);
|
|
619
|
-
|
|
620
|
-
// Bob should only have MINT_TOKENS, not the previous ones
|
|
621
|
-
assertTrue(
|
|
622
|
-
jbPermissions()
|
|
623
|
-
.hasPermission({
|
|
624
|
-
operator: bob,
|
|
625
|
-
account: projectOwner,
|
|
626
|
-
projectId: projectId2,
|
|
627
|
-
permissionId: JBPermissionIds.MINT_TOKENS,
|
|
628
|
-
includeRoot: false,
|
|
629
|
-
includeWildcardProjectId: false
|
|
630
|
-
}),
|
|
631
|
-
"Bob should now have MINT_TOKENS"
|
|
632
|
-
);
|
|
633
|
-
assertFalse(
|
|
634
|
-
jbPermissions()
|
|
635
|
-
.hasPermission({
|
|
636
|
-
operator: bob,
|
|
637
|
-
account: projectOwner,
|
|
638
|
-
projectId: projectId2,
|
|
639
|
-
permissionId: JBPermissionIds.CASH_OUT_TOKENS,
|
|
640
|
-
includeRoot: false,
|
|
641
|
-
includeWildcardProjectId: false
|
|
642
|
-
}),
|
|
643
|
-
"Bob should no longer have CASH_OUT_TOKENS (overwritten)"
|
|
644
|
-
);
|
|
645
|
-
assertFalse(
|
|
646
|
-
jbPermissions()
|
|
647
|
-
.hasPermission({
|
|
648
|
-
operator: bob,
|
|
649
|
-
account: projectOwner,
|
|
650
|
-
projectId: projectId2,
|
|
651
|
-
permissionId: JBPermissionIds.BURN_TOKENS,
|
|
652
|
-
includeRoot: false,
|
|
653
|
-
includeWildcardProjectId: false
|
|
654
|
-
}),
|
|
655
|
-
"Bob should no longer have BURN_TOKENS (overwritten)"
|
|
656
|
-
);
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
660
|
-
// Test 12: ERC2771 meta-tx uses correct msg.sender for permissions
|
|
661
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
662
|
-
|
|
663
|
-
function test_rootPermission_trustedForwarder() public {
|
|
664
|
-
// Grant Bob ROOT on project 2
|
|
665
|
-
uint8[] memory perms = new uint8[](1);
|
|
666
|
-
perms[0] = JBPermissionIds.CASH_OUT_TOKENS;
|
|
667
|
-
|
|
668
|
-
vm.prank(projectOwner);
|
|
669
|
-
jbPermissions()
|
|
670
|
-
.setPermissionsFor(
|
|
671
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
672
|
-
projectOwner,
|
|
673
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
674
|
-
JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
|
|
675
|
-
);
|
|
676
|
-
|
|
677
|
-
// Call from trusted forwarder with Bob appended as sender
|
|
678
|
-
// The permission check should use Bob's address, not the forwarder
|
|
679
|
-
address forwarder = trustedForwarder();
|
|
680
|
-
|
|
681
|
-
// Verify the forwarder is set up correctly
|
|
682
|
-
assertTrue(forwarder != address(0), "Trusted forwarder should be set");
|
|
683
|
-
|
|
684
|
-
// Direct call should return true
|
|
685
|
-
bool hasPerm = jbPermissions()
|
|
686
|
-
.hasPermission({
|
|
687
|
-
operator: bob,
|
|
688
|
-
account: projectOwner,
|
|
689
|
-
projectId: projectId2,
|
|
690
|
-
permissionId: JBPermissionIds.CASH_OUT_TOKENS,
|
|
691
|
-
includeRoot: false,
|
|
692
|
-
includeWildcardProjectId: false
|
|
693
|
-
});
|
|
694
|
-
assertTrue(hasPerm, "Bob should have CASH_OUT_TOKENS via direct call");
|
|
695
|
-
|
|
696
|
-
// Verify that permission checking respects msg.sender context
|
|
697
|
-
// Charlie (unpermissioned) cannot use Bob's permissions
|
|
698
|
-
bool charlieHasPerm = jbPermissions()
|
|
699
|
-
.hasPermission({
|
|
700
|
-
operator: charlie,
|
|
701
|
-
account: projectOwner,
|
|
702
|
-
projectId: projectId2,
|
|
703
|
-
permissionId: JBPermissionIds.CASH_OUT_TOKENS,
|
|
704
|
-
includeRoot: false,
|
|
705
|
-
includeWildcardProjectId: false
|
|
706
|
-
});
|
|
707
|
-
assertFalse(charlieHasPerm, "Charlie should NOT have Bob's CASH_OUT_TOKENS");
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
receive() external payable {}
|
|
711
|
-
}
|