@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,271 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.17;
|
|
3
|
-
|
|
4
|
-
import {Test} from "forge-std/Test.sol";
|
|
5
|
-
import {JBCashOuts} from "../src/libraries/JBCashOuts.sol";
|
|
6
|
-
import {JBConstants} from "../src/libraries/JBConstants.sol";
|
|
7
|
-
|
|
8
|
-
/// @dev Wrapper so library reverts can be caught by vm.expectRevert (library calls are inlined otherwise).
|
|
9
|
-
contract CashOutCountForWrapper {
|
|
10
|
-
function minCashOutCountFor(
|
|
11
|
-
uint256 surplus,
|
|
12
|
-
uint256 desiredOutput,
|
|
13
|
-
uint256 totalSupply,
|
|
14
|
-
uint256 cashOutTaxRate
|
|
15
|
-
)
|
|
16
|
-
external
|
|
17
|
-
pure
|
|
18
|
-
returns (uint256)
|
|
19
|
-
{
|
|
20
|
-
return JBCashOuts.minCashOutCountFor(surplus, desiredOutput, totalSupply, cashOutTaxRate);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/// @title TestCashOutCountFor
|
|
25
|
-
/// @notice Tests for JBCashOuts.minCashOutCountFor — the inverse of the bonding curve.
|
|
26
|
-
contract TestCashOutCountFor is Test {
|
|
27
|
-
uint256 constant MAX_TAX = JBConstants.MAX_CASH_OUT_TAX_RATE;
|
|
28
|
-
|
|
29
|
-
CashOutCountForWrapper wrapper;
|
|
30
|
-
|
|
31
|
-
function setUp() public {
|
|
32
|
-
wrapper = new CashOutCountForWrapper();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// =========================================================================
|
|
36
|
-
// Edge cases
|
|
37
|
-
// =========================================================================
|
|
38
|
-
|
|
39
|
-
function test_zeroDesiredOutput() public pure {
|
|
40
|
-
assertEq(JBCashOuts.minCashOutCountFor(100 ether, 0, 1000e18, 5000), 0);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function test_desiredOutputEqualsSurplus() public pure {
|
|
44
|
-
uint256 count = JBCashOuts.minCashOutCountFor(100 ether, 100 ether, 1000e18, 5000);
|
|
45
|
-
assertEq(count, 1000e18, "Should return totalSupply when desiredOutput == surplus");
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function test_desiredOutputExceedsSurplus() public pure {
|
|
49
|
-
uint256 count = JBCashOuts.minCashOutCountFor(100 ether, 200 ether, 1000e18, 5000);
|
|
50
|
-
assertEq(count, 1000e18, "Should return totalSupply when desiredOutput > surplus");
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function test_maxTaxRate_reverts() public {
|
|
54
|
-
vm.expectRevert(JBCashOuts.JBCashOuts_DesiredOutputNotAchievable.selector);
|
|
55
|
-
wrapper.minCashOutCountFor(100 ether, 50 ether, 1000e18, MAX_TAX);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function test_zeroTaxRate() public pure {
|
|
59
|
-
// With 0 tax: out = S * c / T, so c = out * T / S.
|
|
60
|
-
// surplus=100, desiredOutput=25, totalSupply=200 → c = 25*200/100 = 50.
|
|
61
|
-
uint256 count = JBCashOuts.minCashOutCountFor(100, 25, 200, 0);
|
|
62
|
-
assertEq(count, 50);
|
|
63
|
-
assertGe(JBCashOuts.cashOutFrom(100, count, 200, 0), 25);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function test_zeroTaxRate_roundsUp() public pure {
|
|
67
|
-
// surplus=7, desiredOutput=2, totalSupply=100.
|
|
68
|
-
// Exact: c = 2*100/7 = 28.57... floor = 28. mulDiv(7, 28, 100) = 1 < 2. So c = 29.
|
|
69
|
-
uint256 count = JBCashOuts.minCashOutCountFor(7, 2, 100, 0);
|
|
70
|
-
assertGe(JBCashOuts.cashOutFrom(7, count, 100, 0), 2);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function test_zeroSurplus() public pure {
|
|
74
|
-
// surplus=0, desiredOutput=1 → desiredOutput >= surplus → return totalSupply.
|
|
75
|
-
uint256 count = JBCashOuts.minCashOutCountFor(0, 1, 1000e18, 5000);
|
|
76
|
-
assertEq(count, 1000e18);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// =========================================================================
|
|
80
|
-
// Specific examples
|
|
81
|
-
// =========================================================================
|
|
82
|
-
|
|
83
|
-
function test_halfTax_knownValues() public pure {
|
|
84
|
-
// surplus=100, totalSupply=100, taxRate=5000 (50%).
|
|
85
|
-
// Forward: cashOutFrom(100, 50, 100, 5000) = 37.
|
|
86
|
-
uint256 forwardResult = JBCashOuts.cashOutFrom(100, 50, 100, 5000);
|
|
87
|
-
assertEq(forwardResult, 37);
|
|
88
|
-
|
|
89
|
-
// Inverse: to get 37 out, we need at least 50 tokens.
|
|
90
|
-
uint256 count = JBCashOuts.minCashOutCountFor(100, 37, 100, 5000);
|
|
91
|
-
assertEq(count, 50);
|
|
92
|
-
assertGe(JBCashOuts.cashOutFrom(100, count, 100, 5000), 37);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function test_lowTax() public pure {
|
|
96
|
-
// taxRate=1000 (10%).
|
|
97
|
-
uint256 forwardResult = JBCashOuts.cashOutFrom(1000, 100, 1000, 1000);
|
|
98
|
-
|
|
99
|
-
uint256 count = JBCashOuts.minCashOutCountFor(1000, forwardResult, 1000, 1000);
|
|
100
|
-
assertGe(JBCashOuts.cashOutFrom(1000, count, 1000, 1000), forwardResult);
|
|
101
|
-
assertLe(count, 100);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function test_highTax() public pure {
|
|
105
|
-
// taxRate=9000 (90%).
|
|
106
|
-
uint256 forwardResult = JBCashOuts.cashOutFrom(1000, 500, 1000, 9000);
|
|
107
|
-
|
|
108
|
-
uint256 count = JBCashOuts.minCashOutCountFor(1000, forwardResult, 1000, 9000);
|
|
109
|
-
assertGe(JBCashOuts.cashOutFrom(1000, count, 1000, 9000), forwardResult);
|
|
110
|
-
assertLe(count, 500);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function test_realisticValues() public pure {
|
|
114
|
-
// 10 ETH surplus, 1M tokens, 30% tax.
|
|
115
|
-
uint256 surplus = 10 ether;
|
|
116
|
-
uint256 totalSupply = 1_000_000e18;
|
|
117
|
-
uint256 taxRate = 3000;
|
|
118
|
-
uint256 cashOutAmount = 100_000e18;
|
|
119
|
-
|
|
120
|
-
uint256 forwardResult = JBCashOuts.cashOutFrom(surplus, cashOutAmount, totalSupply, taxRate);
|
|
121
|
-
|
|
122
|
-
uint256 count = JBCashOuts.minCashOutCountFor(surplus, forwardResult, totalSupply, taxRate);
|
|
123
|
-
assertGe(JBCashOuts.cashOutFrom(surplus, count, totalSupply, taxRate), forwardResult);
|
|
124
|
-
assertLe(count, cashOutAmount);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function test_smallSurplus_largeTotalSupply() public pure {
|
|
128
|
-
// Edge case that trips up analytic formulas: surplus << totalSupply.
|
|
129
|
-
uint256 surplus = 3178;
|
|
130
|
-
uint256 totalSupply = 11_740_172_277_586_795;
|
|
131
|
-
uint256 taxRate = 2;
|
|
132
|
-
uint256 desiredOutput = 1589;
|
|
133
|
-
|
|
134
|
-
uint256 count = JBCashOuts.minCashOutCountFor(surplus, desiredOutput, totalSupply, taxRate);
|
|
135
|
-
assertGe(JBCashOuts.cashOutFrom(surplus, count, totalSupply, taxRate), desiredOutput);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// =========================================================================
|
|
139
|
-
// Round-trip: minCashOutCountFor(S, cashOutFrom(S, c, T, r), T, r) <= c
|
|
140
|
-
// =========================================================================
|
|
141
|
-
|
|
142
|
-
function testFuzz_roundTrip_inverseOfForward(
|
|
143
|
-
uint128 surplus,
|
|
144
|
-
uint128 totalSupply,
|
|
145
|
-
uint128 cashOutCount,
|
|
146
|
-
uint16 cashOutTaxRate
|
|
147
|
-
)
|
|
148
|
-
public
|
|
149
|
-
pure
|
|
150
|
-
{
|
|
151
|
-
vm.assume(surplus > 0);
|
|
152
|
-
vm.assume(totalSupply > 0);
|
|
153
|
-
vm.assume(cashOutCount > 0 && cashOutCount <= totalSupply);
|
|
154
|
-
vm.assume(cashOutTaxRate <= MAX_TAX);
|
|
155
|
-
vm.assume(cashOutTaxRate < MAX_TAX);
|
|
156
|
-
|
|
157
|
-
uint256 output = JBCashOuts.cashOutFrom(surplus, cashOutCount, totalSupply, cashOutTaxRate);
|
|
158
|
-
vm.assume(output > 0);
|
|
159
|
-
|
|
160
|
-
uint256 recoveredCount = JBCashOuts.minCashOutCountFor(surplus, output, totalSupply, cashOutTaxRate);
|
|
161
|
-
|
|
162
|
-
// The recovered count should be <= the original count, because the forward function rounds down.
|
|
163
|
-
assertLe(recoveredCount, cashOutCount, "Round-trip: recovered count should be <= original");
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// =========================================================================
|
|
167
|
-
// Correctness: cashOutFrom(S, minCashOutCountFor(S, out, T, r), T, r) >= out
|
|
168
|
-
// =========================================================================
|
|
169
|
-
|
|
170
|
-
function testFuzz_correctness_outputMeetsTarget(
|
|
171
|
-
uint128 surplus,
|
|
172
|
-
uint128 totalSupply,
|
|
173
|
-
uint16 cashOutTaxRate
|
|
174
|
-
)
|
|
175
|
-
public
|
|
176
|
-
pure
|
|
177
|
-
{
|
|
178
|
-
vm.assume(surplus > 1);
|
|
179
|
-
vm.assume(totalSupply > 0);
|
|
180
|
-
vm.assume(cashOutTaxRate <= MAX_TAX);
|
|
181
|
-
vm.assume(cashOutTaxRate < MAX_TAX);
|
|
182
|
-
|
|
183
|
-
uint256 desiredOutput = uint256(surplus) / 2;
|
|
184
|
-
vm.assume(desiredOutput > 0 && desiredOutput < surplus);
|
|
185
|
-
|
|
186
|
-
uint256 count = JBCashOuts.minCashOutCountFor(surplus, desiredOutput, totalSupply, cashOutTaxRate);
|
|
187
|
-
|
|
188
|
-
uint256 actualOutput = JBCashOuts.cashOutFrom(surplus, count, totalSupply, cashOutTaxRate);
|
|
189
|
-
assertGe(actualOutput, desiredOutput, "Correctness: output should meet or exceed target");
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function testFuzz_correctness_fullRange(
|
|
193
|
-
uint128 surplus,
|
|
194
|
-
uint128 totalSupply,
|
|
195
|
-
uint128 desiredOutput,
|
|
196
|
-
uint16 cashOutTaxRate
|
|
197
|
-
)
|
|
198
|
-
public
|
|
199
|
-
pure
|
|
200
|
-
{
|
|
201
|
-
vm.assume(surplus > 0);
|
|
202
|
-
vm.assume(totalSupply > 0);
|
|
203
|
-
vm.assume(cashOutTaxRate <= MAX_TAX);
|
|
204
|
-
vm.assume(cashOutTaxRate < MAX_TAX);
|
|
205
|
-
vm.assume(desiredOutput > 0 && desiredOutput < surplus);
|
|
206
|
-
|
|
207
|
-
uint256 count = JBCashOuts.minCashOutCountFor(surplus, desiredOutput, totalSupply, cashOutTaxRate);
|
|
208
|
-
|
|
209
|
-
assertLe(count, totalSupply, "Count should not exceed totalSupply");
|
|
210
|
-
|
|
211
|
-
uint256 actualOutput = JBCashOuts.cashOutFrom(surplus, count, totalSupply, cashOutTaxRate);
|
|
212
|
-
assertGe(actualOutput, desiredOutput, "Output should meet target");
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// =========================================================================
|
|
216
|
-
// Monotonicity: larger desired output → larger or equal count
|
|
217
|
-
// =========================================================================
|
|
218
|
-
|
|
219
|
-
function testFuzz_monotonicity(
|
|
220
|
-
uint128 surplus,
|
|
221
|
-
uint128 totalSupply,
|
|
222
|
-
uint128 out1,
|
|
223
|
-
uint128 out2,
|
|
224
|
-
uint16 cashOutTaxRate
|
|
225
|
-
)
|
|
226
|
-
public
|
|
227
|
-
pure
|
|
228
|
-
{
|
|
229
|
-
vm.assume(surplus > 2);
|
|
230
|
-
vm.assume(totalSupply > 0);
|
|
231
|
-
vm.assume(cashOutTaxRate <= MAX_TAX);
|
|
232
|
-
vm.assume(cashOutTaxRate < MAX_TAX);
|
|
233
|
-
vm.assume(out1 > 0 && out2 > 0);
|
|
234
|
-
vm.assume(out1 < surplus && out2 < surplus);
|
|
235
|
-
|
|
236
|
-
if (out1 > out2) (out1, out2) = (out2, out1);
|
|
237
|
-
|
|
238
|
-
uint256 count1 = JBCashOuts.minCashOutCountFor(surplus, out1, totalSupply, cashOutTaxRate);
|
|
239
|
-
uint256 count2 = JBCashOuts.minCashOutCountFor(surplus, out2, totalSupply, cashOutTaxRate);
|
|
240
|
-
|
|
241
|
-
assertLe(count1, count2, "Monotonicity: larger output needs >= count");
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// =========================================================================
|
|
245
|
-
// Minimality: count - 1 should produce less than desiredOutput
|
|
246
|
-
// =========================================================================
|
|
247
|
-
|
|
248
|
-
function testFuzz_minimality(
|
|
249
|
-
uint128 surplus,
|
|
250
|
-
uint128 totalSupply,
|
|
251
|
-
uint128 desiredOutput,
|
|
252
|
-
uint16 cashOutTaxRate
|
|
253
|
-
)
|
|
254
|
-
public
|
|
255
|
-
pure
|
|
256
|
-
{
|
|
257
|
-
vm.assume(surplus > 0);
|
|
258
|
-
vm.assume(totalSupply > 1);
|
|
259
|
-
vm.assume(cashOutTaxRate <= MAX_TAX);
|
|
260
|
-
vm.assume(cashOutTaxRate < MAX_TAX);
|
|
261
|
-
vm.assume(desiredOutput > 0 && desiredOutput < surplus);
|
|
262
|
-
|
|
263
|
-
uint256 count = JBCashOuts.minCashOutCountFor(surplus, desiredOutput, totalSupply, cashOutTaxRate);
|
|
264
|
-
|
|
265
|
-
vm.assume(count > 1);
|
|
266
|
-
vm.assume(count < totalSupply);
|
|
267
|
-
|
|
268
|
-
uint256 lesserOutput = JBCashOuts.cashOutFrom(surplus, count - 1, totalSupply, cashOutTaxRate);
|
|
269
|
-
assertLt(lesserOutput, desiredOutput, "Minimality: count-1 should produce less than target");
|
|
270
|
-
}
|
|
271
|
-
}
|
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity >=0.8.6;
|
|
3
|
-
|
|
4
|
-
import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
|
|
5
|
-
import {IJBCashOutHook} from "../src/interfaces/IJBCashOutHook.sol";
|
|
6
|
-
import {IJBController} from "../src/interfaces/IJBController.sol";
|
|
7
|
-
import {IJBMultiTerminal} from "../src/interfaces/IJBMultiTerminal.sol";
|
|
8
|
-
import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
|
|
9
|
-
import {IJBRulesetDataHook} from "../src/interfaces/IJBRulesetDataHook.sol";
|
|
10
|
-
import {IJBToken} from "../src/interfaces/IJBToken.sol";
|
|
11
|
-
import {IJBTokens} from "../src/interfaces/IJBTokens.sol";
|
|
12
|
-
import {JBConstants} from "../src/libraries/JBConstants.sol";
|
|
13
|
-
import {JBRulesetMetadataResolver} from "../src/libraries/JBRulesetMetadataResolver.sol";
|
|
14
|
-
import {JBAccountingContext} from "../src/structs/JBAccountingContext.sol";
|
|
15
|
-
import {JBAfterCashOutRecordedContext} from "../src/structs/JBAfterCashOutRecordedContext.sol";
|
|
16
|
-
import {JBCashOutHookSpecification} from "../src/structs/JBCashOutHookSpecification.sol";
|
|
17
|
-
import {JBFundAccessLimitGroup} from "../src/structs/JBFundAccessLimitGroup.sol";
|
|
18
|
-
import {JBRuleset} from "../src/structs/JBRuleset.sol";
|
|
19
|
-
import {JBRulesetConfig} from "../src/structs/JBRulesetConfig.sol";
|
|
20
|
-
import {JBRulesetMetadata} from "../src/structs/JBRulesetMetadata.sol";
|
|
21
|
-
import {JBSplitGroup} from "../src/structs/JBSplitGroup.sol";
|
|
22
|
-
import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
|
|
23
|
-
import {JBTokenAmount} from "../src/structs/JBTokenAmount.sol";
|
|
24
|
-
import {mulDiv} from "@prb/math/src/Common.sol";
|
|
25
|
-
import {mul as UD60x18mul, unwrap as UD60x18unwrap, wrap as UD60x18wrap} from "@prb/math/src/UD60x18.sol";
|
|
26
|
-
|
|
27
|
-
contract TestCashOutHooks_Local is TestBaseWorkflow {
|
|
28
|
-
using JBRulesetMetadataResolver for JBRuleset;
|
|
29
|
-
|
|
30
|
-
uint112 private constant _WEIGHT = 1000 * 10 ** 18;
|
|
31
|
-
address private constant _DATA_HOOK = address(bytes20(keccak256("datahook")));
|
|
32
|
-
|
|
33
|
-
IJBController private _controller;
|
|
34
|
-
IJBMultiTerminal private _terminal;
|
|
35
|
-
IJBTokens private _tokens;
|
|
36
|
-
address private _projectOwner;
|
|
37
|
-
address private _beneficiary;
|
|
38
|
-
|
|
39
|
-
uint64 _projectId;
|
|
40
|
-
|
|
41
|
-
function setUp() public override {
|
|
42
|
-
super.setUp();
|
|
43
|
-
|
|
44
|
-
vm.label(_DATA_HOOK, "Data Hook");
|
|
45
|
-
|
|
46
|
-
_controller = jbController();
|
|
47
|
-
_projectOwner = multisig();
|
|
48
|
-
_beneficiary = beneficiary();
|
|
49
|
-
_terminal = jbMultiTerminal();
|
|
50
|
-
_tokens = jbTokens();
|
|
51
|
-
|
|
52
|
-
JBRulesetMetadata memory _metadata = JBRulesetMetadata({
|
|
53
|
-
reservedPercent: 0,
|
|
54
|
-
cashOutTaxRate: 0,
|
|
55
|
-
baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
56
|
-
pausePay: false,
|
|
57
|
-
pauseCreditTransfers: false,
|
|
58
|
-
allowOwnerMinting: true,
|
|
59
|
-
allowSetCustomToken: true,
|
|
60
|
-
allowTerminalMigration: false,
|
|
61
|
-
allowSetTerminals: false,
|
|
62
|
-
ownerMustSendPayouts: false,
|
|
63
|
-
allowSetController: false,
|
|
64
|
-
allowAddAccountingContext: true,
|
|
65
|
-
allowAddPriceFeed: false,
|
|
66
|
-
holdFees: false,
|
|
67
|
-
useTotalSurplusForCashOuts: false,
|
|
68
|
-
useDataHookForPay: false,
|
|
69
|
-
useDataHookForCashOut: true,
|
|
70
|
-
dataHook: _DATA_HOOK,
|
|
71
|
-
metadata: 0
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// Package up ruleset configuration.
|
|
75
|
-
JBRulesetConfig[] memory _rulesetConfig = new JBRulesetConfig[](1);
|
|
76
|
-
_rulesetConfig[0].mustStartAtOrAfter = 0;
|
|
77
|
-
_rulesetConfig[0].duration = 0;
|
|
78
|
-
_rulesetConfig[0].weight = _WEIGHT;
|
|
79
|
-
_rulesetConfig[0].weightCutPercent = 0;
|
|
80
|
-
_rulesetConfig[0].approvalHook = IJBRulesetApprovalHook(address(0));
|
|
81
|
-
_rulesetConfig[0].metadata = _metadata;
|
|
82
|
-
_rulesetConfig[0].splitGroups = new JBSplitGroup[](0);
|
|
83
|
-
_rulesetConfig[0].fundAccessLimitGroups = new JBFundAccessLimitGroup[](0);
|
|
84
|
-
|
|
85
|
-
JBTerminalConfig[] memory _terminalConfigurations = new JBTerminalConfig[](1);
|
|
86
|
-
JBAccountingContext[] memory _tokensToAccept = new JBAccountingContext[](1);
|
|
87
|
-
_tokensToAccept[0] = JBAccountingContext({
|
|
88
|
-
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
89
|
-
});
|
|
90
|
-
_terminalConfigurations[0] =
|
|
91
|
-
JBTerminalConfig({terminal: _terminal, accountingContextsToAccept: _tokensToAccept});
|
|
92
|
-
|
|
93
|
-
// Create a first project to collect fees.
|
|
94
|
-
_controller.launchProjectFor({
|
|
95
|
-
owner: _projectOwner,
|
|
96
|
-
projectUri: "myIPFSHash",
|
|
97
|
-
rulesetConfigurations: _rulesetConfig,
|
|
98
|
-
terminalConfigurations: _terminalConfigurations,
|
|
99
|
-
memo: ""
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
_projectId = uint64(
|
|
103
|
-
_controller.launchProjectFor({
|
|
104
|
-
owner: _projectOwner,
|
|
105
|
-
projectUri: "myIPFSHash",
|
|
106
|
-
rulesetConfigurations: _rulesetConfig,
|
|
107
|
-
terminalConfigurations: _terminalConfigurations,
|
|
108
|
-
memo: ""
|
|
109
|
-
})
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
// Issue the project's tokens.
|
|
113
|
-
vm.prank(_projectOwner);
|
|
114
|
-
IJBToken _token = _controller.deployERC20For(_projectId, "TestName", "TestSymbol", bytes32(0));
|
|
115
|
-
|
|
116
|
-
// Make sure the project's new project token is set.
|
|
117
|
-
assertEq(address(_tokens.tokenOf(_projectId)), address(_token));
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function testCashOutHookWithNoFees() public {
|
|
121
|
-
// Reference and bound pay amount.
|
|
122
|
-
uint256 _nativePayAmount = 10 ether;
|
|
123
|
-
uint256 _halfPaid = 5 ether;
|
|
124
|
-
|
|
125
|
-
// Cash out hook address.
|
|
126
|
-
address _cashOutHook = makeAddr("SOFA");
|
|
127
|
-
vm.label(_cashOutHook, "Cash Out Delegate");
|
|
128
|
-
|
|
129
|
-
// Keep a reference to the current ruleset.
|
|
130
|
-
(JBRuleset memory _ruleset,) = _controller.currentRulesetOf(_projectId);
|
|
131
|
-
|
|
132
|
-
vm.deal(address(this), _nativePayAmount);
|
|
133
|
-
uint256 _beneficiaryTokensReceived = _terminal.pay{value: _nativePayAmount}({
|
|
134
|
-
projectId: _projectId,
|
|
135
|
-
amount: _nativePayAmount,
|
|
136
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
137
|
-
beneficiary: address(this),
|
|
138
|
-
minReturnedTokens: 0,
|
|
139
|
-
memo: "Forge Test",
|
|
140
|
-
metadata: ""
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Make sure the beneficiary has a balance of project tokens.
|
|
144
|
-
uint256 _beneficiaryTokenBalance =
|
|
145
|
-
UD60x18unwrap(UD60x18mul(UD60x18wrap(_nativePayAmount), UD60x18wrap(_WEIGHT)));
|
|
146
|
-
assertEq(_tokens.totalBalanceOf(address(this), _projectId), _beneficiaryTokenBalance);
|
|
147
|
-
assertEq(_beneficiaryTokensReceived, _beneficiaryTokenBalance);
|
|
148
|
-
|
|
149
|
-
// Make sure the native token balance in terminal is up to date.
|
|
150
|
-
uint256 _nativeTerminalBalance = _nativePayAmount;
|
|
151
|
-
assertEq(
|
|
152
|
-
jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN),
|
|
153
|
-
_nativeTerminalBalance
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
// Reference cash out hook specifications.
|
|
157
|
-
JBCashOutHookSpecification[] memory _specifications = new JBCashOutHookSpecification[](1);
|
|
158
|
-
|
|
159
|
-
_specifications[0] = JBCashOutHookSpecification({
|
|
160
|
-
hook: IJBCashOutHook(_cashOutHook), noop: false, amount: _halfPaid, metadata: ""
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
vm.startPrank(multisig());
|
|
164
|
-
// Set the hook as feeless.
|
|
165
|
-
_terminal.FEELESS_ADDRESSES().setFeelessAddress(_cashOutHook, true);
|
|
166
|
-
vm.stopPrank();
|
|
167
|
-
|
|
168
|
-
// Cash out context.
|
|
169
|
-
JBAfterCashOutRecordedContext memory _cashOutContext = JBAfterCashOutRecordedContext({
|
|
170
|
-
holder: address(this),
|
|
171
|
-
projectId: _projectId,
|
|
172
|
-
rulesetId: _ruleset.id,
|
|
173
|
-
cashOutCount: _beneficiaryTokenBalance / 2,
|
|
174
|
-
reclaimedAmount: JBTokenAmount({
|
|
175
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
176
|
-
decimals: _terminal.accountingContextForTokenOf(_projectId, JBConstants.NATIVE_TOKEN).decimals,
|
|
177
|
-
currency: _terminal.accountingContextForTokenOf(_projectId, JBConstants.NATIVE_TOKEN).currency,
|
|
178
|
-
value: _halfPaid
|
|
179
|
-
}),
|
|
180
|
-
forwardedAmount: JBTokenAmount({
|
|
181
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
182
|
-
decimals: _terminal.accountingContextForTokenOf(_projectId, JBConstants.NATIVE_TOKEN).decimals,
|
|
183
|
-
currency: _terminal.accountingContextForTokenOf(_projectId, JBConstants.NATIVE_TOKEN).currency,
|
|
184
|
-
value: _halfPaid
|
|
185
|
-
}),
|
|
186
|
-
cashOutTaxRate: 0,
|
|
187
|
-
beneficiary: payable(address(this)),
|
|
188
|
-
hookMetadata: "",
|
|
189
|
-
cashOutMetadata: ""
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
// Mock the hook.
|
|
193
|
-
vm.mockCall(
|
|
194
|
-
_cashOutHook,
|
|
195
|
-
abi.encodeWithSelector(IJBCashOutHook.afterCashOutRecordedWith.selector),
|
|
196
|
-
abi.encode(_cashOutContext)
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
// Assert that the hook gets called with the expected value.
|
|
200
|
-
vm.expectCall(
|
|
201
|
-
_cashOutHook,
|
|
202
|
-
_halfPaid,
|
|
203
|
-
abi.encodeWithSelector(IJBCashOutHook.afterCashOutRecordedWith.selector, _cashOutContext)
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
vm.mockCall(
|
|
207
|
-
_DATA_HOOK,
|
|
208
|
-
abi.encodeWithSelector(IJBRulesetDataHook.beforeCashOutRecordedWith.selector),
|
|
209
|
-
abi.encode(
|
|
210
|
-
_ruleset.cashOutTaxRate(),
|
|
211
|
-
_beneficiaryTokenBalance / 2,
|
|
212
|
-
_beneficiaryTokenBalance,
|
|
213
|
-
_nativePayAmount,
|
|
214
|
-
_specifications
|
|
215
|
-
)
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
_terminal.cashOutTokensOf({
|
|
219
|
-
holder: address(this),
|
|
220
|
-
projectId: _projectId,
|
|
221
|
-
cashOutCount: _beneficiaryTokenBalance / 2,
|
|
222
|
-
tokenToReclaim: JBConstants.NATIVE_TOKEN,
|
|
223
|
-
minTokensReclaimed: 0,
|
|
224
|
-
beneficiary: payable(address(this)),
|
|
225
|
-
metadata: new bytes(0)
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function testCashOutHookWithFeesAndCustomInfo() public {
|
|
230
|
-
// Reference and bound pay amount.
|
|
231
|
-
uint256 _nativePayAmount = 10 ether;
|
|
232
|
-
uint256 _halfPaid = 5 ether;
|
|
233
|
-
|
|
234
|
-
// Cash out hook address.
|
|
235
|
-
address _cashOutHook = makeAddr("SOFA");
|
|
236
|
-
vm.label(_cashOutHook, "Cash Out Delegate");
|
|
237
|
-
|
|
238
|
-
// Keep a reference to the current ruleset.
|
|
239
|
-
(JBRuleset memory _ruleset,) = _controller.currentRulesetOf(_projectId);
|
|
240
|
-
|
|
241
|
-
vm.deal(address(this), _nativePayAmount);
|
|
242
|
-
uint256 _beneficiaryTokensReceived = _terminal.pay{value: _nativePayAmount}({
|
|
243
|
-
projectId: _projectId,
|
|
244
|
-
amount: _nativePayAmount,
|
|
245
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
246
|
-
beneficiary: address(this),
|
|
247
|
-
minReturnedTokens: 0,
|
|
248
|
-
memo: "Forge Test",
|
|
249
|
-
metadata: ""
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
// Make sure the beneficiary has a balance of project tokens.
|
|
253
|
-
uint256 _beneficiaryTokenBalance =
|
|
254
|
-
UD60x18unwrap(UD60x18mul(UD60x18wrap(_nativePayAmount), UD60x18wrap(_WEIGHT)));
|
|
255
|
-
assertEq(_tokens.totalBalanceOf(address(this), _projectId), _beneficiaryTokenBalance);
|
|
256
|
-
assertEq(_beneficiaryTokensReceived, _beneficiaryTokenBalance);
|
|
257
|
-
|
|
258
|
-
// Make sure the native token balance in terminal is up to date.
|
|
259
|
-
uint256 _nativeTerminalBalance = _nativePayAmount;
|
|
260
|
-
assertEq(
|
|
261
|
-
jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN),
|
|
262
|
-
_nativeTerminalBalance
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
// Reference cash out hook specifications.
|
|
266
|
-
JBCashOutHookSpecification[] memory _specifications = new JBCashOutHookSpecification[](1);
|
|
267
|
-
|
|
268
|
-
_specifications[0] = JBCashOutHookSpecification({
|
|
269
|
-
hook: IJBCashOutHook(_cashOutHook), noop: false, amount: _halfPaid, metadata: ""
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
uint256 _customCashOutTaxRate = JBConstants.MAX_CASH_OUT_TAX_RATE / 2;
|
|
273
|
-
uint256 _customCashOutCount = 1 * 10 ** 18;
|
|
274
|
-
uint256 _customTotalSupply = 5 * 10 ** 18;
|
|
275
|
-
|
|
276
|
-
uint256 _forwardedAmount = _halfPaid - (_halfPaid * _terminal.FEE() / JBConstants.MAX_FEE);
|
|
277
|
-
|
|
278
|
-
uint256 _beneficiaryAmount = mulDiv(
|
|
279
|
-
mulDiv(_nativePayAmount, _customCashOutCount, _customTotalSupply),
|
|
280
|
-
(JBConstants.MAX_CASH_OUT_TAX_RATE - _customCashOutTaxRate)
|
|
281
|
-
+ mulDiv(_customCashOutCount, _customCashOutTaxRate, _customTotalSupply),
|
|
282
|
-
JBConstants.MAX_CASH_OUT_TAX_RATE
|
|
283
|
-
);
|
|
284
|
-
|
|
285
|
-
_beneficiaryAmount -= mulDiv(_beneficiaryAmount, _terminal.FEE(), JBConstants.MAX_FEE);
|
|
286
|
-
|
|
287
|
-
// Cash out context.
|
|
288
|
-
JBAfterCashOutRecordedContext memory _cashOutContext = JBAfterCashOutRecordedContext({
|
|
289
|
-
holder: address(this),
|
|
290
|
-
projectId: _projectId,
|
|
291
|
-
rulesetId: _ruleset.id,
|
|
292
|
-
cashOutCount: _beneficiaryTokenBalance / 2,
|
|
293
|
-
reclaimedAmount: JBTokenAmount({
|
|
294
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
295
|
-
decimals: _terminal.accountingContextForTokenOf(_projectId, JBConstants.NATIVE_TOKEN).decimals,
|
|
296
|
-
currency: _terminal.accountingContextForTokenOf(_projectId, JBConstants.NATIVE_TOKEN).currency,
|
|
297
|
-
value: _beneficiaryAmount
|
|
298
|
-
}),
|
|
299
|
-
forwardedAmount: JBTokenAmount({
|
|
300
|
-
token: JBConstants.NATIVE_TOKEN,
|
|
301
|
-
decimals: _terminal.accountingContextForTokenOf(_projectId, JBConstants.NATIVE_TOKEN).decimals,
|
|
302
|
-
currency: _terminal.accountingContextForTokenOf(_projectId, JBConstants.NATIVE_TOKEN).currency,
|
|
303
|
-
value: _forwardedAmount
|
|
304
|
-
}),
|
|
305
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
306
|
-
cashOutTaxRate: uint16(_customCashOutTaxRate),
|
|
307
|
-
beneficiary: payable(address(this)),
|
|
308
|
-
hookMetadata: "",
|
|
309
|
-
cashOutMetadata: ""
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
// Mock the hook.
|
|
313
|
-
vm.mockCall(
|
|
314
|
-
_cashOutHook,
|
|
315
|
-
abi.encodeWithSelector(IJBCashOutHook.afterCashOutRecordedWith.selector),
|
|
316
|
-
abi.encode(_cashOutContext)
|
|
317
|
-
);
|
|
318
|
-
|
|
319
|
-
// Assert that the hook gets called with the expected value.
|
|
320
|
-
vm.expectCall(
|
|
321
|
-
_cashOutHook,
|
|
322
|
-
_forwardedAmount,
|
|
323
|
-
abi.encodeWithSelector(IJBCashOutHook.afterCashOutRecordedWith.selector, _cashOutContext)
|
|
324
|
-
);
|
|
325
|
-
|
|
326
|
-
vm.mockCall(
|
|
327
|
-
_DATA_HOOK,
|
|
328
|
-
abi.encodeWithSelector(IJBRulesetDataHook.beforeCashOutRecordedWith.selector),
|
|
329
|
-
abi.encode(
|
|
330
|
-
_customCashOutTaxRate,
|
|
331
|
-
_customCashOutCount,
|
|
332
|
-
_customTotalSupply,
|
|
333
|
-
_nativeTerminalBalance, // Same as _nativePayAmount (no payouts); avoids stack depth limit.
|
|
334
|
-
_specifications
|
|
335
|
-
)
|
|
336
|
-
);
|
|
337
|
-
|
|
338
|
-
_terminal.cashOutTokensOf({
|
|
339
|
-
holder: address(this),
|
|
340
|
-
projectId: _projectId,
|
|
341
|
-
cashOutCount: _beneficiaryTokenBalance / 2,
|
|
342
|
-
tokenToReclaim: JBConstants.NATIVE_TOKEN,
|
|
343
|
-
minTokensReclaimed: 0,
|
|
344
|
-
beneficiary: payable(address(this)),
|
|
345
|
-
metadata: new bytes(0)
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
receive() external payable {}
|
|
350
|
-
fallback() external payable {}
|
|
351
|
-
}
|