@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
|
@@ -7,8 +7,12 @@ import {IJBFundAccessLimits} from "./interfaces/IJBFundAccessLimits.sol";
|
|
|
7
7
|
import {JBCurrencyAmount} from "./structs/JBCurrencyAmount.sol";
|
|
8
8
|
import {JBFundAccessLimitGroup} from "./structs/JBFundAccessLimitGroup.sol";
|
|
9
9
|
|
|
10
|
-
/// @notice
|
|
11
|
-
///
|
|
10
|
+
/// @notice Controls how much a project can withdraw from its terminals each funding cycle. Two types of limits:
|
|
11
|
+
/// **Payout limits** cap how much can be distributed to splits and the project owner. **Surplus allowances** cap how
|
|
12
|
+
/// much the project owner can pull from the surplus (funds above payout limits). Both reset each ruleset cycle.
|
|
13
|
+
/// @dev Limits are denominated in a currency (which may differ from the held token) and resolved at withdrawal time
|
|
14
|
+
/// via `JBPrices`. An empty `fundAccessLimitGroups` array means zero access (not unlimited) — use `type(uint224).max`
|
|
15
|
+
/// for unlimited.
|
|
12
16
|
contract JBFundAccessLimits is JBControlled, IJBFundAccessLimits {
|
|
13
17
|
//*********************************************************************//
|
|
14
18
|
// --------------------------- custom errors ------------------------- //
|
|
@@ -61,10 +65,11 @@ contract JBFundAccessLimits is JBControlled, IJBFundAccessLimits {
|
|
|
61
65
|
// ---------------------- external transactions ---------------------- //
|
|
62
66
|
//*********************************************************************//
|
|
63
67
|
|
|
64
|
-
/// @notice
|
|
65
|
-
///
|
|
66
|
-
///
|
|
67
|
-
///
|
|
68
|
+
/// @notice Configure how much a project can withdraw from each of its terminals during a ruleset. Payout limits
|
|
69
|
+
/// cap how much can be distributed to splits/owner; surplus allowances cap how much extra the owner can pull from
|
|
70
|
+
/// surplus. Both reset each funding cycle.
|
|
71
|
+
/// @dev Only a project's controller can set fund access limits (called during `queueRulesetsOf`).
|
|
72
|
+
/// @dev Limits within each group must be sorted by currency in strictly increasing order to prevent duplicates.
|
|
68
73
|
/// @param projectId The ID of the project whose fund access limits are being set.
|
|
69
74
|
/// @param rulesetId The ID of the ruleset that the limits will apply within.
|
|
70
75
|
/// @param fundAccessLimitGroups An array containing payout limits and surplus allowances for each payment terminal.
|
|
@@ -152,14 +157,15 @@ contract JBFundAccessLimits is JBControlled, IJBFundAccessLimits {
|
|
|
152
157
|
// ------------------------- external views -------------------------- //
|
|
153
158
|
//*********************************************************************//
|
|
154
159
|
|
|
155
|
-
/// @notice
|
|
156
|
-
///
|
|
160
|
+
/// @notice Look up how much a project can distribute (via `sendPayoutsOf`) from a specific terminal and token,
|
|
161
|
+
/// denominated in a specific currency. Returns 0 if no limit is configured for that currency.
|
|
162
|
+
/// @dev The fixed point return amount uses the same number of decimals as the terminal.
|
|
157
163
|
/// @param projectId The project's ID.
|
|
158
164
|
/// @param rulesetId The ruleset's ID.
|
|
159
165
|
/// @param terminal The terminal the payout limit applies to.
|
|
160
166
|
/// @param token The token the payout limit applies to.
|
|
161
167
|
/// @param currency The currency the payout limit is denominated in.
|
|
162
|
-
/// @return payoutLimit The payout limit, as a fixed point number with the same number of decimals as the
|
|
168
|
+
/// @return payoutLimit The payout limit, as a fixed point number with the same number of decimals as the
|
|
163
169
|
/// terminal.
|
|
164
170
|
function payoutLimitOf(
|
|
165
171
|
uint256 projectId,
|
|
@@ -195,10 +201,9 @@ contract JBFundAccessLimits is JBControlled, IJBFundAccessLimits {
|
|
|
195
201
|
}
|
|
196
202
|
}
|
|
197
203
|
|
|
198
|
-
/// @notice
|
|
199
|
-
///
|
|
200
|
-
///
|
|
201
|
-
/// @dev The fixed point `amount`s returned will use the same number of decimals as the `terminal`.
|
|
204
|
+
/// @notice Get all payout limits for a project's terminal and token during a ruleset. A project can have multiple
|
|
205
|
+
/// payout limits denominated in different currencies (e.g. 10,000 USD + 5 ETH). Each is enforced independently.
|
|
206
|
+
/// @dev The fixed point `amount`s returned use the same number of decimals as the terminal.
|
|
202
207
|
/// @param projectId The project's ID.
|
|
203
208
|
/// @param rulesetId The ruleset's ID.
|
|
204
209
|
/// @param terminal The terminal the payout limits apply to.
|
|
@@ -243,15 +248,16 @@ contract JBFundAccessLimits is JBControlled, IJBFundAccessLimits {
|
|
|
243
248
|
}
|
|
244
249
|
}
|
|
245
250
|
|
|
246
|
-
/// @notice
|
|
247
|
-
///
|
|
251
|
+
/// @notice Look up how much a project's owner can withdraw from the surplus (via `useAllowanceOf`) from a specific
|
|
252
|
+
/// terminal and token, denominated in a specific currency. Returns 0 if no allowance is configured.
|
|
253
|
+
/// @dev The fixed point return amount uses the same number of decimals as the terminal.
|
|
248
254
|
/// @param projectId The project's ID.
|
|
249
255
|
/// @param rulesetId The ruleset's ID.
|
|
250
256
|
/// @param terminal The terminal the surplus allowance applies to.
|
|
251
257
|
/// @param token The token the surplus allowance applies to.
|
|
252
258
|
/// @param currency The currency that the surplus allowance is denominated in.
|
|
253
259
|
/// @return surplusAllowance The surplus allowance, as a fixed point number with the same number of decimals as the
|
|
254
|
-
///
|
|
260
|
+
/// terminal.
|
|
255
261
|
function surplusAllowanceOf(
|
|
256
262
|
uint256 projectId,
|
|
257
263
|
uint256 rulesetId,
|
|
@@ -287,11 +293,9 @@ contract JBFundAccessLimits is JBControlled, IJBFundAccessLimits {
|
|
|
287
293
|
}
|
|
288
294
|
}
|
|
289
295
|
|
|
290
|
-
/// @notice
|
|
291
|
-
///
|
|
292
|
-
///
|
|
293
|
-
/// currency.
|
|
294
|
-
/// @dev The fixed point `amount`s returned will use the same number of decimals as the `terminal`.
|
|
296
|
+
/// @notice Get all surplus allowances for a project's terminal and token during a ruleset. Like payout limits, a
|
|
297
|
+
/// project can have multiple surplus allowances in different currencies, each enforced independently.
|
|
298
|
+
/// @dev The fixed point `amount`s returned use the same number of decimals as the terminal.
|
|
295
299
|
/// @param projectId The project's ID.
|
|
296
300
|
/// @param rulesetId The ruleset's ID.
|
|
297
301
|
/// @param terminal The terminal the surplus allowances apply to.
|
package/src/JBMultiTerminal.sol
CHANGED
|
@@ -45,8 +45,13 @@ import {JBSplit} from "./structs/JBSplit.sol";
|
|
|
45
45
|
import {JBSplitHookContext} from "./structs/JBSplitHookContext.sol";
|
|
46
46
|
import {JBTokenAmount} from "./structs/JBTokenAmount.sol";
|
|
47
47
|
|
|
48
|
-
/// @notice
|
|
49
|
-
///
|
|
48
|
+
/// @notice The main entry point for all money movement in Juicebox. Handles payments (ETH or ERC-20), cash outs
|
|
49
|
+
/// (burning tokens to reclaim funds), payouts (distributing funds to splits), and surplus allowance withdrawals.
|
|
50
|
+
/// Charges a 2.5% protocol fee on outflows (held for 28 days before processing). Supports Permit2 for gasless
|
|
51
|
+
/// ERC-20 approvals.
|
|
52
|
+
/// @dev Each project can have multiple terminals for different tokens. The terminal delegates accounting to
|
|
53
|
+
/// `JBTerminalStore` and splits distribution to `JBSplits`. Fees are sent to project #1 (the fee beneficiary).
|
|
54
|
+
/// All external hook calls (pay hooks, cash-out hooks, split hooks) are wrapped in try-catch to prevent griefing.
|
|
50
55
|
contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
51
56
|
// A library that parses the packed ruleset metadata into a friendlier format.
|
|
52
57
|
using JBRulesetMetadataResolver for JBRuleset;
|
|
@@ -83,6 +88,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
83
88
|
// ------------------------ internal constants ----------------------- //
|
|
84
89
|
//*********************************************************************//
|
|
85
90
|
|
|
91
|
+
/// @notice Denominator for forward-calculating this terminal's fee from a pre-fee amount.
|
|
92
|
+
uint256 internal constant _FEE_AMOUNT_FROM_DENOMINATOR = JBConstants.MAX_FEE / FEE;
|
|
93
|
+
|
|
86
94
|
/// @notice Project ID #1 receives fees. It should be the first project launched during the deployment process.
|
|
87
95
|
uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;
|
|
88
96
|
|
|
@@ -182,10 +190,10 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
182
190
|
// ---------------------- external transactions ---------------------- //
|
|
183
191
|
//*********************************************************************//
|
|
184
192
|
|
|
185
|
-
/// @notice
|
|
186
|
-
///
|
|
187
|
-
/// @dev Only
|
|
188
|
-
///
|
|
193
|
+
/// @notice Registers new tokens that this terminal can accept for a project. Once a token's accounting context is
|
|
194
|
+
/// added, the project can receive payments in that token.
|
|
195
|
+
/// @dev Only the project's owner, an operator with `ADD_ACCOUNTING_CONTEXTS` permission, or the project's
|
|
196
|
+
/// controller can call this.
|
|
189
197
|
/// @param projectId The ID of the project having to add accounting contexts for.
|
|
190
198
|
/// @param accountingContexts The accounting contexts to add.
|
|
191
199
|
function addAccountingContextsFor(
|
|
@@ -216,8 +224,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
216
224
|
}
|
|
217
225
|
}
|
|
218
226
|
|
|
219
|
-
/// @notice Adds funds to a project's balance without minting tokens.
|
|
220
|
-
///
|
|
227
|
+
/// @notice Adds funds to a project's balance without minting tokens. Useful for topping up a project or returning
|
|
228
|
+
/// funds. Can also unlock previously held fees by returning them to the project's balance.
|
|
229
|
+
/// @dev If `shouldReturnHeldFees` is true, the added amount offsets held fees proportionally.
|
|
221
230
|
/// @param projectId The ID of the project to add funds to the balance of.
|
|
222
231
|
/// @param amount The amount of tokens to add to the balance, as a fixed point number with the same number of
|
|
223
232
|
/// decimals as this terminal. If this is a native token terminal, this is ignored and `msg.value` is used instead.
|
|
@@ -248,10 +257,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
248
257
|
});
|
|
249
258
|
}
|
|
250
259
|
|
|
251
|
-
/// @notice
|
|
252
|
-
///
|
|
253
|
-
/// @dev Only
|
|
254
|
-
/// those tokens.
|
|
260
|
+
/// @notice Burns project tokens to reclaim a share of the project's surplus (determined by the bonding curve) or
|
|
261
|
+
/// to trigger custom logic through the ruleset's data hook and cash out hook.
|
|
262
|
+
/// @dev Only the token holder or an operator with `CASH_OUT_TOKENS` permission from that holder can call this.
|
|
255
263
|
/// @param holder The account whose tokens are being cashed out.
|
|
256
264
|
/// @param projectId The ID of the project the project tokens belong to.
|
|
257
265
|
/// @param cashOutCount The number of project tokens to cash out and burn, as a fixed point number with 18
|
|
@@ -330,15 +338,18 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
330
338
|
// This payout is eligible for a fee since the funds are leaving this contract and the split hook isn't a
|
|
331
339
|
// feeless address.
|
|
332
340
|
if (!_isFeeless(address(split.hook))) {
|
|
333
|
-
|
|
341
|
+
unchecked {
|
|
342
|
+
netPayoutAmount -= _feeAmountFrom(amount);
|
|
343
|
+
}
|
|
334
344
|
}
|
|
335
345
|
|
|
336
346
|
// Create the context to send to the split hook.
|
|
337
347
|
JBSplitHookContext memory context = JBSplitHookContext({
|
|
338
348
|
token: token,
|
|
339
349
|
amount: netPayoutAmount,
|
|
340
|
-
decimals: STORE.accountingContextOf({
|
|
341
|
-
|
|
350
|
+
decimals: STORE.accountingContextOf({
|
|
351
|
+
terminal: address(this), projectId: projectId, token: token
|
|
352
|
+
}).decimals,
|
|
342
353
|
projectId: projectId,
|
|
343
354
|
groupId: uint256(uint160(token)),
|
|
344
355
|
split: split
|
|
@@ -370,7 +381,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
370
381
|
// This payout is eligible for a fee if the funds are leaving this contract and the receiving terminal isn't
|
|
371
382
|
// a feeless address.
|
|
372
383
|
if (terminal != this && !_isFeeless(address(terminal))) {
|
|
373
|
-
|
|
384
|
+
unchecked {
|
|
385
|
+
netPayoutAmount -= _feeAmountFrom(amount);
|
|
386
|
+
}
|
|
374
387
|
}
|
|
375
388
|
|
|
376
389
|
// Track the fee-free payout amount. During cashout at zero tax rate, fees apply
|
|
@@ -430,7 +443,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
430
443
|
// This payout is eligible for a fee since the funds are leaving this contract and the recipient isn't a
|
|
431
444
|
// feeless address.
|
|
432
445
|
if (!_isFeeless(recipient)) {
|
|
433
|
-
|
|
446
|
+
unchecked {
|
|
447
|
+
netPayoutAmount -= _feeAmountFrom(amount);
|
|
448
|
+
}
|
|
434
449
|
}
|
|
435
450
|
|
|
436
451
|
// If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the
|
|
@@ -553,7 +568,8 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
553
568
|
}
|
|
554
569
|
}
|
|
555
570
|
|
|
556
|
-
/// @notice Pay a project with tokens.
|
|
571
|
+
/// @notice Pay a project with tokens. The project's current ruleset determines how many project tokens the
|
|
572
|
+
/// beneficiary receives in return.
|
|
557
573
|
/// @param projectId The ID of the project being paid.
|
|
558
574
|
/// @param amount The amount of terminal tokens being received, as a fixed point number with the same number of
|
|
559
575
|
/// decimals as this terminal. If this terminal's token is native, this is ignored and `msg.value` is used in its
|
|
@@ -612,19 +628,13 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
612
628
|
_checkMin({value: beneficiaryTokenCount, min: minReturnedTokens});
|
|
613
629
|
}
|
|
614
630
|
|
|
615
|
-
/// @notice
|
|
616
|
-
///
|
|
617
|
-
///
|
|
618
|
-
/// @dev
|
|
619
|
-
///
|
|
620
|
-
///
|
|
621
|
-
///
|
|
622
|
-
/// (e.g. the fee terminal rejects the payment), the catch block calls `_recordAddedBalanceFor` to credit the fee
|
|
623
|
-
/// amount back to the project. This credit is backed by the tokens that failed to transfer out. No phantom balance
|
|
624
|
-
/// is created because the tokens never left.
|
|
625
|
-
/// @dev The index-increment-before-`_processFee` pattern is intentional: locked (not-yet-unlocked) fees are skipped
|
|
626
|
-
/// via the `unlockTimestamp` check, and advancing the index before the external call prevents reentrancy from
|
|
627
|
-
/// reprocessing the same fee entry.
|
|
631
|
+
/// @notice Processes held fees for a project, sending them to the protocol's fee project. Fees are held for 28 days
|
|
632
|
+
/// after a payout — processing them finalizes the fee payment.
|
|
633
|
+
/// @dev Only processes fees whose `unlockTimestamp` has passed. Stops early if it encounters a still-locked fee.
|
|
634
|
+
/// @dev Reentrancy-safe: re-reads `_nextHeldFeeIndexOf` from storage each iteration and advances the index before
|
|
635
|
+
/// the external `_processFee` call, preventing double-processing.
|
|
636
|
+
/// @dev If `_processFee` reverts (fee terminal rejects), the fee amount is returned to the project's balance
|
|
637
|
+
/// (forgiven, not retried). A `FeeReverted` event is emitted for off-chain observability.
|
|
628
638
|
/// @param projectId The ID of the project to process held fees for.
|
|
629
639
|
/// @param token The token to process held fees for.
|
|
630
640
|
/// @param count The number of fees to process.
|
|
@@ -647,6 +657,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
647
657
|
|
|
648
658
|
// Can't process fees that aren't yet unlocked. Fees unlock sequentially in the array, so nothing left to do
|
|
649
659
|
// if the current fee isn't yet unlocked.
|
|
660
|
+
// forge-lint: disable-next-line(block-timestamp)
|
|
650
661
|
if (heldFee.unlockTimestamp > block.timestamp) break;
|
|
651
662
|
|
|
652
663
|
// Delete the entry and advance the index *before* the external call. This is intentional:
|
|
@@ -664,7 +675,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
664
675
|
_processFee({
|
|
665
676
|
projectId: projectId,
|
|
666
677
|
token: token,
|
|
667
|
-
amount:
|
|
678
|
+
amount: _feeAmountFrom(heldFee.amount),
|
|
668
679
|
beneficiary: heldFee.beneficiary,
|
|
669
680
|
feeTerminal: feeTerminal,
|
|
670
681
|
wasHeld: true
|
|
@@ -684,15 +695,12 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
684
695
|
}
|
|
685
696
|
}
|
|
686
697
|
|
|
687
|
-
/// @notice
|
|
688
|
-
/// payout limit.
|
|
689
|
-
/// @dev If
|
|
690
|
-
///
|
|
691
|
-
/// @dev
|
|
692
|
-
///
|
|
693
|
-
/// be used to incentivize calling this function.
|
|
694
|
-
/// @dev payouts sent to addresses which aren't feeless incur the protocol fee.
|
|
695
|
-
/// @dev Payouts a projects don't incur fees if its terminal is feeless.
|
|
698
|
+
/// @notice Distributes funds from a project's balance to its payout split recipients, up to the current ruleset's
|
|
699
|
+
/// payout limit. Anyone can call this on behalf of any project.
|
|
700
|
+
/// @dev If splits don't add up to 100%, the remainder goes to the project owner. A wildcard split (no hook,
|
|
701
|
+
/// projectId, or beneficiary) sends its share to `msg.sender` — useful for incentivizing the call.
|
|
702
|
+
/// @dev Payouts to non-feeless addresses incur the 2.5% protocol fee. Projects whose terminal is feeless are
|
|
703
|
+
/// exempt.
|
|
696
704
|
/// @param projectId The ID of the project having its payouts sent.
|
|
697
705
|
/// @param token The token being sent.
|
|
698
706
|
/// @param amount The total number of terminal tokens to send, as a fixed point number with same number of decimals
|
|
@@ -720,10 +728,10 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
720
728
|
_checkMin({value: amountPaidOut, min: minTokensPaidOut});
|
|
721
729
|
}
|
|
722
730
|
|
|
723
|
-
/// @notice
|
|
724
|
-
///
|
|
725
|
-
///
|
|
726
|
-
/// @dev Incurs the protocol fee unless the caller is a feeless address.
|
|
731
|
+
/// @notice Withdraws funds from a project's surplus (beyond what's needed for payouts) up to the current ruleset's
|
|
732
|
+
/// surplus allowance. Sent directly to a beneficiary address rather than through splits.
|
|
733
|
+
/// @dev Only the project's owner or an operator with `USE_ALLOWANCE` permission can call this.
|
|
734
|
+
/// @dev Incurs the 2.5% protocol fee unless the caller is a feeless address.
|
|
727
735
|
/// @param projectId The ID of the project to use the surplus allowance of.
|
|
728
736
|
/// @param token The token being paid out from the surplus.
|
|
729
737
|
/// @param amount The amount of terminal tokens to use from the project's current surplus allowance, as a fixed
|
|
@@ -777,8 +785,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
777
785
|
// ------------------------- external views -------------------------- //
|
|
778
786
|
//*********************************************************************//
|
|
779
787
|
|
|
780
|
-
/// @notice
|
|
781
|
-
/// @dev See the `JBAccountingContext` struct for more information.
|
|
788
|
+
/// @notice Returns the accounting context (decimals, currency) for a specific token that a project accepts.
|
|
782
789
|
/// @param projectId The ID of the project to get token accounting context of.
|
|
783
790
|
/// @param token The token to check the accounting context of.
|
|
784
791
|
/// @return The token's accounting context for the token.
|
|
@@ -794,15 +801,16 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
794
801
|
return STORE.accountingContextOf({terminal: address(this), projectId: projectId, token: token});
|
|
795
802
|
}
|
|
796
803
|
|
|
797
|
-
/// @notice
|
|
804
|
+
/// @notice Returns accounting contexts for all tokens a project currently accepts through this terminal.
|
|
798
805
|
/// @param projectId The ID of the project to get the accepted tokens of.
|
|
799
806
|
/// @return tokenContexts The accounting contexts of the accepted tokens.
|
|
800
807
|
function accountingContextsOf(uint256 projectId) external view override returns (JBAccountingContext[] memory) {
|
|
801
808
|
return STORE.accountingContextsOf({terminal: address(this), projectId: projectId});
|
|
802
809
|
}
|
|
803
810
|
|
|
804
|
-
/// @notice
|
|
805
|
-
///
|
|
811
|
+
/// @notice Returns the project's current surplus in this terminal, converted to a specified currency. The surplus
|
|
812
|
+
/// is the balance minus what's needed for payout limits.
|
|
813
|
+
/// @dev If `tokens` is empty, includes all tokens the project accepts.
|
|
806
814
|
/// @param projectId The ID of the project to get the current surplus of.
|
|
807
815
|
/// @param tokens The tokens to include in the surplus calculation. If empty, all tokens are included.
|
|
808
816
|
/// @param decimals The number of decimals to include in the fixed point returned value.
|
|
@@ -827,9 +835,10 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
827
835
|
});
|
|
828
836
|
}
|
|
829
837
|
|
|
830
|
-
/// @notice
|
|
831
|
-
///
|
|
832
|
-
/// @dev Held fees can be
|
|
838
|
+
/// @notice Returns the fees currently being held for a project. Fees are held for 28 days after a payout before
|
|
839
|
+
/// they can be processed (sent to the fee project).
|
|
840
|
+
/// @dev Held fees can be returned to the project by calling `addToBalanceOf` with `shouldReturnHeldFees = true`
|
|
841
|
+
/// before the 28-day lock expires.
|
|
833
842
|
/// @param projectId The ID of the project that is holding fees.
|
|
834
843
|
/// @param token The token that the fees are held in.
|
|
835
844
|
/// @param count The maximum number of held fees to return.
|
|
@@ -868,7 +877,8 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
868
877
|
}
|
|
869
878
|
}
|
|
870
879
|
|
|
871
|
-
/// @notice Simulates
|
|
880
|
+
/// @notice Simulates a cash out without modifying state — use this to preview how many tokens a holder would
|
|
881
|
+
/// reclaim.
|
|
872
882
|
/// @param holder The address whose tokens are being cashed out.
|
|
873
883
|
/// @param projectId The ID of the project whose tokens are being cashed out.
|
|
874
884
|
/// @param cashOutCount The number of project tokens to cash out.
|
|
@@ -909,7 +919,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
909
919
|
});
|
|
910
920
|
}
|
|
911
921
|
|
|
912
|
-
/// @notice Simulates
|
|
922
|
+
/// @notice Simulates a payment without modifying state — use this to preview how many project tokens a payer
|
|
923
|
+
/// would
|
|
924
|
+
/// receive.
|
|
913
925
|
/// @param projectId The ID of the project being paid.
|
|
914
926
|
/// @param token The token being paid in.
|
|
915
927
|
/// @param amount The amount of tokens being paid.
|
|
@@ -1180,16 +1192,22 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1180
1192
|
if (cashOutTaxRate != 0) {
|
|
1181
1193
|
// Non-zero tax: fees apply to the full reclaim amount.
|
|
1182
1194
|
amountEligibleForFees += reclaimAmount;
|
|
1183
|
-
|
|
1195
|
+
unchecked {
|
|
1196
|
+
reclaimAmount -= _feeAmountFrom(reclaimAmount);
|
|
1197
|
+
}
|
|
1184
1198
|
} else {
|
|
1185
1199
|
// Zero tax: fees apply only up to the fee-free surplus (round-trip prevention).
|
|
1186
1200
|
uint256 feeFreeSurplus = _feeFreeSurplusOf[projectId][tokenToReclaim];
|
|
1187
1201
|
if (feeFreeSurplus != 0) {
|
|
1188
1202
|
uint256 feeableAmount = reclaimAmount < feeFreeSurplus ? reclaimAmount : feeFreeSurplus;
|
|
1189
1203
|
// slither-disable-next-line reentrancy-no-eth,reentrancy-eth,reentrancy-benign
|
|
1190
|
-
|
|
1204
|
+
unchecked {
|
|
1205
|
+
_feeFreeSurplusOf[projectId][tokenToReclaim] = feeFreeSurplus - feeableAmount;
|
|
1206
|
+
}
|
|
1191
1207
|
amountEligibleForFees += feeableAmount;
|
|
1192
|
-
|
|
1208
|
+
unchecked {
|
|
1209
|
+
reclaimAmount -= _feeAmountFrom(feeableAmount);
|
|
1210
|
+
}
|
|
1193
1211
|
}
|
|
1194
1212
|
}
|
|
1195
1213
|
}
|
|
@@ -1437,9 +1455,8 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1437
1455
|
}
|
|
1438
1456
|
|
|
1439
1457
|
// Get the fee for the specified amount.
|
|
1440
|
-
uint256 specificationAmountFee =
|
|
1441
|
-
? 0
|
|
1442
|
-
: JBFees.feeAmountFrom({amountBeforeFee: specification.amount, feePercent: FEE});
|
|
1458
|
+
uint256 specificationAmountFee =
|
|
1459
|
+
_isFeeless(address(specification.hook)) ? 0 : _feeAmountFrom(specification.amount);
|
|
1443
1460
|
|
|
1444
1461
|
// Add the specification's amount to the amount eligible for fees.
|
|
1445
1462
|
if (specificationAmountFee != 0) {
|
|
@@ -1571,7 +1588,8 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1571
1588
|
}
|
|
1572
1589
|
}
|
|
1573
1590
|
|
|
1574
|
-
/// @notice
|
|
1591
|
+
/// @notice Internal implementation of payment logic. Records the payment in the store, mints tokens via the
|
|
1592
|
+
/// controller, and fulfills any pay hook specifications from the data hook.
|
|
1575
1593
|
/// @param projectId The ID of the project being paid.
|
|
1576
1594
|
/// @param token The address of the token which the project is being paid with.
|
|
1577
1595
|
/// @param amount The amount of terminal tokens being received, as a fixed point number with the same number of
|
|
@@ -1615,12 +1633,12 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1615
1633
|
// slither-disable-next-line reentrancy-events
|
|
1616
1634
|
newlyIssuedTokenCount = _controllerOf(projectId)
|
|
1617
1635
|
.mintTokensOf({
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1636
|
+
projectId: projectId,
|
|
1637
|
+
tokenCount: tokenCount,
|
|
1638
|
+
beneficiary: beneficiary,
|
|
1639
|
+
memo: "",
|
|
1640
|
+
useReservedPercent: true
|
|
1641
|
+
});
|
|
1624
1642
|
}
|
|
1625
1643
|
|
|
1626
1644
|
emit Pay({
|
|
@@ -1710,8 +1728,8 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1710
1728
|
}
|
|
1711
1729
|
|
|
1712
1730
|
/// @notice Returns held fees to the project who paid them based on the specified amount.
|
|
1713
|
-
/// @dev
|
|
1714
|
-
///
|
|
1731
|
+
/// @dev Partial replenishments use the raw floor calculation so repaying a dust amount cannot both credit the
|
|
1732
|
+
/// payer project and leave the fee project owed the 1-unit minimum fee.
|
|
1715
1733
|
/// @param projectId The project held fees are being returned to.
|
|
1716
1734
|
/// @param token The token that the held fees are in.
|
|
1717
1735
|
/// @param amount The amount to base the calculation on, as a fixed point number with the same number of decimals
|
|
@@ -1747,7 +1765,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1747
1765
|
break;
|
|
1748
1766
|
} else {
|
|
1749
1767
|
// Notice here we take `feeAmountFrom` on the stored `.amount`.
|
|
1750
|
-
uint256 feeAmount =
|
|
1768
|
+
uint256 feeAmount = _feeAmountFrom(heldFee.amount);
|
|
1751
1769
|
|
|
1752
1770
|
// Keep a reference to the amount from which the fee was taken.
|
|
1753
1771
|
uint256 amountPaidOut = heldFee.amount - feeAmount;
|
|
@@ -1761,8 +1779,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1761
1779
|
// Move the start index forward to the held fee after the current one.
|
|
1762
1780
|
newStartIndex = startIndex + i + 1;
|
|
1763
1781
|
} else {
|
|
1764
|
-
//
|
|
1765
|
-
|
|
1782
|
+
// Use the floor variant here. The minimum 1-unit fee applies when a fee is created, not while
|
|
1783
|
+
// splitting an already-held fee entry across repayments.
|
|
1784
|
+
feeAmount = JBFees.feeAmountResultingInFloorForFee25(leftoverAmount);
|
|
1766
1785
|
|
|
1767
1786
|
// Get fee from `leftoverAmount`.
|
|
1768
1787
|
unchecked {
|
|
@@ -1817,10 +1836,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1817
1836
|
(ruleset, amountPaidOut) =
|
|
1818
1837
|
STORE.recordPayoutFor({projectId: projectId, token: token, amount: amount, currency: currency});
|
|
1819
1838
|
|
|
1820
|
-
// Cap fee-free surplus at remaining balance. Non-fee-free funds leave first.
|
|
1821
|
-
// slither-disable-next-line reentrancy-no-eth,reentrancy-eth,reentrancy-benign
|
|
1822
|
-
_capFeeFreeSurplus({projectId: projectId, token: token});
|
|
1823
|
-
|
|
1824
1839
|
// Get a reference to the project's owner.
|
|
1825
1840
|
// The owner will receive tokens minted by paying the platform fee and receive any leftover funds not sent to
|
|
1826
1841
|
// payout splits.
|
|
@@ -1849,17 +1864,20 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1849
1864
|
// Send any leftover funds to the project owner and update the fee tracking accordingly.
|
|
1850
1865
|
if (leftoverPayoutAmount != 0) {
|
|
1851
1866
|
// Keep a reference to the fee for the leftover payout amount.
|
|
1852
|
-
uint256 fee = _isFeeless(projectOwner)
|
|
1853
|
-
|
|
1854
|
-
|
|
1867
|
+
uint256 fee = _isFeeless(projectOwner) ? 0 : _feeAmountFrom(leftoverPayoutAmount);
|
|
1868
|
+
|
|
1869
|
+
uint256 netLeftoverPayoutAmount;
|
|
1870
|
+
unchecked {
|
|
1871
|
+
netLeftoverPayoutAmount = leftoverPayoutAmount - fee;
|
|
1872
|
+
}
|
|
1855
1873
|
|
|
1856
1874
|
// Failed owner transfer consumes the payout limit by design. Same pattern as split payouts:
|
|
1857
1875
|
// the try-catch prevents revert, failed amount is returned to project balance, and the owner can retry
|
|
1858
1876
|
// via addToBalanceOf or in the next cycle.
|
|
1859
|
-
try this.executeTransferTo({addr: projectOwner, token: token, amount:
|
|
1877
|
+
try this.executeTransferTo({addr: projectOwner, token: token, amount: netLeftoverPayoutAmount}) {
|
|
1860
1878
|
if (fee > 0) {
|
|
1861
1879
|
amountEligibleForFees += leftoverPayoutAmount;
|
|
1862
|
-
leftoverPayoutAmount
|
|
1880
|
+
leftoverPayoutAmount = netLeftoverPayoutAmount;
|
|
1863
1881
|
}
|
|
1864
1882
|
} catch (bytes memory reason) {
|
|
1865
1883
|
// slither-disable-next-line reentrancy-events
|
|
@@ -1867,7 +1885,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1867
1885
|
projectId: projectId,
|
|
1868
1886
|
addr: projectOwner,
|
|
1869
1887
|
token: token,
|
|
1870
|
-
amount:
|
|
1888
|
+
amount: netLeftoverPayoutAmount,
|
|
1871
1889
|
fee: fee,
|
|
1872
1890
|
reason: reason,
|
|
1873
1891
|
caller: sender
|
|
@@ -1878,6 +1896,11 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1878
1896
|
}
|
|
1879
1897
|
}
|
|
1880
1898
|
|
|
1899
|
+
// Cap fee-free surplus at remaining balance. Non-fee-free funds leave first.
|
|
1900
|
+
// Placed after all payouts settle so the cap reflects post-payout state.
|
|
1901
|
+
// slither-disable-next-line reentrancy-no-eth,reentrancy-eth,reentrancy-benign
|
|
1902
|
+
_capFeeFreeSurplus({projectId: projectId, token: token});
|
|
1903
|
+
|
|
1881
1904
|
// Take the fee.
|
|
1882
1905
|
uint256 feeTaken = _takeFeeFrom({
|
|
1883
1906
|
projectId: projectId,
|
|
@@ -1918,7 +1941,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1918
1941
|
returns (uint256 feeAmount)
|
|
1919
1942
|
{
|
|
1920
1943
|
// Get a reference to the fee amount.
|
|
1921
|
-
feeAmount =
|
|
1944
|
+
feeAmount = _feeAmountFrom(amount);
|
|
1922
1945
|
|
|
1923
1946
|
if (shouldHoldFees) {
|
|
1924
1947
|
// Store the held fee.
|
|
@@ -2170,4 +2193,18 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
2170
2193
|
tokenAmount =
|
|
2171
2194
|
JBTokenAmount({token: token, decimals: context.decimals, currency: context.currency, value: value});
|
|
2172
2195
|
}
|
|
2196
|
+
|
|
2197
|
+
//*********************************************************************//
|
|
2198
|
+
// -------------------------- private helpers ------------------------ //
|
|
2199
|
+
//*********************************************************************//
|
|
2200
|
+
|
|
2201
|
+
/// @notice The terminal fee charged from a pre-fee `amount`.
|
|
2202
|
+
/// @dev Returns at least 1 for nonzero feeable amounts so dust payouts cannot bypass protocol fees.
|
|
2203
|
+
/// @param amount The amount before the fee is applied.
|
|
2204
|
+
/// @return feeAmount The fee amount.
|
|
2205
|
+
function _feeAmountFrom(uint256 amount) private pure returns (uint256 feeAmount) {
|
|
2206
|
+
feeAmount = amount / _FEE_AMOUNT_FROM_DENOMINATOR;
|
|
2207
|
+
|
|
2208
|
+
return feeAmount == 0 && amount != 0 ? 1 : feeAmount;
|
|
2209
|
+
}
|
|
2173
2210
|
}
|