@bananapus/core-v6 0.0.36 → 0.0.38
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/JBController.sol +26 -5
- package/src/JBMultiTerminal.sol +85 -47
- package/src/JBTerminalStore.sol +6 -6
- package/src/interfaces/IJBController.sol +4 -1
- package/src/libraries/JBFees.sol +47 -9
- package/src/libraries/JBPayoutSplitGroupLib.sol +2 -2
- package/src/periphery/JBMatchingPriceFeed.sol +1 -1
- 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/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,624 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity 0.8.28;
|
|
3
|
-
|
|
4
|
-
import {MockERC20} from "../../../mock/MockERC20.sol";
|
|
5
|
-
import {JBMultiTerminal} from "../../../../src/JBMultiTerminal.sol";
|
|
6
|
-
import {JBPermissioned} from "../../../../src/abstract/JBPermissioned.sol";
|
|
7
|
-
import {IJBCashOutHook} from "../../../../src/interfaces/IJBCashOutHook.sol";
|
|
8
|
-
import {IJBController} from "../../../../src/interfaces/IJBController.sol";
|
|
9
|
-
import {IJBDirectory} from "../../../../src/interfaces/IJBDirectory.sol";
|
|
10
|
-
import {IJBFeelessAddresses} from "../../../../src/interfaces/IJBFeelessAddresses.sol";
|
|
11
|
-
import {IJBPermissions} from "../../../../src/interfaces/IJBPermissions.sol";
|
|
12
|
-
import {IJBRulesetApprovalHook} from "../../../../src/interfaces/IJBRulesetApprovalHook.sol";
|
|
13
|
-
import {IJBTerminalStore} from "../../../../src/interfaces/IJBTerminalStore.sol";
|
|
14
|
-
import {JBConstants} from "../../../../src/libraries/JBConstants.sol";
|
|
15
|
-
import {JBFees} from "../../../../src/libraries/JBFees.sol";
|
|
16
|
-
import {JBAccountingContext} from "../../../../src/structs/JBAccountingContext.sol";
|
|
17
|
-
import {JBAfterCashOutRecordedContext} from "../../../../src/structs/JBAfterCashOutRecordedContext.sol";
|
|
18
|
-
import {JBCashOutHookSpecification} from "../../../../src/structs/JBCashOutHookSpecification.sol";
|
|
19
|
-
import {JBRuleset} from "../../../../src/structs/JBRuleset.sol";
|
|
20
|
-
import {JBTokenAmount} from "../../../../src/structs/JBTokenAmount.sol";
|
|
21
|
-
import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
|
|
22
|
-
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
23
|
-
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
|
24
|
-
import {JBMultiTerminalSetup} from "./JBMultiTerminalSetup.sol";
|
|
25
|
-
|
|
26
|
-
contract TestCashOutTokensOf_Local is JBMultiTerminalSetup {
|
|
27
|
-
uint64 _projectId = 1;
|
|
28
|
-
uint256 _defaultAmount = 1e18;
|
|
29
|
-
uint16 _maxCashOutTaxRate = JBConstants.MAX_CASH_OUT_TAX_RATE;
|
|
30
|
-
uint16 _halfCashOutTaxRate = JBConstants.MAX_CASH_OUT_TAX_RATE / 2;
|
|
31
|
-
|
|
32
|
-
address _holder = makeAddr("holder");
|
|
33
|
-
address payable _bene = payable(makeAddr("beneficiary"));
|
|
34
|
-
address _mockToken = makeAddr("mockToken");
|
|
35
|
-
IJBCashOutHook _mockHook = IJBCashOutHook(makeAddr("cashOutHook"));
|
|
36
|
-
|
|
37
|
-
// mock erc20 necessary for balance checks
|
|
38
|
-
MockERC20 _mockToken2;
|
|
39
|
-
|
|
40
|
-
uint256 _minReclaimed;
|
|
41
|
-
|
|
42
|
-
function setUp() public {
|
|
43
|
-
super.multiTerminalSetup();
|
|
44
|
-
|
|
45
|
-
_mockToken2 = new MockERC20("testToken", "TT");
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function _acceptToken(address token, uint8 decimals, uint32 currency) internal {
|
|
49
|
-
mockExpect(address(projects), abi.encodeCall(IERC721.ownerOf, (_projectId)), abi.encode(address(0)));
|
|
50
|
-
mockExpect(
|
|
51
|
-
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
// Mock ERC20 transfer for non-contract token addresses (needed for SafeERC20 calls later).
|
|
55
|
-
if (token != JBConstants.NATIVE_TOKEN && token.code.length == 0) {
|
|
56
|
-
vm.mockCall(token, abi.encodeWithSelector(IERC20.transfer.selector), abi.encode(true));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
JBAccountingContext[] memory _tokens = new JBAccountingContext[](1);
|
|
60
|
-
_tokens[0] = JBAccountingContext({token: token, decimals: decimals, currency: currency});
|
|
61
|
-
|
|
62
|
-
// Mock recordAccountingContextOf in the store (validation now happens there)
|
|
63
|
-
mockExpect(
|
|
64
|
-
address(store), abi.encodeCall(IJBTerminalStore.recordAccountingContextOf, (_projectId, _tokens)), ""
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
vm.prank(address(this));
|
|
68
|
-
_terminal.addAccountingContextsFor(_projectId, _tokens);
|
|
69
|
-
|
|
70
|
-
// Mock accountingContextOf for subsequent reads (not all code paths call it, so use mockCall only)
|
|
71
|
-
vm.mockCall(
|
|
72
|
-
address(store),
|
|
73
|
-
abi.encodeCall(IJBTerminalStore.accountingContextOf, (address(_terminal), _projectId, token)),
|
|
74
|
-
abi.encode(_tokens[0])
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function test_WhenCallerDNHavePermission() external {
|
|
79
|
-
// it will revert UNAUTHORIZED
|
|
80
|
-
|
|
81
|
-
// mock call to JBPermissions hasPermission
|
|
82
|
-
mockExpect(
|
|
83
|
-
address(permissions),
|
|
84
|
-
abi.encodeCall(
|
|
85
|
-
IJBPermissions.hasPermission,
|
|
86
|
-
(address(_bene), address(_holder), _projectId, JBPermissionIds.CASH_OUT_TOKENS, true, true)
|
|
87
|
-
),
|
|
88
|
-
abi.encode(false)
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
vm.expectRevert(
|
|
92
|
-
abi.encodeWithSelector(
|
|
93
|
-
JBPermissioned.JBPermissioned_Unauthorized.selector,
|
|
94
|
-
_holder,
|
|
95
|
-
_bene,
|
|
96
|
-
_projectId,
|
|
97
|
-
JBPermissionIds.CASH_OUT_TOKENS
|
|
98
|
-
)
|
|
99
|
-
);
|
|
100
|
-
vm.prank(_bene);
|
|
101
|
-
_terminal.cashOutTokensOf(_holder, _projectId, _defaultAmount, _mockToken, _minReclaimed, _bene, "");
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
modifier whenCallerHasPermission() {
|
|
105
|
-
// mock call to JBPermissions hasPermission
|
|
106
|
-
mockExpect(
|
|
107
|
-
address(permissions),
|
|
108
|
-
abi.encodeCall(
|
|
109
|
-
IJBPermissions.hasPermission,
|
|
110
|
-
(address(_bene), address(_holder), _projectId, JBPermissionIds.CASH_OUT_TOKENS, true, true)
|
|
111
|
-
),
|
|
112
|
-
abi.encode(true)
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
_;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function test_GivenCashOutCountLTMinTokensReclaimed() external whenCallerHasPermission {
|
|
119
|
-
// it will revert UNDER_MIN_TOKENS_RECLAIMED
|
|
120
|
-
|
|
121
|
-
uint256 reclaimAmount = 1e9;
|
|
122
|
-
JBCashOutHookSpecification[] memory hookSpecifications = new JBCashOutHookSpecification[](0);
|
|
123
|
-
JBAccountingContext memory mockTokenContext =
|
|
124
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
125
|
-
JBAccountingContext({token: _mockToken, decimals: 18, currency: uint32(uint160(_mockToken))});
|
|
126
|
-
JBAccountingContext[] memory mockBalanceContext = new JBAccountingContext[](1);
|
|
127
|
-
mockBalanceContext[0] = mockTokenContext;
|
|
128
|
-
JBRuleset memory returnedRuleset = JBRuleset({
|
|
129
|
-
cycleNumber: 1,
|
|
130
|
-
id: 1,
|
|
131
|
-
basedOnId: 0,
|
|
132
|
-
start: 0,
|
|
133
|
-
duration: 0,
|
|
134
|
-
weight: 0,
|
|
135
|
-
weightCutPercent: 0,
|
|
136
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
137
|
-
metadata: 0
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// mock feeless address check
|
|
141
|
-
mockExpect(address(feelessAddresses), abi.encodeCall(IJBFeelessAddresses.isFeeless, (_bene)), abi.encode(true));
|
|
142
|
-
|
|
143
|
-
// mock call to JBTerminalStore recordCashOutFor
|
|
144
|
-
mockExpect(
|
|
145
|
-
address(store),
|
|
146
|
-
abi.encodeCall(
|
|
147
|
-
IJBTerminalStore.recordCashOutFor,
|
|
148
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext.token, true, "")
|
|
149
|
-
),
|
|
150
|
-
abi.encode(returnedRuleset, reclaimAmount, _maxCashOutTaxRate, hookSpecifications)
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
// mock call to find the controller (we'll just use this contracts address for simplicity)
|
|
154
|
-
mockExpect(
|
|
155
|
-
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
// mock controller burn call
|
|
159
|
-
mockExpect(
|
|
160
|
-
address(this), abi.encodeCall(IJBController.burnTokensOf, (_holder, _projectId, _defaultAmount, "")), ""
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
// put code at mockToken address to pass OZ Address check
|
|
164
|
-
vm.etch(_mockToken, abi.encode(1));
|
|
165
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
166
|
-
_acceptToken(_mockToken, 18, uint32(uint160(_mockToken)));
|
|
167
|
-
|
|
168
|
-
vm.prank(_bene);
|
|
169
|
-
_terminal.cashOutTokensOf(_holder, _projectId, _defaultAmount, _mockToken, _minReclaimed, _bene, "");
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function test_GivenCashOutCountGtZero() external whenCallerHasPermission {
|
|
173
|
-
// it will call directory controller of and burnTokensOf
|
|
174
|
-
|
|
175
|
-
uint256 reclaimAmount = 1e9;
|
|
176
|
-
JBCashOutHookSpecification[] memory hookSpecifications = new JBCashOutHookSpecification[](0);
|
|
177
|
-
JBAccountingContext memory mockTokenContext =
|
|
178
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
179
|
-
JBAccountingContext({token: _mockToken, decimals: 18, currency: uint32(uint160(_mockToken))});
|
|
180
|
-
JBAccountingContext[] memory mockBalanceContext = new JBAccountingContext[](1);
|
|
181
|
-
mockBalanceContext[0] = mockTokenContext;
|
|
182
|
-
JBRuleset memory returnedRuleset = JBRuleset({
|
|
183
|
-
cycleNumber: 1,
|
|
184
|
-
id: 1,
|
|
185
|
-
basedOnId: 0,
|
|
186
|
-
start: 0,
|
|
187
|
-
duration: 0,
|
|
188
|
-
weight: 0,
|
|
189
|
-
weightCutPercent: 0,
|
|
190
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
191
|
-
metadata: 0
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// mock feeless address check
|
|
195
|
-
mockExpect(address(feelessAddresses), abi.encodeCall(IJBFeelessAddresses.isFeeless, (_bene)), abi.encode(true));
|
|
196
|
-
|
|
197
|
-
// mock call to JBTerminalStore recordCashOutFor
|
|
198
|
-
mockExpect(
|
|
199
|
-
address(store),
|
|
200
|
-
abi.encodeCall(
|
|
201
|
-
IJBTerminalStore.recordCashOutFor,
|
|
202
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext.token, true, "")
|
|
203
|
-
),
|
|
204
|
-
abi.encode(returnedRuleset, reclaimAmount, _maxCashOutTaxRate, hookSpecifications)
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
// mock call to find the controller (we'll just use this contracts address for simplicity)
|
|
208
|
-
mockExpect(
|
|
209
|
-
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
|
|
210
|
-
);
|
|
211
|
-
|
|
212
|
-
// mock controller burn call
|
|
213
|
-
mockExpect(
|
|
214
|
-
address(this), abi.encodeCall(IJBController.burnTokensOf, (_holder, _projectId, _defaultAmount, "")), ""
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
// put code at mockToken address to pass OZ Address check
|
|
218
|
-
vm.etch(_mockToken, abi.encode(1));
|
|
219
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
220
|
-
_acceptToken(_mockToken, 18, uint32(uint160(_mockToken)));
|
|
221
|
-
|
|
222
|
-
vm.expectRevert(abi.encodeWithSelector(JBMultiTerminal.JBMultiTerminal_UnderMin.selector, reclaimAmount, 1e18));
|
|
223
|
-
vm.prank(_bene);
|
|
224
|
-
_terminal.cashOutTokensOf(_holder, _projectId, _defaultAmount, _mockToken, 1e18, _bene, ""); // minReclaimAmount
|
|
225
|
-
// = 1e18 but only 1e9 reclaimed
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function test_GivenReclaimAmountGtZeroBeneficiaryIsNotFeelessAndCashOutRateDneqMAX_CASH_OUT_RATE()
|
|
229
|
-
external
|
|
230
|
-
whenCallerHasPermission
|
|
231
|
-
{
|
|
232
|
-
// it will subtract the fee for the reclaim
|
|
233
|
-
|
|
234
|
-
uint256 reclaimAmount = 1e9;
|
|
235
|
-
JBCashOutHookSpecification[] memory hookSpecifications = new JBCashOutHookSpecification[](0);
|
|
236
|
-
JBAccountingContext memory mockTokenContext =
|
|
237
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
238
|
-
JBAccountingContext({token: _mockToken, decimals: 18, currency: uint32(uint160(_mockToken))});
|
|
239
|
-
JBAccountingContext[] memory mockBalanceContext = new JBAccountingContext[](1);
|
|
240
|
-
mockBalanceContext[0] = mockTokenContext;
|
|
241
|
-
JBRuleset memory returnedRuleset = JBRuleset({
|
|
242
|
-
cycleNumber: 1,
|
|
243
|
-
id: 1,
|
|
244
|
-
basedOnId: 0,
|
|
245
|
-
start: 0,
|
|
246
|
-
duration: 0,
|
|
247
|
-
weight: 0,
|
|
248
|
-
weightCutPercent: 0,
|
|
249
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
250
|
-
metadata: 0
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
// mock feeless address check
|
|
254
|
-
mockExpect(address(feelessAddresses), abi.encodeCall(IJBFeelessAddresses.isFeeless, (_bene)), abi.encode(false));
|
|
255
|
-
|
|
256
|
-
// mock call to JBTerminalStore recordCashOutFor
|
|
257
|
-
mockExpect(
|
|
258
|
-
address(store),
|
|
259
|
-
abi.encodeCall(
|
|
260
|
-
IJBTerminalStore.recordCashOutFor,
|
|
261
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext.token, false, "")
|
|
262
|
-
),
|
|
263
|
-
abi.encode(returnedRuleset, reclaimAmount, _halfCashOutTaxRate, hookSpecifications)
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
// mock call to find the controller (we'll just use this contracts address for simplicity)
|
|
267
|
-
mockExpect(
|
|
268
|
-
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
|
|
269
|
-
);
|
|
270
|
-
|
|
271
|
-
// mock controller burn call
|
|
272
|
-
mockExpect(
|
|
273
|
-
address(this), abi.encodeCall(IJBController.burnTokensOf, (_holder, _projectId, _defaultAmount, "")), ""
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
// put code at mockToken address to pass OZ Address check
|
|
277
|
-
vm.etch(_mockToken, abi.encode(1));
|
|
278
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
279
|
-
_acceptToken(_mockToken, 18, uint32(uint160(_mockToken)));
|
|
280
|
-
|
|
281
|
-
// get fee amount
|
|
282
|
-
uint256 tax = JBFees.feeAmountFrom(reclaimAmount, 25); // 25 = default fee)
|
|
283
|
-
uint256 transferredAmount = reclaimAmount - tax;
|
|
284
|
-
|
|
285
|
-
// transfer reclaimed to beneficiary
|
|
286
|
-
mockExpect(_mockToken, abi.encodeCall(IERC20.transfer, (_bene, transferredAmount)), abi.encode(true));
|
|
287
|
-
|
|
288
|
-
// find the terminal where subtracted fees are sent
|
|
289
|
-
mockExpect(
|
|
290
|
-
address(directory),
|
|
291
|
-
abi.encodeCall(IJBDirectory.primaryTerminalOf, (_projectId, _mockToken)),
|
|
292
|
-
abi.encode(address(_terminal))
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
// executeProcessFee
|
|
296
|
-
mockExpect(
|
|
297
|
-
address(_terminal),
|
|
298
|
-
abi.encodeCall(JBMultiTerminal.executeProcessFee, (_projectId, _mockToken, tax, _bene, _terminal)),
|
|
299
|
-
""
|
|
300
|
-
);
|
|
301
|
-
|
|
302
|
-
vm.prank(_bene);
|
|
303
|
-
_terminal.cashOutTokensOf(_holder, _projectId, _defaultAmount, _mockToken, _minReclaimed, _bene, "");
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// covered above / in other units that test transfers
|
|
307
|
-
/* function test_GivenTheTokenIsNative() external whenCallerHasPermission {
|
|
308
|
-
// it will sendValue
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function test_GivenTheTokenIsErc20() external whenCallerHasPermission {
|
|
312
|
-
// it will safeTransfer tokens
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
function test_GivenAmountEligibleForFeesDneqZero() external whenCallerHasPermission {
|
|
316
|
-
// it will call directory primaryTerminalOf and process the fee
|
|
317
|
-
} */
|
|
318
|
-
|
|
319
|
-
modifier whenADataHookIsConfigured() {
|
|
320
|
-
_;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/* function test_GivenDataHookReturnsCashOutHookSpecsHookIsFeelessAndTokenIsNative()
|
|
324
|
-
external
|
|
325
|
-
whenADataHookIsConfigured
|
|
326
|
-
whenCallerHasPermission
|
|
327
|
-
{
|
|
328
|
-
// it will pass the full amount to the hook and emit HookAfterRecordCashOut
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
} */
|
|
332
|
-
|
|
333
|
-
function test_GivenDataHookReturnsCashOutHookSpecsHookIsFeelessAndTokenIsErc20()
|
|
334
|
-
external
|
|
335
|
-
whenADataHookIsConfigured
|
|
336
|
-
whenCallerHasPermission
|
|
337
|
-
{
|
|
338
|
-
// it will forceApprove pass the full amount to the hook and emit HookAfterRecordCashOut
|
|
339
|
-
|
|
340
|
-
// mint mocked erc20 tokens to hodler
|
|
341
|
-
_mockToken2.mint(address(_terminal), _defaultAmount * 10);
|
|
342
|
-
_mockToken2.mint(address(_holder), _defaultAmount * 10);
|
|
343
|
-
|
|
344
|
-
// approve those tokens to the terminal
|
|
345
|
-
vm.prank(_holder);
|
|
346
|
-
_mockToken2.approve(address(_terminal), _defaultAmount);
|
|
347
|
-
|
|
348
|
-
uint256 reclaimAmount = 1e9;
|
|
349
|
-
JBCashOutHookSpecification[] memory hookSpecifications = new JBCashOutHookSpecification[](1);
|
|
350
|
-
hookSpecifications[0] =
|
|
351
|
-
JBCashOutHookSpecification({hook: _mockHook, noop: false, amount: _defaultAmount, metadata: ""});
|
|
352
|
-
JBAccountingContext memory mockTokenContext = JBAccountingContext({
|
|
353
|
-
token: address(_mockToken2), decimals: 18, currency: uint32(uint160(address(_mockToken2)))
|
|
354
|
-
});
|
|
355
|
-
JBAccountingContext[] memory mockBalanceContext = new JBAccountingContext[](1);
|
|
356
|
-
mockBalanceContext[0] = mockTokenContext;
|
|
357
|
-
JBRuleset memory returnedRuleset = JBRuleset({
|
|
358
|
-
cycleNumber: 1,
|
|
359
|
-
id: 1,
|
|
360
|
-
basedOnId: 0,
|
|
361
|
-
start: 0,
|
|
362
|
-
duration: 0,
|
|
363
|
-
weight: 0,
|
|
364
|
-
weightCutPercent: 0,
|
|
365
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
366
|
-
metadata: 0
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
mockExpect(address(feelessAddresses), abi.encodeCall(IJBFeelessAddresses.isFeeless, (_bene)), abi.encode(true));
|
|
370
|
-
|
|
371
|
-
// mock call to JBTerminalStore recordCashOutFor
|
|
372
|
-
mockExpect(
|
|
373
|
-
address(store),
|
|
374
|
-
abi.encodeCall(
|
|
375
|
-
IJBTerminalStore.recordCashOutFor,
|
|
376
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext.token, true, "")
|
|
377
|
-
),
|
|
378
|
-
abi.encode(returnedRuleset, reclaimAmount, _maxCashOutTaxRate, hookSpecifications)
|
|
379
|
-
);
|
|
380
|
-
|
|
381
|
-
// mock call to find the controller (we'll just use this contracts address for simplicity)
|
|
382
|
-
mockExpect(
|
|
383
|
-
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
|
|
384
|
-
);
|
|
385
|
-
|
|
386
|
-
// mock controller burn call
|
|
387
|
-
mockExpect(
|
|
388
|
-
address(this), abi.encodeCall(IJBController.burnTokensOf, (_holder, _projectId, _defaultAmount, "")), ""
|
|
389
|
-
);
|
|
390
|
-
|
|
391
|
-
mockExpect(
|
|
392
|
-
address(feelessAddresses),
|
|
393
|
-
abi.encodeCall(IJBFeelessAddresses.isFeeless, (address(_mockHook))),
|
|
394
|
-
abi.encode(true)
|
|
395
|
-
);
|
|
396
|
-
|
|
397
|
-
JBTokenAmount memory reclaimedAmount = JBTokenAmount({
|
|
398
|
-
token: address(_mockToken2),
|
|
399
|
-
decimals: 18,
|
|
400
|
-
currency: uint32(uint160(address(_mockToken2))),
|
|
401
|
-
value: reclaimAmount
|
|
402
|
-
});
|
|
403
|
-
JBTokenAmount memory forwardedAmount = JBTokenAmount({
|
|
404
|
-
token: address(_mockToken2),
|
|
405
|
-
decimals: 18,
|
|
406
|
-
currency: uint32(uint160(address(_mockToken2))),
|
|
407
|
-
value: _defaultAmount
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
// needed for hook call
|
|
411
|
-
JBAfterCashOutRecordedContext memory context = JBAfterCashOutRecordedContext({
|
|
412
|
-
holder: _holder,
|
|
413
|
-
projectId: _projectId,
|
|
414
|
-
rulesetId: returnedRuleset.id,
|
|
415
|
-
cashOutCount: _defaultAmount,
|
|
416
|
-
reclaimedAmount: reclaimedAmount,
|
|
417
|
-
forwardedAmount: forwardedAmount,
|
|
418
|
-
cashOutTaxRate: _maxCashOutTaxRate,
|
|
419
|
-
beneficiary: _bene,
|
|
420
|
-
hookMetadata: "",
|
|
421
|
-
cashOutMetadata: ""
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
mockExpect(address(_mockHook), abi.encodeCall(IJBCashOutHook.afterCashOutRecordedWith, (context)), "");
|
|
425
|
-
|
|
426
|
-
// ensure approval is set via forceApprove
|
|
427
|
-
vm.expectCall(address(_mockToken2), abi.encodeCall(IERC20.approve, (address(_mockHook), _defaultAmount)));
|
|
428
|
-
|
|
429
|
-
// Mock the temporary allowance as fully consumed by the hook so the cleanup guard passes.
|
|
430
|
-
vm.mockCall(
|
|
431
|
-
address(_mockToken2),
|
|
432
|
-
abi.encodeCall(IERC20.allowance, (address(_terminal), address(_mockHook))),
|
|
433
|
-
abi.encode(0)
|
|
434
|
-
);
|
|
435
|
-
|
|
436
|
-
_acceptToken(address(_mockToken2), 18, uint32(uint160(address(_mockToken2))));
|
|
437
|
-
|
|
438
|
-
vm.prank(_bene);
|
|
439
|
-
_terminal.cashOutTokensOf(_holder, _projectId, _defaultAmount, address(_mockToken2), _minReclaimed, _bene, "");
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
/* function test_GivenDataHookReturnsCashOutHookSpecsHookIsNotFeelessAndTokenIsNative()
|
|
443
|
-
external
|
|
444
|
-
whenADataHookIsConfigured
|
|
445
|
-
whenCallerHasPermission
|
|
446
|
-
{
|
|
447
|
-
// it will calculate the fee pass the amount to the hook and emit HookAfterRecordCashOut
|
|
448
|
-
} */
|
|
449
|
-
|
|
450
|
-
function test_GivenDataHookReturnsCashOutHookSpecsHookIsNotFeelessAndTokenIsErc20()
|
|
451
|
-
external
|
|
452
|
-
whenADataHookIsConfigured
|
|
453
|
-
whenCallerHasPermission
|
|
454
|
-
{
|
|
455
|
-
// it will forceApprove pass the amount to the hook and emit HookAfterRecordCashOut
|
|
456
|
-
|
|
457
|
-
// mint mocked erc20 tokens to hodler
|
|
458
|
-
_mockToken2.mint(address(_terminal), _defaultAmount * 10);
|
|
459
|
-
_mockToken2.mint(address(_holder), _defaultAmount * 10);
|
|
460
|
-
|
|
461
|
-
// approve those tokens to the terminal
|
|
462
|
-
vm.prank(_holder);
|
|
463
|
-
_mockToken2.approve(address(_terminal), _defaultAmount);
|
|
464
|
-
|
|
465
|
-
uint256 reclaimAmount = 1e9;
|
|
466
|
-
JBCashOutHookSpecification[] memory hookSpecifications = new JBCashOutHookSpecification[](1);
|
|
467
|
-
JBCashOutHookSpecification[] memory paySpecs = new JBCashOutHookSpecification[](0);
|
|
468
|
-
hookSpecifications[0] =
|
|
469
|
-
JBCashOutHookSpecification({hook: _mockHook, noop: false, amount: _defaultAmount, metadata: ""});
|
|
470
|
-
JBAccountingContext memory mockTokenContext = JBAccountingContext({
|
|
471
|
-
token: address(_mockToken2), decimals: 18, currency: uint32(uint160(address(_mockToken2)))
|
|
472
|
-
});
|
|
473
|
-
JBAccountingContext[] memory mockBalanceContext = new JBAccountingContext[](1);
|
|
474
|
-
mockBalanceContext[0] = mockTokenContext;
|
|
475
|
-
JBRuleset memory returnedRuleset = JBRuleset({
|
|
476
|
-
cycleNumber: 1,
|
|
477
|
-
id: 1,
|
|
478
|
-
basedOnId: 0,
|
|
479
|
-
start: 0,
|
|
480
|
-
duration: 0,
|
|
481
|
-
weight: 0,
|
|
482
|
-
weightCutPercent: 0,
|
|
483
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
484
|
-
metadata: 0
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
mockExpect(address(feelessAddresses), abi.encodeCall(IJBFeelessAddresses.isFeeless, (_bene)), abi.encode(true));
|
|
488
|
-
|
|
489
|
-
// mock call to JBTerminalStore recordCashOutFor
|
|
490
|
-
mockExpect(
|
|
491
|
-
address(store),
|
|
492
|
-
abi.encodeCall(
|
|
493
|
-
IJBTerminalStore.recordCashOutFor,
|
|
494
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext.token, true, "")
|
|
495
|
-
),
|
|
496
|
-
abi.encode(returnedRuleset, reclaimAmount, _maxCashOutTaxRate, hookSpecifications)
|
|
497
|
-
);
|
|
498
|
-
|
|
499
|
-
// mock call to find the controller (we'll just use this contracts address for simplicity)
|
|
500
|
-
mockExpect(
|
|
501
|
-
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
|
|
502
|
-
);
|
|
503
|
-
|
|
504
|
-
// mock controller burn call
|
|
505
|
-
mockExpect(
|
|
506
|
-
address(this), abi.encodeCall(IJBController.burnTokensOf, (_holder, _projectId, _defaultAmount, "")), ""
|
|
507
|
-
);
|
|
508
|
-
|
|
509
|
-
mockExpect(
|
|
510
|
-
address(feelessAddresses),
|
|
511
|
-
abi.encodeCall(IJBFeelessAddresses.isFeeless, (address(_mockHook))),
|
|
512
|
-
abi.encode(false)
|
|
513
|
-
);
|
|
514
|
-
|
|
515
|
-
uint256 hookTax = JBFees.feeAmountFrom(_defaultAmount, 25);
|
|
516
|
-
uint256 passedAfterTax = _defaultAmount - hookTax;
|
|
517
|
-
|
|
518
|
-
JBTokenAmount memory reclaimedAmount = JBTokenAmount({
|
|
519
|
-
token: address(_mockToken2),
|
|
520
|
-
decimals: 18,
|
|
521
|
-
currency: uint32(uint160(address(_mockToken2))),
|
|
522
|
-
value: reclaimAmount
|
|
523
|
-
});
|
|
524
|
-
JBTokenAmount memory forwardedAmount = JBTokenAmount({
|
|
525
|
-
token: address(_mockToken2),
|
|
526
|
-
decimals: 18,
|
|
527
|
-
currency: uint32(uint160(address(_mockToken2))),
|
|
528
|
-
value: passedAfterTax
|
|
529
|
-
});
|
|
530
|
-
JBTokenAmount memory feeRepayAmount = JBTokenAmount({
|
|
531
|
-
token: address(_mockToken2), decimals: 18, currency: uint32(uint160(address(_mockToken2))), value: hookTax
|
|
532
|
-
});
|
|
533
|
-
|
|
534
|
-
// needed for hook call
|
|
535
|
-
JBAfterCashOutRecordedContext memory context = JBAfterCashOutRecordedContext({
|
|
536
|
-
holder: _holder,
|
|
537
|
-
projectId: _projectId,
|
|
538
|
-
rulesetId: returnedRuleset.id,
|
|
539
|
-
cashOutCount: _defaultAmount,
|
|
540
|
-
reclaimedAmount: reclaimedAmount,
|
|
541
|
-
forwardedAmount: forwardedAmount,
|
|
542
|
-
cashOutTaxRate: _maxCashOutTaxRate,
|
|
543
|
-
beneficiary: _bene,
|
|
544
|
-
hookMetadata: "",
|
|
545
|
-
cashOutMetadata: ""
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
mockExpect(address(_mockHook), abi.encodeCall(IJBCashOutHook.afterCashOutRecordedWith, (context)), "");
|
|
549
|
-
|
|
550
|
-
// Mock the temporary allowance as fully consumed by the hook so the cleanup guard passes.
|
|
551
|
-
vm.mockCall(
|
|
552
|
-
address(_mockToken2),
|
|
553
|
-
abi.encodeCall(IERC20.allowance, (address(_terminal), address(_mockHook))),
|
|
554
|
-
abi.encode(0)
|
|
555
|
-
);
|
|
556
|
-
|
|
557
|
-
// primary terminal check
|
|
558
|
-
mockExpect(
|
|
559
|
-
address(directory),
|
|
560
|
-
abi.encodeCall(IJBDirectory.primaryTerminalOf, (_projectId, address(_mockToken2))),
|
|
561
|
-
abi.encode(address(_terminal))
|
|
562
|
-
);
|
|
563
|
-
|
|
564
|
-
// mock call to JBTerminalStore recordPaymentFrom
|
|
565
|
-
mockExpect(
|
|
566
|
-
address(store),
|
|
567
|
-
abi.encodeCall(
|
|
568
|
-
IJBTerminalStore.recordPaymentFrom,
|
|
569
|
-
(address(_terminal), feeRepayAmount, _projectId, _bene, bytes(abi.encodePacked(uint256(_projectId))))
|
|
570
|
-
),
|
|
571
|
-
abi.encode(returnedRuleset, 0, paySpecs)
|
|
572
|
-
);
|
|
573
|
-
|
|
574
|
-
_acceptToken(address(_mockToken2), 18, uint32(uint160(address(_mockToken2))));
|
|
575
|
-
|
|
576
|
-
vm.prank(_bene);
|
|
577
|
-
_terminal.cashOutTokensOf(_holder, _projectId, _defaultAmount, address(_mockToken2), _minReclaimed, _bene, "");
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
function test_GivenTheCashOutHookSpecIsNoop() external whenCallerHasPermission {
|
|
581
|
-
uint256 reclaimAmount = 1e9;
|
|
582
|
-
JBCashOutHookSpecification[] memory hookSpecifications = new JBCashOutHookSpecification[](1);
|
|
583
|
-
hookSpecifications[0] =
|
|
584
|
-
JBCashOutHookSpecification({hook: IJBCashOutHook(address(this)), noop: true, amount: 0, metadata: "info"});
|
|
585
|
-
JBAccountingContext memory mockTokenContext =
|
|
586
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
587
|
-
JBAccountingContext({token: _mockToken, decimals: 18, currency: uint32(uint160(_mockToken))});
|
|
588
|
-
JBAccountingContext[] memory mockBalanceContext = new JBAccountingContext[](1);
|
|
589
|
-
mockBalanceContext[0] = mockTokenContext;
|
|
590
|
-
JBRuleset memory returnedRuleset = JBRuleset({
|
|
591
|
-
cycleNumber: 1,
|
|
592
|
-
id: 1,
|
|
593
|
-
basedOnId: 0,
|
|
594
|
-
start: 0,
|
|
595
|
-
duration: 0,
|
|
596
|
-
weight: 0,
|
|
597
|
-
weightCutPercent: 0,
|
|
598
|
-
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
599
|
-
metadata: 0
|
|
600
|
-
});
|
|
601
|
-
|
|
602
|
-
mockExpect(address(feelessAddresses), abi.encodeCall(IJBFeelessAddresses.isFeeless, (_bene)), abi.encode(true));
|
|
603
|
-
mockExpect(
|
|
604
|
-
address(store),
|
|
605
|
-
abi.encodeCall(
|
|
606
|
-
IJBTerminalStore.recordCashOutFor,
|
|
607
|
-
(_holder, _projectId, _defaultAmount, mockTokenContext.token, true, "")
|
|
608
|
-
),
|
|
609
|
-
abi.encode(returnedRuleset, reclaimAmount, _maxCashOutTaxRate, hookSpecifications)
|
|
610
|
-
);
|
|
611
|
-
mockExpect(
|
|
612
|
-
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
|
|
613
|
-
);
|
|
614
|
-
mockExpect(
|
|
615
|
-
address(this), abi.encodeCall(IJBController.burnTokensOf, (_holder, _projectId, _defaultAmount, "")), ""
|
|
616
|
-
);
|
|
617
|
-
|
|
618
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
619
|
-
_acceptToken(_mockToken, 18, uint32(uint160(_mockToken)));
|
|
620
|
-
|
|
621
|
-
vm.prank(_bene);
|
|
622
|
-
_terminal.cashOutTokensOf(_holder, _projectId, _defaultAmount, _mockToken, _minReclaimed, _bene, "");
|
|
623
|
-
}
|
|
624
|
-
}
|