@bananapus/core-v6 0.0.14 → 0.0.16

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.
Files changed (216) hide show
  1. package/ADMINISTRATION.md +4 -0
  2. package/README.md +2 -2
  3. package/SKILLS.md +2 -0
  4. package/STYLE_GUIDE.md +150 -43
  5. package/foundry.toml +3 -3
  6. package/package.json +4 -4
  7. package/remappings.txt +1 -1
  8. package/script/Deploy.s.sol +23 -16
  9. package/script/DeployPeriphery.s.sol +71 -66
  10. package/script/helpers/CoreDeploymentLib.sol +84 -37
  11. package/src/JBChainlinkV3PriceFeed.sol +1 -0
  12. package/src/JBController.sol +19 -4
  13. package/src/JBERC20.sol +12 -3
  14. package/src/JBFundAccessLimits.sol +12 -2
  15. package/src/JBMultiTerminal.sol +3 -1
  16. package/src/JBPermissions.sol +1 -0
  17. package/src/JBProjects.sol +1 -1
  18. package/src/JBRulesets.sol +11 -0
  19. package/src/JBSplits.sol +5 -0
  20. package/src/JBTerminalStore.sol +3 -0
  21. package/src/JBTokens.sol +40 -4
  22. package/src/interfaces/IJBController.sol +6 -1
  23. package/src/interfaces/IJBPayoutTerminal.sol +0 -1
  24. package/src/interfaces/IJBPermitTerminal.sol +1 -0
  25. package/src/interfaces/IJBToken.sol +5 -0
  26. package/src/interfaces/IJBTokens.sol +13 -0
  27. package/src/libraries/JBMetadataResolver.sol +7 -3
  28. package/src/libraries/JBRulesetMetadataResolver.sol +21 -21
  29. package/src/structs/JBAccountingContext.sol +1 -0
  30. package/src/structs/JBAfterCashOutRecordedContext.sol +1 -0
  31. package/src/structs/JBAfterPayRecordedContext.sol +1 -0
  32. package/src/structs/JBBeforeCashOutRecordedContext.sol +1 -0
  33. package/src/structs/JBBeforePayRecordedContext.sol +1 -0
  34. package/src/structs/JBCashOutHookSpecification.sol +1 -0
  35. package/src/structs/JBCurrencyAmount.sol +1 -0
  36. package/src/structs/JBFee.sol +1 -0
  37. package/src/structs/JBFundAccessLimitGroup.sol +1 -0
  38. package/src/structs/JBPayHookSpecification.sol +1 -0
  39. package/src/structs/JBPermissionsData.sol +1 -0
  40. package/src/structs/JBRuleset.sol +1 -0
  41. package/src/structs/JBRulesetConfig.sol +1 -0
  42. package/src/structs/JBRulesetMetadata.sol +1 -0
  43. package/src/structs/JBRulesetWeightCache.sol +1 -0
  44. package/src/structs/JBRulesetWithMetadata.sol +1 -0
  45. package/src/structs/JBSingleAllowance.sol +1 -0
  46. package/src/structs/JBSplit.sol +1 -0
  47. package/src/structs/JBSplitGroup.sol +1 -0
  48. package/src/structs/JBSplitHookContext.sol +1 -0
  49. package/src/structs/JBTerminalConfig.sol +1 -0
  50. package/src/structs/JBTokenAmount.sol +1 -0
  51. package/test/ComprehensiveInvariant.t.sol +15 -5
  52. package/test/{AuditExploits.t.sol → CoreExploitTests.t.sol} +35 -4
  53. package/test/EconomicSimulation.t.sol +10 -2
  54. package/test/EntryPointPermutations.t.sol +18 -5
  55. package/test/FlashLoanAttacks.t.sol +12 -2
  56. package/test/PermissionEscalation.t.sol +54 -22
  57. package/test/RulesetTransitions.t.sol +15 -1
  58. package/test/SplitLoopTests.t.sol +26 -5
  59. package/test/TestAccessToFunds.sol +17 -2
  60. package/test/TestCashOut.sol +15 -2
  61. package/test/TestCashOutCountFor.sol +1 -2
  62. package/test/TestCashOutHooks.sol +47 -25
  63. package/test/TestCashOutTimingEdge.sol +13 -1
  64. package/test/TestDurationUnderflow.sol +13 -1
  65. package/test/TestFeeProcessingFailure.sol +17 -7
  66. package/test/TestFees.sol +14 -1
  67. package/test/TestInterfaceSupport.sol +20 -1
  68. package/test/TestJBERC20Inheritance.sol +11 -1
  69. package/test/TestLaunchProject.sol +13 -1
  70. package/test/TestMetaTx.sol +15 -1
  71. package/test/TestMetadataParserLib.sol +37 -4
  72. package/test/TestMigrationHeldFees.sol +17 -11
  73. package/test/TestMintTokensOf.sol +14 -1
  74. package/test/TestMultiTokenSurplus.sol +14 -1
  75. package/test/TestMultipleAccessLimits.sol +23 -1
  76. package/test/TestPayBurnRedeemFlow.sol +16 -1
  77. package/test/TestPayHooks.sol +33 -14
  78. package/test/TestPermissions.sol +20 -1
  79. package/test/TestPermissionsEdge.sol +5 -1
  80. package/test/TestPermit2Terminal.sol +36 -3
  81. package/test/TestRulesetQueueing.sol +24 -1
  82. package/test/TestRulesetQueuingStress.sol +28 -2
  83. package/test/TestRulesetWeightCaching.sol +5 -2
  84. package/test/TestSplits.sol +23 -1
  85. package/test/TestTerminalMigration.sol +11 -1
  86. package/test/TestTokenFlow.sol +18 -1
  87. package/test/TestWeightCacheStaleAfterRejection.sol +15 -1
  88. package/test/WeirdTokenTests.t.sol +18 -2
  89. package/test/fork/TestChainlinkPriceFeedFork.sol +254 -0
  90. package/test/formal/BondingCurveProperties.t.sol +8 -2
  91. package/test/formal/FeeProperties.t.sol +7 -1
  92. package/test/helpers/JBTest.sol +7 -7
  93. package/test/helpers/TestBaseWorkflow.sol +84 -1
  94. package/test/invariants/Phase3DeepInvariant.t.sol +13 -5
  95. package/test/invariants/RulesetsInvariant.t.sol +12 -2
  96. package/test/invariants/TerminalStoreInvariant.t.sol +11 -2
  97. package/test/invariants/TokensInvariant.t.sol +13 -2
  98. package/test/invariants/handlers/ComprehensiveHandler.sol +19 -1
  99. package/test/invariants/handlers/EconomicHandler.sol +31 -1
  100. package/test/invariants/handlers/Phase3Handler.sol +31 -2
  101. package/test/invariants/handlers/RulesetsHandler.sol +5 -1
  102. package/test/invariants/handlers/TerminalStoreHandler.sol +6 -1
  103. package/test/invariants/handlers/TokensHandler.sol +1 -2
  104. package/test/mock/ERC2771ForwarderMock.sol +1 -1
  105. package/test/mock/MockERC20.sol +1 -3
  106. package/test/mock/MockMaliciousBeneficiary.sol +2 -2
  107. package/test/mock/MockMaliciousSplitHook.sol +2 -1
  108. package/test/mock/MockPriceFeed.sol +1 -1
  109. package/test/units/static/JBChainlinkV3PriceFeed/TestPriceFeed.sol +0 -1
  110. package/test/units/static/JBController/JBControllerSetup.sol +10 -1
  111. package/test/units/static/JBController/TestBurnTokensOf.sol +8 -1
  112. package/test/units/static/JBController/TestClaimTokensFor.sol +4 -1
  113. package/test/units/static/JBController/TestDeployErc20For.sol +7 -1
  114. package/test/units/static/JBController/TestLaunchProjectFor.sol +21 -1
  115. package/test/units/static/JBController/TestLaunchRulesetsFor.sol +21 -1
  116. package/test/units/static/JBController/TestMigrateController.sol +10 -1
  117. package/test/units/static/JBController/TestMintTokensOfUnits.sol +10 -1
  118. package/test/units/static/JBController/TestPayReservedTokenToTerminal.sol +4 -1
  119. package/test/units/static/JBController/TestReceiveMigrationFrom.sol +5 -1
  120. package/test/units/static/JBController/TestRulesetViews.sol +7 -1
  121. package/test/units/static/JBController/TestSendReservedTokensToSplitsOf.sol +21 -1
  122. package/test/units/static/JBController/TestSetSplitGroupsOf.sol +6 -1
  123. package/test/units/static/JBController/TestSetTokenFor.sol +13 -1
  124. package/test/units/static/JBController/TestSetUriOf.sol +5 -1
  125. package/test/units/static/JBController/TestTransferCreditsFrom.sol +11 -1
  126. package/test/units/static/JBDeadline/TestDeadlineFuzz.sol +15 -4
  127. package/test/units/static/JBDirectory/JBDirectorySetup.sol +4 -1
  128. package/test/units/static/JBDirectory/TestPrimaryTerminalOf.sol +5 -1
  129. package/test/units/static/JBDirectory/TestSetControllerOf.sol +11 -1
  130. package/test/units/static/JBDirectory/TestSetControllerOfMigrationOrder.sol +7 -1
  131. package/test/units/static/JBDirectory/TestSetPrimaryTerminalOf.sol +11 -1
  132. package/test/units/static/JBDirectory/TestSetTerminalsOf.sol +10 -1
  133. package/test/units/static/JBERC20/JBERC20Setup.sol +2 -1
  134. package/test/units/static/JBERC20/SigUtils.sol +2 -0
  135. package/test/units/static/JBERC20/TestInitialize.sol +1 -1
  136. package/test/units/static/JBERC20/TestName.sol +1 -1
  137. package/test/units/static/JBERC20/TestNonces.sol +3 -1
  138. package/test/units/static/JBERC20/TestSymbol.sol +1 -1
  139. package/test/units/static/JBFeelessAdresses/JBFeelessSetup.sol +2 -1
  140. package/test/units/static/JBFeelessAdresses/TestInterfaces.sol +2 -1
  141. package/test/units/static/JBFeelessAdresses/TestSetFeelessAddress.sol +1 -1
  142. package/test/units/static/JBFees/TestFeesFuzz.sol +1 -1
  143. package/test/units/static/JBFixedPointNumber/TestAdjustDecimals.sol +0 -1
  144. package/test/units/static/JBFixedPointNumber/TestAdjustDecimalsFuzz.sol +0 -1
  145. package/test/units/static/JBFundAccessLimits/JBFundAccessSetup.sol +3 -1
  146. package/test/units/static/JBFundAccessLimits/TestFundAccessLimitsEdge.sol +4 -1
  147. package/test/units/static/JBFundAccessLimits/TestPayoutLimitOf.sol +4 -1
  148. package/test/units/static/JBFundAccessLimits/TestPayoutLimitsOf.sol +8 -1
  149. package/test/units/static/JBFundAccessLimits/TestSetFundAccessLimitsFor.sol +8 -1
  150. package/test/units/static/JBFundAccessLimits/TestSurplusAllowanceOf.sol +4 -1
  151. package/test/units/static/JBFundAccessLimits/TestSurplusAllowancesOf.sol +7 -1
  152. package/test/units/static/JBMetadataResolver/TestGetDataFor.sol +1 -1
  153. package/test/units/static/JBMetadataResolver/{TestMetadataResolverM20M21.sol → TestMetadataResolverEdgeCases.sol} +6 -5
  154. package/test/units/static/JBMetadataResolver/TestMetadataResolverFuzz.sol +2 -1
  155. package/test/units/static/JBMultiTerminal/JBMultiTerminalSetup.sol +12 -1
  156. package/test/units/static/JBMultiTerminal/TestAccountingContextsOf.sol +9 -1
  157. package/test/units/static/JBMultiTerminal/TestAddAccountingContextsFor.sol +18 -2
  158. package/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol +42 -7
  159. package/test/units/static/JBMultiTerminal/TestCashOutTokensOf.sol +30 -6
  160. package/test/units/static/JBMultiTerminal/TestExecutePayout.sol +18 -2
  161. package/test/units/static/JBMultiTerminal/TestExecuteProcessFee.sol +13 -3
  162. package/test/units/static/JBMultiTerminal/TestMigrateBalanceOf.sol +21 -4
  163. package/test/units/static/JBMultiTerminal/TestPay.sol +32 -6
  164. package/test/units/static/JBMultiTerminal/TestProcessHeldFeesOf.sol +0 -1
  165. package/test/units/static/JBMultiTerminal/TestSendPayoutsOf.sol +15 -1
  166. package/test/units/static/JBMultiTerminal/TestUseAllowanceOf.sol +17 -1
  167. package/test/units/static/JBPermissions/JBPermissionsSetup.sol +2 -1
  168. package/test/units/static/JBPermissions/TestHasPermission.sol +1 -1
  169. package/test/units/static/JBPermissions/TestHasPermissions.sol +1 -1
  170. package/test/units/static/JBPermissions/TestSetPermissionsFor.sol +3 -1
  171. package/test/units/static/JBPrices/JBPricesSetup.sol +6 -1
  172. package/test/units/static/JBPrices/TestAddPriceFeedFor.sol +6 -1
  173. package/test/units/static/JBPrices/TestPricePerUnitOf.sol +4 -1
  174. package/test/units/static/JBPrices/TestPrices.sol +4 -1
  175. package/test/units/static/JBProjects/JBProjectsSetup.sol +2 -1
  176. package/test/units/static/JBProjects/TestCreateFor.sol +3 -1
  177. package/test/units/static/JBProjects/TestInitialProject.sol +2 -1
  178. package/test/units/static/JBProjects/TestInterfaces.sol +0 -1
  179. package/test/units/static/JBProjects/TestSetResolver.sol +2 -1
  180. package/test/units/static/JBProjects/TestTokenUri.sol +3 -1
  181. package/test/units/static/JBRulesetMetadataResolver/TestSetCashOutTaxRateTo.sol +9 -1
  182. package/test/units/static/JBRulesets/JBRulesetsSetup.sol +3 -1
  183. package/test/units/static/JBRulesets/TestCurrentApprovalStatusForLatestRulesetOf.sol +9 -1
  184. package/test/units/static/JBRulesets/TestCurrentOf.sol +10 -1
  185. package/test/units/static/JBRulesets/TestGetRulesetOf.sol +7 -1
  186. package/test/units/static/JBRulesets/TestLatestQueuedRulesetOf.sol +9 -1
  187. package/test/units/static/JBRulesets/TestRulesets.sol +12 -2
  188. package/test/units/static/JBRulesets/TestRulesetsOf.sol +1 -1
  189. package/test/units/static/JBRulesets/TestUpcomingRulesetOf.sol +10 -1
  190. package/test/units/static/JBRulesets/TestUpdateRulesetWeightCache.sol +6 -1
  191. package/test/units/static/JBSplits/JBSplitsSetup.sol +3 -1
  192. package/test/units/static/JBSplits/TestSelfManagedSplitGroups.sol +8 -1
  193. package/test/units/static/JBSplits/TestSetSplitGroupsOf.sol +8 -1
  194. package/test/units/static/JBSplits/TestSplitsLockedEdge.sol +6 -1
  195. package/test/units/static/JBSplits/TestSplitsOf.sol +1 -1
  196. package/test/units/static/JBSplits/TestSplitsPacking.sol +5 -2
  197. package/test/units/static/JBSurplus/TestSurplusFuzz.sol +4 -2
  198. package/test/units/static/JBTerminalStore/JBTerminalStoreSetup.sol +5 -1
  199. package/test/units/static/JBTerminalStore/TestCurrentReclaimableSurplusOf.sol +14 -1
  200. package/test/units/static/JBTerminalStore/TestCurrentSurplusOf.sol +14 -1
  201. package/test/units/static/JBTerminalStore/TestCurrentTotalSurplusOf.sol +3 -1
  202. package/test/units/static/JBTerminalStore/TestRecordCashOutsFor.sol +20 -1
  203. package/test/units/static/JBTerminalStore/TestRecordPaymentFrom.sol +15 -1
  204. package/test/units/static/JBTerminalStore/TestRecordPayoutFor.sol +13 -1
  205. package/test/units/static/JBTerminalStore/TestRecordTerminalMigration.sol +8 -1
  206. package/test/units/static/JBTerminalStore/TestRecordUsedAllowanceOf.sol +16 -1
  207. package/test/units/static/JBTerminalStore/TestUint224Overflow.sol +15 -1
  208. package/test/units/static/JBTokens/JBTokensSetup.sol +5 -1
  209. package/test/units/static/JBTokens/TestBurnFrom.sol +4 -1
  210. package/test/units/static/JBTokens/TestClaimTokensFor.sol +4 -1
  211. package/test/units/static/JBTokens/TestDeployERC20ForUnits.sol +4 -1
  212. package/test/units/static/JBTokens/TestMintFor.sol +4 -1
  213. package/test/units/static/JBTokens/TestSetTokenFor.sol +4 -1
  214. package/test/units/static/JBTokens/TestTotalBalanceOf.sol +1 -1
  215. package/test/units/static/JBTokens/TestTotalSupplyOf.sol +1 -1
  216. package/test/units/static/JBTokens/TestTransferCreditsFrom.sol +3 -1
@@ -1,7 +1,32 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.6;
3
3
 
4
- import /* {*} from */ "./helpers/TestBaseWorkflow.sol";
4
+ import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
5
+ import {MetadataResolverHelper} from "./helpers/MetadataResolverHelper.sol";
6
+ import {MockERC20} from "./mock/MockERC20.sol";
7
+ import {JBMultiTerminal} from "../src/JBMultiTerminal.sol";
8
+ import {JBTokens} from "../src/JBTokens.sol";
9
+ import {JBApprovalStatus} from "../src/enums/JBApprovalStatus.sol";
10
+ import {IJBController} from "../src/interfaces/IJBController.sol";
11
+ import {IJBMultiTerminal} from "../src/interfaces/IJBMultiTerminal.sol";
12
+ import {IJBPayHook} from "../src/interfaces/IJBPayHook.sol";
13
+ import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
14
+ import {IJBRulesetDataHook} from "../src/interfaces/IJBRulesetDataHook.sol";
15
+ import {IJBTerminal} from "../src/interfaces/IJBTerminal.sol";
16
+ import {IJBToken} from "../src/interfaces/IJBToken.sol";
17
+ import {JBConstants} from "../src/libraries/JBConstants.sol";
18
+ import {JBFees} from "../src/libraries/JBFees.sol";
19
+ import {JBAccountingContext} from "../src/structs/JBAccountingContext.sol";
20
+ import {JBCurrencyAmount} from "../src/structs/JBCurrencyAmount.sol";
21
+ import {JBFee} from "../src/structs/JBFee.sol";
22
+ import {JBFundAccessLimitGroup} from "../src/structs/JBFundAccessLimitGroup.sol";
23
+ import {JBPayHookSpecification} from "../src/structs/JBPayHookSpecification.sol";
24
+ import {JBRuleset} from "../src/structs/JBRuleset.sol";
25
+ import {JBRulesetConfig} from "../src/structs/JBRulesetConfig.sol";
26
+ import {JBRulesetMetadata} from "../src/structs/JBRulesetMetadata.sol";
27
+ import {JBSplitGroup} from "../src/structs/JBSplitGroup.sol";
28
+ import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
29
+ import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
5
30
  import {JBCashOuts} from "../src/libraries/JBCashOuts.sol";
6
31
 
7
32
  /// @notice Tests for edge case scenarios in Juicebox V5.
@@ -682,7 +707,7 @@ contract EdgeCases_Local is TestBaseWorkflow {
682
707
  // Cash out all remaining tokens.
683
708
  uint256 tokenBalance = _tokens.totalBalanceOf(_beneficiary, projectId);
684
709
  vm.prank(_beneficiary);
685
- uint256 reclaimAmount = _terminal.cashOutTokensOf({
710
+ _terminal.cashOutTokensOf({
686
711
  holder: _beneficiary,
687
712
  projectId: projectId,
688
713
  cashOutCount: tokenBalance,
@@ -1227,7 +1252,9 @@ contract EdgeCases_Local is TestBaseWorkflow {
1227
1252
  uint256 hugeBorrow = uint256(type(uint112).max) + 500 ether;
1228
1253
 
1229
1254
  // Silent truncation — Solidity 0.8.x does NOT revert on explicit downcasts!
1255
+ // forge-lint: disable-next-line(unsafe-typecast)
1230
1256
  uint112 truncatedCollateral = uint112(hugeCollateral);
1257
+ // forge-lint: disable-next-line(unsafe-typecast)
1231
1258
  uint112 truncatedBorrow = uint112(hugeBorrow);
1232
1259
 
1233
1260
  // The truncated values are dramatically smaller.
@@ -1451,8 +1478,6 @@ contract EdgeCases_Local is TestBaseWorkflow {
1451
1478
  vm.warp(block.timestamp + 2_419_200 + 1); // 28 days + 1 second
1452
1479
 
1453
1480
  // Record terminal ETH before processing.
1454
- uint256 terminalBalanceBefore = address(_terminal).balance;
1455
-
1456
1481
  // Process both held fees.
1457
1482
  _terminal.processHeldFeesOf(projectId, JBConstants.NATIVE_TOKEN, 100);
1458
1483
 
@@ -2052,6 +2077,7 @@ contract EdgeCases_Local is TestBaseWorkflow {
2052
2077
 
2053
2078
  /// @notice Helper: launches a project with only MockERC20 (6 decimals, simulating USDC on Tempo).
2054
2079
  /// No NATIVE_TOKEN accounting context is registered.
2080
+ // forge-lint: disable-next-line(mixed-case-function)
2055
2081
  function _launchProjectERC20(uint16 cashOutTaxRate, uint16 reservedPercent) internal returns (uint256 projectId) {
2056
2082
  MockERC20 token = usdcToken();
2057
2083
 
@@ -2121,6 +2147,7 @@ contract EdgeCases_Local is TestBaseWorkflow {
2121
2147
  }
2122
2148
 
2123
2149
  /// @notice Helper: launches an ERC-20-only project with payout limits.
2150
+ // forge-lint: disable-next-line(mixed-case-function)
2124
2151
  function _launchProjectERC20WithPayoutLimit(
2125
2152
  uint16 cashOutTaxRate,
2126
2153
  uint224 payoutLimit
@@ -2634,8 +2661,11 @@ contract ReentrancyAttacker {
2634
2661
 
2635
2662
  /// @notice Malicious fee terminal that reenters processHeldFeesOf during pay().
2636
2663
  contract ReentrantFeeTerminal is ERC165 {
2664
+ // forge-lint: disable-next-line(screaming-snake-case-immutable)
2637
2665
  IJBMultiTerminal public immutable victim;
2666
+ // forge-lint: disable-next-line(screaming-snake-case-immutable)
2638
2667
  uint256 public immutable targetProjectId;
2668
+ // forge-lint: disable-next-line(screaming-snake-case-immutable)
2639
2669
  address public immutable targetToken;
2640
2670
  uint256 public payCallCount;
2641
2671
 
@@ -2690,6 +2720,7 @@ contract ReentrantFeeTerminal is ERC165 {
2690
2720
 
2691
2721
  /// @notice Malicious approval hook that always reverts.
2692
2722
  contract MaliciousApprovalHook is ERC165, IJBRulesetApprovalHook {
2723
+ // forge-lint: disable-next-line(mixed-case-function)
2693
2724
  function DURATION() external pure override returns (uint256) {
2694
2725
  return 1 days;
2695
2726
  }
@@ -1,8 +1,16 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.6;
3
3
 
4
- import "forge-std/StdInvariant.sol";
5
- import /* {*} from */ "./helpers/TestBaseWorkflow.sol";
4
+ import {StdInvariant} from "forge-std/StdInvariant.sol";
5
+ import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
6
+ import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
7
+ import {JBRulesetMetadataResolver} from "../src/libraries/JBRulesetMetadataResolver.sol";
8
+ import {JBFundAccessLimitGroup} from "../src/structs/JBFundAccessLimitGroup.sol";
9
+ import {JBRuleset} from "../src/structs/JBRuleset.sol";
10
+ import {JBRulesetConfig} from "../src/structs/JBRulesetConfig.sol";
11
+ import {JBRulesetMetadata} from "../src/structs/JBRulesetMetadata.sol";
12
+ import {JBSplitGroup} from "../src/structs/JBSplitGroup.sol";
13
+ import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
6
14
  import {EconomicHandler} from "./invariants/handlers/EconomicHandler.sol";
7
15
  import {JBAccountingContext} from "../src/structs/JBAccountingContext.sol";
8
16
  import {JBConstants} from "../src/libraries/JBConstants.sol";
@@ -1,10 +1,19 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.6;
3
3
 
4
- import /* {*} from */ "./helpers/TestBaseWorkflow.sol";
4
+ import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
5
+ import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
6
+ import {JBRulesetMetadataResolver} from "../src/libraries/JBRulesetMetadataResolver.sol";
7
+ import {JBCurrencyAmount} from "../src/structs/JBCurrencyAmount.sol";
8
+ import {JBFee} from "../src/structs/JBFee.sol";
9
+ import {JBFundAccessLimitGroup} from "../src/structs/JBFundAccessLimitGroup.sol";
10
+ import {JBRuleset} from "../src/structs/JBRuleset.sol";
11
+ import {JBRulesetConfig} from "../src/structs/JBRulesetConfig.sol";
12
+ import {JBRulesetMetadata} from "../src/structs/JBRulesetMetadata.sol";
13
+ import {JBSplitGroup} from "../src/structs/JBSplitGroup.sol";
14
+ import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
5
15
  import {JBAccountingContext} from "../src/structs/JBAccountingContext.sol";
6
16
  import {JBConstants} from "../src/libraries/JBConstants.sol";
7
- import {JBFees} from "../src/libraries/JBFees.sol";
8
17
 
9
18
  /// @title EntryPointPermutations
10
19
  /// @notice Systematically tests every JBMultiTerminal external function with edge-case parameters
@@ -452,7 +461,7 @@ contract EntryPointPermutations_Local is TestBaseWorkflow {
452
461
  );
453
462
 
454
463
  // Held fees should be reduced (partially or fully returned)
455
- JBFee[] memory feesAfter = jbMultiTerminal().heldFeesOf(projectStandard, JBConstants.NATIVE_TOKEN, 100);
464
+ jbMultiTerminal().heldFeesOf(projectStandard, JBConstants.NATIVE_TOKEN, 100);
456
465
 
457
466
  if (feesBefore.length > 0) {
458
467
  // Either fewer fees or smaller amounts
@@ -593,7 +602,9 @@ contract EntryPointPermutations_Local is TestBaseWorkflow {
593
602
  if (payoutLimit > 0) {
594
603
  payoutLimits = new JBCurrencyAmount[](1);
595
604
  payoutLimits[0] = JBCurrencyAmount({
596
- amount: uint224(payoutLimit), currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
605
+ // forge-lint: disable-next-line(unsafe-typecast)
606
+ amount: uint224(payoutLimit),
607
+ currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
597
608
  });
598
609
  } else {
599
610
  payoutLimits = new JBCurrencyAmount[](0);
@@ -602,7 +613,9 @@ contract EntryPointPermutations_Local is TestBaseWorkflow {
602
613
  if (surplusAllowance > 0) {
603
614
  surplusAllowances = new JBCurrencyAmount[](1);
604
615
  surplusAllowances[0] = JBCurrencyAmount({
605
- amount: uint224(surplusAllowance), currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
616
+ // forge-lint: disable-next-line(unsafe-typecast)
617
+ amount: uint224(surplusAllowance),
618
+ currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
606
619
  });
607
620
  } else {
608
621
  surplusAllowances = new JBCurrencyAmount[](0);
@@ -1,7 +1,17 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.6;
3
3
 
4
- import /* {*} from */ "./helpers/TestBaseWorkflow.sol";
4
+ import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
5
+ import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
6
+ import {JBConstants} from "../src/libraries/JBConstants.sol";
7
+ import {JBRulesetMetadataResolver} from "../src/libraries/JBRulesetMetadataResolver.sol";
8
+ import {JBCurrencyAmount} from "../src/structs/JBCurrencyAmount.sol";
9
+ import {JBFundAccessLimitGroup} from "../src/structs/JBFundAccessLimitGroup.sol";
10
+ import {JBRuleset} from "../src/structs/JBRuleset.sol";
11
+ import {JBRulesetConfig} from "../src/structs/JBRulesetConfig.sol";
12
+ import {JBRulesetMetadata} from "../src/structs/JBRulesetMetadata.sol";
13
+ import {JBSplitGroup} from "../src/structs/JBSplitGroup.sol";
14
+ import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
5
15
  import {JBAccountingContext} from "../src/structs/JBAccountingContext.sol";
6
16
 
7
17
  /// @notice Tests that flash-loan style atomic pay+cashOut attacks cannot extract profit.
@@ -254,7 +264,6 @@ contract FlashLoanAttacks_Local is TestBaseWorkflow {
254
264
 
255
265
  // Both should get proportional shares (with cashOutTax reducing it)
256
266
  // Key check: they should get roughly equal amounts since they have equal tokens
257
- uint256 diff = aliceReclaim > bobReclaim ? aliceReclaim - bobReclaim : bobReclaim - aliceReclaim;
258
267
  // Alice cashes out first, so she gets slightly more due to reduced supply.
259
268
  // But the proportional split should be reasonable.
260
269
  assertTrue(aliceReclaim > 0, "Alice should get some reclaim");
@@ -549,6 +558,7 @@ contract FlashLoanAttacks_Local is TestBaseWorkflow {
549
558
 
550
559
  // Attacker front-runs: pays right before payout
551
560
  address attacker = address(0xA77AC0);
561
+ // forge-lint: disable-next-line(mixed-case-variable)
552
562
  uint256 attackerInitialETH = 10 ether;
553
563
  vm.deal(attacker, attackerInitialETH);
554
564
  vm.prank(attacker);
@@ -1,7 +1,20 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.6;
3
3
 
4
- import /* {*} from */ "./helpers/TestBaseWorkflow.sol";
4
+ import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
5
+ import {JBPermissions} from "../src/JBPermissions.sol";
6
+ import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
7
+ import {JBConstants} from "../src/libraries/JBConstants.sol";
8
+ import {JBRulesetMetadataResolver} from "../src/libraries/JBRulesetMetadataResolver.sol";
9
+ import {JBCurrencyAmount} from "../src/structs/JBCurrencyAmount.sol";
10
+ import {JBFundAccessLimitGroup} from "../src/structs/JBFundAccessLimitGroup.sol";
11
+ import {JBPermissionsData} from "../src/structs/JBPermissionsData.sol";
12
+ import {JBRuleset} from "../src/structs/JBRuleset.sol";
13
+ import {JBRulesetConfig} from "../src/structs/JBRulesetConfig.sol";
14
+ import {JBRulesetMetadata} from "../src/structs/JBRulesetMetadata.sol";
15
+ import {JBSplitGroup} from "../src/structs/JBSplitGroup.sol";
16
+ import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
17
+ import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
5
18
  import {JBAccountingContext} from "../src/structs/JBAccountingContext.sol";
6
19
 
7
20
  /// @notice Tests for permission system correctness: ROOT restrictions, wildcard, boundary IDs, escalation prevention.
@@ -38,6 +51,7 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
38
51
  jbPermissions()
39
52
  .setPermissionsFor(
40
53
  projectOwner,
54
+ // forge-lint: disable-next-line(unsafe-typecast)
41
55
  JBPermissionsData({operator: alice, projectId: uint64(projectId2), permissionIds: rootPerms})
42
56
  );
43
57
  }
@@ -175,13 +189,17 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
175
189
  JBPermissions.JBPermissions_Unauthorized.selector,
176
190
  projectOwner,
177
191
  alice,
192
+ // forge-lint: disable-next-line(unsafe-typecast)
178
193
  uint64(projectId2),
179
194
  JBPermissionIds.ROOT
180
195
  )
181
196
  );
182
197
  jbPermissions()
183
198
  .setPermissionsFor(
184
- projectOwner, JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
199
+ // forge-lint: disable-next-line(unsafe-typecast)
200
+ projectOwner,
201
+ // forge-lint: disable-next-line(unsafe-typecast)
202
+ JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
185
203
  );
186
204
  }
187
205
 
@@ -197,7 +215,10 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
197
215
  vm.prank(alice);
198
216
  jbPermissions()
199
217
  .setPermissionsFor(
200
- projectOwner, JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
218
+ // forge-lint: disable-next-line(unsafe-typecast)
219
+ projectOwner,
220
+ // forge-lint: disable-next-line(unsafe-typecast)
221
+ JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
201
222
  );
202
223
 
203
224
  // Verify Bob now has CASH_OUT_TOKENS
@@ -263,7 +284,10 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
263
284
  vm.prank(projectOwner);
264
285
  jbPermissions()
265
286
  .setPermissionsFor(
266
- projectOwner, JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
287
+ // forge-lint: disable-next-line(unsafe-typecast)
288
+ projectOwner,
289
+ // forge-lint: disable-next-line(unsafe-typecast)
290
+ JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
267
291
  );
268
292
 
269
293
  // Verify Bob has it
@@ -287,6 +311,7 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
287
311
  jbPermissions()
288
312
  .setPermissionsFor(
289
313
  projectOwner,
314
+ // forge-lint: disable-next-line(unsafe-typecast)
290
315
  JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: emptyPerms})
291
316
  );
292
317
 
@@ -317,7 +342,10 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
317
342
  vm.prank(projectOwner);
318
343
  jbPermissions()
319
344
  .setPermissionsFor(
320
- projectOwner, JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
345
+ // forge-lint: disable-next-line(unsafe-typecast)
346
+ projectOwner,
347
+ // forge-lint: disable-next-line(unsafe-typecast)
348
+ JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
321
349
  );
322
350
 
323
351
  bool hasPerm = jbPermissions()
@@ -357,7 +385,10 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
357
385
  vm.expectRevert(abi.encodeWithSelector(JBPermissions.JBPermissions_NoZeroPermission.selector));
358
386
  jbPermissions()
359
387
  .setPermissionsFor(
360
- projectOwner, JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
388
+ // forge-lint: disable-next-line(unsafe-typecast)
389
+ projectOwner,
390
+ // forge-lint: disable-next-line(unsafe-typecast)
391
+ JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
361
392
  );
362
393
  }
363
394
 
@@ -468,7 +499,10 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
468
499
  vm.prank(projectOwner);
469
500
  jbPermissions()
470
501
  .setPermissionsFor(
471
- projectOwner, JBPermissionsData({operator: bob, projectId: uint64(pid), permissionIds: perms})
502
+ // forge-lint: disable-next-line(unsafe-typecast)
503
+ projectOwner,
504
+ // forge-lint: disable-next-line(unsafe-typecast)
505
+ JBPermissionsData({operator: bob, projectId: uint64(pid), permissionIds: perms})
472
506
  );
473
507
 
474
508
  // Charlie (no permission) tries to send payouts — should fail because ownerMustSendPayouts
@@ -500,7 +534,7 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
500
534
  // Test 10: ROOT on project 2 has no power over project 3
501
535
  // ═══════════════════════════════════════════════════════════════════
502
536
 
503
- function test_permission_rootOnProject_doesNotAffectOtherProject() public {
537
+ function test_permission_rootOnProject_doesNotAffectOtherProject() public view {
504
538
  // Alice has ROOT on project 2 (from setUp)
505
539
  // Alice should NOT have any permissions on project 3
506
540
  bool hasPermOnProject3 = jbPermissions()
@@ -539,7 +573,10 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
539
573
  vm.prank(projectOwner);
540
574
  jbPermissions()
541
575
  .setPermissionsFor(
542
- projectOwner, JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms1})
576
+ // forge-lint: disable-next-line(unsafe-typecast)
577
+ projectOwner,
578
+ // forge-lint: disable-next-line(unsafe-typecast)
579
+ JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms1})
543
580
  );
544
581
 
545
582
  assertTrue(
@@ -574,7 +611,10 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
574
611
  vm.prank(projectOwner);
575
612
  jbPermissions()
576
613
  .setPermissionsFor(
577
- projectOwner, JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms2})
614
+ // forge-lint: disable-next-line(unsafe-typecast)
615
+ projectOwner,
616
+ // forge-lint: disable-next-line(unsafe-typecast)
617
+ JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms2})
578
618
  );
579
619
 
580
620
  // Bob should only have MINT_TOKENS, not the previous ones
@@ -628,7 +668,10 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
628
668
  vm.prank(projectOwner);
629
669
  jbPermissions()
630
670
  .setPermissionsFor(
631
- projectOwner, JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
671
+ // forge-lint: disable-next-line(unsafe-typecast)
672
+ projectOwner,
673
+ // forge-lint: disable-next-line(unsafe-typecast)
674
+ JBPermissionsData({operator: bob, projectId: uint64(projectId2), permissionIds: perms})
632
675
  );
633
676
 
634
677
  // Call from trusted forwarder with Bob appended as sender
@@ -638,17 +681,6 @@ contract PermissionEscalation_Local is TestBaseWorkflow {
638
681
  // Verify the forwarder is set up correctly
639
682
  assertTrue(forwarder != address(0), "Trusted forwarder should be set");
640
683
 
641
- // Construct the calldata with Bob's address appended (ERC2771 pattern)
642
- bytes memory callData = abi.encodeWithSelector(
643
- IJBPermissions.hasPermission.selector,
644
- bob,
645
- projectOwner,
646
- projectId2,
647
- JBPermissionIds.CASH_OUT_TOKENS,
648
- false,
649
- false
650
- );
651
-
652
684
  // Direct call should return true
653
685
  bool hasPerm = jbPermissions()
654
686
  .hasPermission({
@@ -1,7 +1,18 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.6;
3
3
 
4
- import /* {*} from */ "./helpers/TestBaseWorkflow.sol";
4
+ import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
5
+ import {JBApprovalStatus} from "../src/enums/JBApprovalStatus.sol";
6
+ import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
7
+ import {JBConstants} from "../src/libraries/JBConstants.sol";
8
+ import {JBRulesetMetadataResolver} from "../src/libraries/JBRulesetMetadataResolver.sol";
9
+ import {JBCurrencyAmount} from "../src/structs/JBCurrencyAmount.sol";
10
+ import {JBFundAccessLimitGroup} from "../src/structs/JBFundAccessLimitGroup.sol";
11
+ import {JBRuleset} from "../src/structs/JBRuleset.sol";
12
+ import {JBRulesetConfig} from "../src/structs/JBRulesetConfig.sol";
13
+ import {JBRulesetMetadata} from "../src/structs/JBRulesetMetadata.sol";
14
+ import {JBSplitGroup} from "../src/structs/JBSplitGroup.sol";
15
+ import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
5
16
  import {JBAccountingContext} from "../src/structs/JBAccountingContext.sol";
6
17
  import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
7
18
 
@@ -255,6 +266,7 @@ contract RulesetTransitions_Local is TestBaseWorkflow {
255
266
  uint256[] memory tokensPerCycle = new uint256[](10);
256
267
  for (uint256 i = 0; i < 10; i++) {
257
268
  if (i > 0) vm.warp(block.timestamp + 1 days + 1);
269
+ // forge-lint: disable-next-line(unsafe-typecast)
258
270
  tokensPerCycle[i] = _payProject(pid, address(uint160(0x6000 + i)), 1 ether);
259
271
  }
260
272
 
@@ -660,6 +672,7 @@ contract RulesetTransitions_Local is TestBaseWorkflow {
660
672
 
661
673
  /// @notice Approval hook that approves after a configurable delay.
662
674
  contract DelayedApprovalHook is ERC165, IJBRulesetApprovalHook {
675
+ // forge-lint: disable-next-line(screaming-snake-case-immutable)
663
676
  uint256 public immutable approvalDelay;
664
677
 
665
678
  constructor(uint256 _approvalDelay) {
@@ -685,6 +698,7 @@ contract DelayedApprovalHook is ERC165, IJBRulesetApprovalHook {
685
698
 
686
699
  /// @notice Approval hook that always rejects.
687
700
  contract AlwaysRejectingHook is ERC165, IJBRulesetApprovalHook {
701
+ // forge-lint: disable-next-line(mixed-case-function)
688
702
  function DURATION() external pure override returns (uint256) {
689
703
  return 0;
690
704
  }
@@ -1,7 +1,22 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.6;
3
3
 
4
- import /* {*} from */ "./helpers/TestBaseWorkflow.sol";
4
+ import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
5
+ import {IJBMultiTerminal} from "../src/interfaces/IJBMultiTerminal.sol";
6
+ import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
7
+ import {IJBSplitHook} from "../src/interfaces/IJBSplitHook.sol";
8
+ import {IJBTokens} from "../src/interfaces/IJBTokens.sol";
9
+ import {JBConstants} from "../src/libraries/JBConstants.sol";
10
+ import {JBRulesetMetadataResolver} from "../src/libraries/JBRulesetMetadataResolver.sol";
11
+ import {JBCurrencyAmount} from "../src/structs/JBCurrencyAmount.sol";
12
+ import {JBFundAccessLimitGroup} from "../src/structs/JBFundAccessLimitGroup.sol";
13
+ import {JBRuleset} from "../src/structs/JBRuleset.sol";
14
+ import {JBRulesetConfig} from "../src/structs/JBRulesetConfig.sol";
15
+ import {JBRulesetMetadata} from "../src/structs/JBRulesetMetadata.sol";
16
+ import {JBSplit} from "../src/structs/JBSplit.sol";
17
+ import {JBSplitGroup} from "../src/structs/JBSplitGroup.sol";
18
+ import {JBSplitHookContext} from "../src/structs/JBSplitHookContext.sol";
19
+ import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
5
20
  import {JBAccountingContext} from "../src/structs/JBAccountingContext.sol";
6
21
  import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
7
22
 
@@ -120,7 +135,8 @@ contract SplitLoopTests_Local is TestBaseWorkflow {
120
135
 
121
136
  JBCurrencyAmount[] memory payoutLimits = new JBCurrencyAmount[](1);
122
137
  payoutLimits[0] =
123
- JBCurrencyAmount({amount: uint224(payoutLimit), currency: uint32(uint160(JBConstants.NATIVE_TOKEN))});
138
+ // forge-lint: disable-next-line(unsafe-typecast)
139
+ JBCurrencyAmount({amount: uint224(payoutLimit), currency: uint32(uint160(JBConstants.NATIVE_TOKEN))});
124
140
  JBFundAccessLimitGroup[] memory fundAccessLimitGroups = new JBFundAccessLimitGroup[](1);
125
141
  fundAccessLimitGroups[0] = JBFundAccessLimitGroup({
126
142
  terminal: address(jbMultiTerminal()),
@@ -186,12 +202,14 @@ contract SplitLoopTests_Local is TestBaseWorkflow {
186
202
  projectA = _launchProjectWithSplitsAndPayoutLimit(dummySplits, 10 ether);
187
203
 
188
204
  // Now create B with split to A
205
+ // forge-lint: disable-next-line(unsafe-typecast)
189
206
  splitsB[0].projectId = uint64(projectA);
190
207
  projectB = _launchProjectWithSplitsAndPayoutLimit(splitsB, 10 ether);
191
208
 
192
209
  // Update A's splits to point to B
193
210
  (JBRuleset memory rulesetA,) = jbController().currentRulesetOf(projectA);
194
211
  JBSplitGroup[] memory newSplitGroupsA = new JBSplitGroup[](1);
212
+ // forge-lint: disable-next-line(unsafe-typecast)
195
213
  splitsA[0].projectId = uint64(projectB);
196
214
  newSplitGroupsA[0] = JBSplitGroup({groupId: uint256(uint160(JBConstants.NATIVE_TOKEN)), splits: splitsA});
197
215
  vm.prank(projectOwner);
@@ -372,6 +390,7 @@ contract SplitLoopTests_Local is TestBaseWorkflow {
372
390
  uint256 pid = _launchProjectWithSplitsAndPayoutLimit(new JBSplit[](0), 10 ether);
373
391
 
374
392
  // Update splits to point to self
393
+ // forge-lint: disable-next-line(unsafe-typecast)
375
394
  splits[0].projectId = uint64(pid);
376
395
  (JBRuleset memory ruleset,) = jbController().currentRulesetOf(pid);
377
396
  JBSplitGroup[] memory newSplitGroups = new JBSplitGroup[](1);
@@ -404,12 +423,14 @@ contract SplitLoopTests_Local is TestBaseWorkflow {
404
423
  uint256 numSplits = 200;
405
424
  JBSplit[] memory splits = new JBSplit[](numSplits);
406
425
 
426
+ // forge-lint: disable-next-line(unsafe-typecast)
407
427
  uint32 perSplitPercent = uint32(JBConstants.SPLITS_TOTAL_PERCENT / numSplits);
408
428
 
409
429
  for (uint256 i = 0; i < numSplits; i++) {
410
430
  splits[i] = JBSplit({
411
431
  percent: perSplitPercent,
412
432
  projectId: 0,
433
+ // forge-lint: disable-next-line(unsafe-typecast)
413
434
  beneficiary: payable(address(uint160(0x3000 + i))),
414
435
  preferAddToBalance: false,
415
436
  lockedUntil: 0,
@@ -452,6 +473,7 @@ contract SplitLoopTests_Local is TestBaseWorkflow {
452
473
  splits[i] = JBSplit({
453
474
  percent: oneThird,
454
475
  projectId: 0,
476
+ // forge-lint: disable-next-line(unsafe-typecast)
455
477
  beneficiary: payable(address(uint160(0x4000 + i))),
456
478
  preferAddToBalance: false,
457
479
  lockedUntil: 0,
@@ -463,10 +485,8 @@ contract SplitLoopTests_Local is TestBaseWorkflow {
463
485
 
464
486
  _payProject(pid, address(0xBA1E), 10 ether);
465
487
 
466
- uint256 totalBefore = address(jbMultiTerminal()).balance;
467
-
468
488
  vm.prank(projectOwner);
469
- uint256 netLeftover = jbMultiTerminal()
489
+ jbMultiTerminal()
470
490
  .sendPayoutsOf({
471
491
  projectId: pid,
472
492
  token: JBConstants.NATIVE_TOKEN,
@@ -478,6 +498,7 @@ contract SplitLoopTests_Local is TestBaseWorkflow {
478
498
  // Check no rounding loss greater than 3 wei (one per split)
479
499
  uint256 totalPaidToSplits = 0;
480
500
  for (uint256 i = 0; i < 3; i++) {
501
+ // forge-lint: disable-next-line(unsafe-typecast)
481
502
  totalPaidToSplits += address(uint160(0x4000 + i)).balance;
482
503
  }
483
504
 
@@ -1,8 +1,23 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity >=0.8.6;
3
3
 
4
- import /* {*} from */ "./helpers/TestBaseWorkflow.sol";
5
- import "@openzeppelin/contracts/utils/Address.sol";
4
+ import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
5
+ import {MockERC20} from "./mock/MockERC20.sol";
6
+ import {JBTerminalStore} from "../src/JBTerminalStore.sol";
7
+ import {IJBController} from "../src/interfaces/IJBController.sol";
8
+ import {IJBMultiTerminal} from "../src/interfaces/IJBMultiTerminal.sol";
9
+ import {IJBPrices} from "../src/interfaces/IJBPrices.sol";
10
+ import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
11
+ import {IJBTokens} from "../src/interfaces/IJBTokens.sol";
12
+ import {JBConstants} from "../src/libraries/JBConstants.sol";
13
+ import {JBAccountingContext} from "../src/structs/JBAccountingContext.sol";
14
+ import {JBCurrencyAmount} from "../src/structs/JBCurrencyAmount.sol";
15
+ import {JBFundAccessLimitGroup} from "../src/structs/JBFundAccessLimitGroup.sol";
16
+ import {JBRulesetConfig} from "../src/structs/JBRulesetConfig.sol";
17
+ import {JBRulesetMetadata} from "../src/structs/JBRulesetMetadata.sol";
18
+ import {JBSplitGroup} from "../src/structs/JBSplitGroup.sol";
19
+ import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
20
+ import {mulDiv} from "@prb/math/src/Common.sol";
6
21
  import {MockPriceFeed} from "./mock/MockPriceFeed.sol";
7
22
  import {MaliciousAllowanceBeneficiary, MaliciousPayoutBeneficiary} from "./mock/MockMaliciousBeneficiary.sol";
8
23
 
@@ -1,8 +1,21 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.6;
3
3
 
4
- import /* {*} from */ "./helpers/TestBaseWorkflow.sol";
5
- import {JBCashOuts} from "../src/libraries/JBCashOuts.sol";
4
+ import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
5
+ import {JBTokens} from "../src/JBTokens.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 {IJBTerminal} from "../src/interfaces/IJBTerminal.sol";
10
+ import {JBConstants} from "../src/libraries/JBConstants.sol";
11
+ import {JBAccountingContext} from "../src/structs/JBAccountingContext.sol";
12
+ import {JBFundAccessLimitGroup} from "../src/structs/JBFundAccessLimitGroup.sol";
13
+ import {JBRulesetConfig} from "../src/structs/JBRulesetConfig.sol";
14
+ import {JBRulesetMetadata} from "../src/structs/JBRulesetMetadata.sol";
15
+ import {JBSplitGroup} from "../src/structs/JBSplitGroup.sol";
16
+ import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
17
+ import {mulDiv} from "@prb/math/src/Common.sol";
18
+ import {mul as UD60x18mul, unwrap as UD60x18unwrap, wrap as UD60x18wrap} from "@prb/math/src/UD60x18.sol";
6
19
 
7
20
  // Projects can issue a token, be paid to receieve claimed tokens, burn some of the claimed tokens, cash out the rest
8
21
  // of
@@ -1,8 +1,7 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.17;
3
3
 
4
- import "forge-std/Test.sol";
5
- import {mulDiv} from "@prb/math/src/Common.sol";
4
+ import {Test} from "forge-std/Test.sol";
6
5
  import {JBCashOuts} from "../src/libraries/JBCashOuts.sol";
7
6
  import {JBConstants} from "../src/libraries/JBConstants.sol";
8
7