@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
package/ADMINISTRATION.md CHANGED
@@ -108,6 +108,7 @@ Admin privileges and their scope in nana-core-v6.
108
108
  | `sendReservedTokensToSplitsOf` | Anyone | N/A | Per project | Distributes accumulated reserved tokens to the project's reserved token split group. No permission required -- anyone can trigger this. |
109
109
  | `setSplitGroupsOf` | Project owner or operator | SET_SPLIT_GROUPS (18) | Per project | Sets split groups for a project. Must preserve any currently locked splits. |
110
110
  | `setTokenFor` | Project owner or operator | SET_TOKEN (9) | Per project | Assigns an external ERC-20 token to the project. Requires the ruleset's `allowSetCustomToken` flag. Can only be called once (before any token is set). |
111
+ | `setTokenMetadataOf` | Project owner or operator | SET_TOKEN_METADATA (21) | Per project | Sets the name and symbol of a project's ERC-20 token. The project must have a token deployed. |
111
112
  | `setUriOf` | Project owner or operator | SET_PROJECT_URI (7) | Per project | Updates the project's metadata URI. |
112
113
  | `transferCreditsFrom` | Credit holder or operator | TRANSFER_CREDITS (13) | Per project | Transfers internal token credits between addresses. Requires the ruleset's `pauseCreditTransfers` flag to be false. |
113
114
  | `migrate` | JBDirectory only | N/A (msg.sender == DIRECTORY) | Per project | Called by the directory during controller migration. Reverts if there are pending reserved tokens. |
@@ -140,6 +141,7 @@ Admin privileges and their scope in nana-core-v6.
140
141
  | `deployERC20For` | Project's controller | N/A (onlyControllerOf) | Per project | Deploys a cloned JBERC20 token for the project. |
141
142
  | `mintFor` | Project's controller | N/A (onlyControllerOf) | Per project | Mints new tokens (ERC-20 if deployed) or credits for a holder. |
142
143
  | `setTokenFor` | Project's controller | N/A (onlyControllerOf) | Per project | Sets an external ERC-20 token for the project. Cannot be changed once set. |
144
+ | `setTokenMetadataFor` | Project's controller | N/A (onlyControllerOf) | Per project | Sets the name and symbol of a project's token. |
143
145
  | `transferCreditsFrom` | Project's controller | N/A (onlyControllerOf) | Per project | Transfers credits between addresses. |
144
146
 
145
147
  ### JBSplits
@@ -180,6 +182,7 @@ Admin privileges and their scope in nana-core-v6.
180
182
  | `mint` | Contract owner (JBTokens) | N/A (onlyOwner) | Per token | Mints new tokens to an address. |
181
183
  | `burn` | Contract owner (JBTokens) | N/A (onlyOwner) | Per token | Burns tokens from an address. |
182
184
  | `initialize` | Anyone (once) | N/A | Per token | Initializes the token name, symbol, and owner. Can only be called once. |
185
+ | `setMetadata` | Contract owner (JBTokens) | N/A (onlyOwner) | Per token | Updates the token's name and symbol. |
183
186
 
184
187
  ### JBTerminalStore
185
188
 
@@ -228,6 +231,7 @@ JBPermissions implements a 256-bit packed permission bitmap system:
228
231
  | 18 | SET_SPLIT_GROUPS | `JBController.setSplitGroupsOf` |
229
232
  | 19 | ADD_PRICE_FEED | `JBController.addPriceFeed` |
230
233
  | 20 | ADD_ACCOUNTING_CONTEXTS | `JBMultiTerminal.addAccountingContextsFor` |
234
+ | 21 | SET_TOKEN_METADATA | `JBController.setTokenMetadataOf` |
231
235
 
232
236
  ## Immutable Configuration
233
237
 
package/README.md CHANGED
@@ -97,7 +97,7 @@ All contracts use Solidity `0.8.26`.
97
97
  | `JBProjects` | ERC-721 registry of projects. Minting an NFT creates a project. Optionally mints project #1 to a fee beneficiary owner. |
98
98
  | `JBPermissions` | Bitmap-based permission system. Accounts grant operators specific permissions scoped to project IDs. Supports ROOT (255) for all-permissions and wildcard project ID (0). |
99
99
  | `JBDirectory` | Maps each project to its controller and terminals. Entry point for looking up where to interact with a project. Manages an allowlist of addresses permitted to set a project's first controller. |
100
- | `JBController` | Coordinates rulesets, tokens, splits, and fund access limits. Entry point for launching projects, queuing rulesets, minting/burning tokens, deploying ERC-20s, sending reserved tokens, setting project URIs, adding price feeds, and transferring credits. |
100
+ | `JBController` | Coordinates rulesets, tokens, splits, and fund access limits. Entry point for launching projects, queuing rulesets, minting/burning tokens, deploying ERC-20s, updating token metadata, sending reserved tokens, setting project URIs, adding price feeds, and transferring credits. |
101
101
  | `JBMultiTerminal` | Accepts payments (native ETH and ERC-20s), processes cash outs, distributes payouts, manages surplus allowances, and handles fees. Integrates with Permit2 for ERC-20 approvals. |
102
102
  | `JBTerminalStore` | Bookkeeping engine for all terminal inflows and outflows. Tracks balances, enforces payout limits and surplus allowances, computes cash out reclaim amounts via a bonding curve, and integrates with data hooks. |
103
103
  | `JBRulesets` | Stores and manages project rulesets. Handles queuing, cycling, weight decay, approval hook validation, and weight caching for long-running projects. |
@@ -110,7 +110,7 @@ All contracts use Solidity `0.8.26`.
110
110
 
111
111
  | Contract | Description |
112
112
  |----------|-------------|
113
- | `JBERC20` | Cloneable ERC-20 with ERC20Votes and ERC20Permit. Deployed by `JBTokens` via `Clones.clone()`. Owned by `JBTokens`. |
113
+ | `JBERC20` | Cloneable ERC-20 with ERC20Votes and ERC20Permit. Deployed by `JBTokens` via `Clones.clone()`. Owned by `JBTokens`. Name and symbol can be updated by the project owner via `JBController.setTokenMetadataOf`. |
114
114
  | `JBChainlinkV3PriceFeed` | `IJBPriceFeed` backed by a Chainlink `AggregatorV3Interface` with staleness threshold. Rejects negative/zero prices and incomplete rounds. |
115
115
  | `JBChainlinkV3SequencerPriceFeed` | Extends `JBChainlinkV3PriceFeed` with L2 sequencer uptime validation and grace period for Optimism/Arbitrum. |
116
116
  | `JBMatchingPriceFeed` | Returns 1:1 price (e.g., ETH/NATIVE_TOKEN on applicable chains). Lives in `src/periphery/`. |
package/SKILLS.md CHANGED
@@ -42,6 +42,7 @@ The core Juicebox V6 protocol on EVM: a modular system for launching treasury-ba
42
42
  | `claimTokensFor(address holder, uint256 projectId, uint256 count, address beneficiary)` | Redeems credits for ERC-20 tokens into beneficiary's wallet. |
43
43
  | `setSplitGroupsOf(uint256 projectId, uint256 rulesetId, JBSplitGroup[] splitGroups)` | Sets the split groups for a project's ruleset. |
44
44
  | `setTokenFor(uint256 projectId, IJBToken token)` | Sets an existing ERC-20 token for the project (requires `allowSetCustomToken` in ruleset). |
45
+ | `setTokenMetadataOf(uint256 projectId, string name, string symbol)` | Sets the name and symbol of a project's ERC-20 token. Requires `SET_TOKEN_METADATA` permission. |
45
46
  | `setUriOf(uint256 projectId, string uri)` | Sets the project's metadata URI. |
46
47
  | `transferCreditsFrom(address holder, uint256 projectId, address recipient, uint256 creditCount)` | Transfers credits between addresses (reverts if `pauseCreditTransfers` is set in ruleset). |
47
48
  | `addPriceFeedFor(uint256 projectId, uint256 pricingCurrency, uint256 unitCurrency, IJBPriceFeed feed)` | Registers a price feed (requires `allowAddPriceFeed` in ruleset). |
@@ -129,6 +130,7 @@ The core Juicebox V6 protocol on EVM: a modular system for launching treasury-ba
129
130
  | `totalBalanceOf(address holder, uint256 projectId)` | Returns combined credit + ERC-20 balance. |
130
131
  | `creditBalanceOf(address holder, uint256 projectId)` | Returns the holder's credit balance. |
131
132
  | `tokenOf(uint256 projectId)` | Returns the ERC-20 token for a project (`IJBToken`). |
133
+ | `setTokenMetadataFor(uint256 projectId, string name, string symbol)` | Sets the name and symbol of a project's token. Controller-only. |
132
134
 
133
135
  ### JBSplits
134
136
 
package/STYLE_GUIDE.md CHANGED
@@ -17,8 +17,6 @@ src/
17
17
 
18
18
  One contract/interface/struct/enum per file. Name the file after the type it contains.
19
19
 
20
- **Structs, enums, libraries, and interfaces always go in their subdirectories** (`src/structs/`, `src/enums/`, `src/libraries/`, `src/interfaces/`) — never inline in contract files or placed in `src/` root. This keeps type definitions discoverable and import paths consistent across repos.
21
-
22
20
  ## Pragma Versions
23
21
 
24
22
  ```solidity
@@ -106,14 +104,6 @@ contract JBExample is JBPermissioned, IJBExample {
106
104
  // -------------------------- constructor ---------------------------- //
107
105
  //*********************************************************************//
108
106
 
109
- //*********************************************************************//
110
- // ---------------------- receive / fallback ------------------------- //
111
- //*********************************************************************//
112
-
113
- //*********************************************************************//
114
- // --------------------------- modifiers ----------------------------- //
115
- //*********************************************************************//
116
-
117
107
  //*********************************************************************//
118
108
  // ---------------------- external transactions ---------------------- //
119
109
  //*********************************************************************//
@@ -141,28 +131,23 @@ contract JBExample is JBPermissioned, IJBExample {
141
131
  ```
142
132
 
143
133
  **Section order:**
144
- 1. `using` declarations
145
- 2. Custom errors
146
- 3. Public constants
147
- 4. Internal constants
148
- 5. Public immutable stored properties
149
- 6. Internal immutable stored properties
150
- 7. Public stored properties
151
- 8. Internal stored properties
152
- 9. Constructor
153
- 10. `receive` / `fallback`
154
- 11. Modifiers
155
- 12. External transactions
156
- 13. External views
157
- 14. Public transactions
158
- 15. Internal helpers
159
- 16. Internal views
160
- 17. Private helpers
134
+ 1. Custom errors
135
+ 2. Public constants
136
+ 3. Internal constants
137
+ 4. Public immutable stored properties
138
+ 5. Internal immutable stored properties
139
+ 6. Public stored properties
140
+ 7. Internal stored properties
141
+ 8. Constructor
142
+ 9. External transactions
143
+ 10. External views
144
+ 11. Public transactions
145
+ 12. Internal helpers
146
+ 13. Internal views
147
+ 14. Private helpers
161
148
 
162
149
  Functions are alphabetized within each section.
163
150
 
164
- **Events:** Events are declared in interfaces only, never in implementation contracts. Implementations inherit events from their interface and emit them unqualified. This keeps the ABI definition in one place and allows tests to use interface-qualified event expectations (e.g., `emit IJBController.LaunchProject(...)`).
165
-
166
151
  ## Interface Structure
167
152
 
168
153
  ```solidity
@@ -212,7 +197,7 @@ interface IJBExample is IJBBase {
212
197
  | Public/external function | `camelCase` | `cashOutTokensOf` |
213
198
  | Internal/private function | `_camelCase` | `_processFee` |
214
199
  | Internal storage | `_camelCase` | `_accountingContextForTokenOf` |
215
- | Function parameter | `camelCase` | `projectId`, `cashOutCount` |
200
+ | Function parameter | `camelCase` (no underscores) | `projectId`, `cashOutCount` |
216
201
 
217
202
  ## NatSpec
218
203
 
@@ -268,9 +253,12 @@ uint256 public constant MAX_RESERVED_PERCENT = 10_000;
268
253
 
269
254
  ## Function Calls
270
255
 
271
- Use named parameters for readability when calling functions with 3+ arguments:
256
+ Use named arguments for all function calls with 2 or more arguments — in both `src/` and `script/`:
272
257
 
273
258
  ```solidity
259
+ // Good — named arguments
260
+ token.mint({account: beneficiary, amount: count});
261
+ _transferOwnership({newOwner: address(0), projectId: 0});
274
262
  PERMISSIONS.hasPermission({
275
263
  operator: sender,
276
264
  account: account,
@@ -279,8 +267,18 @@ PERMISSIONS.hasPermission({
279
267
  includeRoot: true,
280
268
  includeWildcardProjectId: true
281
269
  });
270
+
271
+ // Bad — positional arguments with 2+ args
272
+ token.mint(beneficiary, count);
273
+ _transferOwnership(address(0), 0);
282
274
  ```
283
275
 
276
+ Single-argument calls use positional style: `_burn(amount)`.
277
+
278
+ This also applies to constructor calls, struct literals, and inherited/library calls (e.g., OZ `_mint`, `_safeMint`, `safeTransfer`, `allowance`, `Clones.cloneDeterministic`).
279
+
280
+ Named argument keys must use **camelCase** — never underscores. If a function's parameter names use underscores, rename them to camelCase first.
281
+
284
282
  ## Multiline Signatures
285
283
 
286
284
  ```solidity
@@ -324,7 +322,7 @@ try hook.afterPayRecordedWith(context) {} catch (bytes memory reason) {
324
322
 
325
323
  ### foundry.toml
326
324
 
327
- Standard config for `@bananapus/core-v6`:
325
+ Standard config across all repos:
328
326
 
329
327
  ```toml
330
328
  [profile.default]
@@ -334,9 +332,6 @@ optimizer_runs = 200
334
332
  libs = ["node_modules", "lib"]
335
333
  fs_permissions = [{ access = "read-write", path = "./"}]
336
334
 
337
- [profile.ci_sizes]
338
- optimizer_runs = 200
339
-
340
335
  [fuzz]
341
336
  runs = 4096
342
337
 
@@ -351,7 +346,14 @@ multiline_func_header = "all"
351
346
  wrap_comments = true
352
347
  ```
353
348
 
354
- This is the standard config with no deviations.
349
+ **Optional sections (add only when needed):**
350
+ - `[rpc_endpoints]` — repos with fork tests. Maps named endpoints to env vars (e.g. `ethereum = "${RPC_ETHEREUM_MAINNET}"`).
351
+ - `[profile.ci_sizes]` — only when CI needs different optimizer settings than defaults for the size check step (e.g. `optimizer_runs = 200` when the default profile uses a lower value).
352
+
353
+ **Common variations:**
354
+ - `via_ir = true` when hitting stack-too-deep
355
+ - `optimizer = false` when optimization causes stack-too-deep
356
+ - `optimizer_runs` reduced when deep struct nesting causes stack-too-deep at 200 runs
355
357
 
356
358
  ### CI Workflows
357
359
 
@@ -381,8 +383,10 @@ jobs:
381
383
  uses: foundry-rs/foundry-toolchain@v1
382
384
  - name: Run tests
383
385
  run: forge test --fail-fast --summary --detailed --skip "*/script/**"
386
+ env:
387
+ RPC_ETHEREUM_MAINNET: ${{ secrets.RPC_ETHEREUM_MAINNET }}
384
388
  - name: Check contract sizes
385
- run: FOUNDRY_PROFILE=ci_sizes forge build --sizes --skip "*/test/**" --skip "*/script/**" --skip SphinxUtils
389
+ run: forge build --sizes --skip "*/test/**" --skip "*/script/**" --skip SphinxUtils
386
390
  ```
387
391
 
388
392
  **lint.yml:**
@@ -404,14 +408,63 @@ jobs:
404
408
  run: forge fmt --check
405
409
  ```
406
410
 
411
+ **slither.yml** (repos with `src/` contracts only):
412
+ ```yaml
413
+ name: slither
414
+ on:
415
+ pull_request:
416
+ branches:
417
+ - main
418
+ push:
419
+ branches:
420
+ - main
421
+ jobs:
422
+ analyze:
423
+ runs-on: ubuntu-latest
424
+ steps:
425
+ - uses: actions/checkout@v4
426
+ with:
427
+ submodules: recursive
428
+ - uses: actions/setup-node@v4
429
+ with:
430
+ node-version: latest
431
+ - name: Install npm dependencies
432
+ run: npm install --omit=dev
433
+ - name: Install Foundry
434
+ uses: foundry-rs/foundry-toolchain@v1
435
+ - name: Run slither
436
+ uses: crytic/slither-action@v0.3.1
437
+ with:
438
+ slither-config: slither-ci.config.json
439
+ fail-on: medium
440
+ ```
441
+
442
+ **slither-ci.config.json:**
443
+ ```json
444
+ {
445
+ "detectors_to_exclude": "timestamp,uninitialized-local,naming-convention,solc-version,shadowing-local",
446
+ "exclude_informational": true,
447
+ "exclude_low": false,
448
+ "exclude_medium": false,
449
+ "exclude_high": false,
450
+ "disable_color": false,
451
+ "filter_paths": "(mocks/|test/|node_modules/|lib/)",
452
+ "legacy_ast": false
453
+ }
454
+ ```
455
+
456
+ **Variations:**
457
+ - Deployer-only repos (no `src/`, only `script/`) skip slither entirely — the action's internal `forge build` skips `test/` and `script/` by default, leaving nothing to compile.
458
+ - Use inline `// slither-disable-next-line <detector>` to suppress known false positives rather than adding to `detectors_to_exclude` in the config. The comment must be on the line immediately before the flagged expression.
459
+
407
460
  ### package.json
408
461
 
409
462
  ```json
410
463
  {
411
- "name": "@bananapus/core-v6",
464
+ "name": "@bananapus/package-name-v6",
412
465
  "version": "x.x.x",
413
466
  "license": "MIT",
414
- "repository": { "type": "git", "url": "git+https://github.com/Bananapus/nana-core-v6.git" },
467
+ "repository": { "type": "git", "url": "git+https://github.com/Org/repo.git" },
415
468
  "engines": { "node": ">=20.0.0" },
416
469
  "scripts": {
417
470
  "test": "forge test",
@@ -428,13 +481,62 @@ jobs:
428
481
 
429
482
  ### remappings.txt
430
483
 
431
- Every repo has a `remappings.txt`. Minimal content:
484
+ Every repo has a `remappings.txt` as the **single source of truth** for import remappings. Never add remappings to `foundry.toml`.
485
+
486
+ **Principle:** Import paths in Solidity source must match npm package names exactly. With `libs = ["node_modules", "lib"]`, Foundry auto-resolves `@scope/package/path/File.sol` → `node_modules/@scope/package/path/File.sol`. No remapping needed for packages installed as real directories.
487
+
488
+ **Note:** Auto-resolution does **not** work for symlinked packages (e.g. npm workspace links). Workspace repos like `deploy-all-v6` and `nana-cli-v6` need explicit `@scope/package/=node_modules/@scope/package/` remappings for each symlinked dependency.
489
+
490
+ **Minimal content** (most repos):
491
+
492
+ ```
493
+ forge-std/=lib/forge-std/src/
494
+ ```
495
+
496
+ Only add extra remappings for:
497
+ - **`forge-std`** — always needed (git submodule with `src/` subdirectory)
498
+ - **Repo-specific `lib/` submodules** that have no npm package (e.g., `hookmate/=lib/hookmate/src/`)
499
+ - **Symlinked npm packages** — need explicit `@scope/package/=node_modules/@scope/package/` entries
500
+ - **Nested transitive deps** — e.g., `@chainlink/contracts-ccip/` nested inside `@bananapus/suckers-v6/node_modules/`
501
+
502
+ **Never add remappings for:**
503
+ - npm packages that match their import path and are installed as real directories — they auto-resolve
504
+ - Short-form aliases (e.g., `@bananapus/core/` → `@bananapus/core-v6/src/`) — fix the import instead
505
+ - Packages available via npm that are also git submodules — remove the submodule, use npm
432
506
 
507
+ **Import path convention:**
508
+
509
+ | Package | Import path | Resolves to |
510
+ |---------|------------|-------------|
511
+ | `@bananapus/core-v6` | `@bananapus/core-v6/src/libraries/JBConstants.sol` | `node_modules/@bananapus/core-v6/src/...` |
512
+ | `@openzeppelin/contracts` | `@openzeppelin/contracts/token/ERC20/IERC20.sol` | `node_modules/@openzeppelin/contracts/...` |
513
+ | `@uniswap/v4-core` | `@uniswap/v4-core/src/interfaces/IPoolManager.sol` | `node_modules/@uniswap/v4-core/src/...` |
514
+
515
+ ### Linting
516
+
517
+ Solar (Foundry's built-in linter) runs automatically during `forge build`. It scans all `.sol` files in `libs` directories, including `node_modules`.
518
+
519
+ **All test helpers must use relative imports** (e.g. `../../src/structs/JBRuleset.sol`), not bare `src/` imports. This ensures solar can resolve paths when the helper is consumed via npm in downstream repos.
520
+
521
+ ### Fork Tests
522
+
523
+ Fork tests use named RPC endpoints defined in `[rpc_endpoints]` of `foundry.toml`. No skip guards — fork tests should hard-fail if the RPC endpoint is unavailable, making CI failures explicit.
524
+
525
+ ```solidity
526
+ function setUp() public {
527
+ vm.createSelectFork("ethereum");
528
+ // ... setup code
529
+ }
433
530
  ```
434
- @sphinx-labs/contracts/=lib/sphinx/packages/contracts/contracts/foundry
531
+
532
+ The endpoint name (e.g. `"ethereum"`) maps to an env var via `foundry.toml`:
533
+
534
+ ```toml
535
+ [rpc_endpoints]
536
+ ethereum = "${RPC_ETHEREUM_MAINNET}"
435
537
  ```
436
538
 
437
- Additional mappings as needed for repo-specific dependencies.
539
+ For multi-chain fork tests, add all needed endpoints.
438
540
 
439
541
  ### Formatting
440
542
 
@@ -462,4 +564,9 @@ CI checks formatting via `forge fmt --check`.
462
564
 
463
565
  ### Contract Size Checks
464
566
 
465
- CI runs `FOUNDRY_PROFILE=ci_sizes forge build --sizes` to catch contracts approaching the 24KB limit. The `ci_sizes` profile uses `optimizer_runs = 200` for realistic size measurement even when the default profile has different optimizer settings.
567
+ CI runs `forge build --sizes` to catch contracts approaching the 24KB limit. When the repo's default `optimizer_runs` differs from what you want for size checking, use `FOUNDRY_PROFILE=ci_sizes forge build --sizes` with a `[profile.ci_sizes]` section in `foundry.toml`.
568
+
569
+
570
+ ## Repo-Specific Deviations
571
+
572
+ None. This repo follows the standard configuration exactly.
package/foundry.toml CHANGED
@@ -5,9 +5,6 @@ optimizer_runs = 200
5
5
  libs = ["node_modules", "lib"]
6
6
  fs_permissions = [{ access = "read-write", path = "./"}]
7
7
 
8
- [profile.ci_sizes]
9
- optimizer_runs = 200
10
-
11
8
  [fuzz]
12
9
  runs = 4096
13
10
 
@@ -16,6 +13,9 @@ runs = 1024
16
13
  depth = 100
17
14
  fail_on_revert = false
18
15
 
16
+ [rpc_endpoints]
17
+ ethereum = "${RPC_ETHEREUM_MAINNET}"
18
+
19
19
  [fmt]
20
20
  number_underscore = "thousands"
21
21
  multiline_func_header = "all"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/core-v6",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,10 +26,10 @@
26
26
  "artifacts": "source ./.env && npx sphinx artifacts --org-id 'ea165b21-7cdc-4d7b-be59-ecdd4c26bee4' --project-name 'nana-core-v6'"
27
27
  },
28
28
  "dependencies": {
29
- "@bananapus/permission-ids-v6": "^0.0.6",
29
+ "@bananapus/permission-ids-v6": "^0.0.9",
30
30
  "@chainlink/contracts": "^1.3.0",
31
- "@openzeppelin/contracts": "^5.2.0",
32
- "@prb/math": "^4.1.0",
31
+ "@openzeppelin/contracts": "^5.6.1",
32
+ "@prb/math": "^4.1.1",
33
33
  "@uniswap/permit2": "github:Uniswap/permit2"
34
34
  },
35
35
  "devDependencies": {
package/remappings.txt CHANGED
@@ -1 +1 @@
1
- @sphinx-labs/contracts/=lib/sphinx/packages/contracts/contracts/foundry
1
+ forge-std/=lib/forge-std/src/
@@ -1,9 +1,8 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity 0.8.26;
3
3
 
4
- import "@sphinx-labs/contracts/SphinxPlugin.sol";
5
- import {Script, stdJson, VmSafe} from "forge-std/Script.sol";
6
- import {CoreDeploymentLib} from "./helpers/CoreDeploymentLib.sol";
4
+ import {Sphinx} from "@sphinx-labs/contracts/contracts/foundry/SphinxPlugin.sol";
5
+ import {Script} from "forge-std/Script.sol";
7
6
 
8
7
  import {IPermit2} from "@uniswap/permit2/src/interfaces/IPermit2.sol";
9
8
  import {JBPermissions} from "src/JBPermissions.sol";
@@ -16,7 +15,6 @@ import {JBTokens} from "src/JBTokens.sol";
16
15
  import {JBSplits} from "src/JBSplits.sol";
17
16
  import {JBFeelessAddresses} from "src/JBFeelessAddresses.sol";
18
17
  import {JBFundAccessLimits} from "src/JBFundAccessLimits.sol";
19
- import {JBController} from "src/JBController.sol";
20
18
  import {JBTerminalStore} from "src/JBTerminalStore.sol";
21
19
  import {JBMultiTerminal} from "src/JBMultiTerminal.sol";
22
20
 
@@ -28,16 +26,20 @@ contract Deploy is Script, Sphinx {
28
26
 
29
27
  /// @notice The address that is allowed to forward calls to the terminal and controller on a users behalf.
30
28
  string private constant TRUSTED_FORWARDER_NAME = "Juicebox";
29
+ // forge-lint: disable-next-line(mixed-case-variable)
31
30
  address private TRUSTED_FORWARDER;
32
31
 
33
32
  /// @notice The address that will manage the few privileged functions of the protocol.
33
+ // forge-lint: disable-next-line(mixed-case-variable)
34
34
  address private MANAGER;
35
35
 
36
36
  /// @notice The address that will own the fee-project.
37
+ // forge-lint: disable-next-line(mixed-case-variable)
37
38
  address private FEE_PROJECT_OWNER;
38
39
 
39
40
  /// @notice The nonce that gets used across all chains to sync deployment addresses and allow for new deployments of
40
41
  /// the same bytecode.
42
+ // forge-lint: disable-next-line(mixed-case-variable)
41
43
  uint256 private CORE_DEPLOYMENT_NONCE = 6;
42
44
 
43
45
  function configureSphinx() public override {
@@ -63,19 +65,24 @@ contract Deploy is Script, Sphinx {
63
65
 
64
66
  JBPermissions permissions =
65
67
  new JBPermissions{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}(TRUSTED_FORWARDER);
66
- JBProjects projects = new JBProjects{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}(
67
- safeAddress(), safeAddress(), TRUSTED_FORWARDER
68
- );
69
- JBDirectory directory =
70
- new JBDirectory{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}(permissions, projects, safeAddress());
68
+ JBProjects projects = new JBProjects{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}({
69
+ owner: safeAddress(), feeProjectOwner: safeAddress(), trustedForwarder: TRUSTED_FORWARDER
70
+ });
71
+ JBDirectory directory = new JBDirectory{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}({
72
+ permissions: permissions, projects: projects, owner: safeAddress()
73
+ });
71
74
  JBSplits splits = new JBSplits{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}(directory);
72
75
  JBRulesets rulesets = new JBRulesets{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}(directory);
73
- JBPrices prices = new JBPrices{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}(
74
- directory, permissions, projects, safeAddress(), TRUSTED_FORWARDER
75
- );
76
- JBTokens tokens = new JBTokens{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}(
77
- directory, new JBERC20{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}()
78
- );
76
+ JBPrices prices = new JBPrices{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}({
77
+ directory: directory,
78
+ permissions: permissions,
79
+ projects: projects,
80
+ owner: safeAddress(),
81
+ trustedForwarder: TRUSTED_FORWARDER
82
+ });
83
+ JBTokens tokens = new JBTokens{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}({
84
+ directory: directory, token: new JBERC20{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}()
85
+ });
79
86
 
80
87
  new JBFundAccessLimits{salt: keccak256(abi.encode(CORE_DEPLOYMENT_NONCE))}(directory);
81
88
 
@@ -105,7 +112,7 @@ contract Deploy is Script, Sphinx {
105
112
 
106
113
  // Transfer ownership to the fee project owner.
107
114
  if (FEE_PROJECT_OWNER != safeAddress() && FEE_PROJECT_OWNER != address(0)) {
108
- projects.safeTransferFrom(safeAddress(), FEE_PROJECT_OWNER, 1);
115
+ projects.safeTransferFrom({from: safeAddress(), to: FEE_PROJECT_OWNER, tokenId: 1});
109
116
  }
110
117
  }
111
118
  }