@bananapus/core-v6 0.0.1

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 (436) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +112 -0
  3. package/SKILLS.md +151 -0
  4. package/docs/book.css +13 -0
  5. package/docs/book.toml +12 -0
  6. package/docs/solidity.min.js +74 -0
  7. package/docs/src/README.md +703 -0
  8. package/docs/src/SUMMARY.md +94 -0
  9. package/docs/src/src/JBChainlinkV3PriceFeed.sol/contract.JBChainlinkV3PriceFeed.md +83 -0
  10. package/docs/src/src/JBChainlinkV3SequencerPriceFeed.sol/contract.JBChainlinkV3SequencerPriceFeed.md +88 -0
  11. package/docs/src/src/JBController.sol/contract.JBController.md +1121 -0
  12. package/docs/src/src/JBDeadline.sol/contract.JBDeadline.md +84 -0
  13. package/docs/src/src/JBDirectory.sol/contract.JBDirectory.md +294 -0
  14. package/docs/src/src/JBERC20.sol/contract.JBERC20.md +190 -0
  15. package/docs/src/src/JBFeelessAddresses.sol/contract.JBFeelessAddresses.md +80 -0
  16. package/docs/src/src/JBFundAccessLimits.sol/contract.JBFundAccessLimits.md +253 -0
  17. package/docs/src/src/JBMultiTerminal.sol/contract.JBMultiTerminal.md +1472 -0
  18. package/docs/src/src/JBPermissions.sol/contract.JBPermissions.md +199 -0
  19. package/docs/src/src/JBPrices.sol/contract.JBPrices.md +154 -0
  20. package/docs/src/src/JBProjects.sol/contract.JBProjects.md +131 -0
  21. package/docs/src/src/JBRulesets.sol/contract.JBRulesets.md +677 -0
  22. package/docs/src/src/JBSplits.sol/contract.JBSplits.md +237 -0
  23. package/docs/src/src/JBTerminalStore.sol/contract.JBTerminalStore.md +591 -0
  24. package/docs/src/src/JBTokens.sol/contract.JBTokens.md +353 -0
  25. package/docs/src/src/README.md +25 -0
  26. package/docs/src/src/abstract/JBControlled.sol/abstract.JBControlled.md +64 -0
  27. package/docs/src/src/abstract/JBPermissioned.sol/abstract.JBPermissioned.md +84 -0
  28. package/docs/src/src/abstract/README.md +5 -0
  29. package/docs/src/src/enums/JBApprovalStatus.sol/enum.JBApprovalStatus.md +17 -0
  30. package/docs/src/src/enums/README.md +4 -0
  31. package/docs/src/src/interfaces/IJBCashOutHook.sol/interface.IJBCashOutHook.md +29 -0
  32. package/docs/src/src/interfaces/IJBCashOutTerminal.sol/interface.IJBCashOutTerminal.md +57 -0
  33. package/docs/src/src/interfaces/IJBControlled.sol/interface.IJBControlled.md +12 -0
  34. package/docs/src/src/interfaces/IJBController.sol/interface.IJBController.md +334 -0
  35. package/docs/src/src/interfaces/IJBDirectory.sol/interface.IJBDirectory.md +108 -0
  36. package/docs/src/src/interfaces/IJBDirectoryAccessControl.sol/interface.IJBDirectoryAccessControl.md +19 -0
  37. package/docs/src/src/interfaces/IJBFeeTerminal.sol/interface.IJBFeeTerminal.md +91 -0
  38. package/docs/src/src/interfaces/IJBFeelessAddresses.sol/interface.IJBFeelessAddresses.md +26 -0
  39. package/docs/src/src/interfaces/IJBFundAccessLimits.sol/interface.IJBFundAccessLimits.md +88 -0
  40. package/docs/src/src/interfaces/IJBMigratable.sol/interface.IJBMigratable.md +29 -0
  41. package/docs/src/src/interfaces/IJBMultiTerminal.sol/interface.IJBMultiTerminal.md +50 -0
  42. package/docs/src/src/interfaces/IJBPayHook.sol/interface.IJBPayHook.md +28 -0
  43. package/docs/src/src/interfaces/IJBPayoutTerminal.sol/interface.IJBPayoutTerminal.md +105 -0
  44. package/docs/src/src/interfaces/IJBPermissioned.sol/interface.IJBPermissioned.md +12 -0
  45. package/docs/src/src/interfaces/IJBPermissions.sol/interface.IJBPermissions.md +74 -0
  46. package/docs/src/src/interfaces/IJBPermitTerminal.sol/interface.IJBPermitTerminal.md +15 -0
  47. package/docs/src/src/interfaces/IJBPriceFeed.sol/interface.IJBPriceFeed.md +12 -0
  48. package/docs/src/src/interfaces/IJBPrices.sol/interface.IJBPrices.md +74 -0
  49. package/docs/src/src/interfaces/IJBProjectUriRegistry.sol/interface.IJBProjectUriRegistry.md +19 -0
  50. package/docs/src/src/interfaces/IJBProjects.sol/interface.IJBProjects.md +49 -0
  51. package/docs/src/src/interfaces/IJBRulesetApprovalHook.sol/interface.IJBRulesetApprovalHook.md +35 -0
  52. package/docs/src/src/interfaces/IJBRulesetDataHook.sol/interface.IJBRulesetDataHook.md +97 -0
  53. package/docs/src/src/interfaces/IJBRulesets.sol/interface.IJBRulesets.md +165 -0
  54. package/docs/src/src/interfaces/IJBSplitHook.sol/interface.IJBSplitHook.md +31 -0
  55. package/docs/src/src/interfaces/IJBSplits.sol/interface.IJBSplits.md +35 -0
  56. package/docs/src/src/interfaces/IJBTerminal.sol/interface.IJBTerminal.md +141 -0
  57. package/docs/src/src/interfaces/IJBTerminalStore.sol/interface.IJBTerminalStore.md +198 -0
  58. package/docs/src/src/interfaces/IJBToken.sol/interface.IJBToken.md +54 -0
  59. package/docs/src/src/interfaces/IJBTokenUriResolver.sol/interface.IJBTokenUriResolver.md +12 -0
  60. package/docs/src/src/interfaces/IJBTokens.sol/interface.IJBTokens.md +151 -0
  61. package/docs/src/src/interfaces/README.md +33 -0
  62. package/docs/src/src/libraries/JBCashOuts.sol/library.JBCashOuts.md +40 -0
  63. package/docs/src/src/libraries/JBConstants.sol/library.JBConstants.md +52 -0
  64. package/docs/src/src/libraries/JBCurrencyIds.sol/library.JBCurrencyIds.md +19 -0
  65. package/docs/src/src/libraries/JBFees.sol/library.JBFees.md +52 -0
  66. package/docs/src/src/libraries/JBFixedPointNumber.sol/library.JBFixedPointNumber.md +12 -0
  67. package/docs/src/src/libraries/JBMetadataResolver.sol/library.JBMetadataResolver.md +242 -0
  68. package/docs/src/src/libraries/JBRulesetMetadataResolver.sol/library.JBRulesetMetadataResolver.md +180 -0
  69. package/docs/src/src/libraries/JBSplitGroupIds.sol/library.JBSplitGroupIds.md +14 -0
  70. package/docs/src/src/libraries/JBSurplus.sol/library.JBSurplus.md +44 -0
  71. package/docs/src/src/libraries/README.md +12 -0
  72. package/docs/src/src/periphery/JBDeadline1Day.sol/contract.JBDeadline1Day.md +15 -0
  73. package/docs/src/src/periphery/JBDeadline3Days.sol/contract.JBDeadline3Days.md +15 -0
  74. package/docs/src/src/periphery/JBDeadline3Hours.sol/contract.JBDeadline3Hours.md +15 -0
  75. package/docs/src/src/periphery/JBDeadline7Days.sol/contract.JBDeadline7Days.md +15 -0
  76. package/docs/src/src/periphery/JBMatchingPriceFeed.sol/contract.JBMatchingPriceFeed.md +22 -0
  77. package/docs/src/src/periphery/README.md +8 -0
  78. package/docs/src/src/structs/JBAccountingContext.sol/struct.JBAccountingContext.md +20 -0
  79. package/docs/src/src/structs/JBAfterCashOutRecordedContext.sol/struct.JBAfterCashOutRecordedContext.md +43 -0
  80. package/docs/src/src/structs/JBAfterPayRecordedContext.sol/struct.JBAfterPayRecordedContext.md +42 -0
  81. package/docs/src/src/structs/JBBeforeCashOutRecordedContext.sol/struct.JBBeforeCashOutRecordedContext.md +45 -0
  82. package/docs/src/src/structs/JBBeforePayRecordedContext.sol/struct.JBBeforePayRecordedContext.md +41 -0
  83. package/docs/src/src/structs/JBCashOutHookSpecification.sol/struct.JBCashOutHookSpecification.md +22 -0
  84. package/docs/src/src/structs/JBCurrencyAmount.sol/struct.JBCurrencyAmount.md +17 -0
  85. package/docs/src/src/structs/JBFee.sol/struct.JBFee.md +20 -0
  86. package/docs/src/src/structs/JBFundAccessLimitGroup.sol/struct.JBFundAccessLimitGroup.md +39 -0
  87. package/docs/src/src/structs/JBPayHookSpecification.sol/struct.JBPayHookSpecification.md +22 -0
  88. package/docs/src/src/structs/JBPermissionsData.sol/struct.JBPermissionsData.md +21 -0
  89. package/docs/src/src/structs/JBRuleset.sol/struct.JBRuleset.md +55 -0
  90. package/docs/src/src/structs/JBRulesetConfig.sol/struct.JBRulesetConfig.md +51 -0
  91. package/docs/src/src/structs/JBRulesetMetadata.sol/struct.JBRulesetMetadata.md +79 -0
  92. package/docs/src/src/structs/JBRulesetWeightCache.sol/struct.JBRulesetWeightCache.md +16 -0
  93. package/docs/src/src/structs/JBRulesetWithMetadata.sol/struct.JBRulesetWithMetadata.md +16 -0
  94. package/docs/src/src/structs/JBSingleAllowance.sol/struct.JBSingleAllowance.md +26 -0
  95. package/docs/src/src/structs/JBSplit.sol/struct.JBSplit.md +49 -0
  96. package/docs/src/src/structs/JBSplitGroup.sol/struct.JBSplitGroup.md +17 -0
  97. package/docs/src/src/structs/JBSplitHookContext.sol/struct.JBSplitHookContext.md +29 -0
  98. package/docs/src/src/structs/JBTerminalConfig.sol/struct.JBTerminalConfig.md +16 -0
  99. package/docs/src/src/structs/JBTokenAmount.sol/struct.JBTokenAmount.md +23 -0
  100. package/docs/src/src/structs/README.md +25 -0
  101. package/foundry.lock +11 -0
  102. package/foundry.toml +41 -0
  103. package/package.json +38 -0
  104. package/remappings.txt +1 -0
  105. package/script/Deploy.s.sol +111 -0
  106. package/script/DeployPeriphery.s.sol +287 -0
  107. package/script/helpers/CoreDeploymentLib.sol +121 -0
  108. package/slither-ci.config.json +10 -0
  109. package/sphinx.lock +507 -0
  110. package/src/JBChainlinkV3PriceFeed.sol +77 -0
  111. package/src/JBChainlinkV3SequencerPriceFeed.sol +75 -0
  112. package/src/JBController.sol +1186 -0
  113. package/src/JBDeadline.sol +73 -0
  114. package/src/JBDirectory.sol +343 -0
  115. package/src/JBERC20.sol +131 -0
  116. package/src/JBFeelessAddresses.sol +54 -0
  117. package/src/JBFundAccessLimits.sol +308 -0
  118. package/src/JBMultiTerminal.sol +2024 -0
  119. package/src/JBPermissions.sol +252 -0
  120. package/src/JBPrices.sol +227 -0
  121. package/src/JBProjects.sol +126 -0
  122. package/src/JBRulesets.sol +1093 -0
  123. package/src/JBSplits.sol +324 -0
  124. package/src/JBTerminalStore.sol +908 -0
  125. package/src/JBTokens.sol +376 -0
  126. package/src/abstract/JBControlled.sol +48 -0
  127. package/src/abstract/JBPermissioned.sol +77 -0
  128. package/src/enums/JBApprovalStatus.sol +12 -0
  129. package/src/interfaces/IJBCashOutHook.sol +15 -0
  130. package/src/interfaces/IJBCashOutTerminal.sol +51 -0
  131. package/src/interfaces/IJBControlled.sol +10 -0
  132. package/src/interfaces/IJBController.sol +280 -0
  133. package/src/interfaces/IJBDirectory.sol +69 -0
  134. package/src/interfaces/IJBDirectoryAccessControl.sol +15 -0
  135. package/src/interfaces/IJBFeeTerminal.sol +61 -0
  136. package/src/interfaces/IJBFeelessAddresses.sol +17 -0
  137. package/src/interfaces/IJBFundAccessLimits.sol +94 -0
  138. package/src/interfaces/IJBMigratable.sol +24 -0
  139. package/src/interfaces/IJBMultiTerminal.sol +36 -0
  140. package/src/interfaces/IJBPayHook.sol +14 -0
  141. package/src/interfaces/IJBPayoutTerminal.sol +92 -0
  142. package/src/interfaces/IJBPermissioned.sol +10 -0
  143. package/src/interfaces/IJBPermissions.sol +71 -0
  144. package/src/interfaces/IJBPermitTerminal.sol +14 -0
  145. package/src/interfaces/IJBPriceFeed.sol +10 -0
  146. package/src/interfaces/IJBPrices.sol +65 -0
  147. package/src/interfaces/IJBProjectUriRegistry.sol +15 -0
  148. package/src/interfaces/IJBProjects.sol +27 -0
  149. package/src/interfaces/IJBRulesetApprovalHook.sol +21 -0
  150. package/src/interfaces/IJBRulesetDataHook.sol +56 -0
  151. package/src/interfaces/IJBRulesets.sol +151 -0
  152. package/src/interfaces/IJBSplitHook.sol +16 -0
  153. package/src/interfaces/IJBSplits.sol +28 -0
  154. package/src/interfaces/IJBTerminal.sol +120 -0
  155. package/src/interfaces/IJBTerminalStore.sol +225 -0
  156. package/src/interfaces/IJBToken.sol +39 -0
  157. package/src/interfaces/IJBTokenUriResolver.sol +10 -0
  158. package/src/interfaces/IJBTokens.sol +113 -0
  159. package/src/libraries/JBCashOuts.sol +120 -0
  160. package/src/libraries/JBConstants.sol +14 -0
  161. package/src/libraries/JBCurrencyIds.sol +7 -0
  162. package/src/libraries/JBFees.sol +28 -0
  163. package/src/libraries/JBFixedPointNumber.sol +12 -0
  164. package/src/libraries/JBMetadataResolver.sol +306 -0
  165. package/src/libraries/JBRulesetMetadataResolver.sol +160 -0
  166. package/src/libraries/JBSplitGroupIds.sol +7 -0
  167. package/src/libraries/JBSurplus.sol +40 -0
  168. package/src/periphery/JBDeadline1Day.sol +8 -0
  169. package/src/periphery/JBDeadline3Days.sol +8 -0
  170. package/src/periphery/JBDeadline3Hours.sol +8 -0
  171. package/src/periphery/JBDeadline7Days.sol +8 -0
  172. package/src/periphery/JBMatchingPriceFeed.sol +13 -0
  173. package/src/structs/JBAccountingContext.sol +12 -0
  174. package/src/structs/JBAfterCashOutRecordedContext.sol +30 -0
  175. package/src/structs/JBAfterPayRecordedContext.sol +29 -0
  176. package/src/structs/JBBeforeCashOutRecordedContext.sol +31 -0
  177. package/src/structs/JBBeforePayRecordedContext.sol +28 -0
  178. package/src/structs/JBCashOutHookSpecification.sol +15 -0
  179. package/src/structs/JBCurrencyAmount.sol +10 -0
  180. package/src/structs/JBFee.sol +12 -0
  181. package/src/structs/JBFundAccessLimitGroup.sol +28 -0
  182. package/src/structs/JBPayHookSpecification.sol +15 -0
  183. package/src/structs/JBPermissionsData.sol +13 -0
  184. package/src/structs/JBRuleset.sol +42 -0
  185. package/src/structs/JBRulesetConfig.sol +43 -0
  186. package/src/structs/JBRulesetMetadata.sol +56 -0
  187. package/src/structs/JBRulesetWeightCache.sol +9 -0
  188. package/src/structs/JBRulesetWithMetadata.sol +12 -0
  189. package/src/structs/JBSingleAllowance.sol +16 -0
  190. package/src/structs/JBSplit.sol +37 -0
  191. package/src/structs/JBSplitGroup.sol +12 -0
  192. package/src/structs/JBSplitHookContext.sol +20 -0
  193. package/src/structs/JBTerminalConfig.sol +12 -0
  194. package/src/structs/JBTokenAmount.sol +14 -0
  195. package/test/AuditExploits.t.sol +2710 -0
  196. package/test/ComprehensiveInvariant.t.sol +298 -0
  197. package/test/EconomicSimulation.t.sol +340 -0
  198. package/test/EntryPointPermutations.t.sol +671 -0
  199. package/test/FlashLoanAttacks.t.sol +792 -0
  200. package/test/PermissionEscalation.t.sol +679 -0
  201. package/test/RulesetTransitions.t.sol +699 -0
  202. package/test/SplitLoopTests.t.sol +731 -0
  203. package/test/TestAccessToFunds.sol +2644 -0
  204. package/test/TestCashOut.sol +185 -0
  205. package/test/TestCashOutCountFor.sol +272 -0
  206. package/test/TestCashOutHooks.sol +317 -0
  207. package/test/TestCashOutTimingEdge.sol +229 -0
  208. package/test/TestDurationUnderflow.sol +220 -0
  209. package/test/TestFeeProcessingFailure.sol +208 -0
  210. package/test/TestFees.sol +604 -0
  211. package/test/TestInterfaceSupport.sol +62 -0
  212. package/test/TestJBERC20Inheritance.sol +91 -0
  213. package/test/TestLaunchProject.sol +176 -0
  214. package/test/TestMetaTx.sol +203 -0
  215. package/test/TestMetadataParserLib.sol +438 -0
  216. package/test/TestMigrationHeldFees.sol +249 -0
  217. package/test/TestMintTokensOf.sol +172 -0
  218. package/test/TestMultiTokenSurplus.sol +206 -0
  219. package/test/TestMultipleAccessLimits.sol +642 -0
  220. package/test/TestPayBurnRedeemFlow.sol +180 -0
  221. package/test/TestPayHooks.sol +190 -0
  222. package/test/TestPermissions.sol +305 -0
  223. package/test/TestPermissionsEdge.sol +286 -0
  224. package/test/TestPermit2Terminal.sol +339 -0
  225. package/test/TestRulesetQueueing.sol +1001 -0
  226. package/test/TestRulesetQueuingStress.sol +778 -0
  227. package/test/TestRulesetWeightCaching.sol +177 -0
  228. package/test/TestSplits.sol +369 -0
  229. package/test/TestTerminalMigration.sol +167 -0
  230. package/test/TestTokenFlow.sol +174 -0
  231. package/test/WeirdTokenTests.t.sol +764 -0
  232. package/test/formal/BondingCurveProperties.t.sol +411 -0
  233. package/test/formal/FeeProperties.t.sol +246 -0
  234. package/test/helpers/JBTest.sol +129 -0
  235. package/test/helpers/MetadataResolverHelper.sol +116 -0
  236. package/test/helpers/TestBaseWorkflow.sol +317 -0
  237. package/test/invariants/Phase3DeepInvariant.t.sol +404 -0
  238. package/test/invariants/RulesetsInvariant.t.sol +115 -0
  239. package/test/invariants/TerminalStoreInvariant.t.sol +220 -0
  240. package/test/invariants/TokensInvariant.t.sol +184 -0
  241. package/test/invariants/handlers/ComprehensiveHandler.sol +285 -0
  242. package/test/invariants/handlers/EconomicHandler.sol +347 -0
  243. package/test/invariants/handlers/Phase3Handler.sol +414 -0
  244. package/test/invariants/handlers/RulesetsHandler.sol +111 -0
  245. package/test/invariants/handlers/TerminalStoreHandler.sol +146 -0
  246. package/test/invariants/handlers/TokensHandler.sol +127 -0
  247. package/test/mock/ERC2771ForwarderMock.sol +37 -0
  248. package/test/mock/MockERC20.sol +18 -0
  249. package/test/mock/MockMaliciousBeneficiary.sol +67 -0
  250. package/test/mock/MockMaliciousSplitHook.sol +42 -0
  251. package/test/mock/MockPriceFeed.sol +20 -0
  252. package/test/trees/JBController/burnTokensOf.tree +9 -0
  253. package/test/trees/JBController/claimTokensFor.tree +5 -0
  254. package/test/trees/JBController/deployERC20For.tree +5 -0
  255. package/test/trees/JBController/getRulesetOf.tree +5 -0
  256. package/test/trees/JBController/launchProjectFor.tree +12 -0
  257. package/test/trees/JBController/launchRulesetsFor.tree +8 -0
  258. package/test/trees/JBController/migrateController.tree +12 -0
  259. package/test/trees/JBController/mintTokensOf.tree +12 -0
  260. package/test/trees/JBController/payReservedTokenToTerminal.tree +8 -0
  261. package/test/trees/JBController/receiveMigrationFrom.tree +4 -0
  262. package/test/trees/JBController/sendReservedTokensToSplitsOf.tree +12 -0
  263. package/test/trees/JBController/setMetadataOf.tree +5 -0
  264. package/test/trees/JBController/setSplitGroupsOf.tree +5 -0
  265. package/test/trees/JBController/setTokenFor.tree +5 -0
  266. package/test/trees/JBController/transferCreditsFrom.tree +8 -0
  267. package/test/trees/JBDirectory/primaryTerminalOf.tree +8 -0
  268. package/test/trees/JBDirectory/setControllerOf.tree +11 -0
  269. package/test/trees/JBDirectory/setPrimaryTerminalOf.tree +15 -0
  270. package/test/trees/JBDirectory/setTerminalsOf.tree +11 -0
  271. package/test/trees/JBERC20/initialize.tree +7 -0
  272. package/test/trees/JBERC20/name.tree +5 -0
  273. package/test/trees/JBERC20/nonces.tree +5 -0
  274. package/test/trees/JBERC20/symbol.tree +5 -0
  275. package/test/trees/JBFeelessAddresses/setFeelessAddress.tree +5 -0
  276. package/test/trees/JBFeelessAddresses/supportsInterface.tree +5 -0
  277. package/test/trees/JBFundAccessLimits/payoutLimitOf.tree +5 -0
  278. package/test/trees/JBFundAccessLimits/payoutLimitsOf.tree +8 -0
  279. package/test/trees/JBFundAccessLimits/setFundAccessLimitsFor.tree +18 -0
  280. package/test/trees/JBFundAccessLimits/surplusAllowanceOf.tree +5 -0
  281. package/test/trees/JBFundAccessLimits/surplusAllowancesOf.tree +8 -0
  282. package/test/trees/JBMetadataResolver/getDataFor.tree +8 -0
  283. package/test/trees/JBMultiTerminal/accountingContextsOf.tree +5 -0
  284. package/test/trees/JBMultiTerminal/addAccountingContextsFor.tree +10 -0
  285. package/test/trees/JBMultiTerminal/addToBalanceOf.tree +23 -0
  286. package/test/trees/JBMultiTerminal/cashOutTokensOf.tree +23 -0
  287. package/test/trees/JBMultiTerminal/executePayout.tree +32 -0
  288. package/test/trees/JBMultiTerminal/executeProcessFee.tree +14 -0
  289. package/test/trees/JBMultiTerminal/migrateBalanceOf.tree +12 -0
  290. package/test/trees/JBMultiTerminal/pay.tree +23 -0
  291. package/test/trees/JBMultiTerminal/processHeldFeesOf.tree +8 -0
  292. package/test/trees/JBMultiTerminal/sendPayoutsOf.tree +34 -0
  293. package/test/trees/JBMultiTerminal/useAllowanceOf.tree +16 -0
  294. package/test/trees/JBPermissions/hasPermission.tree +8 -0
  295. package/test/trees/JBPermissions/hasPermissions.tree +8 -0
  296. package/test/trees/JBPermissions/setPermissionsFor.tree +5 -0
  297. package/test/trees/JBPrices/addPriceFeedFor.tree +14 -0
  298. package/test/trees/JBPrices/pricePerUnitOf.tree +11 -0
  299. package/test/trees/JBProjects/createFor.tree +11 -0
  300. package/test/trees/JBProjects/setTokenUriResolver.tree +5 -0
  301. package/test/trees/JBProjects/supportsInterface.tree +9 -0
  302. package/test/trees/JBProjects/tokenURI.tree +5 -0
  303. package/test/trees/JBRulesets/currentApprovalStatusForLatestRulesetOf.tree +8 -0
  304. package/test/trees/JBRulesets/currentOf.tree +12 -0
  305. package/test/trees/JBRulesets/getRulesetOf.tree +5 -0
  306. package/test/trees/JBRulesets/latestQueuedRulesetOf.tree +10 -0
  307. package/test/trees/JBRulesets/rulesetsOf.tree +11 -0
  308. package/test/trees/JBRulesets/upcomingRulesetOf.tree +20 -0
  309. package/test/trees/JBRulesets/updateRulesetWeightCache.tree +5 -0
  310. package/test/trees/JBSplits/setSplitGroupsOf.tree +17 -0
  311. package/test/trees/JBSplits/splitsOf.tree +5 -0
  312. package/test/trees/JBTerminalStore/currentReclaimableSurplusOf.tree +16 -0
  313. package/test/trees/JBTerminalStore/currentSurplusOf.tree +25 -0
  314. package/test/trees/JBTerminalStore/currentTotalSurplusOf.tree +5 -0
  315. package/test/trees/JBTerminalStore/recordCashOutsFor.tree +16 -0
  316. package/test/trees/JBTerminalStore/recordPaymentFrom.tree +14 -0
  317. package/test/trees/JBTerminalStore/recordPayoutFor.tree +10 -0
  318. package/test/trees/JBTerminalStore/recordTerminalMigration.tree +5 -0
  319. package/test/trees/JBTerminalStore/recordUsedAllowanceOf.tree +10 -0
  320. package/test/trees/JBTokens/burnFrom.tree +10 -0
  321. package/test/trees/JBTokens/claimTokensFor.tree +10 -0
  322. package/test/trees/JBTokens/deployERC20For.tree +12 -0
  323. package/test/trees/JBTokens/mintFor.tree +10 -0
  324. package/test/trees/JBTokens/setTokenFor.tree +11 -0
  325. package/test/trees/JBTokens/totalBalanceOf.tree +5 -0
  326. package/test/trees/JBTokens/totalSupplyOf.tree +5 -0
  327. package/test/trees/JBTokens/transferCreditsFrom.tree +8 -0
  328. package/test/trees/mintTokensOf.tree +12 -0
  329. package/test/units/static/JBChainlinkV3PriceFeed/TestPriceFeed.sol +220 -0
  330. package/test/units/static/JBController/JBControllerSetup.sol +40 -0
  331. package/test/units/static/JBController/TestBurnTokensOf.sol +107 -0
  332. package/test/units/static/JBController/TestClaimTokensFor.sol +60 -0
  333. package/test/units/static/JBController/TestDeployErc20For.sol +80 -0
  334. package/test/units/static/JBController/TestLaunchProjectFor.sol +282 -0
  335. package/test/units/static/JBController/TestLaunchRulesetsFor.sol +322 -0
  336. package/test/units/static/JBController/TestMigrateController.sol +148 -0
  337. package/test/units/static/JBController/TestMintTokensOfUnits.sol +102 -0
  338. package/test/units/static/JBController/TestPayReservedTokenToTerminal.sol +71 -0
  339. package/test/units/static/JBController/TestReceiveMigrationFrom.sol +95 -0
  340. package/test/units/static/JBController/TestRulesetViews.sol +219 -0
  341. package/test/units/static/JBController/TestSendReservedTokensToSplitsOf.sol +595 -0
  342. package/test/units/static/JBController/TestSetSplitGroupsOf.sol +63 -0
  343. package/test/units/static/JBController/TestSetTokenFor.sol +227 -0
  344. package/test/units/static/JBController/TestSetUriOf.sol +53 -0
  345. package/test/units/static/JBController/TestTransferCreditsFrom.sol +159 -0
  346. package/test/units/static/JBDeadline/TestDeadlineFuzz.sol +194 -0
  347. package/test/units/static/JBDirectory/JBDirectorySetup.sol +22 -0
  348. package/test/units/static/JBDirectory/TestPrimaryTerminalOf.sol +122 -0
  349. package/test/units/static/JBDirectory/TestSetControllerOf.sol +173 -0
  350. package/test/units/static/JBDirectory/TestSetControllerOfMigrationOrder.sol +98 -0
  351. package/test/units/static/JBDirectory/TestSetPrimaryTerminalOf.sol +169 -0
  352. package/test/units/static/JBDirectory/TestSetTerminalsOf.sol +128 -0
  353. package/test/units/static/JBERC20/JBERC20Setup.sol +20 -0
  354. package/test/units/static/JBERC20/SigUtils.sol +34 -0
  355. package/test/units/static/JBERC20/TestInitialize.sol +54 -0
  356. package/test/units/static/JBERC20/TestName.sol +30 -0
  357. package/test/units/static/JBERC20/TestNonces.sol +59 -0
  358. package/test/units/static/JBERC20/TestSymbol.sol +31 -0
  359. package/test/units/static/JBFeelessAdresses/JBFeelessSetup.sol +20 -0
  360. package/test/units/static/JBFeelessAdresses/TestInterfaces.sol +29 -0
  361. package/test/units/static/JBFeelessAdresses/TestSetFeelessAddress.sol +35 -0
  362. package/test/units/static/JBFees/TestFeesFuzz.sol +78 -0
  363. package/test/units/static/JBFixedPointNumber/TestAdjustDecimals.sol +16 -0
  364. package/test/units/static/JBFixedPointNumber/TestAdjustDecimalsFuzz.sol +71 -0
  365. package/test/units/static/JBFundAccessLimits/JBFundAccessSetup.sol +21 -0
  366. package/test/units/static/JBFundAccessLimits/TestFundAccessLimitsEdge.sol +159 -0
  367. package/test/units/static/JBFundAccessLimits/TestPayoutLimitOf.sol +56 -0
  368. package/test/units/static/JBFundAccessLimits/TestPayoutLimitsOf.sol +94 -0
  369. package/test/units/static/JBFundAccessLimits/TestSetFundAccessLimitsFor.sol +182 -0
  370. package/test/units/static/JBFundAccessLimits/TestSurplusAllowanceOf.sol +61 -0
  371. package/test/units/static/JBFundAccessLimits/TestSurplusAllowancesOf.sol +96 -0
  372. package/test/units/static/JBMetadataResolver/TestGetDataFor.sol +89 -0
  373. package/test/units/static/JBMetadataResolver/TestMetadataResolverFuzz.sol +227 -0
  374. package/test/units/static/JBMetadataResolver/TestMetadataResolverM20M21.sol +245 -0
  375. package/test/units/static/JBMultiTerminal/JBMultiTerminalSetup.sol +39 -0
  376. package/test/units/static/JBMultiTerminal/TestAccountingContextsOf.sol +65 -0
  377. package/test/units/static/JBMultiTerminal/TestAddAccountingContextsFor.sol +313 -0
  378. package/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol +432 -0
  379. package/test/units/static/JBMultiTerminal/TestCashOutTokensOf.sol +478 -0
  380. package/test/units/static/JBMultiTerminal/TestExecutePayout.sol +577 -0
  381. package/test/units/static/JBMultiTerminal/TestExecuteProcessFee.sol +176 -0
  382. package/test/units/static/JBMultiTerminal/TestMigrateBalanceOf.sol +190 -0
  383. package/test/units/static/JBMultiTerminal/TestPay.sol +514 -0
  384. package/test/units/static/JBMultiTerminal/TestProcessHeldFeesOf.sol +29 -0
  385. package/test/units/static/JBMultiTerminal/TestSendPayoutsOf.sol +243 -0
  386. package/test/units/static/JBMultiTerminal/TestUseAllowanceOf.sol +310 -0
  387. package/test/units/static/JBPermissions/JBPermissionsSetup.sol +18 -0
  388. package/test/units/static/JBPermissions/TestHasPermission.sol +50 -0
  389. package/test/units/static/JBPermissions/TestHasPermissions.sol +93 -0
  390. package/test/units/static/JBPermissions/TestSetPermissionsFor.sol +62 -0
  391. package/test/units/static/JBPrices/JBPricesSetup.sol +26 -0
  392. package/test/units/static/JBPrices/TestAddPriceFeedFor.sol +102 -0
  393. package/test/units/static/JBPrices/TestPricePerUnitOf.sol +129 -0
  394. package/test/units/static/JBPrices/TestPrices.sol +262 -0
  395. package/test/units/static/JBProjects/JBProjectsSetup.sol +20 -0
  396. package/test/units/static/JBProjects/TestCreateFor.sol +69 -0
  397. package/test/units/static/JBProjects/TestInitialProject.sol +19 -0
  398. package/test/units/static/JBProjects/TestInterfaces.sol +27 -0
  399. package/test/units/static/JBProjects/TestSetResolver.sol +36 -0
  400. package/test/units/static/JBProjects/TestTokenUri.sol +38 -0
  401. package/test/units/static/JBRulesetMetadataResolver/TestSetCashOutTaxRateTo.sol +99 -0
  402. package/test/units/static/JBRulesets/JBRulesetsSetup.sol +21 -0
  403. package/test/units/static/JBRulesets/TestCurrentApprovalStatusForLatestRulesetOf.sol +257 -0
  404. package/test/units/static/JBRulesets/TestCurrentOf.sol +231 -0
  405. package/test/units/static/JBRulesets/TestGetRulesetOf.sol +94 -0
  406. package/test/units/static/JBRulesets/TestLatestQueuedRulesetOf.sol +252 -0
  407. package/test/units/static/JBRulesets/TestRulesets.sol +617 -0
  408. package/test/units/static/JBRulesets/TestRulesetsOf.sol +37 -0
  409. package/test/units/static/JBRulesets/TestUpcomingRulesetOf.sol +526 -0
  410. package/test/units/static/JBRulesets/TestUpdateRulesetWeightCache.sol +91 -0
  411. package/test/units/static/JBSplits/JBSplitsSetup.sol +23 -0
  412. package/test/units/static/JBSplits/TestSelfManagedSplitGroups.sol +502 -0
  413. package/test/units/static/JBSplits/TestSetSplitGroupsOf.sol +370 -0
  414. package/test/units/static/JBSplits/TestSplitsLockedEdge.sol +262 -0
  415. package/test/units/static/JBSplits/TestSplitsOf.sol +24 -0
  416. package/test/units/static/JBSplits/TestSplitsPacking.sol +33 -0
  417. package/test/units/static/JBSurplus/TestSurplusFuzz.sol +125 -0
  418. package/test/units/static/JBTerminalStore/JBTerminalStoreSetup.sol +23 -0
  419. package/test/units/static/JBTerminalStore/TestCurrentReclaimableSurplusOf.sol +434 -0
  420. package/test/units/static/JBTerminalStore/TestCurrentSurplusOf.sol +428 -0
  421. package/test/units/static/JBTerminalStore/TestCurrentTotalSurplusOf.sol +65 -0
  422. package/test/units/static/JBTerminalStore/TestRecordCashOutsFor.sol +479 -0
  423. package/test/units/static/JBTerminalStore/TestRecordPaymentFrom.sol +508 -0
  424. package/test/units/static/JBTerminalStore/TestRecordPayoutFor.sol +257 -0
  425. package/test/units/static/JBTerminalStore/TestRecordTerminalMigration.sol +131 -0
  426. package/test/units/static/JBTerminalStore/TestRecordUsedAllowanceOf.sol +390 -0
  427. package/test/units/static/JBTerminalStore/TestUint224Overflow.sol +187 -0
  428. package/test/units/static/JBTokens/JBTokensSetup.sol +23 -0
  429. package/test/units/static/JBTokens/TestBurnFrom.sol +104 -0
  430. package/test/units/static/JBTokens/TestClaimTokensFor.sol +107 -0
  431. package/test/units/static/JBTokens/TestDeployERC20ForUnits.sol +89 -0
  432. package/test/units/static/JBTokens/TestMintFor.sol +97 -0
  433. package/test/units/static/JBTokens/TestSetTokenFor.sol +95 -0
  434. package/test/units/static/JBTokens/TestTotalBalanceOf.sol +65 -0
  435. package/test/units/static/JBTokens/TestTotalSupplyOf.sol +56 -0
  436. package/test/units/static/JBTokens/TestTransferCreditsFrom.sol +54 -0
@@ -0,0 +1,185 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.6;
3
+
4
+ import /* {*} from */ "./helpers/TestBaseWorkflow.sol";
5
+ import {JBCashOuts} from "../src/libraries/JBCashOuts.sol";
6
+
7
+ // Projects can issue a token, be paid to receieve claimed tokens, burn some of the claimed tokens, cash out the rest
8
+ // of
9
+ // tokens
10
+ contract TestCashOut_Local is TestBaseWorkflow {
11
+ IJBController private _controller;
12
+ IJBMultiTerminal private _terminal;
13
+ JBTokens private _tokens;
14
+ uint112 private _weight;
15
+ JBRulesetMetadata _metadata;
16
+ uint256 private _projectId;
17
+ address private _projectOwner;
18
+ address private _beneficiary;
19
+
20
+ function setUp() public override {
21
+ super.setUp();
22
+
23
+ _projectOwner = multisig();
24
+ _beneficiary = beneficiary();
25
+ _controller = jbController();
26
+ _terminal = jbMultiTerminal();
27
+ _tokens = jbTokens();
28
+ _weight = 1000 * 10 ** 18;
29
+ _metadata = JBRulesetMetadata({
30
+ reservedPercent: 0,
31
+ cashOutTaxRate: JBConstants.MAX_CASH_OUT_TAX_RATE / 2,
32
+ baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
33
+ pausePay: false,
34
+ pauseCreditTransfers: false,
35
+ allowOwnerMinting: false,
36
+ allowSetCustomToken: false,
37
+ allowTerminalMigration: false,
38
+ allowSetTerminals: false,
39
+ ownerMustSendPayouts: false,
40
+ allowSetController: false,
41
+ allowAddAccountingContext: true,
42
+ allowAddPriceFeed: false,
43
+ holdFees: false,
44
+ useTotalSurplusForCashOuts: false,
45
+ useDataHookForPay: false,
46
+ useDataHookForCashOut: false,
47
+ dataHook: address(0),
48
+ metadata: 0
49
+ });
50
+
51
+ JBRulesetConfig[] memory _rulesetConfig = new JBRulesetConfig[](1);
52
+ _rulesetConfig[0].mustStartAtOrAfter = 0;
53
+ _rulesetConfig[0].duration = 0;
54
+ _rulesetConfig[0].weight = _weight;
55
+ _rulesetConfig[0].weightCutPercent = 0;
56
+ _rulesetConfig[0].approvalHook = IJBRulesetApprovalHook(address(0));
57
+ _rulesetConfig[0].metadata = _metadata;
58
+ _rulesetConfig[0].splitGroups = new JBSplitGroup[](0);
59
+ _rulesetConfig[0].fundAccessLimitGroups = new JBFundAccessLimitGroup[](0);
60
+
61
+ JBTerminalConfig[] memory _terminalConfigurations = new JBTerminalConfig[](1);
62
+ JBAccountingContext[] memory _tokensToAccept = new JBAccountingContext[](1);
63
+ _tokensToAccept[0] = JBAccountingContext({
64
+ token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
65
+ });
66
+ _terminalConfigurations[0] =
67
+ JBTerminalConfig({terminal: _terminal, accountingContextsToAccept: _tokensToAccept});
68
+
69
+ // Create a first project to collect fees.
70
+ _controller.launchProjectFor({
71
+ owner: address(420), // Random.
72
+ projectUri: "whatever",
73
+ rulesetConfigurations: _rulesetConfig,
74
+ terminalConfigurations: _terminalConfigurations, // Set terminals to receive fees.
75
+ memo: ""
76
+ });
77
+
78
+ // Create the project to test.
79
+ _projectId = _controller.launchProjectFor({
80
+ owner: _projectOwner,
81
+ projectUri: "myIPFSHash",
82
+ rulesetConfigurations: _rulesetConfig,
83
+ terminalConfigurations: _terminalConfigurations,
84
+ memo: ""
85
+ });
86
+ }
87
+
88
+ function testCashOut(uint256 _tokenAmountToCashOut) external {
89
+ uint112 _nativePayAmount = 10 ether;
90
+
91
+ // Issue the project's tokens.
92
+ vm.prank(_projectOwner);
93
+ _controller.deployERC20For(_projectId, "TestName", "TestSymbol", bytes32(0));
94
+
95
+ // Pay the project.
96
+ _terminal.pay{value: _nativePayAmount}({
97
+ projectId: _projectId,
98
+ amount: _nativePayAmount,
99
+ token: JBConstants.NATIVE_TOKEN,
100
+ beneficiary: _beneficiary,
101
+ minReturnedTokens: 0,
102
+ memo: "Take my money!",
103
+ metadata: new bytes(0)
104
+ });
105
+
106
+ // Make sure the beneficiary has a balance of project tokens.
107
+ uint256 _beneficiaryTokenBalance =
108
+ UD60x18unwrap(UD60x18mul(UD60x18wrap(_nativePayAmount), UD60x18wrap(_weight)));
109
+ assertEq(_tokens.totalBalanceOf(_beneficiary, _projectId), _beneficiaryTokenBalance);
110
+
111
+ // Make sure the native token balance in terminal is up to date.
112
+ uint256 _nativeTerminalBalance = _nativePayAmount;
113
+ assertEq(
114
+ jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN),
115
+ _nativeTerminalBalance
116
+ );
117
+
118
+ // Fuzz 1 to full balance cash out.
119
+ _tokenAmountToCashOut = bound(_tokenAmountToCashOut, 1, _beneficiaryTokenBalance);
120
+
121
+ JBAccountingContext[] memory _tokensContext = new JBAccountingContext[](1);
122
+ _tokensContext[0] = JBAccountingContext({
123
+ token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
124
+ });
125
+
126
+ // Get the expected gross per a different view.
127
+ uint256 _grossPerReclaimable = jbTerminalStore()
128
+ .currentReclaimableSurplusOf(
129
+ _projectId, _tokenAmountToCashOut, new IJBTerminal[](0), _tokensContext, 18, _tokensContext[0].currency
130
+ );
131
+
132
+ // Test: cash out.
133
+ vm.prank(_beneficiary);
134
+ uint256 _nativeReclaimAmt = _terminal.cashOutTokensOf({
135
+ holder: _beneficiary,
136
+ projectId: _projectId,
137
+ cashOutCount: _tokenAmountToCashOut,
138
+ tokenToReclaim: JBConstants.NATIVE_TOKEN,
139
+ minTokensReclaimed: 0,
140
+ beneficiary: payable(_beneficiary),
141
+ metadata: new bytes(0)
142
+ });
143
+
144
+ // Keep a reference to the expected amount cashed out.
145
+ uint256 _grossCashedOut = mulDiv(
146
+ mulDiv(_nativeTerminalBalance, _tokenAmountToCashOut, _beneficiaryTokenBalance),
147
+ _metadata.cashOutTaxRate
148
+ + mulDiv(
149
+ _tokenAmountToCashOut,
150
+ JBConstants.MAX_CASH_OUT_TAX_RATE - _metadata.cashOutTaxRate,
151
+ _beneficiaryTokenBalance
152
+ ),
153
+ JBConstants.MAX_CASH_OUT_TAX_RATE
154
+ );
155
+
156
+ // Ensure currentReclaimable is correct.
157
+ assertEq(_grossCashedOut, _grossPerReclaimable);
158
+
159
+ // Compute the fee taken.
160
+ uint256 _fee = mulDiv(_grossCashedOut, 25_000_000, 1_000_000_000); // 2.5% fee
161
+
162
+ // Compute the net amount received, still in project.
163
+ uint256 _netReceived = _grossCashedOut - _fee;
164
+
165
+ // Make sure the correct amount was returned (2 wei precision).
166
+ assertApproxEqAbs(_nativeReclaimAmt, _netReceived, 2, "incorrect amount returned");
167
+
168
+ // Make sure the beneficiary received correct amount of native tokens.
169
+ assertEq(payable(_beneficiary).balance, _nativeReclaimAmt);
170
+
171
+ // Make sure the beneficiary has correct amount of tokens.
172
+ assertEq(
173
+ _tokens.totalBalanceOf(_beneficiary, _projectId),
174
+ _beneficiaryTokenBalance - _tokenAmountToCashOut,
175
+ "incorrect beneficiary balance"
176
+ );
177
+
178
+ // Make sure the native token balance in terminal should be up to date (with 1 wei precision).
179
+ assertApproxEqAbs(
180
+ jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN),
181
+ _nativeTerminalBalance - _grossCashedOut,
182
+ 1
183
+ );
184
+ }
185
+ }
@@ -0,0 +1,272 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ import "forge-std/Test.sol";
5
+ import {mulDiv} from "@prb/math/src/Common.sol";
6
+ import {JBCashOuts} from "../src/libraries/JBCashOuts.sol";
7
+ import {JBConstants} from "../src/libraries/JBConstants.sol";
8
+
9
+ /// @dev Wrapper so library reverts can be caught by vm.expectRevert (library calls are inlined otherwise).
10
+ contract CashOutCountForWrapper {
11
+ function minCashOutCountFor(
12
+ uint256 surplus,
13
+ uint256 desiredOutput,
14
+ uint256 totalSupply,
15
+ uint256 cashOutTaxRate
16
+ )
17
+ external
18
+ pure
19
+ returns (uint256)
20
+ {
21
+ return JBCashOuts.minCashOutCountFor(surplus, desiredOutput, totalSupply, cashOutTaxRate);
22
+ }
23
+ }
24
+
25
+ /// @title TestCashOutCountFor
26
+ /// @notice Tests for JBCashOuts.minCashOutCountFor — the inverse of the bonding curve.
27
+ contract TestCashOutCountFor is Test {
28
+ uint256 constant MAX_TAX = JBConstants.MAX_CASH_OUT_TAX_RATE;
29
+
30
+ CashOutCountForWrapper wrapper;
31
+
32
+ function setUp() public {
33
+ wrapper = new CashOutCountForWrapper();
34
+ }
35
+
36
+ // =========================================================================
37
+ // Edge cases
38
+ // =========================================================================
39
+
40
+ function test_zeroDesiredOutput() public pure {
41
+ assertEq(JBCashOuts.minCashOutCountFor(100 ether, 0, 1000e18, 5000), 0);
42
+ }
43
+
44
+ function test_desiredOutputEqualsSurplus() public pure {
45
+ uint256 count = JBCashOuts.minCashOutCountFor(100 ether, 100 ether, 1000e18, 5000);
46
+ assertEq(count, 1000e18, "Should return totalSupply when desiredOutput == surplus");
47
+ }
48
+
49
+ function test_desiredOutputExceedsSurplus() public pure {
50
+ uint256 count = JBCashOuts.minCashOutCountFor(100 ether, 200 ether, 1000e18, 5000);
51
+ assertEq(count, 1000e18, "Should return totalSupply when desiredOutput > surplus");
52
+ }
53
+
54
+ function test_maxTaxRate_reverts() public {
55
+ vm.expectRevert(JBCashOuts.JBCashOuts_DesiredOutputNotAchievable.selector);
56
+ wrapper.minCashOutCountFor(100 ether, 50 ether, 1000e18, MAX_TAX);
57
+ }
58
+
59
+ function test_zeroTaxRate() public pure {
60
+ // With 0 tax: out = S * c / T, so c = out * T / S.
61
+ // surplus=100, desiredOutput=25, totalSupply=200 → c = 25*200/100 = 50.
62
+ uint256 count = JBCashOuts.minCashOutCountFor(100, 25, 200, 0);
63
+ assertEq(count, 50);
64
+ assertGe(JBCashOuts.cashOutFrom(100, count, 200, 0), 25);
65
+ }
66
+
67
+ function test_zeroTaxRate_roundsUp() public pure {
68
+ // surplus=7, desiredOutput=2, totalSupply=100.
69
+ // Exact: c = 2*100/7 = 28.57... floor = 28. mulDiv(7, 28, 100) = 1 < 2. So c = 29.
70
+ uint256 count = JBCashOuts.minCashOutCountFor(7, 2, 100, 0);
71
+ assertGe(JBCashOuts.cashOutFrom(7, count, 100, 0), 2);
72
+ }
73
+
74
+ function test_zeroSurplus() public pure {
75
+ // surplus=0, desiredOutput=1 → desiredOutput >= surplus → return totalSupply.
76
+ uint256 count = JBCashOuts.minCashOutCountFor(0, 1, 1000e18, 5000);
77
+ assertEq(count, 1000e18);
78
+ }
79
+
80
+ // =========================================================================
81
+ // Specific examples
82
+ // =========================================================================
83
+
84
+ function test_halfTax_knownValues() public pure {
85
+ // surplus=100, totalSupply=100, taxRate=5000 (50%).
86
+ // Forward: cashOutFrom(100, 50, 100, 5000) = 37.
87
+ uint256 forwardResult = JBCashOuts.cashOutFrom(100, 50, 100, 5000);
88
+ assertEq(forwardResult, 37);
89
+
90
+ // Inverse: to get 37 out, we need at least 50 tokens.
91
+ uint256 count = JBCashOuts.minCashOutCountFor(100, 37, 100, 5000);
92
+ assertEq(count, 50);
93
+ assertGe(JBCashOuts.cashOutFrom(100, count, 100, 5000), 37);
94
+ }
95
+
96
+ function test_lowTax() public pure {
97
+ // taxRate=1000 (10%).
98
+ uint256 forwardResult = JBCashOuts.cashOutFrom(1000, 100, 1000, 1000);
99
+
100
+ uint256 count = JBCashOuts.minCashOutCountFor(1000, forwardResult, 1000, 1000);
101
+ assertGe(JBCashOuts.cashOutFrom(1000, count, 1000, 1000), forwardResult);
102
+ assertLe(count, 100);
103
+ }
104
+
105
+ function test_highTax() public pure {
106
+ // taxRate=9000 (90%).
107
+ uint256 forwardResult = JBCashOuts.cashOutFrom(1000, 500, 1000, 9000);
108
+
109
+ uint256 count = JBCashOuts.minCashOutCountFor(1000, forwardResult, 1000, 9000);
110
+ assertGe(JBCashOuts.cashOutFrom(1000, count, 1000, 9000), forwardResult);
111
+ assertLe(count, 500);
112
+ }
113
+
114
+ function test_realisticValues() public pure {
115
+ // 10 ETH surplus, 1M tokens, 30% tax.
116
+ uint256 surplus = 10 ether;
117
+ uint256 totalSupply = 1_000_000e18;
118
+ uint256 taxRate = 3000;
119
+ uint256 cashOutAmount = 100_000e18;
120
+
121
+ uint256 forwardResult = JBCashOuts.cashOutFrom(surplus, cashOutAmount, totalSupply, taxRate);
122
+
123
+ uint256 count = JBCashOuts.minCashOutCountFor(surplus, forwardResult, totalSupply, taxRate);
124
+ assertGe(JBCashOuts.cashOutFrom(surplus, count, totalSupply, taxRate), forwardResult);
125
+ assertLe(count, cashOutAmount);
126
+ }
127
+
128
+ function test_smallSurplus_largeTotalSupply() public pure {
129
+ // Edge case that trips up analytic formulas: surplus << totalSupply.
130
+ uint256 surplus = 3178;
131
+ uint256 totalSupply = 11_740_172_277_586_795;
132
+ uint256 taxRate = 2;
133
+ uint256 desiredOutput = 1589;
134
+
135
+ uint256 count = JBCashOuts.minCashOutCountFor(surplus, desiredOutput, totalSupply, taxRate);
136
+ assertGe(JBCashOuts.cashOutFrom(surplus, count, totalSupply, taxRate), desiredOutput);
137
+ }
138
+
139
+ // =========================================================================
140
+ // Round-trip: minCashOutCountFor(S, cashOutFrom(S, c, T, r), T, r) <= c
141
+ // =========================================================================
142
+
143
+ function testFuzz_roundTrip_inverseOfForward(
144
+ uint128 surplus,
145
+ uint128 totalSupply,
146
+ uint128 cashOutCount,
147
+ uint16 cashOutTaxRate
148
+ )
149
+ public
150
+ pure
151
+ {
152
+ vm.assume(surplus > 0);
153
+ vm.assume(totalSupply > 0);
154
+ vm.assume(cashOutCount > 0 && cashOutCount <= totalSupply);
155
+ vm.assume(cashOutTaxRate <= MAX_TAX);
156
+ vm.assume(cashOutTaxRate < MAX_TAX);
157
+
158
+ uint256 output = JBCashOuts.cashOutFrom(surplus, cashOutCount, totalSupply, cashOutTaxRate);
159
+ vm.assume(output > 0);
160
+
161
+ uint256 recoveredCount = JBCashOuts.minCashOutCountFor(surplus, output, totalSupply, cashOutTaxRate);
162
+
163
+ // The recovered count should be <= the original count, because the forward function rounds down.
164
+ assertLe(recoveredCount, cashOutCount, "Round-trip: recovered count should be <= original");
165
+ }
166
+
167
+ // =========================================================================
168
+ // Correctness: cashOutFrom(S, minCashOutCountFor(S, out, T, r), T, r) >= out
169
+ // =========================================================================
170
+
171
+ function testFuzz_correctness_outputMeetsTarget(
172
+ uint128 surplus,
173
+ uint128 totalSupply,
174
+ uint16 cashOutTaxRate
175
+ )
176
+ public
177
+ pure
178
+ {
179
+ vm.assume(surplus > 1);
180
+ vm.assume(totalSupply > 0);
181
+ vm.assume(cashOutTaxRate <= MAX_TAX);
182
+ vm.assume(cashOutTaxRate < MAX_TAX);
183
+
184
+ uint256 desiredOutput = uint256(surplus) / 2;
185
+ vm.assume(desiredOutput > 0 && desiredOutput < surplus);
186
+
187
+ uint256 count = JBCashOuts.minCashOutCountFor(surplus, desiredOutput, totalSupply, cashOutTaxRate);
188
+
189
+ uint256 actualOutput = JBCashOuts.cashOutFrom(surplus, count, totalSupply, cashOutTaxRate);
190
+ assertGe(actualOutput, desiredOutput, "Correctness: output should meet or exceed target");
191
+ }
192
+
193
+ function testFuzz_correctness_fullRange(
194
+ uint128 surplus,
195
+ uint128 totalSupply,
196
+ uint128 desiredOutput,
197
+ uint16 cashOutTaxRate
198
+ )
199
+ public
200
+ pure
201
+ {
202
+ vm.assume(surplus > 0);
203
+ vm.assume(totalSupply > 0);
204
+ vm.assume(cashOutTaxRate <= MAX_TAX);
205
+ vm.assume(cashOutTaxRate < MAX_TAX);
206
+ vm.assume(desiredOutput > 0 && desiredOutput < surplus);
207
+
208
+ uint256 count = JBCashOuts.minCashOutCountFor(surplus, desiredOutput, totalSupply, cashOutTaxRate);
209
+
210
+ assertLe(count, totalSupply, "Count should not exceed totalSupply");
211
+
212
+ uint256 actualOutput = JBCashOuts.cashOutFrom(surplus, count, totalSupply, cashOutTaxRate);
213
+ assertGe(actualOutput, desiredOutput, "Output should meet target");
214
+ }
215
+
216
+ // =========================================================================
217
+ // Monotonicity: larger desired output → larger or equal count
218
+ // =========================================================================
219
+
220
+ function testFuzz_monotonicity(
221
+ uint128 surplus,
222
+ uint128 totalSupply,
223
+ uint128 out1,
224
+ uint128 out2,
225
+ uint16 cashOutTaxRate
226
+ )
227
+ public
228
+ pure
229
+ {
230
+ vm.assume(surplus > 2);
231
+ vm.assume(totalSupply > 0);
232
+ vm.assume(cashOutTaxRate <= MAX_TAX);
233
+ vm.assume(cashOutTaxRate < MAX_TAX);
234
+ vm.assume(out1 > 0 && out2 > 0);
235
+ vm.assume(out1 < surplus && out2 < surplus);
236
+
237
+ if (out1 > out2) (out1, out2) = (out2, out1);
238
+
239
+ uint256 count1 = JBCashOuts.minCashOutCountFor(surplus, out1, totalSupply, cashOutTaxRate);
240
+ uint256 count2 = JBCashOuts.minCashOutCountFor(surplus, out2, totalSupply, cashOutTaxRate);
241
+
242
+ assertLe(count1, count2, "Monotonicity: larger output needs >= count");
243
+ }
244
+
245
+ // =========================================================================
246
+ // Minimality: count - 1 should produce less than desiredOutput
247
+ // =========================================================================
248
+
249
+ function testFuzz_minimality(
250
+ uint128 surplus,
251
+ uint128 totalSupply,
252
+ uint128 desiredOutput,
253
+ uint16 cashOutTaxRate
254
+ )
255
+ public
256
+ pure
257
+ {
258
+ vm.assume(surplus > 0);
259
+ vm.assume(totalSupply > 1);
260
+ vm.assume(cashOutTaxRate <= MAX_TAX);
261
+ vm.assume(cashOutTaxRate < MAX_TAX);
262
+ vm.assume(desiredOutput > 0 && desiredOutput < surplus);
263
+
264
+ uint256 count = JBCashOuts.minCashOutCountFor(surplus, desiredOutput, totalSupply, cashOutTaxRate);
265
+
266
+ vm.assume(count > 1);
267
+ vm.assume(count < totalSupply);
268
+
269
+ uint256 lesserOutput = JBCashOuts.cashOutFrom(surplus, count - 1, totalSupply, cashOutTaxRate);
270
+ assertLt(lesserOutput, desiredOutput, "Minimality: count-1 should produce less than target");
271
+ }
272
+ }